use network id to get the network url

This commit is contained in:
Jonathan Rainville 2019-01-18 15:19:49 -05:00
parent 295b42584e
commit fbf850d88d
2 changed files with 39 additions and 30 deletions

View File

@ -29,14 +29,14 @@ module.exports = (embark) => {
const etherscanKeyDocsLink = 'https://etherscancom.freshdesk.com/support/solutions/articles/35000022163-i-need-an-api-key';
embark.registerConsoleCommand({
description: `Verifies a contract on Etherscan using you contract configuration\n\t\tRequires an Etherscan API key.
See: ${etherscanKeyDocsLink}\n\t\tNot specifying the network defaults to mainnet. Available: ropsten, kovan, rinkeby`,
See: ${etherscanKeyDocsLink}`,
matches: (cmd) => {
const [commandName] = cmd.split(' ');
return commandName === 'verify';
},
usage: "verify <apiKey> <contractName> [<network>]",
usage: "verify <apiKey> <contractName>]",
process: (cmd, callback) => {
const [, apiKey, contractName, network] = cmd.split(' ');
const [, apiKey, contractName] = cmd.split(' ');
if (!apiKey || !contractName) {
embark.logger.error('Missing argument. Please provide your Etherscan API key and the contract name'.red);
@ -48,7 +48,7 @@ module.exports = (embark) => {
return callback(null, 'solc version not present in embarkjs.json. Please add it to versions.solc'.red);
}
flattener.verify(apiKey, contractName, network, callback);
flattener.verify(apiKey, contractName, callback);
}
});
};

View File

@ -6,11 +6,17 @@ const querystring = require('querystring');
const OUTPUT_DIR = 'flattenedContracts';
const solcVersionsListLink = 'https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/bin/list.txt';
const MAIN_API_URL = 'https://api.etherscan.io/api';
const TESTNET_API_URL_MAP = {
ropsten: 'https://api-ropsten.etherscan.io/api',
kovan: 'https://api-kovan.etherscan.io/api',
rinkeby: 'https://api-rinkeby.etherscan.io/api'
const API_URL_MAP = {
1: 'https://api.etherscan.io/api',
3: 'https://api-ropsten.etherscan.io/api',
4: 'https://api-rinkeby.etherscan.io/api',
42: 'https://api-kovan.etherscan.io/api'
};
const CONTRACT_URL_MAP = {
1: 'https://etherscan.io/address',
3: 'https://ropsten.etherscan.io/address',
4: 'https://rinkeby.etherscan.io/address',
42: 'https://kovan.etherscan.io/address'
};
const RETRY_COUNT = 5;
const RETRY_SLEEP_TIME = 5000;
@ -23,6 +29,7 @@ class Flattener {
constructor(embark) {
this.embark = embark;
this.events = embark.events;
this.logger = embark.logger;
}
_doFlatten(contracts, callback) {
@ -64,7 +71,7 @@ class Flattener {
if (err) {
eachCb(err);
}
this.embark.logger.info(`Flattened ${path.basename(contract.path)} to ${outputName}`);
this.logger.info(`Flattened ${path.basename(contract.path)} to ${outputName}`);
eachCb();
});
});
@ -74,11 +81,11 @@ class Flattener {
_isContractValid(contract, contractName) {
if (!contract) {
this.embark.logger.error(null, `Contract "${contractName}" was not found in contract list`.red);
this.logger.error(null, `Contract "${contractName}" was not found in contract list`.red);
return false;
}
if (!contract.deployedAddress) {
this.embark.logger.error(null, `Contract "${contractName}" does not have a deployed address. Was the contract deployed?`.red);
this.logger.error(null, `Contract "${contractName}" does not have a deployed address. Was the contract deployed?`.red);
return false;
}
return true;
@ -109,16 +116,13 @@ class Flattener {
}
_getUrl(network) {
if (!network) {
return MAIN_API_URL;
}
if (!TESTNET_API_URL_MAP[network]) {
if (!API_URL_MAP[network]) {
return null;
}
return TESTNET_API_URL_MAP[network];
return API_URL_MAP[network];
}
_doVerify(contract, flattenedCode, apiKey, solcVersion, network, callback) {
_doVerify(contract, flattenedCode, apiKey, solcVersion, networkId, callback) {
const data = {
apikey: apiKey,
module: 'contract',
@ -164,14 +168,14 @@ class Flattener {
return callback(err);
}
const url = this._getUrl(network);
const etherscanContractUrl = `https://${network}.etherscan.io/address`;
const url = this._getUrl(networkId);
const etherscanContractUrl = CONTRACT_URL_MAP[networkId];
if (!url) {
return callback(null, `Unknown network "${network}". Available are: ${Object.keys(TESTNET_API_URL_MAP).join(', ')}`.red);
return callback(null, `The current network (id "${networkId}") not supported by Etherscan. Available are: ${Object.keys(API_URL_MAP).join(', ')}`.red);
}
this.embark.logger.info('Sending the request...');
this.logger.info('Sending the request...');
try {
const response = await axios.request({
@ -187,11 +191,11 @@ class Flattener {
return callback(null, `Error while trying to verify contract: ${JSON.stringify(response.data.result, null, 2)}`.red);
}
this.embark.logger.info('Contract verification in process (this usually takes under 30 seconds)...');
this.logger.info('Contract verification in process (this usually takes under 30 seconds)...');
await this.checkEtherscanVerificationStatus(response.data.result, url, RETRY_COUNT);
callback(null, `Contract verified successfully. You can check it here: ${etherscanContractUrl}/${contract.deployedAddress}#code`);
} catch(error) {
this.embark.logger.error('Error while trying to verify contract');
this.logger.error('Error while trying to verify contract');
callback(null, error.message);
}
});
@ -206,7 +210,7 @@ class Flattener {
});
try {
this.embark.logger.info('Checking the verification status...');
this.logger.info('Checking the verification status...');
const response = await axios.request({
method: 'GET',
url: `${etherscanApiUrl}?${queryParams}`
@ -219,13 +223,13 @@ class Flattener {
if (retries === 0) {
throw new Error(error.message || 'Error while trying to check verification status');
}
this.embark.logger.warn(`Verification not finished. Checking again in ${RETRY_SLEEP_TIME / 1000} seconds...`);
this.logger.warn(`Verification not finished. Checking again in ${RETRY_SLEEP_TIME / 1000} seconds...`);
await sleep(RETRY_SLEEP_TIME);
await this.checkEtherscanVerificationStatus(guid, etherscanApiUrl, retries - 1);
}
}
verify(apiKey, contractName, network, callback) {
verify(apiKey, contractName, callback) {
this.events.request("contracts:contract", contractName, (contract) => {
if (!this._isContractValid(contract, contractName)) {
return callback(null, 'Please make sure you specify the contract name as the class name. E.g. SimpleStorage instead of simple_storage.sol');
@ -234,7 +238,7 @@ class Flattener {
const flattenedContractFile = path.join(OUTPUT_DIR, contract.filename);
let flattenedFileExists = false;
if (fs.existsSync(flattenedContractFile)) {
this.embark.logger.info(`Using the already flattened contract (${flattenedContractFile})`);
this.logger.info(`Using the already flattened contract (${flattenedContractFile})`);
flattenedFileExists = true;
}
@ -261,12 +265,17 @@ class Flattener {
next(null, content, solcVersion.replace('soljson-', '').replace('.js', ''));
})
.catch(next);
},
(content, solcVersion, next) => {
this.events.request("blockchain:networkId", (networkId) => {
next(null, content, solcVersion, networkId);
});
}
], (err, content, solcVersion) => {
], (err, content, solcVersion, networkId) => {
if (err) {
return callback(err);
}
this._doVerify(contract, content, apiKey, solcVersion, network, callback);
this._doVerify(contract, content, apiKey, solcVersion, networkId, callback);
});
});
}