@rsksmart/rsk-cli
Version:
CLI tool for Rootstock network using Viem
104 lines (103 loc) • 4.1 kB
JavaScript
import { createPublicClient, createWalletClient, http, } from "viem";
import { rootstock, rootstockTestnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import fs from "fs";
import crypto from "crypto";
import inquirer from "inquirer";
import chalk from "chalk";
import { walletFilePath } from "./constants.js";
class ViemProvider {
chain;
constructor(testnet) {
this.chain = testnet ? rootstockTestnet : rootstock;
}
async getPublicClient() {
return createPublicClient({
chain: this.chain,
transport: http(),
});
}
async getWalletClient(name) {
const { account } = await this.decryptPrivateKey(name ? name : undefined);
return createWalletClient({
chain: this.chain,
transport: http(),
account: account,
});
}
async decryptPrivateKey(name) {
if (!fs.existsSync(walletFilePath)) {
throw new Error("No wallets found. Please create or import a wallet first.");
}
const walletsData = JSON.parse(fs.readFileSync(walletFilePath, "utf8"));
if (!walletsData.currentWallet || !walletsData.wallets) {
console.log(chalk.red("⚠️ No valid wallet found. Please create or import a wallet first."));
throw new Error();
}
const { currentWallet, wallets } = walletsData;
let wallet = wallets[currentWallet];
if (name) {
if (!wallets[name]) {
console.log(chalk.red("⚠️ Wallet with the provided name does not exist."));
throw new Error();
}
else {
wallet = wallets[name];
}
}
const passwordQuestion = [
{
type: "password",
name: "password",
message: "Enter your password to decrypt the wallet:",
mask: "*",
},
];
const { password } = await inquirer.prompt(passwordQuestion);
const { encryptedPrivateKey, iv } = wallet;
try {
const decipherIv = Uint8Array.from(Buffer.from(iv, "hex"));
const key = crypto.scryptSync(password, decipherIv, 32);
const decipher = crypto.createDecipheriv("aes-256-cbc", Uint8Array.from(key), decipherIv);
let decryptedPrivateKey = decipher.update(encryptedPrivateKey, "hex", "utf8");
decryptedPrivateKey += decipher.final("utf8");
const prefixedPrivateKey = `0x${decryptedPrivateKey.replace(/^0x/, "")}`;
const account = privateKeyToAccount(prefixedPrivateKey);
return { account };
}
catch (error) {
throw new Error("Failed to decrypt the private key. Please check your password and try again.");
}
}
async getWalletClientExternal(walletsData, walletName, password, provider) {
if (!walletsData ||
!walletsData.wallets ||
!walletsData.wallets[walletName]) {
return null;
}
const wallet = walletsData.wallets[walletName];
const { encryptedPrivateKey, iv } = wallet;
let decryptedPrivateKey;
try {
if (!password) {
return null;
}
const decipherIv = Uint8Array.from(Buffer.from(iv, "hex"));
const key = crypto.scryptSync(password, decipherIv, 32);
const decipher = crypto.createDecipheriv("aes-256-cbc", Uint8Array.from(key), decipherIv);
decryptedPrivateKey = decipher.update(encryptedPrivateKey, "hex", "utf8");
decryptedPrivateKey += decipher.final("utf8");
}
catch (error) {
return null;
}
const prefixedPrivateKey = `0x${decryptedPrivateKey.replace(/^0x/, "")}`;
const account = privateKeyToAccount(prefixedPrivateKey);
return createWalletClient({
chain: provider.chain,
transport: http(),
account: account,
});
}
}
export default ViemProvider;