/** * @synor/hardhat-plugin * * Hardhat plugin for Synor blockchain development. * Provides seamless integration between Hardhat and Synor network. */ import { extendConfig, extendEnvironment, task } from "hardhat/config"; import { HardhatConfig, HardhatUserConfig, HardhatRuntimeEnvironment } from "hardhat/types"; import { SynorProvider } from "./provider"; import { SynorDeployer } from "./deployer"; import { SynorNetwork } from "./network"; import "./type-extensions"; // Default Synor network configurations const SYNOR_NETWORKS = { mainnet: { url: "https://rpc.synor.cc", chainId: 1337, accounts: [], }, testnet: { url: "https://testnet-rpc.synor.cc", chainId: 1338, accounts: [], }, devnet: { url: "http://localhost:8545", chainId: 1339, accounts: [], }, }; // Extend Hardhat config with Synor options extendConfig((config: HardhatConfig, userConfig: Readonly) => { // Add Synor-specific configuration config.synor = { defaultNetwork: userConfig.synor?.defaultNetwork ?? "devnet", gasPrice: userConfig.synor?.gasPrice ?? "auto", gasLimit: userConfig.synor?.gasLimit ?? 3000000, confirmations: userConfig.synor?.confirmations ?? 1, timeout: userConfig.synor?.timeout ?? 60000, verifyContracts: userConfig.synor?.verifyContracts ?? true, quantumSafe: userConfig.synor?.quantumSafe ?? true, }; // Add Synor networks if not already defined for (const [name, network] of Object.entries(SYNOR_NETWORKS)) { const networkName = `synor-${name}`; if (!config.networks[networkName]) { config.networks[networkName] = { ...network, ...(userConfig.networks?.[networkName] ?? {}), }; } } }); // Extend Hardhat runtime environment extendEnvironment((hre: HardhatRuntimeEnvironment) => { // Add Synor provider hre.synor = { provider: new SynorProvider(hre), deployer: new SynorDeployer(hre), network: new SynorNetwork(hre), getBalance: async (address: string) => { return hre.synor.provider.getBalance(address); }, getBlockNumber: async () => { return hre.synor.provider.getBlockNumber(); }, sendTransaction: async (tx: any) => { return hre.synor.provider.sendTransaction(tx); }, }; }); // Task: Deploy contract to Synor task("synor:deploy", "Deploy a contract to Synor network") .addParam("contract", "Contract name to deploy") .addOptionalVariadicPositionalParam("args", "Constructor arguments") .setAction(async (taskArgs, hre) => { const { contract, args = [] } = taskArgs; console.log(`Deploying ${contract} to Synor ${hre.network.name}...`); const deployed = await hre.synor.deployer.deploy(contract, args); console.log(`Contract deployed at: ${deployed.address}`); console.log(`Transaction hash: ${deployed.deployTransaction.hash}`); if (hre.config.synor.verifyContracts) { console.log("Verifying contract..."); await hre.synor.network.verifyContract(deployed.address, args); console.log("Contract verified!"); } return deployed; }); // Task: Verify contract on Synor explorer task("synor:verify", "Verify a contract on Synor explorer") .addParam("address", "Contract address") .addParam("contract", "Contract name") .addOptionalVariadicPositionalParam("args", "Constructor arguments") .setAction(async (taskArgs, hre) => { const { address, contract, args = [] } = taskArgs; console.log(`Verifying ${contract} at ${address}...`); await hre.synor.network.verifyContract(address, args, contract); console.log("Contract verified!"); }); // Task: Get network info task("synor:info", "Get Synor network information") .setAction(async (_, hre) => { const info = await hre.synor.network.getNetworkInfo(); console.log("\nSynor Network Information:"); console.log("=========================="); console.log(`Network: ${info.name}`); console.log(`Chain ID: ${info.chainId}`); console.log(`Block Height: ${info.blockHeight}`); console.log(`Latest Block Hash: ${info.latestBlockHash}`); console.log(`Gas Price: ${info.gasPrice} gwei`); console.log(`Protocol Version: ${info.protocolVersion}`); console.log(`Consensus: ${info.consensus}`); console.log(`Quantum Safe: ${info.quantumSafe}`); }); // Task: Fund account from faucet (testnet/devnet only) task("synor:faucet", "Request tokens from Synor faucet") .addParam("address", "Address to fund") .addOptionalParam("amount", "Amount to request (in SYN)", "10") .setAction(async (taskArgs, hre) => { const { address, amount } = taskArgs; if (hre.network.name.includes("mainnet")) { throw new Error("Faucet not available on mainnet"); } console.log(`Requesting ${amount} SYN for ${address}...`); const txHash = await hre.synor.network.requestFaucet(address, amount); console.log(`Faucet transaction: ${txHash}`); }); // Task: Compile contracts for Synor (WASM target) task("synor:compile", "Compile contracts for Synor WASM runtime") .setAction(async (_, hre) => { console.log("Compiling contracts for Synor..."); // First run standard compilation await hre.run("compile"); // Then generate WASM artifacts await hre.synor.deployer.compileToWasm(); console.log("Compilation complete!"); }); // Task: Run tests on Synor fork task("synor:test", "Run tests against Synor network fork") .addOptionalParam("fork", "Block number to fork from", "latest") .setAction(async (taskArgs, hre) => { const { fork } = taskArgs; console.log(`Forking Synor at block ${fork}...`); // Set up fork await hre.synor.network.fork(fork); // Run tests await hre.run("test"); }); // Task: Generate TypeScript types for contracts task("synor:typechain", "Generate TypeScript types for Synor contracts") .setAction(async (_, hre) => { console.log("Generating TypeScript types..."); await hre.synor.deployer.generateTypes(); console.log("Types generated in typechain-types/"); }); // Export types and utilities export { SynorProvider } from "./provider"; export { SynorDeployer } from "./deployer"; export { SynorNetwork } from "./network"; export * from "./types";