Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

Add url and path properties to network config #1386

Merged
merged 2 commits into from
Jan 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 36 additions & 37 deletions packages/cli/src/models/config/NetworkConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ interface ConfigInterface {
networks: { [network: string]: Network };
provider: Provider;
buildDir: string;
// TODO: remove after managing compiler info in project.json
compilers?: CompilersInfo;
}

interface NetworkCamelCase<T> {
Expand All @@ -27,15 +25,26 @@ interface NetworkSnakeCase<T> {

type NetworkId<T> = NetworkCamelCase<T> | NetworkSnakeCase<T> | (NetworkCamelCase<T> & NetworkSnakeCase<T>);

type Network = {
type NetworkURL = {
url: string;
};

type NetworkURLParts = {
host: string;
port: number | string;
port?: number | string;
protocol?: string;
from?: number | string;
gas?: number | string;
gasPrice?: number | string;
provider?: string | (() => any);
} & NetworkId<string | number>;
path?: string;
};

type NetworkConnection = NetworkURL | NetworkURLParts;

type Network = NetworkConnection &
NetworkId<string | number> & {
from?: number | string;
gas?: number | string;
gasPrice?: number | string;
provider?: string | (() => any);
};

interface ArtifactDefaults {
from?: number | string;
Expand All @@ -44,8 +53,6 @@ interface ArtifactDefaults {
}

type Provider = string | ((any) => any);
// TODO: remove after managing compiler info in project.json
type CompilersInfo = any;

const NetworkConfig = {
name: 'NetworkConfig',
Expand All @@ -62,10 +69,9 @@ const NetworkConfig = {
getConfig(root: string = process.cwd()): ConfigInterface {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const zosConfigFile = require(`${root}/networks.js`);
const compilers = zosConfigFile.compilers || this.getDefaultCompilersProperties();
const buildDir = `${root}/build/contracts`;

return { ...zosConfigFile, compilers, buildDir };
return { ...zosConfigFile, buildDir };
},

getBuildDir(): string {
Expand Down Expand Up @@ -94,18 +100,25 @@ const NetworkConfig = {
},

getProvider(network: Network): Provider {
let { provider } = network;

if (!provider) {
const { host, port, protocol } = network;
if (!host) throw Error('A host name must be specified');
if (!port) throw Error('A port must be specified');
provider = `${protocol ? protocol : 'http'}://${host}:${port}`;
} else if (typeof provider === 'function') {
provider = provider();
if (!network.provider) {
return this.getURL(network);
} else if (typeof network.provider === 'function') {
return network.provider();
} else {
return network.provider;
}
},

return provider;
getURL(network: Network): string {
const networkUrl = (network as NetworkURL).url;
if (networkUrl) return networkUrl;

const { host, port, protocol, path } = network as NetworkURLParts;
if (!host) throw Error('A host name is required for the network connection');
let url = `${protocol ?? 'http'}://${host}`;
if (port) url += `:${port}`;
if (path) url += `/${path}`;
return url;
},

getArtifactDefaults(zosConfigFile: ConfigInterface, network: Network): ArtifactDefaults {
Expand All @@ -116,20 +129,6 @@ const NetworkConfig = {
return { ...configDefaults, ...networkDefaults };
},

getDefaultCompilersProperties(): CompilersInfo {
return {
vyper: {},
solc: {
settings: {
optimizer: {
enabled: false,
runs: 200,
},
},
},
};
},

createContractsDir(root: string): void {
const contractsDir = `${root}/contracts`;
this.createDir(contractsDir);
Expand Down
194 changes: 96 additions & 98 deletions packages/cli/test/config/NetworkConfig.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,123 +21,121 @@ describe('NetworkConfig', function() {

afterEach('cleanup files and folders', cleanupfn(tmpDir));

describe('methods', function() {
describe('#initialize', function() {
it('creates an empty contracts folder if missing', function() {
NetworkConfig.initialize(tmpDir);

fs.existsSync(contractsDir).should.be.true;
fs.readdirSync(contractsDir, 'utf8').should.have.lengthOf(1);
fs.readdirSync(contractsDir, 'utf8').should.include('.gitkeep');
});
describe('#initialize', function() {
it('creates an empty contracts folder if missing', function() {
NetworkConfig.initialize(tmpDir);

it('does not create an empty contracts folder if present', function() {
fs.mkdirSync(contractsDir, { recursive: true });
fs.writeFileSync(`${contractsDir}/Sample.sol`, '');
NetworkConfig.initialize(tmpDir);
fs.existsSync(contractsDir).should.be.true;
fs.readdirSync(contractsDir, 'utf8').should.have.lengthOf(1);
fs.readdirSync(contractsDir, 'utf8').should.include('.gitkeep');
});

fs.existsSync(contractsDir).should.be.true;
fs.readdirSync(contractsDir, 'utf8').should.have.lengthOf(1);
fs.readdirSync(contractsDir, 'utf8').should.include('Sample.sol');
});
it('does not create an empty contracts folder if present', function() {
fs.mkdirSync(contractsDir, { recursive: true });
fs.writeFileSync(`${contractsDir}/Sample.sol`, '');
NetworkConfig.initialize(tmpDir);

it('creates a networks.js file if missing', function() {
NetworkConfig.initialize(tmpDir);
fs.existsSync(contractsDir).should.be.true;
fs.readdirSync(contractsDir, 'utf8').should.have.lengthOf(1);
fs.readdirSync(contractsDir, 'utf8').should.include('Sample.sol');
});

fs.existsSync(networkConfigPath).should.be.true;
});
it('creates a networks.js file if missing', function() {
NetworkConfig.initialize(tmpDir);

it('does not create a networks.js file if present', function() {
fs.writeFileSync(networkConfigFile, '');
NetworkConfig.initialize(tmpDir);
fs.existsSync(networkConfigPath).should.be.true;
});

fs.readFileSync(networkConfigPath, 'utf8').should.have.lengthOf(0);
});
it('does not create a networks.js file if present', function() {
fs.writeFileSync(networkConfigFile, '');
NetworkConfig.initialize(tmpDir);

fs.readFileSync(networkConfigPath, 'utf8').should.have.lengthOf(0);
});
});

describe('#exists', function() {
context('when the networks.js file does not exist', function() {
it('returns false', function() {
NetworkConfig.exists(tmpDir).should.eq(false);
});
});
describe('#exists', function() {
it('returns false when the networks.js file does not exist', function() {
NetworkConfig.exists(tmpDir).should.eq(false);
});

it('returns true when the networks.js file exists', function() {
NetworkConfig.initialize(tmpDir);
NetworkConfig.exists(tmpDir).should.eq(true);
});
});

describe('#getConfig', function() {
it('setups the config', function() {
NetworkConfig.initialize(tmpDir);
const config = NetworkConfig.getConfig(networkConfigDir);

config.should.have.all.keys('networks', 'buildDir');
config.should.not.have.key('network');
config.buildDir.should.eq(path.resolve(process.cwd(), tmpDir, 'build/contracts'));
});
});

describe('#loadNetworkConfig', function() {
afterEach('stubs config', function() {
sinon.restore();
});

context('when the networks.js file exists', function() {
it('returns true', function() {
NetworkConfig.initialize(tmpDir);
NetworkConfig.exists(tmpDir).should.eq(true);
});
it('throws an error when provided network does not exist', function() {
NetworkConfig.initialize(tmpDir);
(() => NetworkConfig.loadNetworkConfig('non-existent', networkConfigDir)).should.throw(
/is not defined in your networks.js file/,
);
});

it('setups the current selected network config', function() {
NetworkConfig.initialize(tmpDir);
const config = NetworkConfig.getConfig(networkConfigDir);
const networkConfig = NetworkConfig.loadNetworkConfig('development', networkConfigDir);

networkConfig.provider.should.eq('http://localhost:8545');
networkConfig.artifactDefaults.should.include({
gas: 5000000,
gasPrice: 5000000000,
});
networkConfig.should.deep.include(config);
});

describe('#getConfig', function() {
it('setups the config', function() {
NetworkConfig.initialize(tmpDir);
const config = NetworkConfig.getConfig(networkConfigDir);
it('setups a provider from a function', function() {
const provider = () => 'returned provider';
sinon.stub(NetworkConfig, 'getConfig').returns({
networks: { local: { provider, host: 'localhost', port: '1324' } },
});
NetworkConfig.initialize(tmpDir);
const networkConfig = NetworkConfig.loadNetworkConfig('local', networkConfigDir);
networkConfig.provider.should.eq('returned provider');
});

config.should.have.all.keys('networks', 'compilers', 'buildDir');
config.should.not.have.key('network');
config.buildDir.should.eq(path.resolve(process.cwd(), tmpDir, 'build/contracts'));
it('setups a provider from URL parts', function() {
sinon.stub(NetworkConfig, 'getConfig').returns({
networks: { local: { protocol: 'wss', host: 'localhost', port: '1324', path: 'foo' } },
});
NetworkConfig.initialize(tmpDir);
const networkConfig = NetworkConfig.loadNetworkConfig('local', networkConfigDir);
networkConfig.provider.should.eq('wss://localhost:1324/foo');
});

describe('#loadNetworkConfig', function() {
context('when provided network does not exist', function() {
it('throws an error', function() {
NetworkConfig.initialize(tmpDir);
(() => NetworkConfig.loadNetworkConfig('non-existent', networkConfigDir)).should.throw(
/is not defined in your networks.js file/,
);
});
it('setups a provider from just URL host', function() {
sinon.stub(NetworkConfig, 'getConfig').returns({
networks: { local: { host: 'localhost' } },
});
NetworkConfig.initialize(tmpDir);
const networkConfig = NetworkConfig.loadNetworkConfig('local', networkConfigDir);
networkConfig.provider.should.eq('http://localhost');
});

context('when the network exists', function() {
it('setups the current selected network config', function() {
NetworkConfig.initialize(tmpDir);
const config = NetworkConfig.getConfig(networkConfigDir);
const networkConfig = NetworkConfig.loadNetworkConfig('development', networkConfigDir);

networkConfig.provider.should.eq('http://localhost:8545');
networkConfig.artifactDefaults.should.include({
gas: 5000000,
gasPrice: 5000000000,
});
networkConfig.should.deep.include(config);
});

context('when specifying a diferent provider', function() {
afterEach('stubs config', function() {
sinon.restore();
});

context('when specifying a function as provider', function() {
it('calls the function', function() {
const provider = () => 'returned provider';
sinon.stub(NetworkConfig, 'getConfig').returns({
networks: {
local: { provider, host: 'localhost', port: '1324' },
},
});
NetworkConfig.initialize(tmpDir);
const networkConfig = NetworkConfig.loadNetworkConfig('local', networkConfigDir);
networkConfig.provider.should.eq('returned provider');
});
});

context('when specifying a different protocol', function() {
it('setups a different provider', function() {
sinon.stub(NetworkConfig, 'getConfig').returns({
networks: {
local: { protocol: 'wss', host: 'localhost', port: '1324' },
},
});
NetworkConfig.initialize(tmpDir);
const networkConfig = NetworkConfig.loadNetworkConfig('local', networkConfigDir);
networkConfig.provider.should.eq('wss://localhost:1324');
});
});
});
it('setups a provider from plain URL', function() {
sinon.stub(NetworkConfig, 'getConfig').returns({
networks: { local: { url: 'wss://localhost:1324/foo' } },
});
NetworkConfig.initialize(tmpDir);
const networkConfig = NetworkConfig.loadNetworkConfig('local', networkConfigDir);
networkConfig.provider.should.eq('wss://localhost:1324/foo');
});
});
});