diff options
author | Fabio Berger <me@fabioberger.com> | 2018-05-11 18:32:57 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-05-11 18:32:57 +0800 |
commit | d370296e82c11d67bbb16a1dc73432c3625682aa (patch) | |
tree | c8e5d440bc2b78feae89644c11ba3ed778da6015 /packages | |
parent | f78b5741c3ba3495c066dc800ce62d8a1f3fb75f (diff) | |
parent | f42f608f3f97a5244f09f17ae5ee184c0f775de3 (diff) | |
download | dexon-sol-tools-d370296e82c11d67bbb16a1dc73432c3625682aa.tar dexon-sol-tools-d370296e82c11d67bbb16a1dc73432c3625682aa.tar.gz dexon-sol-tools-d370296e82c11d67bbb16a1dc73432c3625682aa.tar.bz2 dexon-sol-tools-d370296e82c11d67bbb16a1dc73432c3625682aa.tar.lz dexon-sol-tools-d370296e82c11d67bbb16a1dc73432c3625682aa.tar.xz dexon-sol-tools-d370296e82c11d67bbb16a1dc73432c3625682aa.tar.zst dexon-sol-tools-d370296e82c11d67bbb16a1dc73432c3625682aa.zip |
Merge branch 'development' into breakUp0xjs
* development:
Fix ganache subprovider config
Fix a bug in compiler config precedence
Fix linter errors
Fix templates
Remove unused deployer docs configs
Add a legacy endpoint for the deployer
Add a check for compiler output
Add a comment
Put ARTIFACTS_VERSION in a config
Improve a comment
Remove _applyDefaultsToDeployTxDataAsync
Add a HACK comment
Fix linter issues
Rename deployer to sol-compiler
Remove deployer
Remove deployer from 0x.js and migrations
Configure migrations with a compiler.json
Remove deployer from metacoin and contract tests
Update wallet footer and add remove token functionality
# Conflicts:
# .gitignore
# packages/0x.js/package.json
# packages/0x.js/src/0x.ts
# packages/contracts/package.json
# packages/contracts/test/multi_sig_with_time_lock.ts
# packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts
# packages/contracts/util/artifacts.ts
# packages/deployer/test/deployer_test.ts
# packages/migrations/package.json
Diffstat (limited to 'packages')
114 files changed, 887 insertions, 1008 deletions
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index 1af5fcdb6..d048c8be6 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -21,10 +21,9 @@ "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_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/1.0.0/$i.json test/artifacts; done;", - "clean": "shx rm -rf _bundles lib test_temp scripts test/artifacts src/contract_wrappers/generated", + "clean": "shx rm -rf _bundles lib test_temp scripts src/contract_wrappers/generated", "build:umd:prod": "NODE_ENV=production webpack", - "build:commonjs": "tsc && yarn update_artifacts && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", + "build:commonjs": "tsc && 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 lib/test/global_hooks.js --timeout 10000 --bail --exit", "manual:postpublish": "yarn build; node ./scripts/postpublish.js", @@ -34,7 +33,6 @@ }, "config": { "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", @@ -68,7 +66,7 @@ "node": ">=6.0.0" }, "devDependencies": { - "@0xproject/deployer": "^0.4.3", + "@0xproject/sol-compiler": "^0.4.3", "@0xproject/dev-utils": "^0.4.1", "@0xproject/migrations": "^0.0.5", "@0xproject/monorepo-scripts": "^0.1.19", diff --git a/packages/0x.js/test/global_hooks.ts b/packages/0x.js/test/global_hooks.ts index e3c986524..88f202761 100644 --- a/packages/0x.js/test/global_hooks.ts +++ b/packages/0x.js/test/global_hooks.ts @@ -1,7 +1,18 @@ +import { devConstants } from '@0xproject/dev-utils'; import { runMigrationsAsync } from '@0xproject/migrations'; +import * as path from 'path'; -import { deployer } from './utils/deployer'; +import { constants } from './utils/constants'; +import { provider } from './utils/web3_wrapper'; -before('migrate contracts', async () => { - await runMigrationsAsync(deployer); +before('migrate contracts', async function() { + // HACK: Since the migrations take longer then our global mocha timeout limit + // we manually increase it for this before hook. + this.timeout(20000); + const txDefaults = { + gas: devConstants.GAS_ESTIMATE, + from: devConstants.TESTRPC_FIRST_ADDRESS, + }; + const artifactsDir = `../migrations/artifacts/1.0.0`; + await runMigrationsAsync(provider, artifactsDir, txDefaults); }); diff --git a/packages/0x.js/test/utils/deployer.ts b/packages/0x.js/test/utils/deployer.ts deleted file mode 100644 index b092322e2..000000000 --- a/packages/0x.js/test/utils/deployer.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Deployer } from '@0xproject/deployer'; -import { devConstants } from '@0xproject/dev-utils'; -import * as path from 'path'; - -import { constants } from './constants'; - -import { provider } from './web3_wrapper'; - -const artifactsDir = path.resolve('test', 'artifacts'); -const deployerOpts = { - artifactsDir, - provider, - networkId: constants.TESTRPC_NETWORK_ID, - defaults: { - gas: devConstants.GAS_ESTIMATE, - }, -}; -export const deployer = new Deployer(deployerOpts); diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts index 7125171b9..a280f2e63 100644 --- a/packages/abi-gen/src/index.ts +++ b/packages/abi-gen/src/index.ts @@ -114,7 +114,7 @@ for (const abiFileName of abiFileNames) { if (_.isUndefined(ABI)) { logUtils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`); logUtils.log( - `Please make sure your ABI file is either an array with ABI entries or a truffle artifact or 0x deployer artifact`, + `Please make sure your ABI file is either an array with ABI entries or a truffle artifact or 0x sol-compiler artifact`, ); process.exit(1); } diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index e95b18db6..f9298f413 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -1,6 +1,7 @@ import { AbiDefinition, AbiType, + ConstructorAbi, ContractAbi, DataItem, MethodAbi, @@ -24,6 +25,8 @@ export class BaseContract { protected _web3Wrapper: Web3Wrapper; public abi: ContractAbi; public address: string; + public contractName: string; + public constructorArgs: any[] = []; protected static _formatABIDataItemList( abis: DataItem[], values: any[], @@ -37,11 +40,31 @@ export class BaseContract { protected static _bigNumberToString(type: string, value: any): any { return _.isObject(value) && value.isBigNumber ? value.toString() : value; } + protected static _lookupConstructorAbi(abi: ContractAbi): ConstructorAbi { + const constructorAbiIfExists = _.find( + abi, + (abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Constructor, + ) as ConstructorAbi | undefined; + if (!_.isUndefined(constructorAbiIfExists)) { + return constructorAbiIfExists; + } else { + // If the constructor is not explicitly defined, it won't be included in the ABI. It is + // still callable however, so we construct what the ABI would look like were it to exist. + const defaultConstructorAbi: ConstructorAbi = { + type: AbiType.Constructor, + stateMutability: 'nonpayable', + payable: false, + inputs: [], + }; + return defaultConstructorAbi; + } + } protected static _bnToBigNumber(type: string, value: any): any { return _.isObject(value) && value._bn ? new BigNumber(value.toString()) : value; } - protected async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>( + protected static async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>( txData: T, + txDefaults: Partial<TxData>, estimateGasAsync?: (txData: T) => Promise<number>, ): Promise<TxData> { // Gas amount sourced with the following priorities: @@ -49,13 +72,12 @@ export class BaseContract { // 2. Global config passed in at library instantiation // 3. Gas estimate calculation + safety margin const removeUndefinedProperties = _.pickBy; - const txDataWithDefaults = ({ - to: this.address, - ...removeUndefinedProperties(this._web3Wrapper.getContractDefaults()), + const txDataWithDefaults: TxData = { + ...removeUndefinedProperties(txDefaults), ...removeUndefinedProperties(txData as any), // HACK: TS can't prove that T is spreadable. // Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged - } as any) as TxData; + } as any; if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) { const estimatedGas = await estimateGasAsync(txData); txDataWithDefaults.gas = estimatedGas; @@ -82,8 +104,15 @@ export class BaseContract { }) as MethodAbi; return methodAbi; } - constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) { - this._web3Wrapper = new Web3Wrapper(provider, defaults); + constructor( + contractName: string, + abi: ContractAbi, + address: string, + provider: Provider, + txDefaults?: Partial<TxData>, + ) { + this.contractName = contractName; + this._web3Wrapper = new Web3Wrapper(provider, txDefaults); this.abi = abi; this.address = address; const methodAbis = this.abi.filter( diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index 381c4a63f..89a36ecbe 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -70,10 +70,10 @@ export class ContractWrappers { ]); const artifactJSONs = _.values(artifacts); const abiArrays = _.map(artifactJSONs, artifact => artifact.abi); - const defaults = { + const txDefaults = { gasPrice: config.gasPrice, }; - this._web3Wrapper = new Web3Wrapper(provider, defaults); + this._web3Wrapper = new Web3Wrapper(provider, txDefaults); _.forEach(abiArrays, abi => { this._web3Wrapper.abiDecoder.addABI(abi); }); diff --git a/packages/contract_templates/contract.handlebars b/packages/contract_templates/contract.handlebars index cf51dad90..ed11ac8d2 100644 --- a/packages/contract_templates/contract.handlebars +++ b/packages/contract_templates/contract.handlebars @@ -5,8 +5,9 @@ // tslint:disable:no-consecutive-blank-lines // tslint:disable-next-line:no-unused-variable import { BaseContract } from '@0xproject/base-contract'; +import { ContractArtifact } from '@0xproject/sol-compiler'; import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, MethodAbi, Provider, TxData, TxDataPayable } from '@0xproject/types'; -import { BigNumber, classUtils, promisify } from '@0xproject/utils'; +import { BigNumber, classUtils, logUtils, promisify } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as ethers from 'ethers'; import * as _ from 'lodash'; @@ -39,8 +40,49 @@ export class {{contractName}}Contract extends BaseContract { {{> tx contractName=../contractName}} {{/this.constant}} {{/each}} - constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) { - super(abi, address, provider, defaults); + public static async deployFrom0xArtifactAsync( + artifact: ContractArtifact, + provider: Provider, + txDefaults: Partial<TxData>, + {{> typed_params inputs=ctor.inputs}} + ): Promise<{{contractName}}Contract> { + if (_.isUndefined(artifact.compilerOutput)) { + throw new Error('Compiler output not found in the artifact file'); + } + const bytecode = artifact.compilerOutput.evm.bytecode.object; + const abi = artifact.compilerOutput.abi; + return {{contractName}}Contract.deployAsync(bytecode, abi, provider, txDefaults, {{> params inputs=ctor.inputs}}); + } + public static async deployAsync( + bytecode: string, + abi: ContractAbi, + provider: Provider, + txDefaults: Partial<TxData>, + {{> typed_params inputs=ctor.inputs}} + ): Promise<{{contractName}}Contract> { + const constructorAbi = BaseContract._lookupConstructorAbi(abi); + [{{> params inputs=ctor.inputs}}] = BaseContract._formatABIDataItemList( + constructorAbi.inputs, + [{{> params inputs=ctor.inputs}}], + BaseContract._bigNumberToString, + ); + const txData = ethers.Contract.getDeployTransaction(bytecode, abi, {{> params inputs=ctor.inputs}}); + const web3Wrapper = new Web3Wrapper(provider); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + txData, + txDefaults, + web3Wrapper.estimateGasAsync.bind(web3Wrapper), + ); + const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults); + logUtils.log(`transactionHash: ${txHash}`); + const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(txHash); + logUtils.log(`{{contractName}} successfully deployed at ${txReceipt.contractAddress}`); + const contractInstance = new {{contractName}}Contract(abi, txReceipt.contractAddress as string, provider, txDefaults); + contractInstance.constructorArgs = [{{> params inputs=ctor.inputs}}]; + return contractInstance; + } + constructor(abi: ContractAbi, address: string, provider: Provider, txDefaults?: Partial<TxData>) { + super("{{contractName}}", abi, address, provider, txDefaults); 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 58fb2f09c..99fda80e1 100644 --- a/packages/contract_templates/partials/callAsync.handlebars +++ b/packages/contract_templates/partials/callAsync.handlebars @@ -12,10 +12,12 @@ async callAsync( {{> params inputs=inputs}} ) as ethers.CallDescription; const encodedData = ethersFunction.data; - const callDataWithDefaults = await self._applyDefaultsToTxDataAsync( + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { + to: self.address, data: encodedData, - } + }, + self._web3Wrapper.getContractDefaults(), ) const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); let resultArray = ethersFunction.parse(rawCallResult); diff --git a/packages/contract_templates/partials/tx.handlebars b/packages/contract_templates/partials/tx.handlebars index 1bdf80c42..e297d05e6 100644 --- a/packages/contract_templates/partials/tx.handlebars +++ b/packages/contract_templates/partials/tx.handlebars @@ -14,11 +14,13 @@ public {{this.tsName}} = { const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( {{> params inputs=inputs}} ).data; - const txDataWithDefaults = await self._applyDefaultsToTxDataAsync( + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { + to: self.address, ...txData, data: encodedData, }, + self._web3Wrapper.getContractDefaults(), self.{{this.tsName}}.estimateGasAsync.bind( self, {{> params inputs=inputs}} @@ -33,15 +35,17 @@ public {{this.tsName}} = { ): Promise<number> { const self = this as any as {{contractName}}Contract; const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; - [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this)); + [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString); const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( {{> params inputs=inputs}} ).data; - const txDataWithDefaults = await self._applyDefaultsToTxDataAsync( + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { + to: self.address, ...txData, data: encodedData, - } + }, + self._web3Wrapper.getContractDefaults(), ); const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; @@ -51,7 +55,7 @@ public {{this.tsName}} = { ): string { const self = this as any as {{contractName}}Contract; const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; - [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self)); + [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString); const abiEncodedTransactionData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( {{> params inputs=inputs}} ).data; diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 891488bd9..557effca2 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -16,17 +16,17 @@ "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", + "compile": "node ../sol-compiler/lib/src/cli.js", "clean": "shx rm -rf lib src/contract_wrappers/generated", "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'", - "lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'", + "lint": "tslint --project .", "coverage:report:text": "istanbul report text", "coverage:report:html": "istanbul report html && open coverage/index.html", "coverage:report:lcov": "istanbul report lcov", "test:circleci": "yarn test:coverage" }, "config": { - "abis": "../migrations/artifacts/1.0.0/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels).json" + "abis": "../migrations/artifacts/1.0.0/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels|WETH9|MaliciousToken).json" }, "repository": { "type": "git", @@ -60,7 +60,8 @@ }, "dependencies": { "0x.js": "^0.37.2", - "@0xproject/deployer": "^0.4.3", + "@0xproject/base-contract": "^0.3.1", + "@0xproject/sol-compiler": "^0.4.3", "@0xproject/types": "^0.6.3", "@0xproject/typescript-typings": "^0.3.1", "@0xproject/utils": "^0.6.1", @@ -68,7 +69,7 @@ "bn.js": "^4.11.8", "ethereumjs-abi": "^0.6.4", "ethereumjs-util": "^5.1.1", - "ethers-contracts": "^2.2.1", + "ethers": "^3.0.15", "lodash": "^4.17.4", "web3": "^0.20.0" } diff --git a/packages/contracts/test/ether_token.ts b/packages/contracts/test/ether_token.ts index bb6d4cbec..4eb901dc7 100644 --- a/packages/contracts/test/ether_token.ts +++ b/packages/contracts/test/ether_token.ts @@ -4,12 +4,14 @@ import { BigNumber, promisify } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; +import { WETH9Contract } from '../src/contract_wrappers/generated/weth9'; +import { artifacts } from '../util/artifacts'; import { constants } from '../util/constants'; import { ContractName } from '../util/types'; import { chaiSetup } from './utils/chai_setup'; -import { deployer } from './utils/deployer'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -24,7 +26,7 @@ describe('EtherToken', () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); account = accounts[0]; - const etherToken = await deployer.deployAsync(ContractName.EtherToken); + const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.EtherToken, provider, txDefaults); etherTokenAddress = etherToken.address; zeroEx = new ZeroEx(provider, { gasPrice, diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index 689b11062..e40b564c6 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -13,7 +13,9 @@ import { LogErrorContractEventArgs, LogFillContractEventArgs, } from '../../src/contract_wrappers/generated/exchange'; +import { MaliciousTokenContract } from '../../src/contract_wrappers/generated/malicious_token'; import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy'; +import { artifacts } from '../../util/artifacts'; import { Balances } from '../../util/balances'; import { constants } from '../../util/constants'; import { crypto } from '../../util/crypto'; @@ -21,8 +23,8 @@ import { ExchangeWrapper } from '../../util/exchange_wrapper'; import { OrderFactory } from '../../util/order_factory'; import { BalancesByOwner, ContractName, ExchangeContractErrs } from '../../util/types'; import { chaiSetup } from '../utils/chai_setup'; -import { deployer } from '../utils/deployer'; -import { provider, web3Wrapper } from '../utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -54,25 +56,47 @@ describe('Exchange', () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); maker = accounts[0]; [tokenOwner, taker, feeRecipient] = accounts; - const [repInstance, dgdInstance, zrxInstance] = await Promise.all([ - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), + [rep, dgd, zrx] = await Promise.all([ + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), ]); - rep = new DummyTokenContract(repInstance.abi, repInstance.address, provider); - dgd = new DummyTokenContract(dgdInstance.abi, dgdInstance.address, provider); - zrx = new DummyTokenContract(zrxInstance.abi, zrxInstance.address, provider); - const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy); - tokenTransferProxy = new TokenTransferProxyContract( - tokenTransferProxyInstance.abi, - tokenTransferProxyInstance.address, + tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, provider, + txDefaults, ); - const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [ + exchange = await ExchangeContract.deployFrom0xArtifactAsync( + artifacts.Exchange, + provider, + txDefaults, zrx.address, tokenTransferProxy.address, - ]); - exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider); + ); await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] }); zeroEx = new ZeroEx(provider, { exchangeContractAddress: exchange.address, @@ -689,7 +713,11 @@ describe('Exchange', () => { it('should throw if getBalance or getAllowance attempts to change state and \ shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { - const maliciousToken = await deployer.deployAsync(ContractName.MaliciousToken); + const maliciousToken = await MaliciousTokenContract.deployFrom0xArtifactAsync( + artifacts.MaliciousToken, + provider, + txDefaults, + ); await maliciousToken.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: taker, }); diff --git a/packages/contracts/test/exchange/helpers.ts b/packages/contracts/test/exchange/helpers.ts index 8fc30c0b5..441c1bc28 100644 --- a/packages/contracts/test/exchange/helpers.ts +++ b/packages/contracts/test/exchange/helpers.ts @@ -11,13 +11,18 @@ import { LogErrorContractEventArgs, LogFillContractEventArgs, } from '../../src/contract_wrappers/generated/exchange'; + +import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token'; +import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry'; +import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy'; +import { artifacts } from '../../util/artifacts'; import { constants } from '../../util/constants'; import { ExchangeWrapper } from '../../util/exchange_wrapper'; import { OrderFactory } from '../../util/order_factory'; import { ContractName } from '../../util/types'; import { chaiSetup } from '../utils/chai_setup'; -import { deployer } from '../utils/deployer'; -import { provider, web3Wrapper } from '../utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -35,19 +40,53 @@ describe('Exchange', () => { before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); [maker, feeRecipient] = accounts; - const tokenRegistry = await deployer.deployAsync(ContractName.TokenRegistry); - const tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); + const tokenRegistry = await TokenRegistryContract.deployFrom0xArtifactAsync( + artifacts.TokenRegistry, + provider, + txDefaults, + ); + const tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, + provider, + txDefaults, + ); const [rep, dgd, zrx] = await Promise.all([ - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), ]); - const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [ + const exchange = await ExchangeContract.deployFrom0xArtifactAsync( + artifacts.Exchange, + provider, + txDefaults, zrx.address, tokenTransferProxy.address, - ]); - const exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider); - await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] }); + ); + await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] }); const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID }); exchangeWrapper = new ExchangeWrapper(exchange, zeroEx); const defaultOrderParams = { diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts index c658dca79..57ccd05bd 100644 --- a/packages/contracts/test/exchange/wrapper.ts +++ b/packages/contracts/test/exchange/wrapper.ts @@ -15,14 +15,15 @@ import { } from '../../src/contract_wrappers/generated/exchange'; import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry'; import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy'; +import { artifacts } from '../../util/artifacts'; import { Balances } from '../../util/balances'; import { constants } from '../../util/constants'; import { ExchangeWrapper } from '../../util/exchange_wrapper'; import { OrderFactory } from '../../util/order_factory'; import { BalancesByOwner, ContractName } from '../../util/types'; import { chaiSetup } from '../utils/chai_setup'; -import { deployer } from '../utils/deployer'; -import { provider, web3Wrapper } from '../utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -54,27 +55,52 @@ describe('Exchange', () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); tokenOwner = accounts[0]; [maker, taker, feeRecipient] = accounts; - const [repInstance, dgdInstance, zrxInstance] = await Promise.all([ - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), - deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS), + [rep, dgd, zrx] = await Promise.all([ + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), + DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ), ]); - rep = new DummyTokenContract(repInstance.abi, repInstance.address, provider); - dgd = new DummyTokenContract(dgdInstance.abi, dgdInstance.address, provider); - zrx = new DummyTokenContract(zrxInstance.abi, zrxInstance.address, provider); - const tokenRegistryInstance = await deployer.deployAsync(ContractName.TokenRegistry); - tokenRegistry = new TokenRegistryContract(tokenRegistryInstance.abi, tokenRegistryInstance.address, provider); - const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy); - tokenTransferProxy = new TokenTransferProxyContract( - tokenTransferProxyInstance.abi, - tokenTransferProxyInstance.address, + tokenRegistry = await TokenRegistryContract.deployFrom0xArtifactAsync( + artifacts.TokenRegistry, + provider, + txDefaults, + ); + tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, provider, + txDefaults, ); - const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [ + exchange = await ExchangeContract.deployFrom0xArtifactAsync( + artifacts.Exchange, + provider, + txDefaults, zrx.address, tokenTransferProxy.address, - ]); - exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider); + ); await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] }); const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID }); exWrapper = new ExchangeWrapper(exchange, zeroEx); diff --git a/packages/contracts/test/multi_sig_with_time_lock.ts b/packages/contracts/test/multi_sig_with_time_lock.ts index cf3893780..01bc0ec90 100644 --- a/packages/contracts/test/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/multi_sig_with_time_lock.ts @@ -14,8 +14,8 @@ import { MultiSigWrapper } from '../util/multi_sig_wrapper'; import { ContractName, SubmissionContractEventArgs } from '../util/types'; import { chaiSetup } from './utils/chai_setup'; -import { deployer } from './utils/deployer'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper'; const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLock.compilerOutput.abi; chaiSetup.configure(); @@ -47,15 +47,13 @@ describe('MultiSigWalletWithTimeLock', () => { describe('changeTimeLock', () => { describe('initially non-time-locked', async () => { before('deploy a wallet', async () => { - const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ + multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( + artifacts.MultiSigWalletWithTimeLock, + provider, + txDefaults, owners, SIGNATURES_REQUIRED, - 0, - ]); - multiSig = new MultiSigWalletWithTimeLockContract( - multiSigInstance.abi, - multiSigInstance.address, - provider, + new BigNumber(0), ); multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract); @@ -144,15 +142,13 @@ describe('MultiSigWalletWithTimeLock', () => { }); describe('initially time-locked', async () => { before('deploy a wallet', async () => { - const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ + multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( + artifacts.MultiSigWalletWithTimeLock, + provider, + txDefaults, owners, SIGNATURES_REQUIRED, SECONDS_TIME_LOCKED, - ]); - multiSig = new MultiSigWalletWithTimeLockContract( - multiSigInstance.abi, - multiSigInstance.address, - provider, ); multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract); diff --git a/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts b/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts index 3ff5b82ed..775d43d22 100644 --- a/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts +++ b/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts @@ -1,6 +1,6 @@ import { LogWithDecodedArgs, ZeroEx } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; -import { AbiDecoder } from '@0xproject/utils'; +import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import * as Web3 from 'web3'; @@ -15,8 +15,9 @@ import { MultiSigWrapper } from '../util/multi_sig_wrapper'; import { ContractName, SubmissionContractEventArgs, TransactionDataParams } from '../util/types'; import { chaiSetup } from './utils/chai_setup'; -import { deployer } from './utils/deployer'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper'; + const PROXY_ABI = artifacts.TokenTransferProxy.compilerOutput.abi; const MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_AUTHORIZED_ADDRESS_ABI = artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.compilerOutput.abi; @@ -29,8 +30,8 @@ const abiDecoder = new AbiDecoder([MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_A describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => { const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID }); let owners: string[]; - const requiredApprovals = 2; - const SECONDS_TIME_LOCKED = 1000000; + const requiredApprovals = new BigNumber(2); + const SECONDS_TIME_LOCKED = new BigNumber(1000000); // initialize fake addresses let authorizedAddress: string; @@ -46,23 +47,22 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => { owners = [accounts[0], accounts[1]]; [authorizedAddress, unauthorizedAddress] = accounts; const initialOwner = accounts[0]; - const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy); - tokenTransferProxy = new TokenTransferProxyContract( - tokenTransferProxyInstance.abi, - tokenTransferProxyInstance.address, + tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, provider, + txDefaults, ); await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, { from: initialOwner, }); - const multiSigInstance = await deployer.deployAsync( - ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, - [owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address], - ); - multiSig = new MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract( - multiSigInstance.abi, - multiSigInstance.address, + multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract.deployFrom0xArtifactAsync( + artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, provider, + txDefaults, + owners, + requiredApprovals, + SECONDS_TIME_LOCKED, + tokenTransferProxy.address, ); await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: initialOwner, @@ -110,7 +110,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => { }); it('should throw if tx destination is not the tokenTransferProxy', async () => { - const invalidTokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); + const invalidTokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, + provider, + txDefaults, + ); const invalidDestination = invalidTokenTransferProxy.address; const dataParams: TransactionDataParams = { name: 'removeAuthorizedAddress', diff --git a/packages/contracts/test/token_registry.ts b/packages/contracts/test/token_registry.ts index 4c404176b..8b7c3048d 100644 --- a/packages/contracts/test/token_registry.ts +++ b/packages/contracts/test/token_registry.ts @@ -8,13 +8,13 @@ import * as _ from 'lodash'; import * as Web3 from 'web3'; import { TokenRegistryContract } from '../src/contract_wrappers/generated/token_registry'; +import { artifacts } from '../util/artifacts'; import { constants } from '../util/constants'; import { TokenRegWrapper } from '../util/token_registry_wrapper'; import { ContractName } from '../util/types'; import { chaiSetup } from './utils/chai_setup'; -import { deployer } from './utils/deployer'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; +import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -29,8 +29,7 @@ describe('TokenRegistry', () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = accounts[0]; notOwner = accounts[1]; - const tokenRegInstance = await deployer.deployAsync(ContractName.TokenRegistry); - tokenReg = new TokenRegistryContract(tokenRegInstance.abi, tokenRegInstance.address, provider); + tokenReg = await TokenRegistryContract.deployFrom0xArtifactAsync(artifacts.TokenRegistry, provider, txDefaults); tokenRegWrapper = new TokenRegWrapper(tokenReg); }); beforeEach(async () => { diff --git a/packages/contracts/test/token_transfer_proxy/auth.ts b/packages/contracts/test/token_transfer_proxy/auth.ts index 885ff3bc1..97e8d0c2e 100644 --- a/packages/contracts/test/token_transfer_proxy/auth.ts +++ b/packages/contracts/test/token_transfer_proxy/auth.ts @@ -4,11 +4,12 @@ import * as chai from 'chai'; import * as Web3 from 'web3'; import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy'; +import { artifacts } from '../../util/artifacts'; import { constants } from '../../util/constants'; import { ContractName } from '../../util/types'; import { chaiSetup } from '../utils/chai_setup'; -import { deployer } from '../utils/deployer'; -import { provider, web3Wrapper } from '../utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -23,11 +24,10 @@ describe('TokenTransferProxy', () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = address = accounts[0]; notOwner = accounts[1]; - const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy); - tokenTransferProxy = new TokenTransferProxyContract( - tokenTransferProxyInstance.abi, - tokenTransferProxyInstance.address, + tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, provider, + txDefaults, ); }); beforeEach(async () => { diff --git a/packages/contracts/test/token_transfer_proxy/transfer_from.ts b/packages/contracts/test/token_transfer_proxy/transfer_from.ts index dff1a0cfb..c31d8a1cb 100644 --- a/packages/contracts/test/token_transfer_proxy/transfer_from.ts +++ b/packages/contracts/test/token_transfer_proxy/transfer_from.ts @@ -6,12 +6,13 @@ import * as Web3 from 'web3'; import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token'; import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy'; +import { artifacts } from '../../util/artifacts'; import { Balances } from '../../util/balances'; import { constants } from '../../util/constants'; import { ContractName } from '../../util/types'; import { chaiSetup } from '../utils/chai_setup'; -import { deployer } from '../utils/deployer'; -import { provider, web3Wrapper } from '../utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -31,15 +32,20 @@ describe('TokenTransferProxy', () => { before(async () => { accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = notAuthorized = accounts[0]; - const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy); - tokenTransferProxy = new TokenTransferProxyContract( - tokenTransferProxyInstance.abi, - tokenTransferProxyInstance.address, + tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, provider, + txDefaults, + ); + rep = await DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, ); - const repInstance = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS); - rep = new DummyTokenContract(repInstance.abi, repInstance.address, provider); - dmyBalances = new Balances([rep], [accounts[0], accounts[1]]); await Promise.all([ rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { diff --git a/packages/contracts/test/tutorials/arbitrage.ts b/packages/contracts/test/tutorials/arbitrage.ts index 2fbf850d0..3d07a55a2 100644 --- a/packages/contracts/test/tutorials/arbitrage.ts +++ b/packages/contracts/test/tutorials/arbitrage.ts @@ -7,9 +7,13 @@ import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); import * as Web3 from 'web3'; +import { AccountLevelsContract } from '../../src/contract_wrappers/generated/account_levels'; import { ArbitrageContract } from '../../src/contract_wrappers/generated/arbitrage'; +import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token'; import { EtherDeltaContract } from '../../src/contract_wrappers/generated/ether_delta'; import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange'; +import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy'; +import { artifacts } from '../../util/artifacts'; import { Balances } from '../../util/balances'; import { constants } from '../../util/constants'; import { crypto } from '../../util/crypto'; @@ -17,8 +21,8 @@ import { ExchangeWrapper } from '../../util/exchange_wrapper'; import { OrderFactory } from '../../util/order_factory'; import { BalancesByOwner, ContractName } from '../../util/types'; import { chaiSetup } from '../utils/chai_setup'; -import { deployer } from '../utils/deployer'; -import { provider, web3Wrapper } from '../utils/web3_wrapper'; + +import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -37,8 +41,8 @@ describe('Arbitrage', () => { const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); - let weth: Web3.ContractInstance; - let zrx: Web3.ContractInstance; + let weth: DummyTokenContract; + let zrx: DummyTokenContract; let arbitrage: ArbitrageContract; let etherDelta: EtherDeltaContract; @@ -55,33 +59,61 @@ describe('Arbitrage', () => { before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); [coinbase, maker, edMaker, edFrontRunner] = accounts; - weth = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS); - zrx = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS); - const accountLevels = await deployer.deployAsync(ContractName.AccountLevels); + weth = await DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ); + zrx = await DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ); + const accountLevels = await AccountLevelsContract.deployFrom0xArtifactAsync( + artifacts.AccountLevels, + provider, + txDefaults, + ); const edAdminAddress = accounts[0]; - const edMakerFee = 0; - const edTakerFee = 0; - const edFeeRebate = 0; - const etherDeltaInstance = await deployer.deployAsync(ContractName.EtherDelta, [ + const edMakerFee = new BigNumber(0); + const edTakerFee = new BigNumber(0); + const edFeeRebate = new BigNumber(0); + etherDelta = await EtherDeltaContract.deployFrom0xArtifactAsync( + artifacts.EtherDelta, + provider, + txDefaults, edAdminAddress, feeRecipient, accountLevels.address, edMakerFee, edTakerFee, edFeeRebate, - ]); - etherDelta = new EtherDeltaContract(etherDeltaInstance.abi, etherDeltaInstance.address, provider); - const tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); - const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [ + ); + const tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, + provider, + txDefaults, + ); + const exchange = await ExchangeContract.deployFrom0xArtifactAsync( + artifacts.Exchange, + provider, + txDefaults, zrx.address, tokenTransferProxy.address, - ]); - await tokenTransferProxy.addAuthorizedAddress(exchangeInstance.address, { from: accounts[0] }); + ); + await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] }); zeroEx = new ZeroEx(provider, { - exchangeContractAddress: exchangeInstance.address, + exchangeContractAddress: exchange.address, networkId: constants.TESTRPC_NETWORK_ID, }); - const exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider); exWrapper = new ExchangeWrapper(exchange, zeroEx); makerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18); @@ -98,37 +130,39 @@ describe('Arbitrage', () => { takerFee: new BigNumber(0), }; orderFactory = new OrderFactory(zeroEx, defaultOrderParams); - const arbitrageInstance = await deployer.deployAsync(ContractName.Arbitrage, [ + arbitrage = await ArbitrageContract.deployFrom0xArtifactAsync( + artifacts.Arbitrage, + provider, + txDefaults, exchange.address, etherDelta.address, tokenTransferProxy.address, - ]); - arbitrage = new ArbitrageContract(arbitrageInstance.abi, arbitrageInstance.address, provider); + ); // Enable arbitrage and withdrawals of tokens await arbitrage.setAllowances.sendTransactionAsync(weth.address, { from: coinbase }); await arbitrage.setAllowances.sendTransactionAsync(zrx.address, { from: coinbase }); // Give some tokens to arbitrage contract - await weth.setBalance(arbitrage.address, takerTokenAmount, { from: coinbase }); + await weth.setBalance.sendTransactionAsync(arbitrage.address, takerTokenAmount, { from: coinbase }); // Fund the maker on exchange side - await zrx.setBalance(maker, makerTokenAmount, { from: coinbase }); + await zrx.setBalance.sendTransactionAsync(maker, makerTokenAmount, { from: coinbase }); // Set the allowance for the maker on Exchange side - await zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: maker }); + await zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: maker }); amountGive = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18); // Fund the maker on EtherDelta side - await weth.setBalance(edMaker, amountGive, { from: coinbase }); + await weth.setBalance.sendTransactionAsync(edMaker, amountGive, { from: coinbase }); // Set the allowance for the maker on EtherDelta side - await weth.approve(etherDelta.address, INITIAL_ALLOWANCE, { from: edMaker }); + await weth.approve.sendTransactionAsync(etherDelta.address, INITIAL_ALLOWANCE, { from: edMaker }); // Deposit maker funds into EtherDelta await etherDelta.depositToken.sendTransactionAsync(weth.address, amountGive, { from: edMaker }); amountGet = makerTokenAmount; // Fund the front runner on EtherDelta side - await zrx.setBalance(edFrontRunner, amountGet, { from: coinbase }); + await zrx.setBalance.sendTransactionAsync(edFrontRunner, amountGet, { from: coinbase }); // Set the allowance for the front-runner on EtherDelta side - await zrx.approve(etherDelta.address, INITIAL_ALLOWANCE, { from: edFrontRunner }); + await zrx.approve.sendTransactionAsync(etherDelta.address, INITIAL_ALLOWANCE, { from: edFrontRunner }); // Deposit front runner funds into EtherDelta await etherDelta.depositToken.sendTransactionAsync(zrx.address, amountGet, { from: edFrontRunner }); }); @@ -195,11 +229,11 @@ describe('Arbitrage', () => { from: coinbase, }); const res = await zeroEx.awaitTransactionMinedAsync(txHash); - const postBalance = await weth.balanceOf(arbitrage.address); + const postBalance = await weth.balanceOf.callAsync(arbitrage.address); expect(postBalance).to.be.bignumber.equal(amountGive); }); it('should fail and revert if front-runned', async () => { - const preBalance = await weth.balanceOf(arbitrage.address); + const preBalance = await weth.balanceOf.callAsync(arbitrage.address); // Front-running transaction await etherDelta.trade.sendTransactionAsync( tokenGet, @@ -219,7 +253,7 @@ describe('Arbitrage', () => { await expect( arbitrage.makeAtomicTrade.sendTransactionAsync(addresses, values, v, r, s, { from: coinbase }), ).to.be.rejectedWith(constants.REVERT); - const postBalance = await weth.balanceOf(arbitrage.address); + const postBalance = await weth.balanceOf.callAsync(arbitrage.address); expect(preBalance).to.be.bignumber.equal(postBalance); }); }); diff --git a/packages/contracts/test/unlimited_allowance_token.ts b/packages/contracts/test/unlimited_allowance_token.ts index 618bda72d..da2e5fb5b 100644 --- a/packages/contracts/test/unlimited_allowance_token.ts +++ b/packages/contracts/test/unlimited_allowance_token.ts @@ -6,12 +6,12 @@ import * as chai from 'chai'; import * as Web3 from 'web3'; import { DummyTokenContract } from '../src/contract_wrappers/generated/dummy_token'; +import { artifacts } from '../util/artifacts'; import { constants } from '../util/constants'; import { ContractName } from '../util/types'; import { chaiSetup } from './utils/chai_setup'; -import { deployer } from './utils/deployer'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; +import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -33,8 +33,15 @@ describe('UnlimitedAllowanceToken', () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = accounts[0]; spender = accounts[1]; - const tokenInstance = await deployer.deployAsync(ContractName.DummyToken, constants.DUMMY_TOKEN_ARGS); - token = new DummyTokenContract(tokenInstance.abi, tokenInstance.address, provider); + token = await DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ); await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner }); tokenAddress = token.address; }); diff --git a/packages/contracts/test/utils/deployer.ts b/packages/contracts/test/utils/deployer.ts deleted file mode 100644 index 2f0951475..000000000 --- a/packages/contracts/test/utils/deployer.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Deployer } from '@0xproject/deployer'; -import { devConstants } from '@0xproject/dev-utils'; -import * as path from 'path'; - -import { constants } from '../../util/constants'; - -import { web3 } from './web3_wrapper'; - -const deployerOpts = { - provider: web3.currentProvider, - artifactsDir: path.resolve('lib', 'src', 'artifacts'), - networkId: constants.TESTRPC_NETWORK_ID, - defaults: { - gas: devConstants.GAS_ESTIMATE, - }, -}; - -export const deployer = new Deployer(deployerOpts); diff --git a/packages/contracts/test/utils/web3_wrapper.ts b/packages/contracts/test/utils/web3_wrapper.ts index dd6f198c4..ed1c488a2 100644 --- a/packages/contracts/test/utils/web3_wrapper.ts +++ b/packages/contracts/test/utils/web3_wrapper.ts @@ -1,7 +1,11 @@ -import { web3Factory } from '@0xproject/dev-utils'; +import { devConstants, web3Factory } from '@0xproject/dev-utils'; import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; +export const txDefaults = { + from: devConstants.TESTRPC_FIRST_ADDRESS, + gas: devConstants.GAS_ESTIMATE, +}; const providerConfigs = { shouldUseInProcessGanache: true }; export const web3 = web3Factory.create(providerConfigs); export const provider = web3.currentProvider; diff --git a/packages/contracts/test/zrx_token.ts b/packages/contracts/test/zrx_token.ts index b01615b39..0056ed4b5 100644 --- a/packages/contracts/test/zrx_token.ts +++ b/packages/contracts/test/zrx_token.ts @@ -6,12 +6,12 @@ import * as chai from 'chai'; import * as Web3 from 'web3'; import { ZRXTokenContract } from '../src/contract_wrappers/generated/zrx_token'; +import { artifacts } from '../util/artifacts'; import { constants } from '../util/constants'; import { ContractName } from '../util/types'; import { chaiSetup } from './utils/chai_setup'; -import { deployer } from './utils/deployer'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; +import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -34,8 +34,7 @@ describe('ZRXToken', () => { zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID, }); - const zrxInstance = await deployer.deployAsync(ContractName.ZRXToken); - zrx = new ZRXTokenContract(zrxInstance.abi, zrxInstance.address, provider); + zrx = await ZRXTokenContract.deployFrom0xArtifactAsync(artifacts.ZRX, provider, txDefaults); zrxAddress = zrx.address; MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; }); diff --git a/packages/contracts/util/artifacts.ts b/packages/contracts/util/artifacts.ts index d262b8058..8511b0082 100644 --- a/packages/contracts/util/artifacts.ts +++ b/packages/contracts/util/artifacts.ts @@ -1,6 +1,9 @@ -import { ContractArtifact } from '@0xproject/deployer'; +import { ContractArtifact } from '@0xproject/sol-compiler'; +import * as AccountLevels from '../src/artifacts/AccountLevels.json'; +import * as Arbitrage from '../src/artifacts/Arbitrage.json'; import * as DummyToken from '../src/artifacts/DummyToken.json'; +import * as EtherDelta from '../src/artifacts/EtherDelta.json'; import * as Exchange from '../src/artifacts/Exchange.json'; import * as MaliciousToken from '../src/artifacts/MaliciousToken.json'; import * as MultiSigWalletWithTimeLock from '../src/artifacts/MultiSigWalletWithTimeLock.json'; @@ -12,6 +15,9 @@ import * as EtherToken from '../src/artifacts/WETH9.json'; import * as ZRX from '../src/artifacts/ZRXToken.json'; export const artifacts = { + AccountLevels: (AccountLevels as any) as ContractArtifact, + Arbitrage: (Arbitrage as any) as ContractArtifact, + EtherDelta: (EtherDelta as any) as ContractArtifact, ZRX: (ZRX as any) as ContractArtifact, DummyToken: (DummyToken as any) as ContractArtifact, Token: (Token as any) as ContractArtifact, diff --git a/packages/contracts/util/constants.ts b/packages/contracts/util/constants.ts index d1152e683..d287986b7 100644 --- a/packages/contracts/util/constants.ts +++ b/packages/contracts/util/constants.ts @@ -1,7 +1,4 @@ -const DUMMY_TOKEN_NAME = ''; -const DUMMY_TOKEN_SYMBOL = ''; -const DUMMY_TOKEN_DECIMALS = 18; -const DUMMY_TOKEN_TOTAL_SUPPLY = 0; +import { BigNumber } from '@0xproject/utils'; export const constants = { INVALID_OPCODE: 'invalid opcode', @@ -10,5 +7,8 @@ export const constants = { MAX_ETHERTOKEN_WITHDRAW_GAS: 43000, MAX_TOKEN_TRANSFERFROM_GAS: 80000, MAX_TOKEN_APPROVE_GAS: 60000, - DUMMY_TOKEN_ARGS: [DUMMY_TOKEN_NAME, DUMMY_TOKEN_SYMBOL, DUMMY_TOKEN_DECIMALS, DUMMY_TOKEN_TOTAL_SUPPLY], + DUMMY_TOKEN_NAME: '', + DUMMY_TOKEN_SYMBOL: '', + DUMMY_TOKEN_DECIMALS: new BigNumber(18), + DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(0), }; diff --git a/packages/deployer/src/cli.ts b/packages/deployer/src/cli.ts deleted file mode 100644 index 8c89cf382..000000000 --- a/packages/deployer/src/cli.ts +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env node -// We need the above pragma since this script will be run as a command-line tool. - -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import * as _ from 'lodash'; -import * as path from 'path'; -import * as Web3 from 'web3'; -import * as yargs from 'yargs'; - -import { commands } from './commands'; -import { constants } from './utils/constants'; -import { consoleReporter } from './utils/error_reporter'; -import { CliOptions, CompilerOptions, DeployerOptions } from './utils/types'; - -const DEFAULT_CONTRACTS_DIR = path.resolve('src/contracts'); -const DEFAULT_ARTIFACTS_DIR = path.resolve('src/artifacts'); -const DEFAULT_NETWORK_ID = 50; -const DEFAULT_JSONRPC_URL = 'http://localhost:8545'; -const DEFAULT_GAS_PRICE = (10 ** 9 * 2).toString(); -const DEFAULT_CONTRACTS_LIST = '*'; -const SEPARATOR = ','; - -/** - * Compiles all contracts with options passed in through CLI. - * @param argv Instance of process.argv provided by yargs. - */ -async function onCompileCommandAsync(argv: CliOptions): Promise<void> { - const opts: CompilerOptions = { - contractsDir: argv.contractsDir, - artifactsDir: argv.artifactsDir, - contracts: argv.contracts === DEFAULT_CONTRACTS_LIST ? DEFAULT_CONTRACTS_LIST : argv.contracts.split(SEPARATOR), - }; - await commands.compileAsync(opts); -} -/** - * Deploys a single contract with provided name and args. - * @param argv Instance of process.argv provided by yargs. - */ -async function onDeployCommandAsync(argv: CliOptions): Promise<void> { - const url = argv.jsonrpcUrl; - const provider = new Web3.providers.HttpProvider(url); - const web3Wrapper = new Web3Wrapper(provider); - const networkId = await web3Wrapper.getNetworkIdAsync(); - const compilerOpts: CompilerOptions = { - contractsDir: argv.contractsDir, - artifactsDir: argv.artifactsDir, - contracts: argv.contracts === DEFAULT_CONTRACTS_LIST ? DEFAULT_CONTRACTS_LIST : argv.contracts.split(SEPARATOR), - }; - await commands.compileAsync(compilerOpts); - - const defaults = { - gasPrice: new BigNumber(argv.gasPrice), - from: argv.account, - }; - const deployerOpts: DeployerOptions = { - artifactsDir: argv.artifactsDir || DEFAULT_ARTIFACTS_DIR, - jsonrpcUrl: argv.jsonrpcUrl, - networkId, - defaults, - }; - const deployerArgsString = argv.constructorArgs as string; - const deployerArgs = deployerArgsString.split(SEPARATOR); - await commands.deployAsync(argv.contract as string, deployerArgs, deployerOpts); -} -/** - * Adds additional required options for when the user is calling the deploy command. - * @param yargsInstance yargs instance provided in builder function callback. - */ -function deployCommandBuilder(yargsInstance: any) { - return yargsInstance - .option('network-id', { - type: 'number', - default: DEFAULT_NETWORK_ID, - description: 'mainnet=1, kovan=42, testrpc=50', - }) - .option('contract', { - type: 'string', - description: 'name of contract to deploy, excluding .sol extension', - }) - .option('constructor-args', { - type: 'string', - description: 'comma separated list of constructor args to deploy contract with', - }) - .option('jsonrpc-url', { - type: 'string', - default: DEFAULT_JSONRPC_URL, - description: 'url of JSON RPC', - }) - .option('account', { - type: 'string', - description: 'account to use for deploying contracts', - }) - .option('gas-price', { - type: 'string', - default: DEFAULT_GAS_PRICE, - description: 'gasPrice to be used for transactions', - }) - .demandOption(['contract', 'args', 'account']) - .help().argv; -} - -/** - * Adds additional required options for when the user is calling the compile command. - * @param yargsInstance yargs instance provided in builder function callback. - */ -function compileCommandBuilder(yargsInstance: any) { - return yargsInstance - .option('contracts', { - type: 'string', - default: DEFAULT_CONTRACTS_LIST, - description: 'comma separated list of contracts to compile', - }) - .help().argv; -} - -(() => { - const identityCommandBuilder = _.identity; - return yargs - .option('contracts-dir', { - type: 'string', - description: 'path of contracts directory to compile', - }) - .option('artifacts-dir', { - type: 'string', - description: 'path to write contracts artifacts to', - }) - .demandCommand(1) - .command('compile', 'compile contracts', compileCommandBuilder, consoleReporter(onCompileCommandAsync)) - .command( - 'deploy', - 'deploy a single contract with provided arguments', - deployCommandBuilder, - consoleReporter(onDeployCommandAsync), - ) - .help().argv; -})(); diff --git a/packages/deployer/src/commands.ts b/packages/deployer/src/commands.ts deleted file mode 100644 index 8e544a60b..000000000 --- a/packages/deployer/src/commands.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Compiler } from './compiler'; -import { Deployer } from './deployer'; -import { CompilerOptions, DeployerOptions } from './utils/types'; - -export const commands = { - async compileAsync(opts: CompilerOptions): Promise<void> { - const compiler = new Compiler(opts); - await compiler.compileAsync(); - }, - async deployAsync(contractName: string, args: any[], opts: DeployerOptions): Promise<void> { - const deployer = new Deployer(opts); - await deployer.deployAndSaveAsync(contractName, args); - }, -}; diff --git a/packages/deployer/src/deployer.ts b/packages/deployer/src/deployer.ts deleted file mode 100644 index c8c3a9a06..000000000 --- a/packages/deployer/src/deployer.ts +++ /dev/null @@ -1,223 +0,0 @@ -import { AbiType, ConstructorAbi, ContractAbi, Provider, TxData } from '@0xproject/types'; -import { logUtils } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import * as _ from 'lodash'; -import * as solc from 'solc'; -import * as Web3 from 'web3'; - -import { Contract } from './utils/contract'; -import { encoder } from './utils/encoder'; -import { fsWrapper } from './utils/fs_wrapper'; -import { - ContractArtifact, - ContractNetworkData, - DeployerOptions, - ProviderDeployerOptions, - UrlDeployerOptions, -} from './utils/types'; -import { utils } from './utils/utils'; - -// Gas added to gas estimate to make sure there is sufficient gas for deployment. -const EXTRA_GAS = 200000; - -/** - * The Deployer facilitates deploying Solidity smart contracts to the blockchain. - * It can be used to build custom migration scripts. - */ -export class Deployer { - public web3Wrapper: Web3Wrapper; - private _artifactsDir: string; - private _networkId: number; - private _defaults: Partial<TxData>; - /** - * Gets data for current version stored in artifact. - * @param contractArtifact The contract artifact. - * @return Version specific contract data. - */ - private static _getContractCompilerOutputFromArtifactIfExists( - contractArtifact: ContractArtifact, - ): solc.StandardContractOutput { - const compilerOutputIfExists = contractArtifact.compilerOutput; - if (_.isUndefined(compilerOutputIfExists)) { - throw new Error(`Compiler output not found in artifact for contract: ${contractArtifact.contractName}`); - } - return compilerOutputIfExists; - } - /** - * Instantiate a new instance of the Deployer class. - * @param opts Deployer options, including either an RPC url or Provider instance. - * @returns A Deployer instance - */ - constructor(opts: DeployerOptions) { - this._artifactsDir = opts.artifactsDir; - this._networkId = opts.networkId; - this._defaults = opts.defaults; - 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 provider nor jsonrpcUrl. Please pass one of them`); - } - provider = new Web3.providers.HttpProvider(jsonrpcUrl); - } else { - provider = (opts as ProviderDeployerOptions).provider; - } - this.web3Wrapper = new Web3Wrapper(provider, this._defaults); - } - /** - * Loads a contract's corresponding artifacts and deploys it with the supplied constructor arguments. - * @param contractName Name of the contract to deploy. Must match name of an artifact in supplied artifacts directory. - * @param args Array of contract constructor arguments. - * @return Deployed contract instance. - */ - public async deployAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> { - const contractArtifactIfExists: ContractArtifact = this._loadContractArtifactIfExists(contractName); - const compilerOutput = Deployer._getContractCompilerOutputFromArtifactIfExists(contractArtifactIfExists); - const data = compilerOutput.evm.bytecode.object; - const from = await this._getFromAddressAsync(); - const gas = await this._getAllowableGasEstimateAsync(data); - const txData = { - gasPrice: this._defaults.gasPrice, - from, - data, - gas, - }; - if (_.isUndefined(compilerOutput.abi)) { - throw new Error(`ABI not found in ${contractName} artifacts`); - } - const abi = compilerOutput.abi; - const constructorAbi = _.find(abi, { type: AbiType.Constructor }) as ConstructorAbi; - const constructorArgs = _.isUndefined(constructorAbi) ? [] : constructorAbi.inputs; - if (constructorArgs.length !== args.length) { - const constructorSignature = `constructor(${_.map(constructorArgs, arg => `${arg.type} ${arg.name}`).join( - ', ', - )})`; - throw new Error( - `${contractName} expects ${constructorArgs.length} constructor params: ${constructorSignature}. Got ${ - args.length - }`, - ); - } - const web3ContractInstance = await this._deployFromAbiAsync(abi, args, txData); - logUtils.log(`${contractName}.sol successfully deployed at ${web3ContractInstance.address}`); - const contractInstance = new Contract(web3ContractInstance, this._defaults); - return contractInstance; - } - /** - * Loads a contract's artifact, deploys it with supplied constructor arguments, and saves the updated data - * back to the artifact file. - * @param contractName Name of the contract to deploy. Must match name of an artifact in artifacts directory. - * @param args Array of contract constructor arguments. - * @return Deployed contract instance. - */ - public async deployAndSaveAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> { - const contractInstance = await this.deployAsync(contractName, args); - await this._saveContractDataToArtifactAsync(contractName, contractInstance.address, args); - return contractInstance; - } - /** - * Deploys a contract given its ABI, arguments, and transaction data. - * @param abi ABI of contract to deploy. - * @param args Constructor arguments to use in deployment. - * @param txData Tx options used for deployment. - * @return Promise that resolves to a web3 contract instance. - */ - private async _deployFromAbiAsync(abi: ContractAbi, args: any[], txData: TxData): Promise<any> { - const contract: Web3.Contract<Web3.ContractInstance> = this.web3Wrapper.getContractFromAbi(abi); - const deployPromise = new Promise((resolve, reject) => { - /** - * Contract is inferred as 'any' because TypeScript - * is not able to read 'new' from the Contract interface - */ - (contract as any).new(...args, txData, (err: Error, res: any): any => { - if (err) { - reject(err); - } else if (_.isUndefined(res.address) && !_.isUndefined(res.transactionHash)) { - logUtils.log(`transactionHash: ${res.transactionHash}`); - } else { - resolve(res); - } - }); - }); - return deployPromise; - } - /** - * Updates a contract artifact's address and encoded constructor arguments. - * @param contractName Name of contract. Must match an existing artifact. - * @param contractAddress Contract address to save to artifact. - * @param args Contract constructor arguments that will be encoded and saved to artifact. - */ - private async _saveContractDataToArtifactAsync( - contractName: string, - contractAddress: string, - args: any[], - ): Promise<void> { - const contractArtifactIfExists: ContractArtifact = this._loadContractArtifactIfExists(contractName); - const compilerOutput = Deployer._getContractCompilerOutputFromArtifactIfExists(contractArtifactIfExists); - if (_.isUndefined(compilerOutput.abi)) { - throw new Error(`ABI not found in ${contractName} artifacts`); - } - const abi = compilerOutput.abi; - const encodedConstructorArgs = encoder.encodeConstructorArgsFromAbi(args, abi); - const newContractData: ContractNetworkData = { - address: contractAddress, - links: {}, - constructorArgs: encodedConstructorArgs, - }; - const newArtifact = { - ...contractArtifactIfExists, - networks: { - ...contractArtifactIfExists.networks, - [this._networkId]: newContractData, - }, - }; - const artifactString = utils.stringifyWithFormatting(newArtifact); - const artifactPath = `${this._artifactsDir}/${contractName}.json`; - await fsWrapper.writeFileAsync(artifactPath, artifactString); - } - /** - * Loads a contract artifact, if it exists. - * @param contractName Name of the contract, without the extension. - * @return The contract artifact. - */ - private _loadContractArtifactIfExists(contractName: string): ContractArtifact { - const artifactPath = `${this._artifactsDir}/${contractName}.json`; - try { - const contractArtifact: ContractArtifact = require(artifactPath); - return contractArtifact; - } catch (err) { - throw new Error(`Artifact not found for contract: ${contractName} at ${artifactPath}`); - } - } - /** - * Gets the address to use for sending a transaction. - * @return The default from address. If not specified, returns the first address accessible by web3. - */ - private async _getFromAddressAsync(): Promise<string> { - let from: string; - if (_.isUndefined(this._defaults.from)) { - const accounts = await this.web3Wrapper.getAvailableAddressesAsync(); - from = accounts[0]; - } else { - from = this._defaults.from; - } - return from; - } - /** - * Estimates the gas required for a transaction. - * If gas would be over the block gas limit, the max allowable gas is returned instead. - * @param data Bytecode to estimate gas for. - * @return Gas estimate for transaction data. - */ - private async _getAllowableGasEstimateAsync(data: string): Promise<number> { - const block = await this.web3Wrapper.getBlockAsync('latest'); - let gas: number; - try { - const gasEstimate: number = await this.web3Wrapper.estimateGasAsync({ data }); - gas = Math.min(gasEstimate + EXTRA_GAS, block.gasLimit); - } catch (err) { - gas = block.gasLimit; - } - return gas; - } -} diff --git a/packages/deployer/src/utils/contract.ts b/packages/deployer/src/utils/contract.ts deleted file mode 100644 index e8dd5218a..000000000 --- a/packages/deployer/src/utils/contract.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { schemas, SchemaValidator } from '@0xproject/json-schemas'; -import { AbiType, ContractAbi, EventAbi, FunctionAbi, MethodAbi, TxData } from '@0xproject/types'; -import { promisify } from '@0xproject/utils'; -import * as _ from 'lodash'; -import * as Web3 from 'web3'; - -export class Contract implements Web3.ContractInstance { - public address: string; - public abi: ContractAbi; - private _contract: Web3.ContractInstance; - private _defaults: Partial<TxData>; - private _validator: SchemaValidator; - // This class instance is going to be populated with functions and events depending on the ABI - // and we don't know their types in advance - [name: string]: any; - constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) { - this._contract = web3ContractInstance; - this.address = web3ContractInstance.address; - this.abi = web3ContractInstance.abi; - this._defaults = defaults; - this._populateEvents(); - this._populateFunctions(); - this._validator = new SchemaValidator(); - } - private _populateFunctions(): void { - const functionsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Function) as FunctionAbi[]; - _.forEach(functionsAbi, (functionAbi: MethodAbi) => { - if (functionAbi.constant) { - const cbStyleCallFunction = this._contract[functionAbi.name].call; - this[functionAbi.name] = promisify(cbStyleCallFunction, this._contract); - this[functionAbi.name].call = promisify(cbStyleCallFunction, this._contract); - } else { - const cbStyleFunction = this._contract[functionAbi.name]; - const cbStyleCallFunction = this._contract[functionAbi.name].call; - const cbStyleEstimateGasFunction = this._contract[functionAbi.name].estimateGas; - this[functionAbi.name] = this._promisifyWithDefaultParams(cbStyleFunction); - this[functionAbi.name].estimateGasAsync = promisify(cbStyleEstimateGasFunction); - this[functionAbi.name].sendTransactionAsync = this._promisifyWithDefaultParams(cbStyleFunction); - this[functionAbi.name].call = promisify(cbStyleCallFunction, this._contract); - } - }); - } - private _populateEvents(): void { - const eventsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Event) as EventAbi[]; - _.forEach(eventsAbi, (eventAbi: EventAbi) => { - this[eventAbi.name] = this._contract[eventAbi.name]; - }); - } - private _promisifyWithDefaultParams(fn: (...args: any[]) => void): (...args: any[]) => Promise<any> { - const promisifiedWithDefaultParams = async (...args: any[]) => { - const promise = new Promise((resolve, reject) => { - const lastArg = args[args.length - 1]; - let txData: Partial<TxData> = {}; - if (this._isTxData(lastArg)) { - txData = args.pop(); - } - txData = { - ...this._defaults, - ...txData, - }; - const callback = (err: Error, data: any) => { - if (_.isNull(err)) { - resolve(data); - } else { - reject(err); - } - }; - args.push(txData); - args.push(callback); - fn.apply(this._contract, args); - }); - return promise; - }; - return promisifiedWithDefaultParams; - } - private _isTxData(lastArg: any): boolean { - const isValid = this._validator.isValid(lastArg, schemas.txDataSchema); - return isValid; - } -} diff --git a/packages/deployer/src/utils/error_reporter.ts b/packages/deployer/src/utils/error_reporter.ts deleted file mode 100644 index 4e73307f0..000000000 --- a/packages/deployer/src/utils/error_reporter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { logUtils } from '@0xproject/utils'; - -/** - * Makes an async function no-throw printing errors to the console - * @param asyncFn async function to wrap - * @return Wrapped version of the passed function - */ -export function consoleReporter<T>(asyncFn: (arg: T) => Promise<void>): (arg: T) => Promise<void> { - const noThrowFnAsync = async (arg: T) => { - try { - const result = await asyncFn(arg); - return result; - } catch (err) { - logUtils.log(`${err}`); - } - }; - return noThrowFnAsync; -} diff --git a/packages/deployer/src/utils/utils.ts b/packages/deployer/src/utils/utils.ts deleted file mode 100644 index 9b1e59f9d..000000000 --- a/packages/deployer/src/utils/utils.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const utils = { - stringifyWithFormatting(obj: any): string { - const jsonReplacer: null = null; - const numberOfJsonSpaces = 4; - const stringifiedObj = JSON.stringify(obj, jsonReplacer, numberOfJsonSpaces); - return stringifiedObj; - }, -}; diff --git a/packages/dev-utils/src/coverage.ts b/packages/dev-utils/src/coverage.ts index 743573874..6f7640835 100644 --- a/packages/dev-utils/src/coverage.ts +++ b/packages/dev-utils/src/coverage.ts @@ -15,8 +15,7 @@ export const coverage = { _getCoverageSubprovider(): CoverageSubprovider { const artifactsPath = '../migrations/artifacts/1.0.0'; const contractsPath = 'src/contracts'; - const networkId = 50; const defaultFromAddress = constants.TESTRPC_FIRST_ADDRESS; - return new CoverageSubprovider(artifactsPath, contractsPath, networkId, defaultFromAddress); + return new CoverageSubprovider(artifactsPath, contractsPath, defaultFromAddress); }, }; diff --git a/packages/dev-utils/src/web3_factory.ts b/packages/dev-utils/src/web3_factory.ts index 68348d671..4cd343c44 100644 --- a/packages/dev-utils/src/web3_factory.ts +++ b/packages/dev-utils/src/web3_factory.ts @@ -60,9 +60,9 @@ export const web3Factory = { provider.addProvider( new GanacheSubprovider({ logger, - verbose: env.parseBoolean(EnvVars.SolidityCoverage), + verbose: env.parseBoolean(EnvVars.VerboseGanache), port: 8545, - networkId: 50, + network_id: 50, mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic', }), ); diff --git a/packages/fill-scenarios/src/index.ts b/packages/fill-scenarios/src/index.ts index 673a65226..14d5a2614 100644 --- a/packages/fill-scenarios/src/index.ts +++ b/packages/fill-scenarios/src/index.ts @@ -36,7 +36,6 @@ export class FillScenarios { public async initTokenBalancesAsync() { for (const token of this._tokens) { if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') { - const defaults = {}; const dummyToken = new DummyTokenContract( artifacts.DummyToken.abi, token.address, diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index 4cda4b418..be1a33d65 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -18,14 +18,14 @@ "coverage:report:html": "istanbul report html && open coverage/index.html", "coverage:report:lcov": "istanbul report lcov", "test:circleci": "yarn test:coverage", - "compile": "node ../deployer/lib/src/cli.js compile" + "compile": "node ../sol-compiler/lib/src/cli.js compile" }, "author": "", "license": "Apache-2.0", "dependencies": { "@0xproject/abi-gen": "^0.2.13", "@0xproject/base-contract": "^0.3.1", - "@0xproject/deployer": "^0.4.3", + "@0xproject/sol-compiler": "^0.4.3", "@0xproject/sol-cov": "^0.0.10", "@0xproject/subproviders": "^0.10.1", "@0xproject/tslint-config": "^0.4.17", diff --git a/packages/metacoin/src/global.d.ts b/packages/metacoin/src/global.d.ts new file mode 100644 index 000000000..783b92913 --- /dev/null +++ b/packages/metacoin/src/global.d.ts @@ -0,0 +1,4 @@ +declare module '*.json' { + const value: any; + export default value; +} diff --git a/packages/metacoin/test/metacoin_test.ts b/packages/metacoin/test/metacoin_test.ts index 51830d1ef..8369632c2 100644 --- a/packages/metacoin/test/metacoin_test.ts +++ b/packages/metacoin/test/metacoin_test.ts @@ -1,15 +1,19 @@ import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; +import { ContractArtifact } from '@0xproject/sol-compiler'; import { LogWithDecodedArgs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; +import * as MetacoinArtifact from '../artifacts/Metacoin.json'; import { MetacoinContract, TransferContractEventArgs } from '../src/contract_wrappers/metacoin'; import { chaiSetup } from './utils/chai_setup'; -import { deployer } from './utils/deployer'; +import { config } from './utils/config'; import { provider, web3Wrapper } from './utils/web3_wrapper'; +const artifact: ContractArtifact = MetacoinArtifact as any; + chaiSetup.configure(); const { expect } = chai; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); @@ -19,9 +23,8 @@ describe('Metacoin', () => { const ownerAddress = devConstants.TESTRPC_FIRST_ADDRESS; const INITIAL_BALANCE = new BigNumber(10000); before(async () => { - const metacoinInstance = await deployer.deployAsync('Metacoin'); - web3Wrapper.abiDecoder.addABI(metacoinInstance.abi); - metacoin = new MetacoinContract(metacoinInstance.abi, metacoinInstance.address, provider); + metacoin = await MetacoinContract.deployFrom0xArtifactAsync(artifact, provider, config.txDefaults); + web3Wrapper.abiDecoder.addABI(metacoin.abi); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); diff --git a/packages/metacoin/test/utils/config.ts b/packages/metacoin/test/utils/config.ts index d3a830754..389edb388 100644 --- a/packages/metacoin/test/utils/config.ts +++ b/packages/metacoin/test/utils/config.ts @@ -1,3 +1,4 @@ +import { devConstants } from '@0xproject/dev-utils'; import * as path from 'path'; export const config = { @@ -5,5 +6,8 @@ export const config = { artifactsDir: path.resolve(__dirname, '../../artifacts'), contractsDir: path.resolve(__dirname, '../../contracts'), ganacheLogFile: 'ganache.log', + txDefaults: { + from: devConstants.TESTRPC_FIRST_ADDRESS, + }, mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic', }; diff --git a/packages/metacoin/test/utils/coverage.ts b/packages/metacoin/test/utils/coverage.ts index 6b249384f..debd544ed 100644 --- a/packages/metacoin/test/utils/coverage.ts +++ b/packages/metacoin/test/utils/coverage.ts @@ -15,6 +15,6 @@ export const coverage = { }, _getCoverageSubprovider(): CoverageSubprovider { const defaultFromAddress = devConstants.TESTRPC_FIRST_ADDRESS; - return new CoverageSubprovider(config.artifactsDir, config.contractsDir, config.networkId, defaultFromAddress); + return new CoverageSubprovider(config.artifactsDir, config.contractsDir, defaultFromAddress); }, }; diff --git a/packages/metacoin/test/utils/deployer.ts b/packages/metacoin/test/utils/deployer.ts deleted file mode 100644 index 5a631fa0a..000000000 --- a/packages/metacoin/test/utils/deployer.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Deployer } from '@0xproject/deployer'; -import { devConstants } from '@0xproject/dev-utils'; -import * as path from 'path'; - -import { config } from './config'; -import { web3Wrapper } from './web3_wrapper'; - -const deployerOpts = { - provider: web3Wrapper.getProvider(), - artifactsDir: config.artifactsDir, - networkId: config.networkId, - defaults: { - from: devConstants.TESTRPC_FIRST_ADDRESS, - }, -}; - -export const deployer = new Deployer(deployerOpts); diff --git a/packages/migrations/compiler.json b/packages/migrations/compiler.json new file mode 100644 index 000000000..0d126f4b6 --- /dev/null +++ b/packages/migrations/compiler.json @@ -0,0 +1,20 @@ +{ + "artifactsDir": "artifacts/1.0.0", + "contractsDir": "../contracts/src/contracts", + "contracts": [ + "Exchange", + "DummyToken", + "ZRXToken", + "Token", + "WETH9", + "TokenTransferProxy", + "MultiSigWallet", + "MultiSigWalletWithTimeLock", + "MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress", + "MaliciousToken", + "TokenRegistry", + "Arbitrage", + "EtherDelta", + "AccountLevels" + ] +} diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 883e489f0..95922f7b6 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -6,20 +6,24 @@ "types": "lib/index.d.ts", "scripts": { "build:watch": "tsc -w", + "prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers", + "copy_artifacts": "copyfiles -u 4 'artifacts/1.0.0/**/*' ./lib/src/artifacts", "build": "tsc", "clean": "shx rm -rf lib artifacts", "lint": "tslint --project .", "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" + "copy_artifacts": "copyfiles 'artifacts/1.0.0/**/*' ./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 --backend ethers && prettier --write 'src/contract_wrappers/**.ts'", + "compile": "node ../sol-compiler/lib/src/cli.js compile" }, "config": { - "contracts": "Exchange,DummyToken,ZRXToken,Token,WETH9,TokenTransferProxy,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,MaliciousToken,TokenRegistry,Arbitrage,EtherDelta,AccountLevels" + "abis": "artifacts/1.0.0/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels|WETH9|MaliciousToken).json" }, "license": "Apache-2.0", "devDependencies": { "@0xproject/dev-utils": "^0.4.1", + "@0xproject/types": "^0.6.3", "@0xproject/tslint-config": "^0.4.17", "npm-run-all": "^4.1.2", "shx": "^0.2.2", @@ -27,9 +31,12 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/deployer": "^0.4.3", + "@0xproject/sol-compiler": "^0.4.3", + "@0xproject/base-contract": "^0.3.1", + "@0xproject/typescript-typings": "^0.3.1", "@0xproject/utils": "^0.6.1", "@0xproject/web3-wrapper": "^0.6.3", + "ethers": "^3.0.15", "lodash": "^4.17.4" }, "publishConfig": { diff --git a/packages/migrations/src/artifact_writer.ts b/packages/migrations/src/artifact_writer.ts new file mode 100644 index 000000000..2da5a09dd --- /dev/null +++ b/packages/migrations/src/artifact_writer.ts @@ -0,0 +1,26 @@ +import { BaseContract } from '@0xproject/base-contract'; +import { ContractArtifact } from '@0xproject/sol-compiler'; +import * as fs from 'fs'; +import * as path from 'path'; + +export class ArtifactWriter { + private _artifactsDir: string; + private _networkId: number; + constructor(artifactsDir: string, networkId: number) { + this._artifactsDir = artifactsDir; + this._networkId = networkId; + } + // This updates the artifact file but does not update the `artifacts` module above. It will not + // contain the saved artifact changes. + public saveArtifact(contract: BaseContract): void { + const contractName = contract.contractName; + const artifactFile = path.join(this._artifactsDir, `${contractName}.json`); + const artifact: ContractArtifact = JSON.parse(fs.readFileSync(artifactFile).toString()); + artifact.networks[this._networkId] = { + address: contract.address, + links: {}, + constructorArgs: JSON.stringify(contract.constructorArgs), + }; + fs.writeFileSync(artifactFile, JSON.stringify(artifact, null, '\t')); + } +} diff --git a/packages/migrations/src/artifacts.ts b/packages/migrations/src/artifacts.ts new file mode 100644 index 000000000..42eb1c33e --- /dev/null +++ b/packages/migrations/src/artifacts.ts @@ -0,0 +1,31 @@ +import { ContractArtifact } from '@0xproject/sol-compiler'; + +import * as AccountLevels from '../artifacts/1.0.0/AccountLevels.json'; +import * as Arbitrage from '../artifacts/1.0.0/Arbitrage.json'; +import * as DummyToken from '../artifacts/1.0.0/DummyToken.json'; +import * as EtherDelta from '../artifacts/1.0.0/EtherDelta.json'; +import * as Exchange from '../artifacts/1.0.0/Exchange.json'; +import * as MaliciousToken from '../artifacts/1.0.0/MaliciousToken.json'; +import * as MultiSigWalletWithTimeLock from '../artifacts/1.0.0/MultiSigWalletWithTimeLock.json'; +import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress from '../artifacts/1.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json'; +import * as Token from '../artifacts/1.0.0/Token.json'; +import * as TokenRegistry from '../artifacts/1.0.0/TokenRegistry.json'; +import * as TokenTransferProxy from '../artifacts/1.0.0/TokenTransferProxy.json'; +import * as EtherToken from '../artifacts/1.0.0/WETH9.json'; +import * as ZRX from '../artifacts/1.0.0/ZRXToken.json'; + +export const artifacts = { + AccountLevels: (AccountLevels as any) as ContractArtifact, + Arbitrage: (Arbitrage as any) as ContractArtifact, + EtherDelta: (EtherDelta as any) as ContractArtifact, + ZRX: (ZRX as any) as ContractArtifact, + DummyToken: (DummyToken as any) as ContractArtifact, + Token: (Token as any) as ContractArtifact, + Exchange: (Exchange as any) as ContractArtifact, + EtherToken: (EtherToken as any) as ContractArtifact, + TokenRegistry: (TokenRegistry as any) as ContractArtifact, + MaliciousToken: (MaliciousToken as any) as ContractArtifact, + TokenTransferProxy: (TokenTransferProxy as any) as ContractArtifact, + MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact, + MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: (MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress as any) as ContractArtifact, +}; diff --git a/packages/migrations/src/migrate.ts b/packages/migrations/src/migrate.ts index 76dcbd847..b00ba698f 100644 --- a/packages/migrations/src/migrate.ts +++ b/packages/migrations/src/migrate.ts @@ -1,24 +1,21 @@ #!/usr/bin/env node -import { Deployer } from '@0xproject/deployer'; -import { devConstants } from '@0xproject/dev-utils'; +import { devConstants, web3Factory } from '@0xproject/dev-utils'; +import { Provider } from '@0xproject/types'; 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 txDefaults = { + from: devConstants.TESTRPC_FIRST_ADDRESS, }; - - const deployer = new Deployer(deployerOpts); - - await runMigrationsAsync(deployer); + const providerConfigs = { shouldUseInProcessGanache: false }; + const web3 = web3Factory.create(providerConfigs); + const provider = web3.currentProvider; + const artifactsDir = 'artifacts/1.0.0'; + await runMigrationsAsync(provider, artifactsDir, txDefaults); + process.exit(0); })().catch(err => { logUtils.log(err); process.exit(1); diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index 6313efcff..96973fb62 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -1,8 +1,17 @@ -import { Deployer } from '@0xproject/deployer'; +import { Provider, TxData } from '@0xproject/types'; import { BigNumber, NULL_BYTES } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; +import { ArtifactWriter } from './artifact_writer'; +import { artifacts } from './artifacts'; +import { DummyTokenContract } from './contract_wrappers/dummy_token'; +import { ExchangeContract } from './contract_wrappers/exchange'; +import { MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract } from './contract_wrappers/multi_sig_wallet_with_time_lock_except_remove_authorized_address'; +import { TokenRegistryContract } from './contract_wrappers/token_registry'; +import { TokenTransferProxyContract } from './contract_wrappers/token_transfer_proxy'; +import { WETH9Contract } from './contract_wrappers/weth9'; +import { ZRXTokenContract } from './contract_wrappers/zrx_token'; import { ContractName } from './types'; import { tokenInfo } from './utils/token_info'; @@ -10,27 +19,54 @@ import { tokenInfo } from './utils/token_info'; * Custom migrations should be defined in this function. This will be called with the CLI 'migrate' command. * Migrations could be written to run in parallel, but if you want contract addresses to be created deterministically, * the migration should be written to run synchronously. - * @param deployer Deployer instance. + * @param provider Web3 provider instance. + * @param artifactsDir The directory with compiler artifact files. + * @param txDefaults Default transaction values to use when deploying contracts. */ -export const runMigrationsAsync = async (deployer: Deployer) => { - const web3Wrapper: Web3Wrapper = deployer.web3Wrapper; - const accounts: string[] = await web3Wrapper.getAvailableAddressesAsync(); +export const runMigrationsAsync = async (provider: Provider, artifactsDir: string, txDefaults: Partial<TxData>) => { + const web3Wrapper = new Web3Wrapper(provider); + const networkId = await web3Wrapper.getNetworkIdAsync(); + const artifactsWriter = new ArtifactWriter(artifactsDir, networkId); + const tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( + artifacts.TokenTransferProxy, + provider, + txDefaults, + ); + artifactsWriter.saveArtifact(tokenTransferProxy); + const zrxToken = await ZRXTokenContract.deployFrom0xArtifactAsync(artifacts.ZRX, provider, txDefaults); + artifactsWriter.saveArtifact(zrxToken); - const tokenTransferProxy = await deployer.deployAndSaveAsync(ContractName.TokenTransferProxy); - const zrxToken = await deployer.deployAndSaveAsync(ContractName.ZRXToken); - const etherToken = await deployer.deployAndSaveAsync(ContractName.WETH9); - const tokenReg = await deployer.deployAndSaveAsync(ContractName.TokenRegistry); + const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.EtherToken, provider, txDefaults); + artifactsWriter.saveArtifact(etherToken); + const tokenReg = await TokenRegistryContract.deployFrom0xArtifactAsync( + artifacts.TokenRegistry, + provider, + txDefaults, + ); + artifactsWriter.saveArtifact(tokenReg); - const exchangeArgs = [zrxToken.address, tokenTransferProxy.address]; + const accounts: string[] = await web3Wrapper.getAvailableAddressesAsync(); const owners = [accounts[0], accounts[1]]; const confirmationsRequired = new BigNumber(2); const secondsRequired = new BigNumber(0); - const multiSigArgs = [owners, confirmationsRequired, secondsRequired, tokenTransferProxy.address]; - const exchange = await deployer.deployAndSaveAsync(ContractName.Exchange, exchangeArgs); - const multiSig = await deployer.deployAndSaveAsync( - ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, - multiSigArgs, + const exchange = await ExchangeContract.deployFrom0xArtifactAsync( + artifacts.Exchange, + provider, + txDefaults, + zrxToken.address, + tokenTransferProxy.address, ); + artifactsWriter.saveArtifact(exchange); + const multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract.deployFrom0xArtifactAsync( + artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, + provider, + txDefaults, + owners, + confirmationsRequired, + secondsRequired, + tokenTransferProxy.address, + ); + artifactsWriter.saveArtifact(multiSig); const owner = accounts[0]; await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }); @@ -70,8 +106,15 @@ export const runMigrationsAsync = async (deployer: Deployer) => { ); for (const token of tokenInfo) { const totalSupply = new BigNumber(100000000000000000000); - const args = [token.name, token.symbol, token.decimals, totalSupply]; - const dummyToken = await deployer.deployAsync(ContractName.DummyToken, args); + const dummyToken = await DummyTokenContract.deployFrom0xArtifactAsync( + artifacts.DummyToken, + provider, + txDefaults, + token.name, + token.symbol, + token.decimals, + totalSupply, + ); await tokenReg.addToken.sendTransactionAsync( dummyToken.address, token.name, diff --git a/packages/migrations/src/types.ts b/packages/migrations/src/types.ts index 1887bfd96..21daf47f0 100644 --- a/packages/migrations/src/types.ts +++ b/packages/migrations/src/types.ts @@ -1,3 +1,5 @@ +import { BigNumber } from '@0xproject/utils'; + export interface MultiSigConfig { owners: string[]; confirmationsRequired: number; @@ -12,7 +14,7 @@ export interface Token { address?: string; name: string; symbol: string; - decimals: number; + decimals: BigNumber; ipfsHash: string; swarmHash: string; } diff --git a/packages/migrations/src/utils/token_info.ts b/packages/migrations/src/utils/token_info.ts index 968665c7d..e72a80220 100644 --- a/packages/migrations/src/utils/token_info.ts +++ b/packages/migrations/src/utils/token_info.ts @@ -1,4 +1,4 @@ -import { NULL_BYTES } from '@0xproject/utils'; +import { BigNumber, NULL_BYTES } from '@0xproject/utils'; import { Token } from '../types'; @@ -6,35 +6,35 @@ export const tokenInfo: Token[] = [ { name: 'Augur Reputation Token', symbol: 'REP', - decimals: 18, + decimals: new BigNumber(18), ipfsHash: NULL_BYTES, swarmHash: NULL_BYTES, }, { name: 'Digix DAO Token', symbol: 'DGD', - decimals: 18, + decimals: new BigNumber(18), ipfsHash: NULL_BYTES, swarmHash: NULL_BYTES, }, { name: 'Golem Network Token', symbol: 'GNT', - decimals: 18, + decimals: new BigNumber(18), ipfsHash: NULL_BYTES, swarmHash: NULL_BYTES, }, { name: 'MakerDAO', symbol: 'MKR', - decimals: 18, + decimals: new BigNumber(18), ipfsHash: NULL_BYTES, swarmHash: NULL_BYTES, }, { name: 'Melon Token', symbol: 'MLN', - decimals: 18, + decimals: new BigNumber(18), ipfsHash: NULL_BYTES, swarmHash: NULL_BYTES, }, diff --git a/packages/monorepo-scripts/src/find_unused_dependencies.ts b/packages/monorepo-scripts/src/find_unused_dependencies.ts index bfc38044c..df303f6ce 100644 --- a/packages/monorepo-scripts/src/find_unused_dependencies.ts +++ b/packages/monorepo-scripts/src/find_unused_dependencies.ts @@ -10,7 +10,7 @@ import { constants } from './constants'; import { utils } from './utils'; // For some reason, `depcheck` hangs on some packages. Add them here. -const IGNORE_PACKAGES = ['@0xproject/deployer']; +const IGNORE_PACKAGES = ['@0xproject/sol-compiler']; (async () => { utils.log('*** NOTE: Not all deps listed here are actually not required. ***'); diff --git a/packages/monorepo-scripts/src/publish.ts b/packages/monorepo-scripts/src/publish.ts index e37e1d232..a5be40014 100644 --- a/packages/monorepo-scripts/src/publish.ts +++ b/packages/monorepo-scripts/src/publish.ts @@ -32,7 +32,7 @@ const packageNameToWebsitePath: { [name: string]: string } = { contracts: 'contracts', connect: 'connect', 'json-schemas': 'json-schemas', - deployer: 'deployer', + 'sol-compiler': 'sol-compiler', 'sol-cov': 'sol-cov', subproviders: 'subproviders', 'order-utils': 'order-utils', @@ -214,7 +214,7 @@ async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[]) } // Save updated CHANGELOG.json - fs.writeFileSync(changelogJSONPath, JSON.stringify(changelogs, null, 4)); + fs.writeFileSync(changelogJSONPath, JSON.stringify(changelogs, null, '\t')); await utils.prettifyAsync(changelogJSONPath, constants.monorepoRootPath); utils.log(`${packageName}: Updated CHANGELOG.json`); // Generate updated CHANGELOG.md diff --git a/packages/monorepo-scripts/src/test_installation.ts b/packages/monorepo-scripts/src/test_installation.ts index 78e0f0929..e84221f9d 100644 --- a/packages/monorepo-scripts/src/test_installation.ts +++ b/packages/monorepo-scripts/src/test_installation.ts @@ -46,7 +46,7 @@ import { utils } from './utils'; include: ['index.ts'], }; const tsconfigFilePath = path.join(testDirectory, 'tsconfig.json'); - fs.writeFileSync(tsconfigFilePath, JSON.stringify(tsConfig, null, 4)); + fs.writeFileSync(tsconfigFilePath, JSON.stringify(tsConfig, null, '\t')); utils.log(`Compiling ${packageName}`); const tscBinaryPath = path.join(monorepoRootPath, './node_modules/typescript/bin/tsc'); await execAsync(tscBinaryPath, { cwd: testDirectory }); diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json index ec46957d2..b6b6c6c7d 100644 --- a/packages/react-docs-example/package.json +++ b/packages/react-docs-example/package.json @@ -4,7 +4,7 @@ "version": "0.0.11", "description": "An example app using react-docs", "scripts": { - "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", + "lint": "tslint --project .", "build": "tsc", "build:example": "NODE_ENV=production webpack", "build:watch": "tsc -w", diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index fd4b7c676..ca9ae610e 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "lint": "tslint --project . 'src/**/*.ts' 'src/**/*.tsx'", + "lint": "tslint --project .", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "build:watch": "tsc -w", "clean": "shx rm -rf lib scripts", diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index ce5001985..b9a46376c 100644 --- a/packages/react-shared/package.json +++ b/packages/react-shared/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "lint": "tslint --project . 'src/**/*.ts' 'src/**/*.tsx'", + "lint": "tslint --project .", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "build:watch": "tsc -w", "clean": "shx rm -rf lib scripts", diff --git a/packages/deployer/.npmignore b/packages/sol-compiler/.npmignore index 44df80fad..44df80fad 100644 --- a/packages/deployer/.npmignore +++ b/packages/sol-compiler/.npmignore diff --git a/packages/deployer/CHANGELOG.json b/packages/sol-compiler/CHANGELOG.json index 3f18ae121..3f18ae121 100644 --- a/packages/deployer/CHANGELOG.json +++ b/packages/sol-compiler/CHANGELOG.json diff --git a/packages/deployer/CHANGELOG.md b/packages/sol-compiler/CHANGELOG.md index 4eb0ed453..4eb0ed453 100644 --- a/packages/deployer/CHANGELOG.md +++ b/packages/sol-compiler/CHANGELOG.md diff --git a/packages/deployer/README.md b/packages/sol-compiler/README.md index ef0ddd59d..bb8175952 100644 --- a/packages/deployer/README.md +++ b/packages/sol-compiler/README.md @@ -1,21 +1,21 @@ -## @0xproject/deployer +## @0xproject/sol-compiler -This repository contains a CLI tool that facilitates compiling and deployment of smart contracts. +This repository contains a CLI tool that facilitates compiling smart contracts. -### Read the [Documentation](https://0xproject.com/docs/deployer). +### Read the [Documentation](https://0xproject.com/docs/sol-compiler). ## Installation #### CLI Installation ```bash -yarn global add @0xproject/deployer +yarn global add @0xproject/sol-compiler ``` #### API Installation ```bash -yarn add @0xproject/deployer +yarn add @0xproject/sol-compiler ``` If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: @@ -29,14 +29,13 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol **Import** ```typescript -import { Deployer, Compiler } from '@0xproject/deployer'; +import { Compiler } from '@0xproject/sol-compiler'; ``` or ```javascript -var Deployer = require('@0xproject/deployer').Deployer; -var Compiler = require('@0xproject/deployer').Compiler; +var Compiler = require('@0xproject/sol-compiler').Compiler; ``` ## Contributing diff --git a/packages/deployer/coverage/.gitkeep b/packages/sol-compiler/coverage/.gitkeep index e69de29bb..e69de29bb 100644 --- a/packages/deployer/coverage/.gitkeep +++ b/packages/sol-compiler/coverage/.gitkeep diff --git a/packages/deployer/package.json b/packages/sol-compiler/package.json index 4434652bb..19d390c32 100644 --- a/packages/deployer/package.json +++ b/packages/sol-compiler/package.json @@ -1,7 +1,7 @@ { - "name": "@0xproject/deployer", + "name": "@0xproject/sol-compiler", "version": "0.4.3", - "description": "Smart contract deployer of 0x protocol", + "description": "Solidity compiler wrapper and artifactor", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { @@ -27,13 +27,13 @@ "extraFileIncludes": [ "../types/src/index.ts" ], - "s3BucketPath": "s3://doc-jsons/deployer/", - "s3StagingBucketPath": "s3://staging-doc-jsons/deployer/" + "s3BucketPath": "s3://doc-jsons/sol-compiler/", + "s3StagingBucketPath": "s3://staging-doc-jsons/sol-compiler/" } } }, "bin": { - "0x-deployer": "lib/src/cli.js" + "sol-compiler": "lib/src/cli.js" }, "repository": { "type": "git", @@ -44,7 +44,7 @@ "bugs": { "url": "https://github.com/0xProject/0x-monorepo/issues" }, - "homepage": "https://github.com/0xProject/0x-monorepo/packages/deployer/README.md", + "homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-compiler/README.md", "devDependencies": { "@0xproject/dev-utils": "^0.4.1", "@0xproject/monorepo-scripts": "^0.1.19", diff --git a/packages/deployer/solc_bin/.gitkeep b/packages/sol-compiler/solc_bin/.gitkeep index e69de29bb..e69de29bb 100644 --- a/packages/deployer/solc_bin/.gitkeep +++ b/packages/sol-compiler/solc_bin/.gitkeep diff --git a/packages/sol-compiler/src/cli.ts b/packages/sol-compiler/src/cli.ts new file mode 100644 index 000000000..71bb80c7d --- /dev/null +++ b/packages/sol-compiler/src/cli.ts @@ -0,0 +1,46 @@ +#!/usr/bin/env node +// We need the above pragma since this script will be run as a command-line tool. + +import { BigNumber, logUtils } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as _ from 'lodash'; +import * as path from 'path'; +import * as Web3 from 'web3'; +import * as yargs from 'yargs'; + +import { Compiler } from './compiler'; +import { constants } from './utils/constants'; +import { CompilerOptions } from './utils/types'; + +const DEFAULT_CONTRACTS_LIST = '*'; +const SEPARATOR = ','; + +(async () => { + const argv = yargs + .option('contracts-dir', { + type: 'string', + description: 'path of contracts directory to compile', + }) + .option('artifacts-dir', { + type: 'string', + description: 'path to write contracts artifacts to', + }) + .option('contracts', { + type: 'string', + description: 'comma separated list of contracts to compile', + }) + .help().argv; + const contracts = _.isUndefined(argv.contracts) + ? undefined + : argv.contracts === DEFAULT_CONTRACTS_LIST ? DEFAULT_CONTRACTS_LIST : argv.contracts.split(SEPARATOR); + const opts: CompilerOptions = { + contractsDir: argv.contractsDir, + artifactsDir: argv.artifactsDir, + contracts, + }; + const compiler = new Compiler(opts); + await compiler.compileAsync(); +})().catch(err => { + logUtils.log(err); + process.exit(1); +}); diff --git a/packages/deployer/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index e81df3c0a..efb30091b 100644 --- a/packages/deployer/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -134,7 +134,7 @@ export class Compiler { const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); const didSourceChange = currentArtifact.sourceTreeHashHex !== sourceTreeHashHex; - shouldCompile = isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; + shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } if (!shouldCompile) { return; @@ -203,6 +203,20 @@ export class Compiler { }. Please make sure your contract has the same name as it's file name`, ); } + if (!_.isUndefined(compiledData.evm)) { + if (!_.isUndefined(compiledData.evm.bytecode) && !_.isUndefined(compiledData.evm.bytecode.object)) { + compiledData.evm.bytecode.object = ethUtil.addHexPrefix(compiledData.evm.bytecode.object); + } + if ( + !_.isUndefined(compiledData.evm.deployedBytecode) && + !_.isUndefined(compiledData.evm.deployedBytecode.object) + ) { + compiledData.evm.deployedBytecode.object = ethUtil.addHexPrefix( + compiledData.evm.deployedBytecode.object, + ); + } + } + const sourceCodes = _.mapValues( compiled.sources, (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source, diff --git a/packages/deployer/src/globals.d.ts b/packages/sol-compiler/src/globals.d.ts index 94e63a32d..94e63a32d 100644 --- a/packages/deployer/src/globals.d.ts +++ b/packages/sol-compiler/src/globals.d.ts diff --git a/packages/deployer/src/index.ts b/packages/sol-compiler/src/index.ts index 31a75677b..4b4c51de2 100644 --- a/packages/deployer/src/index.ts +++ b/packages/sol-compiler/src/index.ts @@ -1,3 +1,2 @@ -export { Deployer } from './deployer'; export { Compiler } from './compiler'; export { ContractArtifact, ContractNetworks } from './utils/types'; diff --git a/packages/deployer/src/monorepo_scripts/postpublish.ts b/packages/sol-compiler/src/monorepo_scripts/postpublish.ts index dcb99d0f7..dcb99d0f7 100644 --- a/packages/deployer/src/monorepo_scripts/postpublish.ts +++ b/packages/sol-compiler/src/monorepo_scripts/postpublish.ts diff --git a/packages/deployer/src/monorepo_scripts/stage_docs.ts b/packages/sol-compiler/src/monorepo_scripts/stage_docs.ts index e732ac8eb..e732ac8eb 100644 --- a/packages/deployer/src/monorepo_scripts/stage_docs.ts +++ b/packages/sol-compiler/src/monorepo_scripts/stage_docs.ts diff --git a/packages/deployer/src/solc/bin_paths.ts b/packages/sol-compiler/src/solc/bin_paths.ts index 1b5e8c6f1..1b5e8c6f1 100644 --- a/packages/deployer/src/solc/bin_paths.ts +++ b/packages/sol-compiler/src/solc/bin_paths.ts diff --git a/packages/deployer/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts index 3731385e2..3731385e2 100644 --- a/packages/deployer/src/utils/compiler.ts +++ b/packages/sol-compiler/src/utils/compiler.ts diff --git a/packages/deployer/src/utils/constants.ts b/packages/sol-compiler/src/utils/constants.ts index df2ddb3b2..df2ddb3b2 100644 --- a/packages/deployer/src/utils/constants.ts +++ b/packages/sol-compiler/src/utils/constants.ts diff --git a/packages/deployer/src/utils/encoder.ts b/packages/sol-compiler/src/utils/encoder.ts index 806efbbca..806efbbca 100644 --- a/packages/deployer/src/utils/encoder.ts +++ b/packages/sol-compiler/src/utils/encoder.ts diff --git a/packages/deployer/src/utils/fs_wrapper.ts b/packages/sol-compiler/src/utils/fs_wrapper.ts index cc7b06175..cc7b06175 100644 --- a/packages/deployer/src/utils/fs_wrapper.ts +++ b/packages/sol-compiler/src/utils/fs_wrapper.ts diff --git a/packages/deployer/src/utils/types.ts b/packages/sol-compiler/src/utils/types.ts index 19c27df67..b12a11b79 100644 --- a/packages/deployer/src/utils/types.ts +++ b/packages/sol-compiler/src/utils/types.ts @@ -50,17 +50,6 @@ export interface SolcErrors { [key: string]: boolean; } -export interface CliOptions extends yargs.Arguments { - artifactsDir: string; - contractsDir: string; - jsonrpcUrl: string; - networkId: number; - gasPrice: string; - account?: string; - contract?: string; - args?: string; -} - export interface CompilerOptions { contractsDir?: string; artifactsDir?: string; @@ -68,22 +57,6 @@ export interface CompilerOptions { contracts?: string[] | '*'; } -export interface BaseDeployerOptions { - artifactsDir: string; - networkId: number; - defaults: Partial<TxData>; -} - -export interface ProviderDeployerOptions extends BaseDeployerOptions { - provider: Provider; -} - -export interface UrlDeployerOptions extends BaseDeployerOptions { - jsonrpcUrl: string; -} - -export type DeployerOptions = UrlDeployerOptions | ProviderDeployerOptions; - export interface ContractSourceData { [contractName: string]: ContractSpecificSourceData; } diff --git a/packages/sol-compiler/src/utils/utils.ts b/packages/sol-compiler/src/utils/utils.ts new file mode 100644 index 000000000..4f2de2caa --- /dev/null +++ b/packages/sol-compiler/src/utils/utils.ts @@ -0,0 +1,6 @@ +export const utils = { + stringifyWithFormatting(obj: any): string { + const stringifiedObj = JSON.stringify(obj, null, '\t'); + return stringifiedObj; + }, +}; diff --git a/packages/deployer/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index 4c53a871a..79bb3b873 100644 --- a/packages/deployer/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -38,7 +38,7 @@ describe('#Compiler', function() { const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts); const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); // The last 43 bytes of the binaries are metadata which may not be equivalent - const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice(0, -86); + const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice(2, -86); const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -86); expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata); }); diff --git a/packages/deployer/test/compiler_utils_test.ts b/packages/sol-compiler/test/compiler_utils_test.ts index 393f6d3f3..4fe7b994e 100644 --- a/packages/deployer/test/compiler_utils_test.ts +++ b/packages/sol-compiler/test/compiler_utils_test.ts @@ -55,8 +55,8 @@ describe('Compiler utils', () => { const dependencies = parseDependencies({ source, path }); const expectedDependencies = [ 'zeppelin-solidity/contracts/token/ERC20/ERC20.sol', - 'packages/deployer/lib/test/fixtures/contracts/TokenTransferProxy.sol', - 'packages/deployer/lib/test/fixtures/contracts/base/SafeMath.sol', + 'packages/sol-compiler/lib/test/fixtures/contracts/TokenTransferProxy.sol', + 'packages/sol-compiler/lib/test/fixtures/contracts/base/SafeMath.sol', ]; _.each(expectedDependencies, expectedDepdency => { const foundDependency = _.find(dependencies, dependency => _.endsWith(dependency, expectedDepdency)); diff --git a/packages/deployer/test/fixtures/contracts/Exchange.sol b/packages/sol-compiler/test/fixtures/contracts/Exchange.sol index e3725335b..e3725335b 100644 --- a/packages/deployer/test/fixtures/contracts/Exchange.sol +++ b/packages/sol-compiler/test/fixtures/contracts/Exchange.sol diff --git a/packages/deployer/test/fixtures/contracts/TokenTransferProxy.sol b/packages/sol-compiler/test/fixtures/contracts/TokenTransferProxy.sol index 44570d459..44570d459 100644 --- a/packages/deployer/test/fixtures/contracts/TokenTransferProxy.sol +++ b/packages/sol-compiler/test/fixtures/contracts/TokenTransferProxy.sol diff --git a/packages/deployer/test/fixtures/contracts/base/SafeMath.sol b/packages/sol-compiler/test/fixtures/contracts/base/SafeMath.sol index 92ce11cde..92ce11cde 100644 --- a/packages/deployer/test/fixtures/contracts/base/SafeMath.sol +++ b/packages/sol-compiler/test/fixtures/contracts/base/SafeMath.sol diff --git a/packages/deployer/test/fixtures/contracts/base/Token.sol b/packages/sol-compiler/test/fixtures/contracts/base/Token.sol index 483010d7d..483010d7d 100644 --- a/packages/deployer/test/fixtures/contracts/base/Token.sol +++ b/packages/sol-compiler/test/fixtures/contracts/base/Token.sol diff --git a/packages/deployer/test/fixtures/exchange_bin.ts b/packages/sol-compiler/test/fixtures/exchange_bin.ts index 914e76bf5..914e76bf5 100644 --- a/packages/deployer/test/fixtures/exchange_bin.ts +++ b/packages/sol-compiler/test/fixtures/exchange_bin.ts diff --git a/packages/deployer/test/util/constants.ts b/packages/sol-compiler/test/util/constants.ts index 88d6db550..88d6db550 100644 --- a/packages/deployer/test/util/constants.ts +++ b/packages/sol-compiler/test/util/constants.ts diff --git a/packages/deployer/test/util/provider.ts b/packages/sol-compiler/test/util/provider.ts index e0fcb362a..e0fcb362a 100644 --- a/packages/deployer/test/util/provider.ts +++ b/packages/sol-compiler/test/util/provider.ts diff --git a/packages/deployer/tsconfig.json b/packages/sol-compiler/tsconfig.json index 63cbc75c3..63cbc75c3 100644 --- a/packages/deployer/tsconfig.json +++ b/packages/sol-compiler/tsconfig.json diff --git a/packages/deployer/tslint.json b/packages/sol-compiler/tslint.json index ffaefe83a..ffaefe83a 100644 --- a/packages/deployer/tslint.json +++ b/packages/sol-compiler/tslint.json diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 0a64af4e5..0cef9ff87 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -14,7 +14,7 @@ "run_mocha": "mocha lib/test/**/*_test.js --exit", "clean": "shx rm -rf lib scripts test/fixtures/artifacts src/artifacts", "build": "copyfiles 'test/fixtures/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", - "compile_test": "node ../deployer/lib/src/cli.js compile", + "compile_test": "node ../sol-compiler/lib/src/cli.js compile", "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", @@ -54,10 +54,9 @@ "solidity-parser-antlr": "^0.2.8" }, "devDependencies": { - "@0xproject/deployer": "^0.3.5", "@0xproject/monorepo-scripts": "^0.1.19", "@0xproject/tslint-config": "^0.4.17", - "@types/istanbul": "^0.4.29", + "@types/istanbul": "^0.4.30", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", "chai": "^4.0.1", diff --git a/packages/sol-cov/src/collect_contract_data.ts b/packages/sol-cov/src/collect_contract_data.ts index bb20e98be..2c2a12835 100644 --- a/packages/sol-cov/src/collect_contract_data.ts +++ b/packages/sol-cov/src/collect_contract_data.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import { ContractData } from './types'; -export const collectContractsData = (artifactsPath: string, sourcesPath: string, networkId: number) => { +export const collectContractsData = (artifactsPath: string, sourcesPath: string) => { const artifactsGlob = `${artifactsPath}/**/*.json`; const artifactFileNames = glob.sync(artifactsGlob, { absolute: true }); const contractsData: ContractData[] = []; diff --git a/packages/sol-cov/src/coverage_manager.ts b/packages/sol-cov/src/coverage_manager.ts index 6a57d07c9..f50f010b9 100644 --- a/packages/sol-cov/src/coverage_manager.ts +++ b/packages/sol-cov/src/coverage_manager.ts @@ -1,3 +1,4 @@ +import { addHexPrefix } from 'ethereumjs-util'; import * as fs from 'fs'; import { Collector } from 'istanbul'; import * as _ from 'lodash'; @@ -36,21 +37,18 @@ export class CoverageManager { constructor( artifactsPath: string, sourcesPath: string, - networkId: number, getContractCodeAsync: (address: string) => Promise<string>, ) { this._getContractCodeAsync = getContractCodeAsync; this._sourcesPath = sourcesPath; - this._contractsData = collectContractsData(artifactsPath, this._sourcesPath, networkId); + this._contractsData = collectContractsData(artifactsPath, this._sourcesPath); } public appendTraceInfo(traceInfo: TraceInfo): void { this._traceInfos.push(traceInfo); } public async writeCoverageAsync(): Promise<void> { const finalCoverage = await this._computeCoverageAsync(); - const jsonReplacer: null = null; - const numberOfJsonSpaces = 4; - const stringifiedCoverage = JSON.stringify(finalCoverage, jsonReplacer, numberOfJsonSpaces); + const stringifiedCoverage = JSON.stringify(finalCoverage, null, '\t'); fs.writeFileSync('coverage/coverage.json', stringifiedCoverage); } private _getSingleFileCoverageForTrace( @@ -134,7 +132,7 @@ export class CoverageManager { if (traceInfo.address !== constants.NEW_CONTRACT) { // Runtime transaction let runtimeBytecode = (traceInfo as TraceInfoExistingContract).runtimeBytecode; - runtimeBytecode = utils.removeHexPrefix(runtimeBytecode); + runtimeBytecode = addHexPrefix(runtimeBytecode); const contractData = _.find(this._contractsData, { runtimeBytecode }) as ContractData; if (_.isUndefined(contractData)) { throw new Error(`Transaction to an unknown address: ${traceInfo.address}`); @@ -159,7 +157,7 @@ export class CoverageManager { } else { // Contract creation transaction let bytecode = (traceInfo as TraceInfoNewContract).bytecode; - bytecode = utils.removeHexPrefix(bytecode); + bytecode = addHexPrefix(bytecode); const contractData = _.find(this._contractsData, contractDataCandidate => bytecode.startsWith(contractDataCandidate.bytecode), ) as ContractData; @@ -185,7 +183,6 @@ export class CoverageManager { } } } - // TODO: Remove any cast as soon as https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24233 gets merged - return (collector as any).getFinalCoverage(); + return collector.getFinalCoverage(); } } diff --git a/packages/sol-cov/src/coverage_subprovider.ts b/packages/sol-cov/src/coverage_subprovider.ts index 6504d5a46..b08291afb 100644 --- a/packages/sol-cov/src/coverage_subprovider.ts +++ b/packages/sol-cov/src/coverage_subprovider.ts @@ -28,19 +28,13 @@ export class CoverageSubprovider extends Subprovider { * Instantiates a CoverageSubprovider instance * @param artifactsPath Path to the smart contract artifacts * @param sourcesPath Path to the smart contract source files - * @param networkId network id * @param defaultFromAddress default from address to use when sending transactions */ - constructor(artifactsPath: string, sourcesPath: string, networkId: number, defaultFromAddress: string) { + constructor(artifactsPath: string, sourcesPath: string, defaultFromAddress: string) { super(); this._lock = new Lock(); this._defaultFromAddress = defaultFromAddress; - this._coverageManager = new CoverageManager( - artifactsPath, - sourcesPath, - networkId, - this._getContractCodeAsync.bind(this), - ); + this._coverageManager = new CoverageManager(artifactsPath, sourcesPath, this._getContractCodeAsync.bind(this)); } /** * Write the test coverage results to a file in Istanbul format. diff --git a/packages/sol-cov/test/collect_contracts_data_test.ts b/packages/sol-cov/test/collect_contracts_data_test.ts index 943a4a878..c7c1dfe32 100644 --- a/packages/sol-cov/test/collect_contracts_data_test.ts +++ b/packages/sol-cov/test/collect_contracts_data_test.ts @@ -12,8 +12,7 @@ describe('Collect contracts data', () => { it('correctly collects contracts data', () => { const artifactsPath = path.resolve(__dirname, 'fixtures/artifacts'); const sourcesPath = path.resolve(__dirname, 'fixtures/contracts'); - const networkId = 50; - const contractsData = collectContractsData(artifactsPath, sourcesPath, networkId); + const contractsData = collectContractsData(artifactsPath, sourcesPath); _.forEach(contractsData, contractData => { expect(contractData).to.have.keys([ 'sourceCodes', diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index 92235f6a1..a5b34a35e 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -7,7 +7,7 @@ "build:watch": "tsc -w", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib scripts", - "lint": "tslint --project . 'rules/**/*.ts'", + "lint": "tslint --project .", "manual:postpublish": "yarn build; node ./scripts/postpublish.js" }, "repository": { diff --git a/packages/typescript-typings/types/ethers/index.d.ts b/packages/typescript-typings/types/ethers/index.d.ts index 7e04c7dd1..addf85613 100644 --- a/packages/typescript-typings/types/ethers/index.d.ts +++ b/packages/typescript-typings/types/ethers/index.d.ts @@ -1,4 +1,6 @@ declare module 'ethers' { + import { TxData } from '@0xproject/types'; + export interface TransactionDescription { name: string; signature: string; @@ -26,6 +28,7 @@ declare module 'ethers' { constructor(abi: any); } export class Contract { + public static getDeployTransaction(bytecode: string, abi: any, ...args: any[]): Partial<TxData>; constructor(address: string, abi: any, provider: any); } } diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index 49fddb27b..349e1ed7e 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -29,7 +29,7 @@ export class Web3Wrapper { public isZeroExWeb3Wrapper = true; public abiDecoder: AbiDecoder; private _web3: Web3; - private _defaults: Partial<TxData>; + private _txDefaults: Partial<TxData>; private _jsonRpcRequestId: number; /** * Check if an address is a valid Ethereum address @@ -83,10 +83,10 @@ export class Web3Wrapper { * Instantiates a new Web3Wrapper. * @param provider The Web3 provider instance you would like the Web3Wrapper to use for interacting with * the backing Ethereum node. - * @param defaults Override TxData defaults sent with RPC requests to the backing Ethereum node. + * @param txDefaults Override TxData defaults sent with RPC requests to the backing Ethereum node. * @return An instance of the Web3Wrapper class. */ - constructor(provider: Provider, defaults?: Partial<TxData>) { + constructor(provider: Provider, txDefaults?: Partial<TxData>) { if (_.isUndefined((provider as any).sendAsync)) { // Web3@1.0 provider doesn't support synchronous http requests, // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x` @@ -96,7 +96,7 @@ export class Web3Wrapper { this.abiDecoder = new AbiDecoder([]); this._web3 = new Web3(); this._web3.setProvider(provider); - this._defaults = defaults || {}; + this._txDefaults = txDefaults || {}; this._jsonRpcRequestId = 0; } /** @@ -104,7 +104,7 @@ export class Web3Wrapper { * @return TxData defaults (e.g gas, gasPrice, nonce, etc...) */ public getContractDefaults(): Partial<TxData> { - return this._defaults; + return this._txDefaults; } /** * Retrieve the Web3 provider diff --git a/packages/website/md/docs/deployer/installation.md b/packages/website/md/docs/deployer/installation.md deleted file mode 100644 index c02dbadc6..000000000 --- a/packages/website/md/docs/deployer/installation.md +++ /dev/null @@ -1,24 +0,0 @@ -#### CLI Installation - -```bash -yarn global add @0xproject/deployer -``` - -#### API Installation - -```bash -yarn add @0xproject/deployer -``` - -**Import** - -```typescript -import { Deployer, Compiler } from '@0xproject/deployer'; -``` - -or - -```javascript -var Deployer = require('@0xproject/deployer').Deployer; -var Compiler = require('@0xproject/deployer').Compiler; -``` diff --git a/packages/website/md/docs/deployer/introduction.md b/packages/website/md/docs/deployer/introduction.md deleted file mode 100644 index 7ebd26a3c..000000000 --- a/packages/website/md/docs/deployer/introduction.md +++ /dev/null @@ -1,18 +0,0 @@ -Welcome to the [Deployer](https://github.com/0xProject/0x-monorepo/tree/development/packages/deployer) documentation! Deployer is a tool for compiling and deploying Solidity smart contracts with ease. - -It serves a similar purpose as parts of the [Truffle framework](http://truffleframework.com/), but with the UNIX philosophy in mind: Make each program do one thing well. This tool is for intermediate to advanced Solidity developers that require greater configurability and reliability. - -Deployer has the following advantages over Truffle: - -* Deploy each smart contract with a specific version of Solidity. -* Improved artifact files: - * Properly segregated artifacts to support storing different versions of smart contract deployed on different networks. - * Storage of constructor args, source maps and paths to all requisite source files. - * An easy to maintain codebase: TypeScript + Single repo. - * Allows you to specify the deployer RPC address. - * Supports Solidity version ranges - contract compiled with latest Solidity version that satisfies the range. - * Migrations that work with `async/await`. - * Migrations that can be written synchronously in order to guarentee deterministic contract addresses. - * No race conditions when running migrations. - -Deployer can be used as a command-line tool or as an imported module. diff --git a/packages/website/md/docs/deployer/usage.md b/packages/website/md/docs/deployer/usage.md deleted file mode 100644 index 295af55e1..000000000 --- a/packages/website/md/docs/deployer/usage.md +++ /dev/null @@ -1,56 +0,0 @@ -#### CLI Usage - -```bash -$ 0x-deployer --help -0x-deployer [command] - -Commands: - 0x-deployer compile compile contracts - 0x-deployer deploy deploy a single contract with provided arguments - -Options: - --version Show version number [boolean] - --contracts-dir path of contracts directory to compile [string] [default: - "/path/to/contracts"] - --network-id mainnet=1, kovan=42, testrpc=50 [number] [default: 50] - --should-optimize enable optimizer [boolean] [default: false] - --artifacts-dir path to write contracts artifacts to [string] [default: - "/path/to/artifacts"] - --jsonrpc-port port connected to JSON RPC [number] [default: 8545] - --gas-price gasPrice to be used for transactions - [string] [default: "2000000000"] - --account account to use for deploying contracts [string] - --contracts comma separated list of contracts to compile - [string] [default: "*"] - --help Show help [boolean] -``` - -#### API Usage - -##### Migrations - -You can write migration scripts (similar to `truffle migrate`), that deploys multiple contracts and configures them. Below you'll find a simple example of such a script to help you get started. - -```typescript -import { Deployer } from '@0xproject/deployer'; -import * as path from 'path'; - -const deployerOpts = { - artifactsDir: path.resolve('src', 'artifacts'), - jsonrpcUrl: 'http://localhost:8545', - networkId: 50, - defaults: { - gas: 1000000, - }, -}; - -const deployer = new Deployer(deployerOpts); - -(async () => { - const etherToken = await deployer.deployAndSaveAsync('WETH9'); -})().catch(console.log); -``` - -**Tip:** Be sure to start an Ethereum node at the supplied `jsonrpcUrl`. We recommend testing with [Ganache-cli](https://github.com/trufflesuite/ganache-cli) - -A more sophisticated example can be found [here](https://github.com/0xProject/0x-monorepo/tree/development/packages/contracts/migrations) diff --git a/packages/website/md/docs/sol-compiler/installation.md b/packages/website/md/docs/sol-compiler/installation.md new file mode 100644 index 000000000..9c8561d9b --- /dev/null +++ b/packages/website/md/docs/sol-compiler/installation.md @@ -0,0 +1,23 @@ +#### CLI Installation + +```bash +yarn global add @0xproject/sol-compiler +``` + +#### API Installation + +```bash +yarn add @0xproject/sol-compiler +``` + +**Import** + +```typescript +import { Compiler } from '@0xproject/sol-compiler'; +``` + +or + +```javascript +var Compiler = require('@0xproject/sol-compiler').Compiler; +``` diff --git a/packages/website/md/docs/sol-compiler/introduction.md b/packages/website/md/docs/sol-compiler/introduction.md new file mode 100644 index 000000000..aa1939006 --- /dev/null +++ b/packages/website/md/docs/sol-compiler/introduction.md @@ -0,0 +1,13 @@ +Welcome to the [sol-compiler](https://github.com/0xProject/0x-monorepo/tree/development/packages/sol-compiler) documentation! Sol-compiler is a tool for compiling Solidity smart contracts and generating artifacts with ease. + +It serves a similar purpose as parts of the [Truffle framework](http://truffleframework.com/), but with the UNIX philosophy in mind: Make each program do one thing well. This tool is for intermediate to advanced Solidity developers that require greater configurability and reliability. + +Sol-compiler has the following advantages over Truffle: + +* Compile each smart contract with a specific version of Solidity. +* Improved artifact files: + * Storage of constructor args, source maps and paths to all requisite source files. + * An easy to maintain codebase: TypeScript + Single repo. + * Supports Solidity version ranges - contract compiled with latest Solidity version that satisfies the range. + +Sol-compiler can be used as a command-line tool or as an imported module. diff --git a/packages/website/md/docs/sol-compiler/usage.md b/packages/website/md/docs/sol-compiler/usage.md new file mode 100644 index 000000000..79c9b32ba --- /dev/null +++ b/packages/website/md/docs/sol-compiler/usage.md @@ -0,0 +1,24 @@ +#### CLI Usage + +```bash +$ sol-compiler +Options: + --version Show version number [boolean] + --contracts-dir path of contracts directory to compile [string] + --artifacts-dir path to write contracts artifacts to [string] + --contracts comma separated list of contracts to compile + [string] [default: "*"] + --help Show help [boolean] +``` + +#### API Usage + +```typescript +import { Compiler } from '@0xproject/sol-compiler'; + +const compiler = new Compiler(); + +(async () => { + await compiler.compileAllAsync(); +})().catch(console.log); +``` diff --git a/packages/website/md/docs/sol_cov/usage.md b/packages/website/md/docs/sol_cov/usage.md index ea1982d97..63a88f595 100644 --- a/packages/website/md/docs/sol_cov/usage.md +++ b/packages/website/md/docs/sol_cov/usage.md @@ -12,7 +12,7 @@ const contractsPath = 'src/contracts'; const networkId = 50; // Some calls might not have `from` address specified. Nevertheless - transactions need to be submitted from an address with at least some funds. defaultFromAddress is the address that will be used to submit those calls as transactions from. const defaultFromAddress = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; -const coverageSubprovider = new CoverageSubprovider(artifactsPath, contractsPath, networkId, defaultFromAddress); +const coverageSubprovider = new CoverageSubprovider(artifactsPath, contractsPath, defaultFromAddress); provider.addProvider(coverageSubprovider); ``` diff --git a/packages/website/translations/chinese.json b/packages/website/translations/chinese.json index d37b1abdf..966457a93 100644 --- a/packages/website/translations/chinese.json +++ b/packages/website/translations/chinese.json @@ -56,7 +56,7 @@ "ABOUT": "关于我们", "CAREERS": "人才招聘", "CONTACT": "联系方式", - "DEPLOYER": "Deployer", + "SOL_COMPILER": "Solidity Compiler", "JSON_SCHEMAS": "JSON Schemas", "SOL_COV": "Solidity Coverage", "SUBPROVIDERS": "Subproviders", diff --git a/packages/website/translations/english.json b/packages/website/translations/english.json index 8d7485e9a..f3acea3be 100644 --- a/packages/website/translations/english.json +++ b/packages/website/translations/english.json @@ -57,7 +57,7 @@ "ABOUT": "about", "CAREERS": "careers", "CONTACT": "contact", - "DEPLOYER": "Deployer", + "SOL_COMPILER": "Solidity Compiler", "JSON_SCHEMAS": "JSON Schemas", "SOL_COV": "Solidity Coverage", "SUBPROVIDERS": "Subproviders", diff --git a/packages/website/translations/korean.json b/packages/website/translations/korean.json index 028476d2c..7414207f7 100644 --- a/packages/website/translations/korean.json +++ b/packages/website/translations/korean.json @@ -56,7 +56,7 @@ "ABOUT": "기업 정보", "CAREERS": "채용", "CONTACT": "문의", - "DEPLOYER": "Deployer", + "SOL_COMPILER": "Solidity Compiler", "JSON_SCHEMAS": "JSON Schemas", "SOL_COV": "Solidity Coverage", "SUBPROVIDERS": "Subproviders", diff --git a/packages/website/translations/russian.json b/packages/website/translations/russian.json index 9254ab1c0..75ab02a27 100644 --- a/packages/website/translations/russian.json +++ b/packages/website/translations/russian.json @@ -56,7 +56,7 @@ "ABOUT": "Kоманда", "CAREERS": "Карьера", "CONTACT": "Связаться с нами", - "DEPLOYER": "Deployer", + "SOL_COMPILER": "Solidity Compiler", "JSON_SCHEMAS": "JSON Schemas", "SOL_COV": "Solidity Coverage", "SUBPROVIDERS": "Subproviders", diff --git a/packages/website/translations/spanish.json b/packages/website/translations/spanish.json index eb8f4035c..8f537ea40 100644 --- a/packages/website/translations/spanish.json +++ b/packages/website/translations/spanish.json @@ -57,7 +57,7 @@ "ABOUT": "equipo", "CAREERS": "empleo", "CONTACT": "contacto", - "DEPLOYER": "Deployer", + "SOL_COMPILER": "Solidity Compiler", "JSON_SCHEMAS": "JSON Schemas", "SOL_COV": "Solidity Coverage", "SUBPROVIDERS": "Subproviders", diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index b5e8150c4..4cbc65ce4 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -14,8 +14,10 @@ import { TopBar, TopBarDisplayType } from 'ts/components/top_bar/top_bar'; import { FlashMessage } from 'ts/components/ui/flash_message'; import { Wallet } from 'ts/components/wallet/wallet'; import { localStorage } from 'ts/local_storage/local_storage'; +import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { Dispatcher } from 'ts/redux/dispatcher'; import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, TokenByAddress, TokenVisibility } from 'ts/types'; +import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; import { utils } from 'ts/utils/utils'; @@ -49,7 +51,13 @@ interface PortalState { prevPathname: string; isDisclaimerDialogOpen: boolean; isLedgerDialogOpen: boolean; - isAssetPickerDialogOpen: boolean; + tokenManagementState: TokenManagementState; +} + +enum TokenManagementState { + Add = 'Add', + Remove = 'Remove', + None = 'None', } const THROTTLE_TIMEOUT = 100; @@ -90,7 +98,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { prevUserAddress: this.props.userAddress, prevPathname: this.props.location.pathname, isDisclaimerDialogOpen: !hasAcceptedDisclaimer, - isAssetPickerDialogOpen: false, + tokenManagementState: TokenManagementState.None, isLedgerDialogOpen: false, }; } @@ -142,6 +150,11 @@ export class Portal extends React.Component<PortalProps, PortalState> { ); const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); + const isAssetPickerDialogOpen = this.state.tokenManagementState !== TokenManagementState.None; + const tokenVisibility = + this.state.tokenManagementState === TokenManagementState.Add + ? TokenVisibility.UNTRACKED + : TokenVisibility.TRACKED; return ( <div style={styles.root}> <DocumentTitle title="0x Portal DApp" /> @@ -180,6 +193,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { providerType={this.props.providerType} onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)} onAddToken={this._onAddToken.bind(this)} + onRemoveToken={this._onRemoveToken.bind(this)} /> </div> <div className="flex-auto px3" style={styles.scrollContainer}> @@ -217,11 +231,11 @@ export class Portal extends React.Component<PortalProps, PortalState> { networkId={this.props.networkId} blockchain={this._blockchain} dispatcher={this.props.dispatcher} - isOpen={this.state.isAssetPickerDialogOpen} + isOpen={isAssetPickerDialogOpen} currentTokenAddress={''} onTokenChosen={this._onTokenChosen.bind(this)} tokenByAddress={this.props.tokenByAddress} - tokenVisibility={TokenVisibility.UNTRACKED} + tokenVisibility={tokenVisibility} /> </div> </div> @@ -230,14 +244,29 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _onTokenChosen(tokenAddress: string) { if (_.isEmpty(tokenAddress)) { this.setState({ - isAssetPickerDialogOpen: false, + tokenManagementState: TokenManagementState.None, }); return; } const token = this.props.tokenByAddress[tokenAddress]; - this.props.dispatcher.updateTokenByAddress([token]); + const isDefaultTrackedToken = _.includes(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, token.symbol); + if (this.state.tokenManagementState === TokenManagementState.Remove && !isDefaultTrackedToken) { + if (token.isRegistered) { + // Remove the token from tracked tokens + const newToken = { + ...token, + isTracked: false, + }; + this.props.dispatcher.updateTokenByAddress([newToken]); + } else { + this.props.dispatcher.removeTokenToTokenByAddress(token); + } + trackedTokenStorage.removeTrackedToken(this.props.userAddress, this.props.networkId, tokenAddress); + } else if (isDefaultTrackedToken) { + this.props.dispatcher.showFlashMessage(`Cannot remove ${token.name} because it's a default token`); + } this.setState({ - isAssetPickerDialogOpen: false, + tokenManagementState: TokenManagementState.None, }); } private _onToggleLedgerDialog() { @@ -247,7 +276,12 @@ export class Portal extends React.Component<PortalProps, PortalState> { } private _onAddToken() { this.setState({ - isAssetPickerDialogOpen: !this.state.isAssetPickerDialogOpen, + tokenManagementState: TokenManagementState.Add, + }); + } + private _onRemoveToken() { + this.setState({ + tokenManagementState: TokenManagementState.Remove, }); } private _onPortalDisclaimerAccepted() { diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 2502bea6d..5a1b50310 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -149,10 +149,10 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { primaryText={this.props.translate.get(Key.OrderUtils, Deco.CapWords)} /> </Link>, - <Link key="subMenuItem-deployer" to={WebsitePaths.Deployer} className="text-decoration-none"> + <Link key="subMenuItem-sol-compiler" to={WebsitePaths.SolCompiler} className="text-decoration-none"> <MenuItem style={{ fontSize: styles.menuItem.fontSize }} - primaryText={this.props.translate.get(Key.Deployer, Deco.CapWords)} + primaryText={this.props.translate.get(Key.SolCompiler, Deco.CapWords)} /> </Link>, <Link key="subMenuItem-sol-cov" to={WebsitePaths.SolCov} className="text-decoration-none"> @@ -328,10 +328,10 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { </MenuItem> </Link> )} - {!this._isViewingDeployerDocs() && ( - <Link to={WebsitePaths.Deployer} className="text-decoration-none"> + {!this._isViewingSolCompilerDocs() && ( + <Link to={WebsitePaths.SolCompiler} className="text-decoration-none"> <MenuItem className="py2"> - {this.props.translate.get(Key.Deployer, Deco.Cap)}{' '} + {this.props.translate.get(Key.SolCompiler, Deco.Cap)}{' '} {this.props.translate.get(Key.Docs, Deco.Cap)} </MenuItem> </Link> @@ -390,7 +390,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { (!this._isViewing0xjsDocs() && !this._isViewingSmartContractsDocs() && !this._isViewingWeb3WrapperDocs() && - !this._isViewingDeployerDocs() && + !this._isViewingSolCompilerDocs() && !this._isViewingJsonSchemasDocs() && !this._isViewingSolCovDocs() && !this._isViewingSubprovidersDocs() && @@ -476,8 +476,8 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { _.includes(this.props.location.pathname, WebsiteLegacyPaths.Web3Wrapper) ); } - private _isViewingDeployerDocs() { - return _.includes(this.props.location.pathname, WebsitePaths.Deployer); + private _isViewingSolCompilerDocs() { + return _.includes(this.props.location.pathname, WebsitePaths.SolCompiler); } private _isViewingJsonSchemasDocs() { return _.includes(this.props.location.pathname, WebsitePaths.JSONSchemas); @@ -498,7 +498,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { this._isViewingFAQ() || this._isViewingSmartContractsDocs() || this._isViewingWeb3WrapperDocs() || - this._isViewingDeployerDocs() || + this._isViewingSolCompilerDocs() || this._isViewingJsonSchemasDocs() || this._isViewingSolCovDocs() || this._isViewingSubprovidersDocs() || diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index a28012aaf..079c0e3b3 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -9,8 +9,11 @@ import { import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import FlatButton from 'material-ui/FlatButton'; +import FloatingActionButton from 'material-ui/FloatingActionButton'; import { List, ListItem } from 'material-ui/List'; import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet'; +import ContentAdd from 'material-ui/svg-icons/content/add'; +import ContentRemove from 'material-ui/svg-icons/content/remove'; import NavigationArrowDownward from 'material-ui/svg-icons/navigation/arrow-downward'; import NavigationArrowUpward from 'material-ui/svg-icons/navigation/arrow-upward'; import Close from 'material-ui/svg-icons/navigation/close'; @@ -56,6 +59,7 @@ export interface WalletProps { providerType: ProviderType; onToggleLedgerDialog: () => void; onAddToken: () => void; + onRemoveToken: () => void; } interface WalletState { @@ -138,6 +142,7 @@ const ZRX_TOKEN_SYMBOL = 'ZRX'; const ETHER_SYMBOL = 'ETH'; const ICON_DIMENSION = 24; const TOKEN_AMOUNT_DISPLAY_PRECISION = 3; +const BODY_ITEM_KEY = 'BODY'; const HEADER_ITEM_KEY = 'HEADER'; const FOOTER_ITEM_KEY = 'FOOTER'; const DISCONNECTED_ITEM_KEY = 'DISCONNECTED'; @@ -248,7 +253,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { }; return ( <ListItem - key="body" + key={BODY_ITEM_KEY} innerDivStyle={bodyStyle} onMouseEnter={this._onSidebarHover.bind(this)} onMouseLeave={this._onSidebarHoverOff.bind(this)} @@ -269,13 +274,31 @@ export class Wallet extends React.Component<WalletProps, WalletState> { }); } private _renderFooterRows() { - const primaryText = '+ other tokens'; return ( <ListItem key={FOOTER_ITEM_KEY} - primaryText={primaryText} + primaryText={ + <div className="flex"> + <FloatingActionButton mini={true} zDepth={0} onClick={this.props.onAddToken}> + <ContentAdd /> + </FloatingActionButton> + <FloatingActionButton mini={true} zDepth={0} className="px1" onClick={this.props.onRemoveToken}> + <ContentRemove /> + </FloatingActionButton> + <div + style={{ + paddingLeft: 10, + position: 'relative', + top: '50%', + transform: 'translateY(33%)', + }} + > + add/remove tokens + </div> + </div> + } + disabled={true} innerDivStyle={styles.footerItemInnerDiv} - onClick={this.props.onAddToken} /> ); } diff --git a/packages/website/ts/containers/deployer_documentation.ts b/packages/website/ts/containers/sol_compiler_documentation.ts index e20cc195b..2f6486146 100644 --- a/packages/website/ts/containers/deployer_documentation.ts +++ b/packages/website/ts/containers/sol_compiler_documentation.ts @@ -12,9 +12,9 @@ import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ -const IntroMarkdown = require('md/docs/deployer/introduction'); -const InstallationMarkdown = require('md/docs/deployer/installation'); -const UsageMarkdown = require('md/docs/deployer/usage'); +const IntroMarkdown = require('md/docs/sol-compiler/introduction'); +const InstallationMarkdown = require('md/docs/sol-compiler/installation'); +const UsageMarkdown = require('md/docs/sol-compiler/usage'); /* tslint:enable:no-var-requires */ const docSections = { @@ -22,21 +22,19 @@ const docSections = { installation: 'installation', usage: 'usage', compiler: 'compiler', - deployer: 'deployer', types: docConstants.TYPES_SECTION_NAME, }; const docsInfoConfig: DocsInfoConfig = { - id: DocPackages.Deployer, + id: DocPackages.SolCompiler, type: SupportedDocJson.TypeDoc, - displayName: 'Deployer', + displayName: 'Solidity Compiler', packageUrl: 'https://github.com/0xProject/0x-monorepo', menu: { introduction: [docSections.introduction], install: [docSections.installation], usage: [docSections.usage], compiler: [docSections.compiler], - deployer: [docSections.deployer], types: [docSections.types], }, sectionNameToMarkdown: { @@ -45,32 +43,18 @@ const docsInfoConfig: DocsInfoConfig = { [docSections.usage]: UsageMarkdown, }, sectionNameToModulePath: { - [docSections.compiler]: ['"deployer/src/compiler"'], - [docSections.deployer]: ['"deployer/src/deployer"'], - [docSections.types]: ['"deployer/src/utils/types"', '"types/src/index"'], + [docSections.compiler]: ['"sol-compiler/src/compiler"'], + [docSections.types]: ['"sol-compiler/src/utils/types"', '"types/src/index"'], }, menuSubsectionToVersionWhenIntroduced: {}, sections: docSections, - visibleConstructors: [docSections.compiler, docSections.deployer], + visibleConstructors: [docSections.compiler], 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: [ - 'CompilerOptions', - 'DeployerOptions', - 'BaseDeployerOptions', - 'UrlDeployerOptions', - 'ProviderDeployerOptions', - 'TxData', - ], - typeNameToExternalLink: { - 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: { - ContractInstance: 'Web3', - }, + publicTypes: ['CompilerOptions'], + typeNameToExternalLink: {}, + typeNameToPrefix: {}, }, }; const docsInfo = new DocsInfo(docsInfoConfig); diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts index a14d06a3f..2178baea8 100644 --- a/packages/website/ts/containers/subproviders_documentation.ts +++ b/packages/website/ts/containers/subproviders_documentation.ts @@ -74,7 +74,7 @@ const docsInfoConfig: DocsInfoConfig = { [docSections.redundantRPCSubprovider]: ['"subproviders/src/subproviders/redundant_rpc"'], [docSections.ganacheSubprovider]: ['"subproviders/src/subproviders/ganache"'], [docSections.nonceTrackerSubprovider]: ['"subproviders/src/subproviders/nonce_tracker"'], - [docSections.types]: ['"deployer/src/utils/types"', '"types/src/index"', '"subproviders/src/types"'], + [docSections.types]: ['"sol-compiler/src/utils/types"', '"types/src/index"', '"subproviders/src/types"'], }, menuSubsectionToVersionWhenIntroduced: {}, sections: docSections, diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index 1b1255214..49bcdeaac 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -54,8 +54,8 @@ const LazyConnectDocumentation = createLazyComponent('Documentation', async () = const LazyWeb3WrapperDocumentation = createLazyComponent('Documentation', async () => System.import<any>(/* webpackChunkName: "web3WrapperDocs" */ 'ts/containers/web3_wrapper_documentation'), ); -const LazyDeployerDocumentation = createLazyComponent('Documentation', async () => - System.import<any>(/* webpackChunkName: "deployerDocs" */ 'ts/containers/deployer_documentation'), +const LazySolCompilerDocumentation = createLazyComponent('Documentation', async () => + System.import<any>(/* webpackChunkName: "solCompilerDocs" */ 'ts/containers/sol_compiler_documentation'), ); const LazyJSONSchemasDocumentation = createLazyComponent('Documentation', async () => System.import<any>(/* webpackChunkName: "jsonSchemasDocs" */ 'ts/containers/json_schemas_documentation'), @@ -91,7 +91,10 @@ render( <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} /> + <Route + path={`${WebsitePaths.SolCompiler}/:version?`} + component={LazySolCompilerDocumentation} + /> <Route path={`${WebsitePaths.SolCov}/:version?`} component={LazySolCovDocumentation} /> <Route path={`${WebsitePaths.JSONSchemas}/:version?`} @@ -123,6 +126,10 @@ render( path={`${WebsiteLegacyPaths.Web3Wrapper}/:version?`} component={LazyWeb3WrapperDocumentation} /> + <Route + path={`${WebsiteLegacyPaths.Deployer}/:version?`} + component={LazySolCompilerDocumentation} + /> <Route component={NotFound as any} /> </Switch> diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx index 9feb27dac..be8ae02f4 100644 --- a/packages/website/ts/pages/documentation/doc_page.tsx +++ b/packages/website/ts/pages/documentation/doc_page.tsx @@ -30,7 +30,7 @@ const docIdToSubpackageName: { [id: string]: string } = { [DocPackages.Connect]: 'connect', [DocPackages.SmartContracts]: 'contracts', [DocPackages.Web3Wrapper]: 'web3-wrapper', - [DocPackages.Deployer]: 'deployer', + [DocPackages.SolCompiler]: 'sol-compiler', [DocPackages.JSONSchemas]: 'json-schemas', [DocPackages.SolCov]: 'sol-cov', [DocPackages.Subproviders]: 'subproviders', diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 67e4a5d7d..58929a0c6 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -344,6 +344,7 @@ export enum Docs { export enum WebsiteLegacyPaths { ZeroExJs = '/docs/0xjs', Web3Wrapper = '/docs/web3_wrapper', + Deployer = '/docs/deployer', } export enum WebsitePaths { @@ -357,7 +358,7 @@ export enum WebsitePaths { SmartContracts = '/docs/contracts', Connect = '/docs/connect', Web3Wrapper = '/docs/web3-wrapper', - Deployer = '/docs/deployer', + SolCompiler = '/docs/sol-compiler', JSONSchemas = '/docs/json-schemas', SolCov = '/docs/sol-cov', Subproviders = '/docs/subproviders', @@ -370,7 +371,7 @@ export enum DocPackages { ZeroExJs = 'ZERO_EX_JS', SmartContracts = 'SMART_CONTRACTS', Web3Wrapper = 'WEB3_WRAPPER', - Deployer = 'DEPLOYER', + SolCompiler = 'SOL_COMPILER', JSONSchemas = 'JSON_SCHEMAS', SolCov = 'SOL_COV', Subproviders = 'SUBPROVIDERS', @@ -423,7 +424,7 @@ export enum Key { About = 'ABOUT', Careers = 'CAREERS', Contact = 'CONTACT', - Deployer = 'DEPLOYER', + SolCompiler = 'SOL_COMPILER', JsonSchemas = 'JSON_SCHEMAS', SolCov = 'SOL_COV', Subproviders = 'SUBPROVIDERS', |