UNPKG

@kadena/hardhat-chainweb

Version:
435 lines 20.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const construction_1 = require("hardhat/internal/core/providers/construction"); const config_1 = require("hardhat/config"); const chainweb_js_1 = require("./utils/chainweb.js"); const configure_js_1 = require("./utils/configure.js"); const chainweb_graph_js_1 = require("./utils/chainweb-graph.js"); const hardhat_ethers_provider_js_1 = require("@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider.js"); const web3_1 = __importDefault(require("web3")); const runRPCNode_js_1 = require("./server/runRPCNode.js"); const network_contracts_js_1 = require("./utils/network-contracts.js"); const picocolors_1 = __importDefault(require("picocolors")); const pure_utils_js_1 = require("./pure-utils.js"); const minimist_1 = __importDefault(require("minimist")); (0, config_1.extendConfig)((config, userConfig) => { var _a, _b, _c, _d; if (!userConfig.chainweb) { throw new Error('hardhat_kadena plugins is imported but chainweb configuration is not presented in hardhat.config.js'); } if (Object.keys(userConfig.chainweb).length === 0) { throw new Error('You need to provide at least one chainweb configuration in hardhat.config.js'); } const argv = (0, minimist_1.default)(process.argv.slice(2)); config.defaultChainweb = (_c = (_b = (_a = argv['chainweb']) !== null && _a !== void 0 ? _a : process.env['HK_ACTIVE_CHAINWEB_NAME']) !== null && _b !== void 0 ? _b : userConfig.defaultChainweb) !== null && _c !== void 0 ? _c : 'hardhat'; const defaultChainwebChainIdOffset = 0; const hardhatConfig = { chains: 2, chainwebChainIdOffset: defaultChainwebChainIdOffset, ...userConfig.chainweb.hardhat, type: 'in-process', }; const localhostConfig = { chains: hardhatConfig.chains, chainIdOffset: (_d = hardhatConfig.chainIdOffset) !== null && _d !== void 0 ? _d : 626000, externalHostUrl: 'http://localhost:8545', chainwebChainIdOffset: hardhatConfig.chainwebChainIdOffset, ...userConfig.chainweb['localhost'], type: 'external', }; const userConfigWithLocalhost = { ...userConfig.chainweb, hardhat: hardhatConfig, localhost: localhostConfig, }; if (!(config.defaultChainweb in userConfigWithLocalhost)) { throw new Error(`Default chainweb ${config.defaultChainweb} not found in hardhat.config.js`); } Object.entries(userConfigWithLocalhost).forEach(([name, chainwebUserConfig]) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; if (chainwebUserConfig === undefined) return; if (!chainwebUserConfig.chains) { throw new Error('Number of chains is not presented in hardhat.config.js'); } let type = (_a = chainwebUserConfig.type) !== null && _a !== void 0 ? _a : 'in-process'; if (name === 'hardhat') { type = 'in-process'; } if (name === 'localhost') { type = 'external'; } const isDefaultChainweb = name === config.defaultChainweb; if (type === 'in-process') { const chainwebInProcessUserConfig = chainwebUserConfig; if (chainwebInProcessUserConfig.graph) { const graph = (_b = chainwebInProcessUserConfig.graph) !== null && _b !== void 0 ? _b : {}; if (chainwebInProcessUserConfig.chains && Object.keys(graph).length != chainwebInProcessUserConfig.chains) { throw new Error('Number of chains in graph does not match the graph configuration'); } } const offset = (_c = chainwebInProcessUserConfig.chainwebChainIdOffset) !== null && _c !== void 0 ? _c : 0; const graphWithOffset = (0, chainweb_graph_js_1.createGraph)(chainwebInProcessUserConfig.chains).reduce((acc, targets, source) => ({ ...acc, [source + offset]: targets.map((target) => target + offset), }), {}); // add networks to hardhat const chainwebConfig = { graph: (_d = chainwebInProcessUserConfig.graph) !== null && _d !== void 0 ? _d : graphWithOffset, logging: 'info', type: 'in-process', chainIdOffset: 626000, accounts: config.networks.hardhat.accounts, precompiles: { chainwebChainId: network_contracts_js_1.CHAIN_ID_ADDRESS, spvVerify: network_contracts_js_1.VERIFY_ADDRESS, }, chainwebChainIdOffset: defaultChainwebChainIdOffset, ...chainwebInProcessUserConfig, }; const [networkConfig, etherscanCustomChains, etherscanApiKeys] = (0, configure_js_1.getKadenaNetworks)({ availableNetworks: userConfig.networks, hardhatNetwork: config.networks.hardhat, networkStem: (0, pure_utils_js_1.getNetworkStem)(name), numberOfChains: chainwebConfig.chains, accounts: (_e = chainwebConfig.accounts) !== null && _e !== void 0 ? _e : (_f = chainwebConfig.networkOptions) === null || _f === void 0 ? void 0 : _f.accounts, loggingEnabled: chainwebConfig.logging === 'debug', forking: ((_h = (_g = chainwebConfig.networkOptions) === null || _g === void 0 ? void 0 : _g.forking) === null || _h === void 0 ? void 0 : _h.url) ? { enabled: true, ...chainwebConfig.networkOptions.forking } : undefined, networkOptions: chainwebConfig.networkOptions, chainIdOffset: chainwebConfig.chainIdOffset, chainwebChainIdOffset: chainwebConfig.chainwebChainIdOffset, etherscan: isDefaultChainweb ? chainwebConfig.etherscan : undefined, }); config.networks = { ...config.networks, ...networkConfig, }; if (isDefaultChainweb && chainwebConfig.etherscan) { config.etherscan = { apiKey: etherscanApiKeys, customChains: etherscanCustomChains, enabled: true, }; } config.chainweb[name] = chainwebConfig; } else { const externalUserConfig = chainwebUserConfig; const chainwebConfig = { type: 'external', chainIdOffset: 626000, externalHostUrl: 'http://localhost:8545', accounts: 'remote', chainwebChainIdOffset: defaultChainwebChainIdOffset, ...externalUserConfig, precompiles: { chainwebChainId: (_k = (_j = externalUserConfig.precompiles) === null || _j === void 0 ? void 0 : _j.chainwebChainId) !== null && _k !== void 0 ? _k : network_contracts_js_1.CHAIN_ID_ADDRESS, spvVerify: (_m = (_l = externalUserConfig.precompiles) === null || _l === void 0 ? void 0 : _l.spvVerify) !== null && _m !== void 0 ? _m : network_contracts_js_1.VERIFY_ADDRESS, }, }; const [networkConfig, etherscanCustomChains, etherscanApiKeys] = (0, configure_js_1.getKadenaExternalNetworks)({ availableNetworks: userConfig.networks, networkStem: (0, pure_utils_js_1.getNetworkStem)(name), numberOfChains: chainwebConfig.chains, accounts: chainwebConfig.accounts, baseUrl: chainwebConfig.externalHostUrl, networkOptions: chainwebConfig.networkOptions, chainIdOffset: chainwebConfig.chainIdOffset, chainwebChainIdOffset: chainwebConfig.chainwebChainIdOffset, etherscan: isDefaultChainweb ? chainwebConfig.etherscan : undefined, }); // add networks to hardhat config.networks = { ...config.networks, ...networkConfig, }; config.chainweb[name] = chainwebConfig; if (isDefaultChainweb && chainwebConfig.etherscan) { config.etherscan = { apiKey: etherscanApiKeys, customChains: etherscanCustomChains, enabled: true, }; } } }); }); const createExternalProvider = async (hre, chainwebName) => { const utils = await Promise.resolve().then(() => __importStar(require('./utils.js'))); const networkStem = (0, pure_utils_js_1.getNetworkStem)(chainwebName); return { deployContractOnChains: utils.deployContractOnChains, getProvider: (cid) => { const name = `${networkStem}${cid}`; return (0, construction_1.createProvider)(hre.config, name, hre.artifacts); }, requestSpvProof: (targetChain, origin) => utils.requestSpvProof(targetChain, origin), switchChain: async (cid) => { if (typeof cid === 'string') { await hre.switchNetwork(cid); console.log(`Switched to ${cid}`); } else { console.log(`Switched to ${networkStem}${cid}`); await hre.switchNetwork(`${networkStem}${cid}`); } }, getChainIds: utils.getChainIds, callChainIdContract: utils.callChainIdContract, createTamperedProof: (targetChain, origin) => utils.createTamperedProof(targetChain, origin), computeOriginHash: pure_utils_js_1.computeOriginHash, runOverChains: utils.runOverChains, }; }; const createInternalProvider = async (hre, chainwebName, overrideForking) => { const chainweb = hre.config.chainweb[chainwebName]; if (!chainweb || chainweb.type !== 'in-process') { throw new Error('Chainweb configuration not found'); } const utils = await Promise.resolve().then(() => __importStar(require('./utils.js'))); const networkStem = (0, pure_utils_js_1.getNetworkStem)(chainwebName); const chainwebNetwork = new chainweb_js_1.ChainwebNetwork({ chainweb, networks: hre.config.networks, chainwebName: chainwebName, overrideForking, }); async function startHardhatNetwork() { await chainwebNetwork.start(); } let stopped = false; async function stopHardhatNetwork() { if (stopped) return; await chainwebNetwork.stop(); stopped = true; process.exit(0); } let setNetworkReady; const isNetworkReadyPromise = new Promise((resolve) => { setNetworkReady = resolve; }); let started = false; const spinupChainweb = async () => { if (started) return; started = true; process.on('exit', stopHardhatNetwork); process.on('SIGINT', stopHardhatNetwork); process.on('SIGTERM', stopHardhatNetwork); process.on('uncaughtException', stopHardhatNetwork); return startHardhatNetwork() .then(() => { setNetworkReady(); }) .catch(() => { process.exit(1); }); }; const originalSwitchNetwork = hre.switchNetwork; hre.switchNetwork = async (networkNameOrIndex) => { await isNetworkReadyPromise; const networkName = typeof networkNameOrIndex === 'number' ? `${networkStem}${networkNameOrIndex}` : networkNameOrIndex; if (networkName.startsWith(networkStem)) { const cid = parseInt(networkName.slice(networkStem.length)); const provider = chainwebNetwork.getProvider(cid); hre.network.name = networkName; hre.network.config = hre.config.networks[networkName]; hre.network.provider = provider; // update underlying library's provider data if ('ethers' in hre) { hre.ethers.provider = new hardhat_ethers_provider_js_1.HardhatEthersProvider(provider, networkName); } if ('web3' in hre) { hre.web3 = new web3_1.default(provider); } console.log(`Switched to ${cid}`); return; } originalSwitchNetwork(networkName); }; spinupChainweb(); return { deployContractOnChains: utils.deployContractOnChains, getProvider: async (cid) => { await isNetworkReadyPromise; const provider = chainwebNetwork.getProvider(cid); return provider; }, requestSpvProof: (targetChain, origin) => utils.requestSpvProof(targetChain, origin, chainwebNetwork), switchChain: async (cid) => { await isNetworkReadyPromise; if (typeof cid === 'string') { await hre.switchNetwork(cid); } else { await hre.switchNetwork(`${networkStem}${cid}`); } }, getChainIds: utils.getChainIds, callChainIdContract: utils.callChainIdContract, createTamperedProof: (targetChain, origin) => utils.createTamperedProof(targetChain, origin, chainwebNetwork), computeOriginHash: pure_utils_js_1.computeOriginHash, runOverChains: utils.runOverChains, }; }; // const spinupChainweb = () => (0, config_1.extendEnvironment)((hre) => { let api = undefined; let initDone = () => { }; const init = new Promise((resolve) => { initDone = resolve; }); const safeCall = // eslint-disable-next-line @typescript-eslint/no-explicit-any (cb) => async (...args) => { await init; if (api !== undefined) { return cb()(...args); } throw new Error('Chainweb plugin not initialized'); }; hre.chainweb = { initialize: async (args) => { if (api) return; const chainweb = hre.config.chainweb[hre.config.defaultChainweb]; if (!chainweb) { throw new Error('Chainweb configuration not found'); } console.log('Chainweb:', picocolors_1.default.bgGreenBright(` ${hre.config.defaultChainweb} `), 'Chains:', picocolors_1.default.bgGreenBright(` ${chainweb.chains} `), '\n'); if (chainweb.type === 'external') { api = await createExternalProvider(hre, hre.config.defaultChainweb); } else { api = await createInternalProvider(hre, hre.config.defaultChainweb, args === null || args === void 0 ? void 0 : args.forking); } initDone(); }, getProvider: safeCall(() => api.getProvider), requestSpvProof: safeCall(() => api.requestSpvProof), switchChain: safeCall(() => api.switchChain), getChainIds: safeCall(() => api.getChainIds), callChainIdContract: safeCall(() => api.callChainIdContract), deployContractOnChains: safeCall(() => api.deployContractOnChains), createTamperedProof: safeCall(() => api.createTamperedProof), computeOriginHash: pure_utils_js_1.computeOriginHash, runOverChains: safeCall(() => api.runOverChains), }; if (process.env['HK_INIT_CHAINWEB'] === 'true') { hre.chainweb.initialize(); } }); const chainwebSwitch = ['chainweb', 'The name of the chainweb to use']; (0, config_1.task)('node', `Starts a JSON-RPC server on top of Default Chainweb; use ${picocolors_1.default.bgBlackBright(' --network ')} if you want to run a single network rather than a chainweb`) .addOptionalParam(...chainwebSwitch) .setAction(async (taskArgs, hre, runSuper) => { var _a, _b; const hasNetwork = process.argv.includes('--network'); if (taskArgs.chainweb && hasNetwork) { console.error('You can only specify one of chainweb or network, not both'); return; } if (hasNetwork) { return runSuper(taskArgs); } hre.config.defaultChainweb = (_b = (_a = taskArgs.chainweb) !== null && _a !== void 0 ? _a : hre.config.defaultChainweb) !== null && _b !== void 0 ? _b : 'hardhat'; const config = hre.config.chainweb[hre.config.defaultChainweb]; if (!config) { console.log(`Chainweb configuration ${hre.config.defaultChainweb} not found`); return; } if (config.type === 'external') { console.error('You can only start a node for in-process chainweb'); return; } let options = undefined; if (taskArgs.fork) { options = { forking: { url: taskArgs.fork, blockNumber: taskArgs.forkBlockNumber, }, }; } await hre.chainweb.initialize(options); return (0, runRPCNode_js_1.runRPCNode)(taskArgs, hre); }); (0, config_1.task)('test', `Run mocha tests; Supports Chainweb`) .addOptionalParam(...chainwebSwitch) .setAction(async (taskArgs, hre, runSuper) => { var _a, _b; if (!hre.chainweb.initialize) { console.error('Chainweb _initialize is not a function'); return; } hre.config.defaultChainweb = (_b = (_a = taskArgs.chainweb) !== null && _a !== void 0 ? _a : hre.config.defaultChainweb) !== null && _b !== void 0 ? _b : 'hardhat'; hre.chainweb.initialize(); if (!process.argv.includes('--network')) { const [first] = await hre.chainweb.getChainIds(); await hre.chainweb.switchChain(first); } return runSuper(taskArgs); }); (0, config_1.task)('run', `Runs a user-defined script after compiling the project; Supports Chainweb`) .addOptionalParam(...chainwebSwitch) .setAction(async (taskArgs, hre, runSuper) => { var _a, _b; // Since hardhat run the script in a separate process, we need to set the following configurations // as environment variables then Hardhat forward them to the script process process.env['HK_ACTIVE_CHAINWEB_NAME'] = hre.config.defaultChainweb = (_b = (_a = taskArgs.chainweb) !== null && _a !== void 0 ? _a : hre.config.defaultChainweb) !== null && _b !== void 0 ? _b : 'hardhat'; // then we know that the chainweb should run the initialization process.env['HK_INIT_CHAINWEB'] = 'true'; return runSuper(taskArgs); }); (0, config_1.task)('print-config', 'print the final configuration') .addOptionalParam(...chainwebSwitch) .setAction(async (_taskArgs, hre) => { console.dir(hre.config, { depth: null, colors: true }); }); //# sourceMappingURL=plugin.js.map