@newos/upgradeability-transpiler
Version:
Transpiles Solidity contracts to updgradable versions compatible with NewOs.
103 lines • 5.11 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const lodash_1 = require("lodash");
const ast_utils_1 = require("./solc/ast-utils");
const transpiler_1 = require("./transpiler");
const index_1 = require("./transformations/index");
const get_inheritance_chain_1 = require("./solc/get-inheritance-chain");
function transpileContracts(contracts, artifacts, contractsFolder) {
contractsFolder = path_1.default.normalize(contractsFolder);
// check that we have valid ast tree
for (const art of artifacts) {
ast_utils_1.throwIfInvalidNode(art.ast);
}
// create contract name | id to artifact map for quick access to artifacts
const contractsToArtifactsMap = artifacts.reduce((acc, art) => {
acc[art.contractName] = art;
const contract = ast_utils_1.getContract(art);
acc[contract.id] = art;
return acc;
}, {});
// build a list of all contracts to transpile
const contractsToTranspile = [
...new Set(lodash_1.flatten(contracts.map(contract => get_inheritance_chain_1.getInheritanceChain(contract, contractsToArtifactsMap)))),
].filter(art => {
const contractNode = ast_utils_1.getContract(art);
return ast_utils_1.isContract(contractNode);
});
// build a array of transformations per Solidity file
const fileTrans = contractsToTranspile.reduce((acc, art) => {
const contractName = art.contractName;
const source = art.source;
const contractNode = ast_utils_1.getContract(art);
if (!acc[art.sourcePath]) {
const directive = `\nimport "@newos/upgrades/contracts/Initializable.sol";`;
acc[art.sourcePath] = {
transformations: [
index_1.appendDirective(art.ast, directive),
...index_1.fixImportDirectives(art, artifacts, contractsToTranspile),
...index_1.purgeExceptContracts(art.ast, contractsToTranspile),
],
source: '',
};
}
acc[art.sourcePath].transformations = [
...acc[art.sourcePath].transformations,
index_1.prependBaseClass(contractNode, source, 'Initializable'),
...index_1.transformParentsNames(contractNode, source, contractsToTranspile),
...index_1.transformConstructor(contractNode, source, contractsToTranspile, contractsToArtifactsMap),
...index_1.purgeVarInits(contractNode, source),
index_1.transformContractName(contractNode, source, `${contractName}Upgradeable`),
];
return acc;
}, {});
// build a final array of files to return
return contractsToTranspile.reduce((acc, art) => {
const contractName = art.contractName;
const source = art.source;
const fileTran = fileTrans[art.sourcePath];
if (!fileTran.source) {
fileTran.source = transpiler_1.transpile(source, fileTran.transformations);
}
const entry = acc.find(o => o.fileName === path_1.default.basename(art.sourcePath));
if (!entry) {
const upgradeablePath = path_1.default.normalize(art.sourcePath).replace('.sol', 'Upgradeable.sol');
let patchedFilePath = upgradeablePath;
// Truffle stores an absolute file path in a sourcePath of an artifact field
// "sourcePath": "/Users/iYalovoy/repo/openzeppelin-sdk/tests/cli/workdir/contracts/Samples.sol"
// OpenZeppelin stores relative paths
// "sourcePath": "contracts/Foo.sol"
// OpenZeppelin sourcePath would start with `contracts` for contracts present in the `contracts` folder of a project
// Both Truffle and OpenZeppelin support packages
// "sourcePath": "@newos/upgrades/contracts/Initializable.sol",
// Relative paths can only be specified using `.` and `..` for both compilers
// if path exists then it is a local contract build by Truffle
if (fs_extra_1.default.existsSync(art.sourcePath)) {
patchedFilePath = upgradeablePath.replace(contractsFolder, '');
}
else {
if (upgradeablePath.startsWith('contracts')) {
patchedFilePath = upgradeablePath.replace('contracts/', '');
}
}
patchedFilePath = `./contracts/__upgradeable__/${patchedFilePath}`;
acc.push({
source: fileTran.source,
path: patchedFilePath,
fileName: path_1.default.basename(art.sourcePath),
contracts: [contractName],
});
}
else {
entry.contracts.push(contractName);
}
return acc;
}, []);
}
exports.transpileContracts = transpileContracts;
//# sourceMappingURL=index.js.map