@rsksmart/rsk-cli
Version:
CLI tool for Rootstock network using Viem
171 lines (170 loc) • 6.42 kB
JavaScript
import chalk from "chalk";
import fs from "fs";
import { walletFilePath } from "../utils/constants.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 logWarning(params, message) {
logMessage(params, message, chalk.yellow);
}
export async function historyCommand(params) {
try {
// Check if API key exists in storage or passed as argument
let apiKeyFromStorage = getApiKeyFromStorage();
let finalApiKey = params.apiKey || apiKeyFromStorage;
if (!params.isExternal && params.apiKey && !apiKeyFromStorage) {
await writeApiKey(params.apiKey);
}
if (!finalApiKey) {
const errorMessage = "🔑 Add the Alchemy API key as a parameter in the command. Provide it once, and it will be securely saved for future use.";
logError(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
let walletsData;
if (params.isExternal && params.walletsData) {
walletsData = params.walletsData;
}
else {
if (!fs.existsSync(walletFilePath)) {
const errorMessage = "No saved wallet found. Please create a wallet first.";
logError(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
walletsData = JSON.parse(fs.readFileSync(walletFilePath, "utf8"));
}
if (!walletsData.currentWallet || !walletsData.wallets) {
const errorMessage = "⚠️ No valid wallet found. Please create or import a wallet first.";
logError(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
const { currentWallet, wallets } = walletsData;
const wallet = wallets[currentWallet];
const { address: walletAddress } = wallet;
logInfo(params, `🔍 Fetching transaction history on Rootstock ${params.testnet ? "Testnet" : "Mainnet"} for ${walletAddress}...`);
const data = JSON.stringify({
jsonrpc: "2.0",
id: 0,
method: "alchemy_getAssetTransfers",
params: [
{
fromBlock: "0x0",
fromAddress: walletAddress,
category: ["external", "erc20", "erc721", "erc1155"],
withMetadata: true,
},
],
});
const testnetUrl = `https://rootstock-testnet.g.alchemy.com/v2/${finalApiKey}`;
const mainnetUrl = `https://rootstock-mainnet.g.alchemy.com/v2/${finalApiKey}`;
const baseURL = params.testnet ? testnetUrl : mainnetUrl;
const response = await fetch(baseURL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: data,
});
if (!response.ok) {
const errorMessage = `API request failed with status: ${response.status}`;
logError(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
const result = await response.json();
// Handle Alchemy-specific errors
if (result.error) {
const errorMessage = `Error from Alchemy: ${result.error.message}`;
logError(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
let transfers = result.result?.transfers;
if (!transfers || transfers.length === 0) {
const errorMessage = "⚠️ No transactions found.";
logWarning(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
const totalTransfers = transfers.length;
if (params.number) {
transfers = transfers.slice(0, parseInt(params.number));
}
if (!params.isExternal) {
for (const transfer of transfers) {
logSuccess(params, "✅ Transfer:");
logInfo(params, ` From: ${transfer.from}`);
logInfo(params, ` To: ${transfer.to}`);
logInfo(params, ` Token: ${transfer.asset || "N/A"}`);
logInfo(params, ` Value: ${transfer.value || "N/A"}`);
logInfo(params, ` Tx Hash: ${transfer.hash}`);
logInfo(params, ` Time: ${new Date(transfer.metadata.blockTimestamp)}`);
}
}
return {
success: true,
data: {
walletAddress,
network: params.testnet ? "Rootstock Testnet" : "Rootstock Mainnet",
transfers,
totalTransfers,
},
};
}
catch (error) {
const errorMessage = `An unknown error occurred: ${error.message || error}`;
logError(params, errorMessage);
return {
error: errorMessage,
success: false,
};
}
}
async function writeApiKey(apiKey) {
try {
// Read the existing wallet file
const walletsData = JSON.parse(fs.readFileSync(walletFilePath, "utf8"));
// Add or update the alchemyApiKey
walletsData.alchemyApiKey = apiKey;
// Write the updated JSON back to the file
fs.writeFileSync(walletFilePath, JSON.stringify(walletsData, null, 2));
}
catch (error) {
throw new Error(`Error updating Alchemy API key: ${error.message || error}`);
}
}
function getApiKeyFromStorage() {
try {
if (fs.existsSync(walletFilePath)) {
const configData = JSON.parse(fs.readFileSync(walletFilePath, "utf8"));
return configData.alchemyApiKey;
}
return undefined;
}
catch (error) {
throw new Error(`Error reading alchemy API key: ${error.message || error}`);
}
}