UNPKG

@buildship/hardhat-ipfs-upload

Version:
167 lines 7.64 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const child_process_1 = require("child_process"); const config_1 = require("hardhat/config"); const minimist_1 = __importDefault(require("minimist")); const nft_storage_1 = require("nft.storage"); const NFT_STORAGE_API_KEY = process.env.NFT_STORAGE_API_KEY; const argv = minimist_1.default(process.argv.slice(2)); // Uploads a compiled contract to IPFS and returns its hash config_1.task("upload", "Uploads a compiled contract to IPFS and returns deploy link") .addPositionalParam("contract", "Contract to deploy") .addOptionalParam("args", "Deploy arguments") .addOptionalParam("ascii", "ASCII art file path (.txt)") .setAction(async (taskArgs, hre) => { try { if (!NFT_STORAGE_API_KEY) { console.error("Please put NFT_STORAGE_API_KEY in .env"); process.exit(-1); } const client = new nft_storage_1.NFTStorage({ token: NFT_STORAGE_API_KEY }); await hre.run("compile"); // console.log('process.argv', process.argv) const { contract, args, ascii } = taskArgs; console.log("Using contract", contract); if (!contract) { console.log(`Usage: npx hardhat upload [contract name] --args '"arg1","arg2"'`); return; } if (!fs_1.default.existsSync(contract)) { console.error(`Contract ${contract} not found`); return; } // const factory = await hre.ethers.getContractFactory(contractName); // extract filename from contract const filename = contract.split("/").pop().replace(".sol", ""); if (!filename) { console.log(`File has no name`); return; } // read dir ./artifacts/${contract} and open the {filename}.json file const contractArtifact = JSON.parse(fs_1.default .readFileSync(`./artifacts/${contract}/${filename}.json`) .toString()); let solcInput, solcLongVersion; try { const artifactDbg = `./artifacts/${contract}/${filename}.dbg.json`; const { buildInfo } = JSON.parse(fs_1.default.readFileSync(artifactDbg).toString()); const buildInfoPath = path_1.default.join(`./artifacts/${contract}`, buildInfo); const info = fs_1.default.readFileSync(buildInfoPath).toString(); const { solcLongVersion: version, input } = JSON.parse(info); solcInput = input; solcLongVersion = version; console.log(`Build info: ${buildInfoPath}`); } catch (err) { console.log(`Build info not found:\n`, err.message); return; } const { abi, bytecode, ...artifact } = contractArtifact; // if process.argv elements contain "help" if (argv._.find((elem) => elem.includes("help"))) { console.log(`Usage: npx hardhat upload [contract name] --args '"arg1","arg2"'`); return; } let flattened; try { // try flattening contract const sourcePath = contract; // create dir ./tmp if (!fs_1.default.existsSync("./tmp")) { fs_1.default.mkdirSync("./tmp"); } // await run("flatten", [ sourcePath, "./tmp/Flattened.sol" ]); // const sh = `npx truffle-flattener ${sourcePath} | awk '/SPDX-License-Identifier/&&c++>0 {next} 1' | awk '/pragma experimental ABIEncoderV2;/&&c++>0 {next} 1' > ./tmp/Flattened.sol`; const sh = `npx hardhat flatten "${sourcePath}" > ./tmp/Flattened.sol`; // run the flattener console.log("\nRunning command:", sh); await new Promise((resolve, reject) => { child_process_1.exec(sh, (err, stdout, stderr) => { if (err || stderr) { console.log("Error flattening contract:", err); return reject(err); } // pipe stdout and stderr to console // tslint:disable-next-line stdout && console.log(`\nOutput: ${stdout.split("\n").join("\n\t")}`); // tslint:disable-next-line stderr && console.log(`\nErrors: ${stderr.split("\n").join("\n\t")}`); resolve(true); }); }); flattened = fs_1.default.readFileSync("./tmp/Flattened.sol", "utf8"); if (!flattened) { throw new Error("No flattened contract"); } // from https://github.com/boringcrypto/dictator-dao/blob/a3de9f606d05852eb5cfa811a3f38870ab22800a/hardhat.config.js#L60 // Remove every line started with "// SPDX-License-Identifier:" flattened = flattened.replace(/SPDX-License-Identifier:/gm, "License-Identifier:"); flattened = `// SPDX-License-Identifier: MIXED\n\n${flattened}`; // Remove every line started with "pragma experimental ABIEncoderV2;" except the first one flattened = flattened.replace(/pragma experimental ABIEncoderV2;\n/gm, ((i) => (m) => (!i++ ? m : ""))(0)); flattened = flattened.trim(); if (ascii) { // read file from ascii and paste in front of flattened const art = fs_1.default.readFileSync(ascii, "utf8"); flattened = `${art}\n\n${flattened}`; } // write it back fs_1.default.writeFileSync("./tmp/Flattened.sol", flattened); } catch (err) { // process exit with error message console.error(`\nError:`, err); return; } finally { // rm flattened file // tslint:disable-next-line !process.env.KEEP && fs_1.default.unlinkSync("./tmp/Flattened.sol"); // fs.rmdirSync("./tmp"); } console.log(`\nDeploying ${contract}`); // const longVersion = await getLongVersion( // hre.config.solidity.compilers[0].version // ); // const longVersionString = longVersion.replace(/^v/, ""); const contractInfo = { name: contractArtifact.contractName, filename, abi, bytecode, artifact, extra: { metadata: JSON.stringify({ ...hre.config.solidity.compilers[0], compiler: { ...hre.config.solidity.compilers[0], version: solcLongVersion, }, }), }, input: solcInput, flattened, }; const blob = new nft_storage_1.Blob([JSON.stringify(contractInfo)], { type: "application/json", }); const cid = await client.storeBlob(blob); console.log(`Metadata uploaded to https://cloudflare-ipfs.com/ipfs/${cid}\n`); console.log(`Deploy here:`); const argsString = args ? `?args=%5B${encodeURIComponent(args)}%5D` : "?args=%5B%5D"; console.log(`https://gate-goerli.buildship.xyz/deploy/${cid}${argsString}`); } catch (err) { console.error(err); } }); //# sourceMappingURL=upload.js.map