aboutsummaryrefslogtreecommitdiffstats
path: root/packages/deployer/src/deployer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/deployer/src/deployer.ts')
-rw-r--r--packages/deployer/src/deployer.ts223
1 files changed, 0 insertions, 223 deletions
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;
- }
-}