UNPKG

@rsksmart/rsk-cli

Version:

CLI tool for Rootstock network using Viem

104 lines (103 loc) 4.1 kB
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;