@rsksmart/rsk-cli
Version:
CLI tool for Rootstock network using Viem
193 lines (192 loc) • 6.97 kB
JavaScript
import chalk from "chalk";
import fs from "fs";
import ora from "ora";
import { getConfig } from "./config.js";
function logMessage(params, message, color = chalk.white) {
if (!params.isExternal) {
console.log(color(message));
}
}
function logError(params, message) {
logMessage(params, `❌ ${message}`, chalk.red);
}
function logSuccess(params, message) {
logMessage(params, message, chalk.green);
}
function logInfo(params, message) {
logMessage(params, message, chalk.blue);
}
function startSpinner(params, spinner, message) {
if (!params.isExternal) {
if (message) {
spinner.start(message);
}
else {
spinner.start();
}
}
}
function stopSpinner(params, spinner) {
if (!params.isExternal) {
spinner.stop();
}
}
function succeedSpinner(params, spinner, message) {
if (!params.isExternal) {
spinner.succeed(message);
}
}
function failSpinner(params, spinner, message) {
if (!params.isExternal) {
spinner.fail(message);
}
}
export async function verifyCommand(params) {
const config = getConfig();
const isTestnet = params.testnet ?? (config.defaultNetwork === 'testnet');
logInfo(params, `🔧 Initializing verification on ${isTestnet ? "testnet" : "mainnet"}...`);
const baseUrl = isTestnet
? "https://be.explorer.testnet.rootstock.io"
: "https://be.explorer.rootstock.io";
const response = await fetch(`${baseUrl}/api/v3/addresses/verification/${params.address.toLowerCase()}`);
const resData = await response.json();
if (resData.data !== null) {
const explorerUrl = isTestnet
? `https://explorer.testnet.rootstock.io/address/${params.address}`
: `https://explorer.rootstock.io/address/${params.address}`;
logSuccess(params, `✅ Contract ${params.address} is already verified.`);
return {
success: true,
data: {
contractAddress: params.address,
contractName: params.name,
network: isTestnet ? "Rootstock Testnet" : "Rootstock Mainnet",
explorerUrl: explorerUrl,
verified: true,
alreadyVerified: true,
},
};
}
let parsedJson;
if (params.isExternal) {
try {
parsedJson = JSON.parse(params.jsonPath);
}
catch (error) {
return {
error: "Error parsing JSON Standard Input content",
success: false,
};
}
}
else {
logInfo(params, `📄 Reading JSON Standard Input from ${params.jsonPath}...`);
try {
const json = fs.readFileSync(params.jsonPath, "utf8");
parsedJson = JSON.parse(json);
}
catch (error) {
const errorMessage = "Please check your JSON Standard Input file and try again.";
logError(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
}
logInfo(params, `🔎 Verifying contract ${params.name} deployed at ${params.address}...`);
const spinner = params.isExternal ? ora({ isEnabled: false }) : ora();
startSpinner(params, spinner);
try {
if (!parsedJson.hasOwnProperty("solcLongVersion") ||
!parsedJson.hasOwnProperty("input")) {
const errorMessage = "Please check your JSON Standard Input file and try again.";
failSpinner(params, spinner, errorMessage);
return {
error: errorMessage,
success: false,
};
}
const solidityVersion = parsedJson.solcLongVersion.split('+')[0];
const { sources, settings } = parsedJson.input;
const transformedSettings = {
optimizer: settings.optimizer || { enabled: false, runs: 200 },
evmVersion: settings.evmVersion || 'london',
};
parsedJson.sources = sources;
parsedJson.settings = settings;
const verificationData = {
address: params.address.toLowerCase(),
name: params.name,
version: solidityVersion,
sources: JSON.stringify(sources),
settings: transformedSettings,
};
if (params.args && params.args.length > 0) {
stopSpinner(params, spinner);
logInfo(params, `📄 Using constructor arguments: ${params.args.join(", ")}`);
startSpinner(params, spinner);
verificationData.constructorArguments = params.args;
}
const formData = new FormData();
formData.append('data', JSON.stringify(verificationData));
const jsonBlob = new Blob([JSON.stringify(parsedJson)], { type: 'application/json' });
formData.append('file', jsonBlob, 'standard-input.json');
let response;
try {
response = await fetch(`${baseUrl}/api/v3/verifications/verify`, {
method: "POST",
body: formData,
});
}
catch (fetchError) {
const errorMessage = "Network error during contract verification";
failSpinner(params, spinner, errorMessage);
return {
error: errorMessage,
success: false,
};
}
if (!response.ok) {
const errorMessage = "Error during contract verification";
failSpinner(params, spinner, errorMessage);
return {
error: errorMessage,
success: false,
};
}
const resData = await response.json();
if (!resData.success) {
const errorMessage = resData.message || "Contract verification failed";
failSpinner(params, spinner, errorMessage);
return {
error: errorMessage,
success: false,
};
}
const explorerUrl = isTestnet
? `https://explorer.testnet.rootstock.io/address/${params.address}`
: `https://explorer.rootstock.io/address/${params.address}`;
succeedSpinner(params, spinner, "📜 Contract verified successfully!");
logInfo(params, `🔗 View on Explorer: ${explorerUrl}`);
return {
success: true,
data: {
contractAddress: params.address,
contractName: params.name,
network: isTestnet ? "Rootstock Testnet" : "Rootstock Mainnet",
explorerUrl: explorerUrl,
verified: true,
verificationData: resData.data,
},
};
}
catch (error) {
const errorMessage = "Error during contract verification";
failSpinner(params, spinner, errorMessage);
return {
error: errorMessage,
success: false,
};
}
}