Solidity: How to compile multiple smart contracts in compile.js file? - javascript

I would like to compile multiple contracts in one compile.js file but I'm not sure how to do it.
My compile.js file with a single contract looks like this:
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const lotteryPath = path.resolve(__dirname, 'contracts', 'Lottery.sol');
const source = fs.readFileSync(lotteryPath, 'utf8');
module.exports = solc.compile(source, 1);
How can I add more contracts to the compile.js file? I understand that the 1 must be changed to the number of contracts, but not sure what else is required?

Here is an example I did. You can find it in my public repo. Briefly, I have a "build" folder where I write the output of each compiled contract to Json files.
const path = require("path"); //nodejs ’path’ module
const solc = require("solc"); //solidity compiler module
const fs = require("fs-extra"); //file system module
// Feth path of build
const buildPath = path.resolve(__dirname, "build");
const contractspath = path.resolve(__dirname, "contracts");
// Removes folder build and every file in it
fs.removeSync(buildPath);
// Fetch all Contract files in Contracts folder
const fileNames = fs.readdirSync(contractspath);
// Gets ABI of all contracts into variable input
const input = fileNames.reduce(
(input, fileName) => {
const filePath = path.resolve(__dirname, "contracts", fileName);
const source = fs.readFileSync(filePath, "utf8");
return { sources: { ...input.sources, [fileName]: source } };
},
{ sources: {} }
);
// Compile all contracts
const output = solc.compile(input, 1).contracts;
// Re-Create build folder for output files from each contract
fs.ensureDirSync(buildPath);
// Output contains all objects from all contracts
// Write the contents of each to different files
for (let contract in output) {
fs.outputJsonSync(
path.resolve(buildPath, contract.split(":")[1] + ".json"),
output[contract]
);
}
Basically, if you do not change your path struct to mine, you have to change you this part of the above code:
// Feth path of build
const buildPath = path.resolve(__dirname, "build");
const contractspath = path.resolve(__dirname, "contracts");

The approved solution does not work for solidity >0.6.0 and <=0.8.1.
For the mentioned versions, I solved it as follows:
const path = require("path");
const fs = require("fs-extra");
const solc = require("solc");
const buildPath = path.resolve(__dirname, "build");
fs.removeSync(buildPath);
const contractPath = path.resolve(__dirname, "contracts");
const fileNames = fs.readdirSync(contractPath);
const compilerInput = {
language: "Solidity",
sources: fileNames.reduce((input, fileName) => {
const filePath = path.resolve(contractPath, fileName);
const source = fs.readFileSync(filePath, "utf8");
return { ...input, [fileName]: { content: source } };
}, {}),
settings: {
outputSelection: {
"*": {
"*": ["abi", "evm.bytecode.object"],
},
},
},
};
// Compile All contracts
const compiled = JSON.parse(solc.compile(JSON.stringify(compilerInput)));
fs.ensureDirSync(buildPath);
fileNames.map((fileName) => {
const contracts = Object.keys(compiled.contracts[fileName]);
contracts.map((contract) => {
fs.outputJsonSync(
path.resolve(buildPath, contract + ".json"),
compiled.contracts[fileName][contract]
);
});
});
be sure to check that your pragma solidity x.x.x matches with the version specified in your package.json. For example, if I'm using solidity 0.6.12 my solidity compiles would be:
"dependencies": {
...
"solc": "^0.6.12",
...
}

compile.js:
const path= require('path');
const solc = require('solc');
const fs = require('fs-extra');
const builtPath = path.resolve(__dirname, 'build');
//remove file in build module
fs.removeSync(builtPath);
const healthPath = path.resolve(__dirname, 'contract','health.sol');
//read content present in file
console.log(healthPath);
const source = fs.readFileSync(healthPath,'utf8');
//compile contract
const output = solc.compile(source,1).contracts;
//create build folder
fs.ensureDirSync(builtPath);
console.log(output);
for(let contract in output)
{
fs.outputJsonSync(
path.resolve(buildPath, contract.replace(':','')+ '.json'),
output[contract]
);
}

Related

Webpack configuration problem with module.exports entry

I'm trying to configurate webpack but I stuck because of this error. I think the problem is with entry. But when i try to add it without path: like in tutorial i get "(property) path: path.PlatformPath" ',' expected
const webpack = require('webpack')
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const IS_DEVELOPMENT = process.env.NODE_ENV === 'dev'
const dirApp = path.join(__dirname, 'app')
const dirAssets = path.join(__dirname, 'assets')
const dirStyles = path.join(__dirname, 'styles')
const dirNode = 'node_modules'
module.exports = {
entry: {
path: path.join(dirApp, 'index.js'),
path: path.join(dirStyles, 'index.scss'),
},
resolve: {
modules: {
dirApp,
dirAssets,
dirStyles,
dirNode
}
}
}
I get this error
[webpack-cli] Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.resolve.modules should be an array:
object { alias?, aliasFields?, byDependency?, cache?, cachePredicate?, cacheWithContext?, conditionNames?, descriptionFiles?, enforceExtension?, exportsFields?, extensionAlias?, extensions?,
fallback?, fileSystem?, fullySpecified?, importsFields?, mainFields?, mainFiles?, modules?, plugins?, preferAbsolute?, preferRelative?, resolver?, restrictions?, roots?, symlinks?, unsafeCache?, useSyncFileSystemCalls? }
-> Folder names or directory paths where to find modules.
Your resolve.modules is Object, but should be Array. Check here for docs.

How to import a namespaced css from node_modules in the entries of a rewired create-react-app? Is react-app-rewire-multiple-entry the way to go?

I have a create-react-app not ejected and rewired with react-app-rewired and customized with customize-cra.
This is the scenario and I currently can't change it.
Here it is the configuration of config-overrides.js:
const path = require('path')
const fs = require('fs')
const {
override,
overrideDevServer,
watchAll,
removeModuleScopePlugin,
addWebpackModuleRule
} = require('customize-cra')
const theme = process.env.REACT_APP_THEME
const currentDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(currentDirectory, relativePath)
module.exports = {
webpack: override(
removeModuleScopePlugin(),
addWebpackModuleRule({
test: /\.svg$/,
loader: 'raw-loader',
include: [
resolveApp('../source/' + theme + '/icons/dist')
]
})
),
devServer: overrideDevServer(
watchAll()
),
paths: paths => {
paths.appBuild = path.join(paths.appBuild, theme)
return paths
}
}
A new need now is to import in the app some css from a local package, setup in package.json with a local namespace
"dependencies": {
"#namespace/helpers": "*",
I thought to use react-app-rewire-multiple-entry that seems the perfect lib to import multiple entries for a rewired create-react-app
Here is the new update:
const path = require('path')
const fs = require('fs')
const {
override,
overrideDevServer,
watchAll,
removeModuleScopePlugin,
addWebpackModuleRule
} = require('customize-cra')
const theme = process.env.REACT_APP_THEME
const currentDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(currentDirectory, relativePath)
// new css entries configuration
const cssEntries = require('react-app-rewire-multiple-entry')([
{
entry: './src/index.tsx',
helpers_1: '../node_modules/#namespace/helpers/dist/index.css',
helpers_2: '#namespace/helpers/dist/index.css'
}
])
module.exports = {
webpack: override(
cssEntries.addMultiEntry, // new css entries
removeModuleScopePlugin(),
addWebpackModuleRule({
test: /\.svg$/,
loader: 'raw-loader',
include: [
resolveApp('../source/' + theme + '/icons/dist')
]
})
),
devServer: overrideDevServer(
watchAll()
),
paths: paths => {
paths.appBuild = path.join(paths.appBuild, theme)
return paths
}
}
But both approaches currently implemented (first helpers_1: '../node_modules/#namespace/helpers/dist/index.css', and then helpers_2: '#namespace/helpers/dist/index.css') are not loading the css in the create-react-app.
Any ideas to fix it?
Or something wrong that you see?
Thanks in advance

How to unzip file with Node.js

I need to zip and unzip file with Node.js but I have a problem.
const fs = require("fs");
const zlib = require('zlib');
function UnZip(zip, paths) {
var inp = fs.createReadStream("f:/test.zip");
var Exzip = zlib.createUnzip();
inp.pipe(Exzip).pipe("f:/");
}
Error:
TypeError: dest.on is not a function
Here is how you can do it with zlib module.
const fs = require('fs');
const zlib = require('zlib');
const fileContents = fs.createReadStream('file1.txt.gz');
const writeStream = fs.createWriteStream('file1.txt');
const unzip = zlib.createGunzip();
fileContents.pipe(unzip).pipe(writeStream);
Zipping the file
const archiver = require('archiver'),
archive = archiver('zip'),
fs = require('fs'),
output = fs.createWriteStream( 'mocks.zip');
archive.pipe(output);
// temp.txt file must be available in your folder where you
// are writting the code or you can give the whole path
const file_buffer = fs.readFileSync('temp.txt')
archive.append(file_buffer, { name: 'tttt.txt'});
archive.finalize().then((err, bytes) => {
if (err) {
throw err;
}
console.log(err + bytes + ' total bytes');
});
unzipping a file
const unzip = require('unzip'),
fs = require('fs');
fs.createReadStream('temp1.zip').pipe(unzip.Extract({ path: 'path' }))

Webpack require.context does not work with Path.resolve

webpack.config.js
"use strict";
const Path = require("path");
const resolvePath = (...paths) => Path.resolve(__dirname, ...paths);
module.exports = {
entry: {
data: "./src/data/index.ts" // resolvePath("src", "data", "index.ts") does not work
}
/** more **/
}
index.ts
const req = require.context("./yaml", true, /\.ya?ml$/i);
req.keys().forEach((key: any) => req(key));
Using "./src/data/index.ts" or resolvePath("src", "data", "index.ts") compile the code. But only "./src/data/index.ts" includes the YAML files. YAML files are located at ./src/data/yaml.
How does Path.resolve affect require.context? If I want to use Path.resolve, how should I write the correct require.context?

How to run(sync) multiple .js files from a directory

I'm trying to run multiple .js files from a directory:
exampleDir/test.js
console.log('hi');
run.js
const fs = require('fs');
const {execFileSync} = require('child_process');
const testsFolder = './exampleDir/';
const files = fs.readdirSync(testsFolder);
const funcs = files.map(function(file) {
const out = execFileSync(`node ${testsFolder}${file}`);
console.log(out.toString());
});
however I get:
> example#1.0.0 test /home/perdugames/example
> node ./run.js
child_process.js:624
throw err;
^
Error: spawnSync node ./exampleDir/test.js ENOENT
...
File paths should be specified unambiguously, preferably independent of current working directory and relative to current module. To create a new Node process, there are spawn and spawnSync in child_process:
...
const path = require('path');
const testsFolder = path.join(__dirname, './exampleDir/');
const files = fs.readdirSync(testsFolder);
const funcs = files.map(function(file) {
const filePath = path.join(testsFolder, file);
const out = spawnSync(filePath);
console.log(out.stdout.toString());
});

Categories