Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
Support compilation of deep build dependency sources
Browse files Browse the repository at this point in the history
  • Loading branch information
njgheorghita committed Mar 11, 2020
1 parent d12e48d commit 1f650ad
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 100 deletions.
4 changes: 2 additions & 2 deletions packages/config/src/configDefaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export const getInitialConfig = ({
ipfsHost: "ipfs.infura.io",
ipfsProtocol: "https",
ipfsPort: "5001",
registry: "erc1319://0x5a5FE036d2557Ef4C85341fe4f9848e38173eFBa:3"
registryUri: "erc1319://0x5a5FE036d2557Ef4C85341fe4f9848e38173eFBa:3"
},
ens: {
enabled: true,
enabled: false, // update to true?
registryAddress: null
},
compilers: {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/lib/commands/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ const command = {
description: "Install a package from the Ethereum Package Registry",
builder: {},
help: {
usage: "truffle install <ethpm_uri>",
usage: "truffle install <ethpmUri>",
options: [
{
option: "package_name",
option: "ethpmUri",
description: "ethPM URI for the target package to install. (required)"
}
]
Expand Down
148 changes: 76 additions & 72 deletions packages/core/lib/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { isAddress } = require("web3-utils");
const path = require("path");
const fs = require("fs");
const ENSJS = require("ethereum-ens");
const TruffleContractSchema = require("@truffle/contract-schema");
//const TruffleContractSchema = require("@truffle/contract-schema");

SUPPORTED_CHAIN_IDS = {
1: "mainnet",
Expand All @@ -34,6 +34,7 @@ const Package = {
expect.options(options, [
"ethpm", // default ethpm settings
"ethpmUri", // target uri to install
"ens",
"logger",
"working_directory",
"contracts_build_directory"
Expand Down Expand Up @@ -91,7 +92,7 @@ const Package = {
);
}
try {
const ensjs = new ENSJS(provider, options.ens.registry.address);
const ensjs = new ENSJS(provider, options.ens.registryAddress);
ethpmUri.address = await ensjs.resolver(ethpmUri.address).addr();
} catch (err) {
done(new TruffleError(`Unable to resolve uri: ${err.message}`));
Expand Down Expand Up @@ -223,11 +224,11 @@ const Package = {
// contract-schema doesn't define devdoc/userdoc but artifacts have it - can we include?
};
// seems like abi validation is too strict / outdated?
try {
await TruffleContractSchema.validate(validContractSchema);
} catch (err) {
done(new TruffleError(`ethPM package import error: ${err.message}`));
}
//try {
//await TruffleContractSchema.validate(validContractSchema);
//} catch (err) {
//done(new TruffleError(`ethPM package import error: ${err.message}`));
//}
await artifactor.save(validContractSchema);
}
options.logger.log("Saved artifacts.");
Expand All @@ -249,32 +250,31 @@ const Package = {
"ipfsHost",
"ipfsPort",
"ipfsProtocol",
"registry",
"registryUri",
"infuraKey"
]);
} catch (err) {
done(new TruffleError(err.message));
}

const registryURI = new EthpmURI(options.ethpm.registry);
const registryProviderURI = getInfuraEndpointForChainId(
registryURI.chainId,
const registryUri = new EthpmURI(options.ethpm.registryUri);
const registryProviderUri = getInfuraEndpointForChainId(
registryUri.chainId,
options.ethpm.infuraKey
);
registryProvider = new Web3.providers.HttpProvider(registryProviderURI, {
registryProvider = new Web3.providers.HttpProvider(registryProviderUri, {
keepAlive: true
});

options.logger.log("Gathering contracts..."); // incorrect place
let ethpm;
try {
ethpm = await EthPM.configure({
manifests: "ethpm/manifests/v2",
storage: "ethpm/storage/ipfs",
registries: "ethpm/registries/web3"
}).connect({
provider: registryProvider, // bad hardcoded provider
registryAddress: registryURI.address,
provider: registryProvider,
registryAddress: registryUri.address,
ipfs: {
host: options.ethpm.ipfsHost,
port: options.ethpm.ipfsPort,
Expand Down Expand Up @@ -332,71 +332,47 @@ const Package = {
const targetConfig = Object.assign(ethpmFields, ethpmConfig);
const pkg = await ethpm.manifests.read(JSON.stringify(targetConfig));
const manifest = await ethpm.manifests.write(pkg);
const manifestURI = await ethpm.storage.write(manifest);
const manifestUri = await ethpm.storage.write(manifest);

options.logger.log(`Publishing package to ${options.ethpm.registry}`);
options.logger.log(`Publishing package to registry...`);
try {
const w3 = new Web3(options.provider);
const encoded = ethpm.registries.registry.methods
const encodedTxData = ethpm.registries.registry.methods
.release(
ethpmConfig.package_name,
ethpmConfig.version,
manifestURI.href
manifestUri.href
)
.encodeABI();
const tx = await w3.eth.signTransaction({
from: options.provider.addresses[0],
to: registryURI.address,
to: registryUri.address,
gas: 4712388,
gasPrice: 100000000000,
data: encoded
data: encodedTxData
});
await w3.eth.sendSignedTransaction(tx.raw);
} catch (err) {
done(new TruffleError(`Error publishing package: ${err}`));
done(
new TruffleError(
`Error publishing package: ${err}.\nDoes ${
ethpmConfig.package_name
}@${ethpmConfig.version} already exist on registry: ${
registryUri.raw
}?`
)
);
}
done(
options.logger.log(
`Published ${ethpmConfig.package_name}@${ethpmConfig.version} to ${
options.ethpm.registry
}` // add link to explorer?
registryUri.raw
}`
)
);
//return JSON.parse(manifest); // remove this
}
};

function validateSupportedChainId(chainId) {
if (!(chainId in SUPPORTED_CHAIN_IDS)) {
throw new TruffleError(
`Detected chain ID: ${chainId} is not a supported chain id. Supported values include ${Object.keys(
SUPPORTED_CHAIN_IDS
)}`
);
}
}

function getInfuraEndpointForChainId(chainId, infuraKey) {
validateSupportedChainId(chainId);
return `https://${SUPPORTED_CHAIN_IDS[chainId]}.infura.io/v3/${infuraKey}`;
}

async function convertNetworkIdToBlockchainUri(networkId, infuraKey) {
// mock value for ganache dev chains
if (networkId > 100) {
return "blockchain://329ff0a289d0ffba148c495b9cffd078d2f5a272538616b1b412c75f268134a4/block/46ef23590d0c99840621ac95b503ed569f79c65be452acd50478bfe721205ce1";
}
validateSupportedChainId(networkId); // chain id vs network id
const infuraUri = getInfuraEndpointForChainId(networkId, infuraKey);
const w3 = new Web3(new Web3.providers.HttpProvider(infuraUri));
const genesisBlock = await w3.eth.getBlock(0);
const latestBlock = await w3.eth.getBlock("latest");
return `blockchain://${genesisBlock.hash.replace(
"0x",
""
)}/block/${latestBlock.hash.replace("0x", "")}`;
}

// Returns a list of publishable artifacts
// aka contract_types and deployments found in all artifacts
async function getPublishableArtifacts(options, ethpm) {
Expand Down Expand Up @@ -466,23 +442,23 @@ async function getPublishableArtifacts(options, ethpm) {
};
}

// handles sources installed via ethpm
async function resolveSources(sourcePaths, contractsDirectory, ethpm) {
const sources = {};
// TODO! how do we include installed pkgs in the publishing process?
// just add as build dependencies? probably
// flatten and include in pkg? probably not
for (let sourcePath of Object.keys(sourcePaths)) {
if (sourcePath !== "undefined") {
const ipfsHash = await ethpm.storage.write(sourcePaths[sourcePath]);
// resolve all sources (including ethpm) to absolute contracts dir
const absolute = path.resolve(contractsDirectory, sourcePath);
// resolve all sources to relative path
const resolved = path.relative(contractsDirectory, absolute);
sources[`./${resolved}`] = ipfsHash.href;
}
//
// Utils
//

function validateSupportedChainId(chainId) {
if (!(chainId in SUPPORTED_CHAIN_IDS)) {
throw new TruffleError(
`Detected chain ID: ${chainId} is not a supported chain id. Supported values include ${Object.keys(
SUPPORTED_CHAIN_IDS
)}`
);
}
return sources;
}

function getInfuraEndpointForChainId(chainId, infuraKey) {
validateSupportedChainId(chainId);
return `https://${SUPPORTED_CHAIN_IDS[chainId]}.infura.io/v3/${infuraKey}`;
}

function fetchInstalledBuildDependencies(workingDirectory) {
Expand All @@ -504,4 +480,32 @@ function fetchInstalledBuildDependencies(workingDirectory) {
return installedBuildDependencies;
}

async function convertNetworkIdToBlockchainUri(networkId, infuraKey) {
validateSupportedChainId(networkId);
const infuraUri = getInfuraEndpointForChainId(networkId, infuraKey);
const w3 = new Web3(new Web3.providers.HttpProvider(infuraUri));
const genesisBlock = await w3.eth.getBlock(0);
const latestBlock = await w3.eth.getBlock("latest");
return `blockchain://${genesisBlock.hash.replace(
"0x",
""
)}/block/${latestBlock.hash.replace("0x", "")}`;
}

// handles sources installed via ethpm
async function resolveSources(sourcePaths, contractsDirectory, ethpm) {
const sources = {};
for (let sourcePath of Object.keys(sourcePaths)) {
if (sourcePath !== "undefined") {
const ipfsHash = await ethpm.storage.write(sourcePaths[sourcePath]);
// resolve all sources (including ethpm) to absolute contracts dir
const absolute = path.resolve(contractsDirectory, sourcePath);
// resolve all sources to relative path
const resolved = path.relative(contractsDirectory, absolute);
sources[`./${resolved}`] = ipfsHash.href;
}
}
return sources;
}

module.exports = Package;
1 change: 0 additions & 1 deletion packages/core/test/ethpm.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const Migrate = require("@truffle/migrate");

const INSTALL_PROVIDER_URI =
"https://mainnet.infura.io/v3/7707850c2fb7465ebe6f150d67182e22";
//const INFURA_KEY = "b2679bb624354d1b9a2586154651b51f";
const INFURA_KEY = "7707850c2fb7465ebe6f150d67182e22";

describe("EthPM install", function() {
Expand Down
40 changes: 17 additions & 23 deletions packages/resolver/epm.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
var path = require("path");
var fs = require("fs");
var glob = require("glob");

function EPM(working_directory, contracts_build_directory) {
this.working_directory = working_directory;
this.contracts_build_directory = contracts_build_directory;
this.allEthpmFiles = glob.sync("**/*", {
cwd: path.join(this.working_directory, "_ethpm_packages")
});
}

EPM.prototype.require = function(import_path, _search_path) {
Expand Down Expand Up @@ -70,19 +74,12 @@ EPM.prototype.require = function(import_path, _search_path) {
var internal_path = import_path.substring(separator + 1);
var installDir = this.working_directory;

// can find build_deps one level deep
let parent_separator;
let parent_name;

if (imported_from !== null) {
parent_separator = imported_from.indexOf("/");
parent_name = imported_from.substring(0, parent_separator);
}

// If nothing's found, body returns `undefined`
var body;
var matches = this.allEthpmFiles.filter(p => p.includes(import_path));

while (true) {
// check for root level ethpm sources
var file_path = path.join(
installDir,
"_ethpm_packages",
Expand All @@ -96,20 +93,17 @@ EPM.prototype.require = function(import_path, _search_path) {
break;
} catch (err) {}

if (parent_name !== undefined) {
file_path = path.join(
installDir,
"_ethpm_packages",
parent_name,
"_ethpm_packages",
package_name,
"_src",
import_path
);
try {
body = fs.readFileSync(file_path, { encoding: "utf8" });
break;
} catch (err) {}
// DOES NOT SUPPORT DUPLICATE IMPORT PATHS W/IN AGGREGATED PKGS
if (matches.length > 0) {
if (matches.length === 1) {
try {
body = fs.readFileSync(
path.join(installDir, "_ethpm_packages", matches[0]),
{ encoding: "utf8" }
);
break;
} catch (err) {}
}
}

// Recurse outwards until impossible
Expand Down

0 comments on commit 1f650ad

Please sign in to comment.