hashscan-verify
Version:
Hardhat plugin for verifying smart contracts on HashScan (Hedera's contract verification service)
131 lines • 5.52 kB
JavaScript
import { task } from "hardhat/config";
import "hardhat/types/tasks";
import { NetworkConfig, HEDERA_NETWORKS } from "./config/networks.js";
import { SourcifyService } from "./services/sourcify-service.js";
import { ValidationService } from "./services/validation-service.js";
import { ArtifactResolver } from "./services/artifact-resolver.js";
const hashscanVerifyTask = task("hashscan-verify", "Verify contract on HashScan/Sourcify")
.addPositionalArgument({
name: "address",
description: "Deployed contract address",
})
.addOption({
name: "contract",
description: "Fully qualified contract name (e.g., contracts/Counter.sol:Counter)",
defaultValue: "",
})
.addVariadicArgument({
name: "constructorArgs",
description: "Constructor arguments (if any)",
defaultValue: [],
})
.setAction(async () => ({
default: async (args, hre) => {
var _a, _b, _c;
const { address, contract, constructorArgs = [] } = args;
// Validation
const validator = new ValidationService();
const validationError = validator.validateInput(address, contract);
if (validationError) {
console.error(validationError);
return;
}
const { contractPath, contractName } = validator.parseContract(contract);
// Get network configuration
const connection = await ((_a = hre.network) === null || _a === void 0 ? void 0 : _a.connect());
const chainId = (_b = connection === null || connection === void 0 ? void 0 : connection.networkConfig) === null || _b === void 0 ? void 0 : _b.chainId;
if (!chainId) {
console.error("Error: Could not determine chain ID. Make sure you're using the --network flag.");
return;
}
const networkConfig = NetworkConfig.fromChainId(chainId);
const apiUrl = ((_c = hre.config.sourcify) === null || _c === void 0 ? void 0 : _c.apiUrl) || networkConfig.defaultApiUrl;
// Initialize services
const sourcifyService = new SourcifyService(apiUrl);
const artifactResolver = new ArtifactResolver(hre);
// Check if already verified
const isVerified = await sourcifyService.checkIfVerified(address, chainId.toString());
if (isVerified.status) {
console.log(`Contract is already verified with ${isVerified.status} match.`);
}
else {
console.log(`Verifying ${contractName} at ${address}...`);
try {
// Resolve artifact and build info
const { artifact, buildInfo, sourcePaths } = await artifactResolver.resolve(contractPath, contractName);
// Verify contract
const result = await sourcifyService.verify({
address,
chainId: chainId.toString(),
contractName,
artifact,
buildInfo,
sourcePaths,
});
if (result.status === "perfect") {
console.log("✔ Contract verified successfully (perfect match)");
}
else if (result.status === "partial") {
console.log("✔ Contract verified successfully (partial match)");
}
else {
console.error(`✗ Verification failed: ${result.message}`);
}
}
catch (error) {
console.error(`✗ Verification failed: ${error.message}`);
}
}
const viewUrl = networkConfig.getHashScanUrl(address);
if (viewUrl) {
console.log(`\nView on HashScan: ${viewUrl}`);
}
else {
console.log(`\nChain ID ${chainId} is not a recognized Hedera network.`);
}
},
}));
async function extendUserConfig(config, next) {
var _a, _b;
const nextConfig = await next(config);
const hardhatNetwork = (_a = process.env.HARDHAT_NETWORK) !== null && _a !== void 0 ? _a : "";
const explicitApiUrl = (_b = process.env.HASHSCAN_API_URL) !== null && _b !== void 0 ? _b : process.env.SOURCIFY_API_URL;
const isLocalNetwork = /^(localhost|hedera_local|local)$/i.test(hardhatNetwork);
const computedApiUrl = explicitApiUrl !== null && explicitApiUrl !== void 0 ? explicitApiUrl : (isLocalNetwork ? "http://localhost:8080" : "https://server-verify.hashscan.io");
const sourcifyConfig = {
apiUrl: computedApiUrl,
};
return {
...nextConfig,
sourcify: sourcifyConfig,
};
}
async function resolveUserConfig(userConfig, resolveConfigurationVariable, next) {
var _a;
const resolved = await next(userConfig, resolveConfigurationVariable);
const nets = (_a = resolved.networks) !== null && _a !== void 0 ? _a : {};
// Set chain IDs for Hedera networks if not already set
HEDERA_NETWORKS.forEach((network) => {
network.names.forEach((name) => {
if (nets[name] && nets[name].chainId == null) {
nets[name].chainId = network.chainId;
}
});
});
return resolved;
}
const plugin = {
id: "hashscan-verify",
dependencies: () => [],
hookHandlers: {
config: async () => ({
default: async () => ({
extendUserConfig,
resolveUserConfig,
}),
}),
},
tasks: [hashscanVerifyTask.build()],
};
export default plugin;
//# sourceMappingURL=index.js.map