From ece32932f77eafaccc4968f0d7184af3d079fdc0 Mon Sep 17 00:00:00 2001 From: Pratham Date: Sun, 24 Nov 2024 16:05:12 +0530 Subject: [PATCH 01/32] feat: add external wallet balance option --- bin/index.ts | 6 ++++-- package.json | 1 + src/commands/balance.ts | 40 ++++++++++++++++++++++++---------------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/bin/index.ts b/bin/index.ts index 70f3977..3ce2ae7 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -9,10 +9,11 @@ import chalk from "chalk"; import { deployCommand } from "../src/commands/deploy.js"; import { verifyCommand } from "../src/commands/verify.js"; import { ReadContract } from "../src/commands/contract.js"; +import { Address } from "viem"; interface CommandOptions { testnet?: boolean; - address?: string; + address?: Address; value?: string; txid?: string; abi?: string; @@ -55,8 +56,9 @@ program .command("balance") .description("Check the balance of the saved wallet") .option("-t, --testnet", "Check the balance on the testnet") + .option("-a, --address
", "Check the balance of a specific address") .action(async (options: CommandOptions) => { - await balanceCommand(!!options.testnet); + await balanceCommand(!!options.testnet, options.address); }); program diff --git a/package.json b/package.json index 76a6900..2c196b6 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "build": "tsc", "wallet": "pnpm run build && node dist/bin/index.js wallet", "balance": "pnpm run build && node dist/bin/index.js balance", + "balance-of": "pnpm run build && node dist/bin/index.js balance -t --address 0x02C8345B2DF9Ff6122b0bE7B79cB219d956bd701", "transfer": "pnpm run build && node dist/bin/index.js transfer --testnet --address 0xa5f45f5bddefC810C48aCC1D5CdA5e5a4c6BC59E --value 0.001", "tx-status": "pnpm run build && node dist/bin/index.js tx --testnet --txid 0x876a0a9b167889350c41930a4204e5d9acf5704a7f201447a337094189af961c4" }, diff --git a/src/commands/balance.ts b/src/commands/balance.ts index 1b647fb..3886cdf 100644 --- a/src/commands/balance.ts +++ b/src/commands/balance.ts @@ -2,34 +2,42 @@ import ViemProvider from "../utils/viemProvider.js"; import fs from "fs"; import path from "path"; import chalk from "chalk"; - +import { Address, isAddress } from "viem"; const walletFilePath = path.join(process.cwd(), "rootstock-wallet.json"); -export async function balanceCommand(testnet: boolean) { +export async function balanceCommand(testnet: boolean, address?: Address) { try { - if (!fs.existsSync(walletFilePath)) { - console.log( - chalk.red("🚫 No saved wallet found. Please create a wallet first.") - ); - return; - } + let targetAddress: Address; - const walletData = JSON.parse(fs.readFileSync(walletFilePath, "utf8")); - const { address } = walletData; - - if (!address) { - console.log(chalk.red("⚠️ No valid address found in the saved wallet.")); - return; + if (address) { + if (!isAddress(address)) { + console.log(chalk.red("🚫 Invalid address provided")); + return; + } + targetAddress = address; + } else { + if (!fs.existsSync(walletFilePath)) { + console.log(chalk.red("🚫 No saved wallet found")); + return; + } + const { address: savedAddress } = JSON.parse( + fs.readFileSync(walletFilePath, "utf8") + ); + if (!savedAddress) { + console.log(chalk.red("⚠️ Invalid wallet data")); + return; + } + targetAddress = savedAddress; } const provider = new ViemProvider(testnet); const client = await provider.getPublicClient(); - const balance = await client.getBalance({ address }); + const balance = await client.getBalance({ address: targetAddress }); const rbtcBalance = Number(balance) / 10 ** 18; - console.log(chalk.white(`📄 Wallet Address:`), chalk.green(address)); + console.log(chalk.white(`📄 Wallet Address:`), chalk.green(targetAddress)); console.log( chalk.white(`🌐 Network:`), chalk.green(testnet ? "Rootstock Testnet" : "Rootstock Mainnet") From 2e1b9e7e0f1dea77e72a94dffdcd392594228465 Mon Sep 17 00:00:00 2001 From: Pratham Date: Sun, 24 Nov 2024 16:27:44 +0530 Subject: [PATCH 02/32] feat: revet changes --- bin/index.ts | 6 ++---- package.json | 1 - src/commands/balance.ts | 40 ++++++++++++++++------------------------ 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/bin/index.ts b/bin/index.ts index 3ce2ae7..70f3977 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -9,11 +9,10 @@ import chalk from "chalk"; import { deployCommand } from "../src/commands/deploy.js"; import { verifyCommand } from "../src/commands/verify.js"; import { ReadContract } from "../src/commands/contract.js"; -import { Address } from "viem"; interface CommandOptions { testnet?: boolean; - address?: Address; + address?: string; value?: string; txid?: string; abi?: string; @@ -56,9 +55,8 @@ program .command("balance") .description("Check the balance of the saved wallet") .option("-t, --testnet", "Check the balance on the testnet") - .option("-a, --address
", "Check the balance of a specific address") .action(async (options: CommandOptions) => { - await balanceCommand(!!options.testnet, options.address); + await balanceCommand(!!options.testnet); }); program diff --git a/package.json b/package.json index 2c196b6..76a6900 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "build": "tsc", "wallet": "pnpm run build && node dist/bin/index.js wallet", "balance": "pnpm run build && node dist/bin/index.js balance", - "balance-of": "pnpm run build && node dist/bin/index.js balance -t --address 0x02C8345B2DF9Ff6122b0bE7B79cB219d956bd701", "transfer": "pnpm run build && node dist/bin/index.js transfer --testnet --address 0xa5f45f5bddefC810C48aCC1D5CdA5e5a4c6BC59E --value 0.001", "tx-status": "pnpm run build && node dist/bin/index.js tx --testnet --txid 0x876a0a9b167889350c41930a4204e5d9acf5704a7f201447a337094189af961c4" }, diff --git a/src/commands/balance.ts b/src/commands/balance.ts index 3886cdf..1b647fb 100644 --- a/src/commands/balance.ts +++ b/src/commands/balance.ts @@ -2,42 +2,34 @@ import ViemProvider from "../utils/viemProvider.js"; import fs from "fs"; import path from "path"; import chalk from "chalk"; -import { Address, isAddress } from "viem"; + const walletFilePath = path.join(process.cwd(), "rootstock-wallet.json"); -export async function balanceCommand(testnet: boolean, address?: Address) { +export async function balanceCommand(testnet: boolean) { try { - let targetAddress: Address; - - if (address) { - if (!isAddress(address)) { - console.log(chalk.red("🚫 Invalid address provided")); - return; - } - targetAddress = address; - } else { - if (!fs.existsSync(walletFilePath)) { - console.log(chalk.red("🚫 No saved wallet found")); - return; - } - const { address: savedAddress } = JSON.parse( - fs.readFileSync(walletFilePath, "utf8") + if (!fs.existsSync(walletFilePath)) { + console.log( + chalk.red("🚫 No saved wallet found. Please create a wallet first.") ); - if (!savedAddress) { - console.log(chalk.red("⚠️ Invalid wallet data")); - return; - } - targetAddress = savedAddress; + return; + } + + const walletData = JSON.parse(fs.readFileSync(walletFilePath, "utf8")); + const { address } = walletData; + + if (!address) { + console.log(chalk.red("⚠️ No valid address found in the saved wallet.")); + return; } const provider = new ViemProvider(testnet); const client = await provider.getPublicClient(); - const balance = await client.getBalance({ address: targetAddress }); + const balance = await client.getBalance({ address }); const rbtcBalance = Number(balance) / 10 ** 18; - console.log(chalk.white(`📄 Wallet Address:`), chalk.green(targetAddress)); + console.log(chalk.white(`📄 Wallet Address:`), chalk.green(address)); console.log( chalk.white(`🌐 Network:`), chalk.green(testnet ? "Rootstock Testnet" : "Rootstock Mainnet") From ef6988d5fd93b8eb55c7b2575f446938c4a31420 Mon Sep 17 00:00:00 2001 From: Pratham Date: Sun, 24 Nov 2024 18:29:01 +0530 Subject: [PATCH 03/32] feat: add check token balance --- bin/index.ts | 39 +++++- package.json | 1 + src/commands/token.ts | 263 ++++++++++++++++++++++++++++++++++++++ src/constants/erc20ABI.ts | 40 ++++++ src/utils/index.ts | 26 ++++ src/utils/tokenHelper.ts | 36 ++++++ 6 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 src/commands/token.ts create mode 100644 src/constants/erc20ABI.ts create mode 100644 src/utils/tokenHelper.ts diff --git a/bin/index.ts b/bin/index.ts index 70f3977..d520976 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -9,10 +9,13 @@ import chalk from "chalk"; import { deployCommand } from "../src/commands/deploy.js"; import { verifyCommand } from "../src/commands/verify.js"; import { ReadContract } from "../src/commands/contract.js"; +import { Address } from "viem"; +import { checkTokenBalance, transferToken } from "../src/commands/token.js"; interface CommandOptions { testnet?: boolean; - address?: string; + address?: Address; + contract?: Address; value?: string; txid?: string; abi?: string; @@ -142,4 +145,38 @@ program await ReadContract(options.address! as `0x${string}`, !!options.testnet); }); +const token = program + .command("token") + .description("Interact with ERC20 tokens"); + +token + .command("balance") + .description("Check token balance") + .requiredOption("-c,--contract
", "Token contract address") + .option("-a ,--address
", "Token holder address") + .option("-t, --testnet", "Use testnet") + .action(async (options: CommandOptions) => { + await checkTokenBalance( + !!options.testnet, + options.contract as Address, + options.address + ); + }); + +token + .command("transfer") + .description("Transfer tokens") + .requiredOption("-c,--contract
", "Token contract address") + .requiredOption("-a,--address
", "Recipient address") + .requiredOption("-v,--value ", "Amount to transfer") + .option("-t, --testnet", "Use testnet") + .action(async (options: CommandOptions) => { + await transferToken( + !!options.testnet, + options.contract as Address, + options.address as Address, + options.value! + ); + }); + program.parse(process.argv); diff --git a/package.json b/package.json index 76a6900..cc81816 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "scripts": { "build": "tsc", + "dev": "tsc -w", "wallet": "pnpm run build && node dist/bin/index.js wallet", "balance": "pnpm run build && node dist/bin/index.js balance", "transfer": "pnpm run build && node dist/bin/index.js transfer --testnet --address 0xa5f45f5bddefC810C48aCC1D5CdA5e5a4c6BC59E --value 0.001", diff --git a/src/commands/token.ts b/src/commands/token.ts new file mode 100644 index 0000000..8c9e91d --- /dev/null +++ b/src/commands/token.ts @@ -0,0 +1,263 @@ +import ViemProvider from "../utils/viemProvider.js"; +import chalk from "chalk"; +import fs from "fs"; +import path from "path"; +import { Address, formatUnits } from "viem"; +import { getTokenInfo } from "../utils/tokenHelper.js"; +import { erc20ABI } from "../constants/erc20ABI.js"; +import { isValidContract, validateAndFormatAddress } from "../utils/index.js"; + +const walletFilePath = path.join(process.cwd(), "rootstock-wallet.json"); + +// export async function checkTokenBalance( +// testnet: boolean, +// contractAddress: Address, +// holderAddress: Address +// ) { +// try { +// if (!fs.existsSync(walletFilePath)) { +// console.log( +// chalk.red("🚫 No saved wallet found. Please create a wallet first.") +// ); +// return; +// } + +// const walletData = JSON.parse(fs.readFileSync(walletFilePath, "utf8")); +// const { address: walletAddress } = walletData; + +// if (!walletAddress) { +// console.log(chalk.red("⚠️ No valid address found in the saved wallet.")); +// return; +// } + +// const provider = new ViemProvider(testnet); + +// const publicClient = await provider.getPublicClient(); +// const balance = await publicClient.getBalance({ address: walletAddress }); + +// const rbtcBalance = Number(balance) / 10 ** 18; + +// console.log(chalk.white(`📄 Wallet Address:`), chalk.green(walletAddress)); +// console.log(chalk.white(`🎯 Recipient Address:`), chalk.green(toAddress)); +// console.log( +// chalk.white(`💵 Amount to Transfer:`), +// chalk.green(`${value} RBTC`) +// ); +// console.log( +// chalk.white(`💰 Current Balance:`), +// chalk.green(`${rbtcBalance} RBTC`) +// ); + +// if (rbtcBalance < value) { +// console.log( +// chalk.red(`🚫 Insufficient balance to transfer ${value} RBTC.`) +// ); +// return; +// } + +// const walletClient = await provider.getWalletClient(); + +// const account = walletClient.account; +// if (!account) { +// console.log( +// chalk.red( +// "⚠️ Failed to retrieve the account. Please ensure your wallet is correctly set up." +// ) +// ); +// return; +// } + +// const txHash = await walletClient.sendTransaction({ +// account: account, +// chain: provider.chain, +// to: toAddress, +// value: BigInt(value * 10 ** 18), +// }); + +// console.log( +// chalk.white(`🔄 Transaction initiated. TxHash:`), +// chalk.green(txHash) +// ); +// const spinner = ora("⏳ Waiting for confirmation...").start(); + +// const receipt = await publicClient.waitForTransactionReceipt({ +// hash: txHash, +// }); +// spinner.stop(); + +// if (receipt.status === "success") { +// console.log(chalk.green("✅ Transaction confirmed successfully!")); +// console.log( +// chalk.white(`📦 Block Number:`), +// chalk.green(receipt.blockNumber) +// ); +// console.log( +// chalk.white(`⛽ Gas Used:`), +// chalk.green(receipt.gasUsed.toString()) +// ); + +// const explorerUrl = testnet +// ? `https://explorer.testnet.rootstock.io/tx/${txHash}` +// : `https://explorer.rootstock.io/tx/${txHash}`; +// console.log( +// chalk.white(`🔗 View on Explorer:`), +// chalk.dim(`${explorerUrl}`) +// ); +// } else { +// console.log(chalk.red("❌ Transaction failed.")); +// } +// } catch (error) { +// if (error instanceof Error) { +// console.error( +// chalk.red("🚨 Error during transfer:"), +// chalk.yellow(error.message) +// ); +// } else { +// console.error(chalk.red("🚨 An unknown error occurred.")); +// } +// } +// } + +function getAddress(address?: Address): Address | undefined { + if (address) { + return validateAndFormatAddress(address); + } + + if (!fs.existsSync(walletFilePath)) { + console.log(chalk.red("🚫 No saved wallet found")); + return undefined; + } + + try { + const { address: savedAddress } = JSON.parse( + fs.readFileSync(walletFilePath, "utf8") + ); + return validateAndFormatAddress(savedAddress); + } catch (error) { + console.log(chalk.red("⚠️ Invalid wallet data")); + return undefined; + } +} + +export async function checkTokenBalance( + testnet: boolean, + contractAddress: Address, + holderAddress?: Address +): Promise { + try { + const formattedContractAddress = validateAndFormatAddress(contractAddress); + if (!formattedContractAddress) { + console.log(chalk.red("🚫 Invalid contract address")); + return; + } + + const targetAddress = getAddress(holderAddress); + + if (!targetAddress) { + console.log(chalk.red("🚫 Invalid holder address")); + return; + } + + const provider = new ViemProvider(testnet); + const client = await provider.getPublicClient(); + + const isContract = await isValidContract(client, formattedContractAddress); + if (!isContract) { + console.log( + chalk.red( + "🚫 Contract not found. Please verify:\n 1. You're on the correct network (testnet/mainnet)\n 2. The contract address is correct" + ) + ); + return; + } + + const { name, symbol, decimals } = await getTokenInfo( + provider, + formattedContractAddress + ); + + const balance = await client.readContract({ + address: formattedContractAddress, + abi: erc20ABI, + functionName: "balanceOf", + args: [targetAddress], + }); + + const formattedBalance = formatUnits(balance as bigint, decimals); + + console.log(chalk.white("📄 Token Information:")); + console.log(chalk.white(" Name:"), chalk.green(name)); + console.log(chalk.white(" Symbol:"), chalk.green(symbol)); + console.log(chalk.white(" Contract:"), chalk.green(contractAddress)); + console.log(chalk.white("👤 Holder Address:"), chalk.green(targetAddress)); + console.log( + chalk.white("💰 Balance:"), + chalk.green(`${formattedBalance} ${symbol}`) + ); + console.log( + chalk.white("🌐 Network:"), + chalk.green(testnet ? "Rootstock Testnet" : "Rootstock Mainnet") + ); + } catch (error) { + if (error instanceof Error) { + console.error(chalk.red("🚨 Error:"), chalk.yellow(error.message)); + } else { + console.error(chalk.red("🚨 An unknown error occurred")); + } + } +} + +export async function transferToken( + testnet: boolean, + tokenAddress: Address, + toAddress: Address, + value: string +) { + try { + const formattedTokenAddress = validateAndFormatAddress(tokenAddress); + if (!formattedTokenAddress) { + console.log(chalk.red("🚫 Invalid contract address")); + return; + } + + const formattedToAddress = validateAndFormatAddress(toAddress); + if (!formattedToAddress) { + console.log(chalk.red("🚫 Invalid recipient address")); + return; + } + + const fromAddress = getAddress(); + if (!fromAddress) { + console.log( + chalk.red("🚫 No saved wallet found. Please create a wallet first.") + ); + return; + } + + const provider = new ViemProvider(testnet); + + const publicClient = await provider.getPublicClient(); + + const isContract = await isValidContract( + publicClient, + formattedTokenAddress + ); + if (!isContract) { + console.log( + chalk.red( + "🚫 Contract not found. Please verify:\n 1. You're on the correct network (testnet/mainnet)\n 2. The contract address is correct" + ) + ); + return; + } + } catch (error) { + if (error instanceof Error) { + console.error( + chalk.red("🚨 Error during transfer:"), + chalk.yellow(error.message) + ); + } else { + console.error(chalk.red("🚨 An unknown error occurred.")); + } + } +} diff --git a/src/constants/erc20ABI.ts b/src/constants/erc20ABI.ts new file mode 100644 index 0000000..fe68871 --- /dev/null +++ b/src/constants/erc20ABI.ts @@ -0,0 +1,40 @@ +export const erc20ABI = [ + { + constant: true, + inputs: [], + name: "name", + outputs: [{ name: "", type: "string" }], + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [{ name: "", type: "string" }], + type: "function", + }, + { + constant: true, + inputs: [], + name: "decimals", + outputs: [{ name: "", type: "uint8" }], + type: "function", + }, + { + constant: true, + inputs: [{ name: "_owner", type: "address" }], + name: "balanceOf", + outputs: [{ name: "balance", type: "uint256" }], + type: "function", + }, + { + constant: false, + inputs: [ + { name: "_to", type: "address" }, + { name: "_value", type: "uint256" }, + ], + name: "transfer", + outputs: [{ name: "", type: "bool" }], + type: "function", + }, +] as const; diff --git a/src/utils/index.ts b/src/utils/index.ts index 7b18fbe..fd2e6e9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,29 @@ +import { Address, isAddress, PublicClient } from "viem"; +import chalk from "chalk"; + export function wait(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } + +export function validateAndFormatAddress(address: string): Address | undefined { + if (!address) return undefined; + + const formattedAddress = address.toLowerCase(); + if (!isAddress(formattedAddress)) { + console.log(chalk.red("🚫 Invalid address")); + return undefined; + } + return formattedAddress as Address; +} + +export async function isValidContract( + client: PublicClient, + address: Address +): Promise { + try { + const code = await client.getBytecode({ address }); + return code !== undefined && code !== "0x"; + } catch (error) { + return false; + } +} diff --git a/src/utils/tokenHelper.ts b/src/utils/tokenHelper.ts new file mode 100644 index 0000000..451cf05 --- /dev/null +++ b/src/utils/tokenHelper.ts @@ -0,0 +1,36 @@ +import { Address } from "viem"; +import ViemProvider from "./viemProvider"; +import { erc20ABI } from "../constants/erc20ABI.js"; + +interface TokenInfo { + name: string; + symbol: string; + decimals: number; +} + +export async function getTokenInfo( + provider: ViemProvider, + contractAddress: Address +): Promise { + const client = await provider.getPublicClient(); + + const [name, symbol, decimals] = await Promise.all([ + client.readContract({ + address: contractAddress, + abi: erc20ABI, + functionName: "name", + }) as Promise, + client.readContract({ + address: contractAddress, + abi: erc20ABI, + functionName: "symbol", + }) as Promise, + client.readContract({ + address: contractAddress, + abi: erc20ABI, + functionName: "decimals", + }) as Promise, + ]); + + return { name, symbol, decimals }; +} From 94dbad713db6e215c6dec28db0b732141fe39feb Mon Sep 17 00:00:00 2001 From: chrisarevalodev Date: Tue, 3 Dec 2024 12:52:27 +0700 Subject: [PATCH 04/32] added scorecard workflows --- .github/dependabot.yml | 11 ++++++ .github/workflows/codeQL.yml | 42 +++++++++++++++++++++ .github/workflows/dependency-review.yml | 20 ++++++++++ .github/workflows/scorecard.yml | 47 ++++++++++++++++++++++++ README.md | 5 +++ SECURITY.MD | 26 +++++++++++++ rootstock-logo.png | Bin 0 -> 15378 bytes 7 files changed, 151 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/codeQL.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .github/workflows/scorecard.yml create mode 100644 SECURITY.MD create mode 100644 rootstock-logo.png diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..bb85b6f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: npm + directory: / + schedule: + interval: daily diff --git a/.github/workflows/codeQL.yml b/.github/workflows/codeQL.yml new file mode 100644 index 0000000..4280710 --- /dev/null +++ b/.github/workflows/codeQL.yml @@ -0,0 +1,42 @@ +name: "CodeQL" + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + schedule: + - cron: "0 0 * * *" + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + security-events: write + + strategy: + fail-fast: false + matrix: + language: [javascript] + + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Initialize CodeQL + uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..b5ccfb5 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +name: "Dependency Review" +on: [pull_request] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + dependency-review: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: "Checkout Repository" + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + + - name: "Dependency Review" + uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4 + with: + fail-on-severity: high + comment-summary-in-pr: true diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..a38452b --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,47 @@ +name: Scorecard supply-chain security +on: + branch_protection_rule: + schedule: + - cron: "33 2 * * 2" + push: + branches: ["main"] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + security-events: write + id-token: write + + steps: + - name: "Checkout code" + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 #v4.4.3 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + with: + sarif_file: results.sarif diff --git a/README.md b/README.md index 0249515..45801db 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/rsksmart/rsk-runes/badge)](https://scorecard.dev/viewer/?uri=github.com/rsksmart/rsk-runes) +[![CodeQL](https://github.com/rsksmart/rskj/workflows/CodeQL/badge.svg)](https://github.com/rsksmart/rsk-runes/actions?query=workflow%3ACodeQL) + +RSK Logo + # rsk-cli ## Description diff --git a/SECURITY.MD b/SECURITY.MD new file mode 100644 index 0000000..7820deb --- /dev/null +++ b/SECURITY.MD @@ -0,0 +1,26 @@ +# Reporting Security Issues + +The Rootstock team and community take security bugs in rootstock seriously. Beside this project is out of our Bug Bounty Program scope, we appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +## Responsible Disclosure + +For all security related issues, rsk-runes has two main points of contact. Reach us at or use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/rsksmart/rsk-runes/security/advisories/new) tab. + +The Rootstock team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. + +**Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/rsksmart/rsk-runes/issues). + +## Vulnerability Handling + +### Response Time + +RootstockLabs will make a best effort to meet the following response times for reported vulnerabilities: + +- Time to first response (from report submit) - 5 business days +- Time to triage (from report submit) - 7 business days + +We’ll try to keep you informed about our progress throughout the process. + +### Disclose Policy + +Follow our [disclosure guidelines](https://www.rootstocklabs.com/bounty-program/). diff --git a/rootstock-logo.png b/rootstock-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..44d7e44db671117c0b174611aab923a5f5f55872 GIT binary patch literal 15378 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 Gv;PAeVk Date: Tue, 3 Dec 2024 19:18:53 +0530 Subject: [PATCH 05/32] feat: add wallet backup --- src/commands/wallet.ts | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/commands/wallet.ts b/src/commands/wallet.ts index d5336db..505ea48 100644 --- a/src/commands/wallet.ts +++ b/src/commands/wallet.ts @@ -5,6 +5,7 @@ import fs from "fs-extra"; import crypto from "crypto"; import { loadWallets } from "../utils/index.js"; import { walletFilePath } from "../utils/constants.js"; +import path from "path"; type InquirerAnswers = { action?: string; @@ -16,6 +17,7 @@ type InquirerAnswers = { setCurrentWallet?: boolean; confirmDelete?: boolean; newWalletName?: string; + backupPath?: string; }; export async function walletCommand() { @@ -47,6 +49,7 @@ export async function walletCommand() { "🔍 List saved wallets", "🔁 Switch wallet", "📝 Update wallet name", + "📂 Backup wallet data", "❌ Delete wallet", ], }, @@ -481,6 +484,27 @@ export async function walletCommand() { writeWalletData(walletFilePath, walletsData); } + + if (action === "📂 Backup wallet data") { + const backupPathQuestion: any = [ + { + type: "input", + name: "backupPath", + message: "💾 Enter the path where you want to save the backup:", + }, + ]; + + const { backupPath } = await inquirer.prompt( + backupPathQuestion + ); + + if (!backupPath) { + console.log(chalk.red("⚠️ Backup path is required!")); + return; + } + + await backupCommand(backupPath); + } } catch (error: any) { console.error( chalk.red("❌ Error creating or managing wallets:"), @@ -504,3 +528,51 @@ async function writeWalletData(walletFilePath: string, walletsData: any) { ); } } + +async function backupCommand(backupPath: string) { + try { + if (!fs.existsSync(walletFilePath)) { + console.log(chalk.red("🚫 No saved wallet found. Please create a wallet first.")); + return; + } + + if (!backupPath) { + console.log(chalk.red("⚠️ Please provide a valid file path for backup.")); + return; + } + + let absoluteBackupPath = path.resolve(backupPath); + const backupDir = path.dirname(absoluteBackupPath); + + if (fs.existsSync(absoluteBackupPath) && fs.lstatSync(absoluteBackupPath).isDirectory()) { + absoluteBackupPath = path.join(absoluteBackupPath, 'wallet_backup.json'); + console.log(chalk.yellow(`⚠️ You provided a directory. Using default file name: wallet_backup.json`)); + } + + if (!fs.existsSync(backupDir)) { + fs.mkdirSync(backupDir, { recursive: true }); + console.log(chalk.green(`📂 Created backup directory: ${backupDir}`)); + } + + const walletData = fs.readFileSync(walletFilePath, "utf8"); + + try { + fs.writeFileSync(absoluteBackupPath, walletData, "utf8"); + console.log( + chalk.green("✅ Wallet backup created successfully!"), + chalk.green(`\n💾 Backup saved successfully at: ${absoluteBackupPath}`) + ); + } catch (writeError: any) { + console.error( + chalk.red("🚨 Error saving the backup file:"), + chalk.yellow(writeError.message) + ); + } + + } catch (error: any) { + console.error( + chalk.red("🚨 Error during wallet backup:"), + chalk.yellow(error.message) + ); + } +} \ No newline at end of file From 08c15a8eaeb7b307a6f2c1e2aeb2b258c386eca3 Mon Sep 17 00:00:00 2001 From: chrisarevalodev Date: Wed, 4 Dec 2024 22:27:01 +0700 Subject: [PATCH 06/32] updated codeql badge ans version for compatibility --- .github/workflows/codeQL.yml | 5 +++-- .github/workflows/dependency-review.yml | 2 +- README.md | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeQL.yml b/.github/workflows/codeQL.yml index 4280710..d037220 100644 --- a/.github/workflows/codeQL.yml +++ b/.github/workflows/codeQL.yml @@ -9,7 +9,8 @@ on: - cron: "0 0 * * *" # Declare default permissions as read only. -permissions: read-all +permissions: + contents: read jobs: analyze: @@ -25,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Initialize CodeQL uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index b5ccfb5..9afbf90 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: "Dependency Review" - uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4 + uses: actions/dependency-review-action@4081bf99e2866ebe428fc0477b69eb4fcda7220a # v4.4.0 with: fail-on-severity: high comment-summary-in-pr: true diff --git a/README.md b/README.md index 45801db..9a7838c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/rsksmart/rsk-runes/badge)](https://scorecard.dev/viewer/?uri=github.com/rsksmart/rsk-runes) -[![CodeQL](https://github.com/rsksmart/rskj/workflows/CodeQL/badge.svg)](https://github.com/rsksmart/rsk-runes/actions?query=workflow%3ACodeQL) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/rsksmart/rsk-cli/badge)](https://scorecard.dev/viewer/?uri=github.com/rsksmart/rsk-cli) +[![CodeQL](https://github.com/rsksmart/rskj/workflows/CodeQL/badge.svg)](https://github.com/rsksmart/rsk-cli/actions?query=workflow%3ACodeQL) RSK Logo From ec031c446565775cfe44cc4c3f67e92c4d0e8064 Mon Sep 17 00:00:00 2001 From: Ezequiel Martin Rodriguez <123201718+ezequiel-rodriguez@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:32:24 -0300 Subject: [PATCH 07/32] Update SECURITY.MD --- SECURITY.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.MD b/SECURITY.MD index 7820deb..b9084b6 100644 --- a/SECURITY.MD +++ b/SECURITY.MD @@ -4,7 +4,7 @@ The Rootstock team and community take security bugs in rootstock seriously. Besi ## Responsible Disclosure -For all security related issues, rsk-runes has two main points of contact. Reach us at or use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/rsksmart/rsk-runes/security/advisories/new) tab. +For all security related issues, rsk-runes has two main points of contact. Reach us at or use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/rsksmart/rsk-cli/security/advisories/new) tab. The Rootstock team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. From f26b0864d581d851f1507a7f7e4ae0416b021fcf Mon Sep 17 00:00:00 2001 From: Ezequiel Martin Rodriguez <123201718+ezequiel-rodriguez@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:32:32 -0300 Subject: [PATCH 08/32] Update SECURITY.MD --- SECURITY.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.MD b/SECURITY.MD index b9084b6..870e58a 100644 --- a/SECURITY.MD +++ b/SECURITY.MD @@ -8,7 +8,7 @@ For all security related issues, rsk-runes has two main points of contact. Reach The Rootstock team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. -**Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/rsksmart/rsk-runes/issues). +**Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/rsksmart/rsk-cli/issues). ## Vulnerability Handling From f3a4ad67f39f508b8dedce90c58cc3ba083afabd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:10:56 +0000 Subject: [PATCH 09/32] chore(deps): bump actions/dependency-review-action from 4.4.0 to 4.5.0 Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.4.0 to 4.5.0. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/4081bf99e2866ebe428fc0477b69eb4fcda7220a...3b139cfc5fae8b618d3eae3675e383bb1769c019) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 9afbf90..f8ff9ed 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: "Dependency Review" - uses: actions/dependency-review-action@4081bf99e2866ebe428fc0477b69eb4fcda7220a # v4.4.0 + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 with: fail-on-severity: high comment-summary-in-pr: true From dd06e9b0370fa6f8fb5b2b84cc3633c9865461b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:11:10 +0000 Subject: [PATCH 10/32] chore(deps-dev): bump @types/bun from 1.1.10 to 1.1.14 Bumps [@types/bun](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/bun) from 1.1.10 to 1.1.14. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/bun) --- updated-dependencies: - dependency-name: "@types/bun" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 113 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74ab2df..820f197 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,22 @@ { "name": "@rsksmart/rsk-cli", - "version": "1.0.3", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@rsksmart/rsk-cli", - "version": "1.0.3", + "version": "1.0.5", "license": "MIT", "dependencies": { "@openzeppelin/contracts": "^5.0.2", + "@rsksmart/rsk-precompiled-abis": "^6.0.0-ARROWHEAD", + "@types/fs-extra": "^11.0.4", "chalk": "^5.3.0", "cli-table3": "^0.6.5", "commander": "^12.1.0", "figlet": "^1.7.0", + "fs-extra": "^11.2.0", "inquirer": "^10.1.8", "ora": "^8.0.1", "viem": "^2.19.4" @@ -23,8 +26,6 @@ }, "devDependencies": { "@types/bun": "latest", - "@types/chalk": "^2.2.0", - "@types/commander": "^2.12.2", "@types/figlet": "^1.5.8", "solc": "0.8.20", "typescript": "^5.0.0" @@ -313,6 +314,12 @@ "integrity": "sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==", "license": "MIT" }, + "node_modules/@rsksmart/rsk-precompiled-abis": { + "version": "6.0.0-ARROWHEAD", + "resolved": "https://registry.npmjs.org/@rsksmart/rsk-precompiled-abis/-/rsk-precompiled-abis-6.0.0-ARROWHEAD.tgz", + "integrity": "sha512-+g22mIXjdTHoakCXnjttA9MMJMVyYzZ8VsAL4bMPeTZ8kn9OCZBpXkAtCsXkDCGeYCgrWD9F3VS59vBb/AOdGA==", + "license": "ISC" + }, "node_modules/@scure/base": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", @@ -362,44 +369,41 @@ } }, "node_modules/@types/bun": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.1.10.tgz", - "integrity": "sha512-76KYVSwrHwr9zsnk6oLXOGs9KvyBg3U066GLO4rk6JZk1ypEPGCUDZ5yOiESyIHWs9cx9iC8r01utYN32XdmgA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.1.14.tgz", + "integrity": "sha512-opVYiFGtO2af0dnWBdZWlioLBoxSdDO5qokaazLhq8XQtGZbY4pY3/JxY8Zdf/hEwGubbp7ErZXoN1+h2yesxA==", "dev": true, "license": "MIT", "dependencies": { - "bun-types": "1.1.29" + "bun-types": "1.1.37" } }, - "node_modules/@types/chalk": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-2.2.0.tgz", - "integrity": "sha512-1zzPV9FDe1I/WHhRkf9SNgqtRJWZqrBWgu7JGveuHmmyR9CnAPCie2N/x+iHrgnpYBIcCJWHBoMRv2TRWktsvw==", - "deprecated": "This is a stub types definition for chalk (https://github.com/chalk/chalk). chalk provides its own type definitions, so you don't need @types/chalk installed!", + "node_modules/@types/figlet": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@types/figlet/-/figlet-1.5.8.tgz", + "integrity": "sha512-G22AUvy4Tl95XLE7jmUM8s8mKcoz+Hr+Xm9W90gJsppJq9f9tHvOGkrpn4gRX0q/cLtBdNkWtWCKDg2UDZoZvQ==", "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", "license": "MIT", "dependencies": { - "chalk": "*" + "@types/jsonfile": "*", + "@types/node": "*" } }, - "node_modules/@types/commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==", - "deprecated": "This is a stub types definition for commander (https://github.com/tj/commander.js). commander provides its own type definitions, so you don't need @types/commander installed!", - "dev": true, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", "license": "MIT", "dependencies": { - "commander": "*" + "@types/node": "*" } }, - "node_modules/@types/figlet": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/@types/figlet/-/figlet-1.5.8.tgz", - "integrity": "sha512-G22AUvy4Tl95XLE7jmUM8s8mKcoz+Hr+Xm9W90gJsppJq9f9tHvOGkrpn4gRX0q/cLtBdNkWtWCKDg2UDZoZvQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/mute-stream": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", @@ -425,9 +429,9 @@ "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", - "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", "dev": true, "license": "MIT", "dependencies": { @@ -495,9 +499,9 @@ } }, "node_modules/bun-types": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.1.29.tgz", - "integrity": "sha512-En3/TzSPMPyl5UlUB1MHzHpcrZDakTm7mS203eLoX1fBoEa3PW+aSS8GAqVJ7Is/m34Z5ogL+ECniLY0uDaCPw==", + "version": "1.1.37", + "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.1.37.tgz", + "integrity": "sha512-C65lv6eBr3LPJWFZ2gswyrGZ82ljnH8flVE03xeXxKhi2ZGtFiO4isRKTKnitbSqtRAcaqYSR6djt1whI66AbA==", "dev": true, "license": "MIT", "dependencies": { @@ -661,6 +665,20 @@ } } }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/get-east-asian-width": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", @@ -673,6 +691,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -759,6 +783,18 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/log-symbols": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", @@ -1096,6 +1132,15 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "license": "MIT" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/viem": { "version": "2.21.14", "resolved": "https://registry.npmjs.org/viem/-/viem-2.21.14.tgz", From 63dc86e5c69fb8e9629bc25246e051d5e664dd6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 02:24:11 +0000 Subject: [PATCH 11/32] chore(deps): bump ora from 8.1.0 to 8.1.1 Bumps [ora](https://github.com/sindresorhus/ora) from 8.1.0 to 8.1.1. - [Release notes](https://github.com/sindresorhus/ora/releases) - [Commits](https://github.com/sindresorhus/ora/compare/v8.1.0...v8.1.1) --- updated-dependencies: - dependency-name: ora dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 820f197..3392c35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "rsk-cli": "dist/bin/index.js" }, "devDependencies": { - "@types/bun": "latest", + "@types/bun": "*", "@types/figlet": "^1.5.8", "solc": "0.8.20", "typescript": "^5.0.0" @@ -869,9 +869,9 @@ } }, "node_modules/ora": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.0.tgz", - "integrity": "sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.1.tgz", + "integrity": "sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==", "license": "MIT", "dependencies": { "chalk": "^5.3.0", From bfffee7c5c4c2a920438f76d5f5729c19eb1a90d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 02:24:12 +0000 Subject: [PATCH 12/32] chore(deps-dev): bump typescript from 5.6.2 to 5.7.2 Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.2 to 5.7.2. - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml) - [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.2...v5.7.2) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 820f197..d91c7f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "rsk-cli": "dist/bin/index.js" }, "devDependencies": { - "@types/bun": "latest", + "@types/bun": "*", "@types/figlet": "^1.5.8", "solc": "0.8.20", "typescript": "^5.0.0" @@ -1113,9 +1113,9 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "devOptional": true, "license": "Apache-2.0", "bin": { From b95b4e9d20744342dba12162aa180b997782f628 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 02:24:17 +0000 Subject: [PATCH 13/32] chore(deps): bump inquirer from 10.2.2 to 12.1.0 Bumps [inquirer](https://github.com/SBoudrias/Inquirer.js) from 10.2.2 to 12.1.0. - [Release notes](https://github.com/SBoudrias/Inquirer.js/releases) - [Commits](https://github.com/SBoudrias/Inquirer.js/compare/inquirer@10.2.2...inquirer@12.1.0) --- updated-dependencies: - dependency-name: inquirer dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 270 ++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 131 insertions(+), 141 deletions(-) diff --git a/package-lock.json b/package-lock.json index 820f197..cb628e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "commander": "^12.1.0", "figlet": "^1.7.0", "fs-extra": "^11.2.0", - "inquirer": "^10.1.8", + "inquirer": "^12.1.0", "ora": "^8.0.1", "viem": "^2.19.4" }, @@ -25,7 +25,7 @@ "rsk-cli": "dist/bin/index.js" }, "devDependencies": { - "@types/bun": "latest", + "@types/bun": "*", "@types/figlet": "^1.5.8", "solc": "0.8.20", "typescript": "^5.0.0" @@ -51,48 +51,51 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.5.0.tgz", - "integrity": "sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.0.2.tgz", + "integrity": "sha512-+gznPl8ip8P8HYHYecDtUtdsh1t2jvb+sWCD72GAiZ9m45RqwrLmReDaqdC0umQfamtFXVRoMVJ2/qINKGm9Tg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/confirm": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.2.0.tgz", - "integrity": "sha512-oOIwPs0Dvq5220Z8lGL/6LHRTEr9TgLHmiI99Rj1PJ1p1czTys+olrgBqZk4E2qC0YTzeHprxSQmoHioVdJ7Lw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.2.tgz", + "integrity": "sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3" + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/core": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.2.1.tgz", - "integrity": "sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.0.tgz", + "integrity": "sha512-I+ETk2AL+yAVbvuKx5AJpQmoaWhpiTFOg/UJb7ZkMAK4blmtG8ATh5ct+T/8xNld0CZG/2UhtkdMwpgvld92XQ==", "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.6", - "@inquirer/type": "^2.0.0", - "@types/mute-stream": "^0.0.4", - "@types/node": "^22.5.5", - "@types/wrap-ansi": "^3.0.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", - "mute-stream": "^1.0.0", + "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^6.2.0", @@ -102,186 +105,186 @@ "node": ">=18" } }, - "node_modules/@inquirer/core/node_modules/@inquirer/type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-2.0.0.tgz", - "integrity": "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==", - "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/core/node_modules/@types/node": { - "version": "22.7.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.2.tgz", - "integrity": "sha512-866lXSrpGpgyHBZUa2m9YNWqHDjjM0aBTJlNtYaGEw4rqY/dcD7deRVTbBBAJelfA7oaGDbNftXF/TL/A6RgoA==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@inquirer/core/node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "license": "MIT" - }, "node_modules/@inquirer/editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.2.0.tgz", - "integrity": "sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.1.0.tgz", + "integrity": "sha512-K1gGWsxEqO23tVdp5MT3H799OZ4ER1za7Dlc8F4um0W7lwSv0KGR/YyrUEyimj0g7dXZd8XknM/5QA2/Uy+TbA==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", "external-editor": "^3.1.0" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/expand": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.3.0.tgz", - "integrity": "sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.2.tgz", + "integrity": "sha512-WdgCX1cUtinz+syKyZdJomovULYlKUWZbVYZzhf+ZeeYf4htAQ3jLymoNs3koIAKfZZl3HUBb819ClCBfyznaw==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/figures": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.6.tgz", - "integrity": "sha512-yfZzps3Cso2UbM7WlxKwZQh2Hs6plrbjs1QnzQDZhK2DgyCo6D8AaHps9olkNcUFlcYERMqU3uJSp1gmy3s/qQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@inquirer/input": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.3.0.tgz", - "integrity": "sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.0.2.tgz", + "integrity": "sha512-yCLCraigU085EcdpIVEDgyfGv4vBiE4I+k1qRkc9C5dMjWF42ADMGy1RFU94+eZlz4YlkmFsiyHZy0W1wdhaNg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3" + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-1.1.0.tgz", - "integrity": "sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.2.tgz", + "integrity": "sha512-MKQhYofdUNk7eqJtz52KvM1dH6R93OMrqHduXCvuefKrsiMjHiMwjc3NZw5Imm2nqY7gWd9xdhYrtcHMJQZUxA==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3" + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/password": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.2.0.tgz", - "integrity": "sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.2.tgz", + "integrity": "sha512-tQXGSu7IO07gsYlGy3VgXRVsbOWqFBMbqAUrJSc1PDTQQ5Qdm+QVwkP0OC0jnUZ62D19iPgXOMO+tnWG+HhjNQ==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/prompts": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.5.0.tgz", - "integrity": "sha512-BHDeL0catgHdcHbSFFUddNzvx/imzJMft+tWDPwTm3hfu8/tApk1HrooNngB2Mb4qY+KaRWF+iZqoVUPeslEog==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.1.0.tgz", + "integrity": "sha512-5U/XiVRH2pp1X6gpNAjWOglMf38/Ys522ncEHIKT1voRUvSj/DQnR22OVxHnwu5S+rCFaUiPQ57JOtMFQayqYA==", "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^2.5.0", - "@inquirer/confirm": "^3.2.0", - "@inquirer/editor": "^2.2.0", - "@inquirer/expand": "^2.3.0", - "@inquirer/input": "^2.3.0", - "@inquirer/number": "^1.1.0", - "@inquirer/password": "^2.2.0", - "@inquirer/rawlist": "^2.3.0", - "@inquirer/search": "^1.1.0", - "@inquirer/select": "^2.5.0" + "@inquirer/checkbox": "^4.0.2", + "@inquirer/confirm": "^5.0.2", + "@inquirer/editor": "^4.1.0", + "@inquirer/expand": "^4.0.2", + "@inquirer/input": "^4.0.2", + "@inquirer/number": "^3.0.2", + "@inquirer/password": "^4.0.2", + "@inquirer/rawlist": "^4.0.2", + "@inquirer/search": "^3.0.2", + "@inquirer/select": "^4.0.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/rawlist": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.3.0.tgz", - "integrity": "sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.2.tgz", + "integrity": "sha512-3XGcskMoVF8H0Dl1S5TSZ3rMPPBWXRcM0VeNVsS4ByWeWjSeb0lPqfnBg6N7T0608I1B2bSVnbi2cwCrmOD1Yw==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/search": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-1.1.0.tgz", - "integrity": "sha512-h+/5LSj51dx7hp5xOn4QFnUaKeARwUCLs6mIhtkJ0JYPBLmEYjdHSYh7I6GrLg9LwpJ3xeX0FZgAG1q0QdCpVQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.2.tgz", + "integrity": "sha512-Zv4FC7w4dJ13BOJfKRQCICQfShinGjb1bCEIHxTSnjj2telu3+3RHwHubPG9HyD4aix5s+lyAMEK/wSFD75HLA==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/select": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.5.0.tgz", - "integrity": "sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.2.tgz", + "integrity": "sha512-uSWUzaSYAEj0hlzxa1mUB6VqrKaYx0QxGBLZzU4xWFxaSyGaXxsSE4OSOwdU24j0xl8OajgayqFXW0l2bkl2kg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/type": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", - "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", + "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@noble/curves": { @@ -404,15 +407,6 @@ "@types/node": "*" } }, - "node_modules/@types/mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/node": { "version": "20.12.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", @@ -422,12 +416,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/wrap-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", - "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", - "license": "MIT" - }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -710,22 +698,24 @@ } }, "node_modules/inquirer": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-10.2.2.tgz", - "integrity": "sha512-tyao/4Vo36XnUItZ7DnUXX4f1jVao2mSrleV/5IPtW/XAEA26hRVsbc68nuTEKWcr5vMP/1mVoT2O7u8H4v1Vg==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.1.0.tgz", + "integrity": "sha512-3/iexk64jn3EF0tjWYfOJi/DNWtcSSwg4ER67cnopO2xlCTUQjFCTMH9NBNQAMO/+dC3sEvKJtGJsqXnCkSsFg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/prompts": "^5.5.0", - "@inquirer/type": "^1.5.3", - "@types/mute-stream": "^0.0.4", + "@inquirer/core": "^10.1.0", + "@inquirer/prompts": "^7.1.0", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2", - "mute-stream": "^1.0.0", + "mute-stream": "^2.0.0", "run-async": "^3.0.0", "rxjs": "^7.8.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/is-fullwidth-code-point": { @@ -845,12 +835,12 @@ } }, "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/onetime": { diff --git a/package.json b/package.json index f16f391..6b44ed8 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "commander": "^12.1.0", "figlet": "^1.7.0", "fs-extra": "^11.2.0", - "inquirer": "^10.1.8", + "inquirer": "^12.1.0", "ora": "^8.0.1", "viem": "^2.19.4" } From 26349bf8135a84a30bb1f1b1a32c4fe242134ba3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 02:30:47 +0000 Subject: [PATCH 14/32] chore(deps-dev): bump solc from 0.8.20 to 0.8.28 Bumps [solc](https://github.com/ethereum/solc-js) from 0.8.20 to 0.8.28. - [Commits](https://github.com/ethereum/solc-js/compare/v0.8.20...v0.8.28) --- updated-dependencies: - dependency-name: solc dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a83366..a04634e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "devDependencies": { "@types/bun": "*", "@types/figlet": "^1.5.8", - "solc": "0.8.20", + "solc": "0.8.28", "typescript": "^5.0.0" }, "peerDependencies": { @@ -1013,9 +1013,9 @@ } }, "node_modules/solc": { - "version": "0.8.20", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.20.tgz", - "integrity": "sha512-fPRnGspIEqmhu63RFO3pc79sLA7ZmzO0Uy0L5l6hEt2wAsq0o7UV6pXkAp3Mfv9IBhg7Px/oTu3a+y4gs3BWrQ==", + "version": "0.8.28", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.28.tgz", + "integrity": "sha512-AFCiJ+b4RosyyNhnfdVH4ZR1+TxiL91iluPjw0EJslIu4LXGM9NYqi2z5y8TqochC4tcH9QsHfwWhOIC9jPDKA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index f16f391..9f5d2e9 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "devDependencies": { "@types/bun": "latest", "@types/figlet": "^1.5.8", - "solc": "0.8.20", + "solc": "0.8.28", "typescript": "^5.0.0" }, "peerDependencies": { From ae05f6d261b1b91edeaf003797a371fd748c9d1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 05:36:10 +0000 Subject: [PATCH 15/32] chore(deps): bump github/codeql-action from 3.26.12 to 3.27.6 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.12 to 3.27.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3.26.12...aa578102511db1f4524ed59b8cc2bae4f6e88195) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeQL.yml | 6 +++--- .github/workflows/scorecard.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeQL.yml b/.github/workflows/codeQL.yml index d037220..63f316f 100644 --- a/.github/workflows/codeQL.yml +++ b/.github/workflows/codeQL.yml @@ -29,15 +29,15 @@ jobs: uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Initialize CodeQL - uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 + uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 #v3.27.6 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 + uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 #v3.27.6 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13 + uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 #v3.27.6 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a38452b..a3cf387 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -42,6 +42,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/upload-sarif@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 with: sarif_file: results.sarif From d3c93b450b6926720bc23b38a689cfe3da25d9b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 05:36:19 +0000 Subject: [PATCH 16/32] chore(deps): bump @openzeppelin/contracts from 5.0.2 to 5.1.0 Bumps [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) from 5.0.2 to 5.1.0. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases) - [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md) - [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v5.0.2...v5.1.0) --- updated-dependencies: - dependency-name: "@openzeppelin/contracts" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a83366..58fecea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -309,9 +309,9 @@ } }, "node_modules/@openzeppelin/contracts": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.2.tgz", - "integrity": "sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.1.0.tgz", + "integrity": "sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==", "license": "MIT" }, "node_modules/@rsksmart/rsk-precompiled-abis": { From e842685477af8147bc02492f377a194a44550db0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:44:24 +0000 Subject: [PATCH 17/32] chore(deps): bump figlet and @types/figlet Bumps [figlet](https://github.com/patorjk/figlet.js) and [@types/figlet](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/figlet). These dependencies needed to be updated together. Updates `figlet` from 1.7.0 to 1.8.0 - [Release notes](https://github.com/patorjk/figlet.js/releases) - [Commits](https://github.com/patorjk/figlet.js/commits/1.8.0) Updates `@types/figlet` from 1.5.8 to 1.7.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/figlet) --- updated-dependencies: - dependency-name: figlet dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: "@types/figlet" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f26b9c..c0cdfaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -382,9 +382,9 @@ } }, "node_modules/@types/figlet": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/@types/figlet/-/figlet-1.5.8.tgz", - "integrity": "sha512-G22AUvy4Tl95XLE7jmUM8s8mKcoz+Hr+Xm9W90gJsppJq9f9tHvOGkrpn4gRX0q/cLtBdNkWtWCKDg2UDZoZvQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@types/figlet/-/figlet-1.7.0.tgz", + "integrity": "sha512-KwrT7p/8Eo3Op/HBSIwGXOsTZKYiM9NpWRBJ5sVjWP/SmlS+oxxRvJht/FNAtliJvja44N3ul1yATgohnVBV0Q==", "dev": true, "license": "MIT" }, @@ -621,9 +621,9 @@ } }, "node_modules/figlet": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.7.0.tgz", - "integrity": "sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.0.tgz", + "integrity": "sha512-chzvGjd+Sp7KUvPHZv6EXV5Ir3Q7kYNpCr4aHrRW79qFtTefmQZNny+W1pW9kf5zeE6dikku2W50W/wAH2xWgw==", "license": "MIT", "bin": { "figlet": "bin/index.js" From 8cc4173ac35ffa2a94b158e8bdfb2241ae458355 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:44:31 +0000 Subject: [PATCH 18/32] chore(deps): bump viem from 2.21.14 to 2.21.54 Bumps [viem](https://github.com/wevm/viem) from 2.21.14 to 2.21.54. - [Release notes](https://github.com/wevm/viem/releases) - [Commits](https://github.com/wevm/viem/compare/viem@2.21.14...viem@2.21.54) --- updated-dependencies: - dependency-name: viem dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 162 ++++++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 62 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f26b9c..152e7e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,9 +35,9 @@ } }, "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", + "integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==", "license": "MIT" }, "node_modules/@colors/colors": { @@ -288,24 +288,39 @@ } }, "node_modules/@noble/curves": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", - "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", + "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "@noble/hashes": "1.6.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", + "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", + "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", "license": "MIT", "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -324,48 +339,36 @@ "license": "ISC" }, "node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz", + "integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==", "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.0.tgz", + "integrity": "sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA==", "license": "MIT", "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" + "@noble/curves": "~1.7.0", + "@noble/hashes": "~1.6.0", + "@scure/base": "~1.2.1" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip39": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.4.0.tgz", - "integrity": "sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.5.0", - "@scure/base": "~1.1.8" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.0.tgz", + "integrity": "sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==", "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "dependencies": { + "@noble/hashes": "~1.6.0", + "@scure/base": "~1.2.1" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -427,9 +430,9 @@ } }, "node_modules/abitype": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz", - "integrity": "sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.7.tgz", + "integrity": "sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" @@ -606,6 +609,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -752,13 +761,13 @@ } }, "node_modules/isows": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz", - "integrity": "sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", "funding": [ { "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" + "url": "https://github.com/sponsors/wevm" } ], "license": "MIT", @@ -940,6 +949,35 @@ "node": ">=0.10.0" } }, + "node_modules/ox": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.1.2.tgz", + "integrity": "sha512-ak/8K0Rtphg9vnRJlbOdaX9R7cmxD2MiSthjWGaQdMk3D7hrAlDoM+6Lxn7hN52Za3vrXfZ7enfke/5WjolDww==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/restore-cursor": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", @@ -1132,9 +1170,9 @@ } }, "node_modules/viem": { - "version": "2.21.14", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.21.14.tgz", - "integrity": "sha512-uM6XmY9Q/kJRVSopJAGsakmtNDpk/EswqXUzwOp9DzhGuwgpWtw2MgwpfFdIyqBDFIw+TTypCIUTcwJSgEYSzA==", + "version": "2.21.54", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.21.54.tgz", + "integrity": "sha512-G9mmtbua3UtnVY9BqAtWdNp+3AO+oWhD0B9KaEsZb6gcrOWgmA4rz02yqEMg+qW9m6KgKGie7q3zcHqJIw6AqA==", "funding": [ { "type": "github", @@ -1143,15 +1181,15 @@ ], "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.4.0", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.4.0", - "abitype": "1.0.5", - "isows": "1.0.4", - "webauthn-p256": "0.0.5", - "ws": "8.17.1" + "@noble/curves": "1.7.0", + "@noble/hashes": "1.6.1", + "@scure/bip32": "1.6.0", + "@scure/bip39": "1.5.0", + "abitype": "1.0.7", + "isows": "1.0.6", + "ox": "0.1.2", + "webauthn-p256": "0.0.10", + "ws": "8.18.0" }, "peerDependencies": { "typescript": ">=5.0.4" @@ -1163,9 +1201,9 @@ } }, "node_modules/webauthn-p256": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.5.tgz", - "integrity": "sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz", + "integrity": "sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==", "funding": [ { "type": "github", @@ -1193,9 +1231,9 @@ } }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "license": "MIT", "engines": { "node": ">=10.0.0" From 48e50a4ff0372001e319b997794e4f5e4355f90b Mon Sep 17 00:00:00 2001 From: Pratham Date: Fri, 6 Dec 2024 12:23:08 +0530 Subject: [PATCH 19/32] feat: remove token option --- bin/index.ts | 38 +---- src/commands/balance.ts | 121 +++++++++++++--- src/commands/token.ts | 263 ----------------------------------- src/constants/tokenAdress.ts | 16 +++ src/utils/index.ts | 25 ++++ src/utils/tokenHelper.ts | 56 +++++--- 6 files changed, 176 insertions(+), 343 deletions(-) delete mode 100644 src/commands/token.ts create mode 100644 src/constants/tokenAdress.ts diff --git a/bin/index.ts b/bin/index.ts index d520976..fb1ec1d 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -10,7 +10,6 @@ import { deployCommand } from "../src/commands/deploy.js"; import { verifyCommand } from "../src/commands/verify.js"; import { ReadContract } from "../src/commands/contract.js"; import { Address } from "viem"; -import { checkTokenBalance, transferToken } from "../src/commands/token.js"; interface CommandOptions { testnet?: boolean; @@ -58,8 +57,9 @@ program .command("balance") .description("Check the balance of the saved wallet") .option("-t, --testnet", "Check the balance on the testnet") + .option("-a ,--address
", "Token holder address") .action(async (options: CommandOptions) => { - await balanceCommand(!!options.testnet); + await balanceCommand(!!options.testnet, options.address); }); program @@ -145,38 +145,4 @@ program await ReadContract(options.address! as `0x${string}`, !!options.testnet); }); -const token = program - .command("token") - .description("Interact with ERC20 tokens"); - -token - .command("balance") - .description("Check token balance") - .requiredOption("-c,--contract
", "Token contract address") - .option("-a ,--address
", "Token holder address") - .option("-t, --testnet", "Use testnet") - .action(async (options: CommandOptions) => { - await checkTokenBalance( - !!options.testnet, - options.contract as Address, - options.address - ); - }); - -token - .command("transfer") - .description("Transfer tokens") - .requiredOption("-c,--contract
", "Token contract address") - .requiredOption("-a,--address
", "Recipient address") - .requiredOption("-v,--value ", "Amount to transfer") - .option("-t, --testnet", "Use testnet") - .action(async (options: CommandOptions) => { - await transferToken( - !!options.testnet, - options.contract as Address, - options.address as Address, - options.value! - ); - }); - program.parse(process.argv); diff --git a/src/commands/balance.ts b/src/commands/balance.ts index 1b647fb..e9d7a06 100644 --- a/src/commands/balance.ts +++ b/src/commands/balance.ts @@ -1,43 +1,118 @@ import ViemProvider from "../utils/viemProvider.js"; -import fs from "fs"; -import path from "path"; import chalk from "chalk"; +import inquirer from "inquirer"; +import { getTokenInfo, resolveTokenAddress } from "../utils/tokenHelper.js"; +import ora from "ora"; +import { console } from "inspector"; +import { + getAddress, + isValidContract, + validateAndFormatAddress, +} from "../utils/index.js"; +import { Address, formatUnits } from "viem"; +import { TOKENS } from "../constants/tokenAdress.js"; -const walletFilePath = path.join(process.cwd(), "rootstock-wallet.json"); - -export async function balanceCommand(testnet: boolean) { +export async function balanceCommand( + testnet: boolean, + holderAddress?: Address +) { + const spinner = ora(); try { - if (!fs.existsSync(walletFilePath)) { - console.log( - chalk.red("🚫 No saved wallet found. Please create a wallet first.") - ); + const targetAddress = getAddress(holderAddress); + + if (!targetAddress) { + console.log(chalk.red("⚠️ No valid aholder ddress found")); return; } + const provider = new ViemProvider(testnet); + const client = await provider.getPublicClient(); - const walletData = JSON.parse(fs.readFileSync(walletFilePath, "utf8")); - const { address } = walletData; + const { token } = await inquirer.prompt({ + type: "list", + name: "token", + message: "Select token to check balance:", + choices: ["rBTC", ...Object.keys(TOKENS), "Custom Token"], + }); - if (!address) { - console.log(chalk.red("⚠️ No valid address found in the saved wallet.")); + if (token === "rBTC") { + spinner.start(chalk.white("🔍 Checking balance...")); + const balance = await client.getBalance({ address: targetAddress }); + const rbtcBalance = formatUnits(balance, 18); + + spinner.succeed(chalk.green("Balance retrieved successfully")); + + console.log( + chalk.white(`📄 Wallet Address:`), + chalk.green(targetAddress) + ); + console.log( + chalk.white(`🌐 Network:`), + chalk.green(testnet ? "Rootstock Testnet" : "Rootstock Mainnet") + ); + console.log( + chalk.white(`💰 Current Balance:`), + chalk.green(`${rbtcBalance} RBTC`) + ); + console.log( + chalk.blue( + `🔗 Ensure that transactions are being conducted on the correct network.` + ) + ); return; } - const provider = new ViemProvider(testnet); - const client = await provider.getPublicClient(); + let tokenAddress: Address; - const balance = await client.getBalance({ address }); + if (token === "Custom Token") { + spinner.stop(); + const { address } = await inquirer.prompt({ + type: "input", + name: "address", + message: "Enter the token address:", + validate: async (input: string) => { + try { + const address = input as Address; + const formattedContractAddress = validateAndFormatAddress(address); + if (!formattedContractAddress) { + console.log(chalk.red()); + return "🚫 Invalid contract address"; + } + if (!(await isValidContract(client, formattedContractAddress))) { + return " 🚫 Invalid contract address or contract not found"; + } + return true; + } catch { + return false; + } + }, + }); + tokenAddress = address.toLowerCase() as Address; + } else { + tokenAddress = resolveTokenAddress(token, testnet); + } - const rbtcBalance = Number(balance) / 10 ** 18; + spinner.start(chalk.white("🔍 Checking balance...")); - console.log(chalk.white(`📄 Wallet Address:`), chalk.green(address)); - console.log( - chalk.white(`🌐 Network:`), - chalk.green(testnet ? "Rootstock Testnet" : "Rootstock Mainnet") + const { balance, decimals, name, symbol } = await getTokenInfo( + client, + tokenAddress, + targetAddress ); + const formattedBalance = formatUnits(balance, decimals); + + spinner.succeed(chalk.green("Balance retrieved successfully")); + console.log( - chalk.white(`💰 Current Balance:`), - chalk.green(`${rbtcBalance} RBTC`) + chalk.white(`📄 Token Information: + Name: ${chalk.green(name)} + Contract: ${chalk.green(tokenAddress)} + 👤 Holder Address: ${chalk.green(targetAddress)} + 💰 Balance: ${chalk.green(`${formattedBalance} ${symbol}`)} + 🌐 Network: ${chalk.green( + testnet ? "Rootstock Testnet" : "Rootstock Mainnet" + )}`) ); + console.log( chalk.blue( `🔗 Ensure that transactions are being conducted on the correct network.` diff --git a/src/commands/token.ts b/src/commands/token.ts deleted file mode 100644 index 8c9e91d..0000000 --- a/src/commands/token.ts +++ /dev/null @@ -1,263 +0,0 @@ -import ViemProvider from "../utils/viemProvider.js"; -import chalk from "chalk"; -import fs from "fs"; -import path from "path"; -import { Address, formatUnits } from "viem"; -import { getTokenInfo } from "../utils/tokenHelper.js"; -import { erc20ABI } from "../constants/erc20ABI.js"; -import { isValidContract, validateAndFormatAddress } from "../utils/index.js"; - -const walletFilePath = path.join(process.cwd(), "rootstock-wallet.json"); - -// export async function checkTokenBalance( -// testnet: boolean, -// contractAddress: Address, -// holderAddress: Address -// ) { -// try { -// if (!fs.existsSync(walletFilePath)) { -// console.log( -// chalk.red("🚫 No saved wallet found. Please create a wallet first.") -// ); -// return; -// } - -// const walletData = JSON.parse(fs.readFileSync(walletFilePath, "utf8")); -// const { address: walletAddress } = walletData; - -// if (!walletAddress) { -// console.log(chalk.red("⚠️ No valid address found in the saved wallet.")); -// return; -// } - -// const provider = new ViemProvider(testnet); - -// const publicClient = await provider.getPublicClient(); -// const balance = await publicClient.getBalance({ address: walletAddress }); - -// const rbtcBalance = Number(balance) / 10 ** 18; - -// console.log(chalk.white(`📄 Wallet Address:`), chalk.green(walletAddress)); -// console.log(chalk.white(`🎯 Recipient Address:`), chalk.green(toAddress)); -// console.log( -// chalk.white(`💵 Amount to Transfer:`), -// chalk.green(`${value} RBTC`) -// ); -// console.log( -// chalk.white(`💰 Current Balance:`), -// chalk.green(`${rbtcBalance} RBTC`) -// ); - -// if (rbtcBalance < value) { -// console.log( -// chalk.red(`🚫 Insufficient balance to transfer ${value} RBTC.`) -// ); -// return; -// } - -// const walletClient = await provider.getWalletClient(); - -// const account = walletClient.account; -// if (!account) { -// console.log( -// chalk.red( -// "⚠️ Failed to retrieve the account. Please ensure your wallet is correctly set up." -// ) -// ); -// return; -// } - -// const txHash = await walletClient.sendTransaction({ -// account: account, -// chain: provider.chain, -// to: toAddress, -// value: BigInt(value * 10 ** 18), -// }); - -// console.log( -// chalk.white(`🔄 Transaction initiated. TxHash:`), -// chalk.green(txHash) -// ); -// const spinner = ora("⏳ Waiting for confirmation...").start(); - -// const receipt = await publicClient.waitForTransactionReceipt({ -// hash: txHash, -// }); -// spinner.stop(); - -// if (receipt.status === "success") { -// console.log(chalk.green("✅ Transaction confirmed successfully!")); -// console.log( -// chalk.white(`📦 Block Number:`), -// chalk.green(receipt.blockNumber) -// ); -// console.log( -// chalk.white(`⛽ Gas Used:`), -// chalk.green(receipt.gasUsed.toString()) -// ); - -// const explorerUrl = testnet -// ? `https://explorer.testnet.rootstock.io/tx/${txHash}` -// : `https://explorer.rootstock.io/tx/${txHash}`; -// console.log( -// chalk.white(`🔗 View on Explorer:`), -// chalk.dim(`${explorerUrl}`) -// ); -// } else { -// console.log(chalk.red("❌ Transaction failed.")); -// } -// } catch (error) { -// if (error instanceof Error) { -// console.error( -// chalk.red("🚨 Error during transfer:"), -// chalk.yellow(error.message) -// ); -// } else { -// console.error(chalk.red("🚨 An unknown error occurred.")); -// } -// } -// } - -function getAddress(address?: Address): Address | undefined { - if (address) { - return validateAndFormatAddress(address); - } - - if (!fs.existsSync(walletFilePath)) { - console.log(chalk.red("🚫 No saved wallet found")); - return undefined; - } - - try { - const { address: savedAddress } = JSON.parse( - fs.readFileSync(walletFilePath, "utf8") - ); - return validateAndFormatAddress(savedAddress); - } catch (error) { - console.log(chalk.red("⚠️ Invalid wallet data")); - return undefined; - } -} - -export async function checkTokenBalance( - testnet: boolean, - contractAddress: Address, - holderAddress?: Address -): Promise { - try { - const formattedContractAddress = validateAndFormatAddress(contractAddress); - if (!formattedContractAddress) { - console.log(chalk.red("🚫 Invalid contract address")); - return; - } - - const targetAddress = getAddress(holderAddress); - - if (!targetAddress) { - console.log(chalk.red("🚫 Invalid holder address")); - return; - } - - const provider = new ViemProvider(testnet); - const client = await provider.getPublicClient(); - - const isContract = await isValidContract(client, formattedContractAddress); - if (!isContract) { - console.log( - chalk.red( - "🚫 Contract not found. Please verify:\n 1. You're on the correct network (testnet/mainnet)\n 2. The contract address is correct" - ) - ); - return; - } - - const { name, symbol, decimals } = await getTokenInfo( - provider, - formattedContractAddress - ); - - const balance = await client.readContract({ - address: formattedContractAddress, - abi: erc20ABI, - functionName: "balanceOf", - args: [targetAddress], - }); - - const formattedBalance = formatUnits(balance as bigint, decimals); - - console.log(chalk.white("📄 Token Information:")); - console.log(chalk.white(" Name:"), chalk.green(name)); - console.log(chalk.white(" Symbol:"), chalk.green(symbol)); - console.log(chalk.white(" Contract:"), chalk.green(contractAddress)); - console.log(chalk.white("👤 Holder Address:"), chalk.green(targetAddress)); - console.log( - chalk.white("💰 Balance:"), - chalk.green(`${formattedBalance} ${symbol}`) - ); - console.log( - chalk.white("🌐 Network:"), - chalk.green(testnet ? "Rootstock Testnet" : "Rootstock Mainnet") - ); - } catch (error) { - if (error instanceof Error) { - console.error(chalk.red("🚨 Error:"), chalk.yellow(error.message)); - } else { - console.error(chalk.red("🚨 An unknown error occurred")); - } - } -} - -export async function transferToken( - testnet: boolean, - tokenAddress: Address, - toAddress: Address, - value: string -) { - try { - const formattedTokenAddress = validateAndFormatAddress(tokenAddress); - if (!formattedTokenAddress) { - console.log(chalk.red("🚫 Invalid contract address")); - return; - } - - const formattedToAddress = validateAndFormatAddress(toAddress); - if (!formattedToAddress) { - console.log(chalk.red("🚫 Invalid recipient address")); - return; - } - - const fromAddress = getAddress(); - if (!fromAddress) { - console.log( - chalk.red("🚫 No saved wallet found. Please create a wallet first.") - ); - return; - } - - const provider = new ViemProvider(testnet); - - const publicClient = await provider.getPublicClient(); - - const isContract = await isValidContract( - publicClient, - formattedTokenAddress - ); - if (!isContract) { - console.log( - chalk.red( - "🚫 Contract not found. Please verify:\n 1. You're on the correct network (testnet/mainnet)\n 2. The contract address is correct" - ) - ); - return; - } - } catch (error) { - if (error instanceof Error) { - console.error( - chalk.red("🚨 Error during transfer:"), - chalk.yellow(error.message) - ); - } else { - console.error(chalk.red("🚨 An unknown error occurred.")); - } - } -} diff --git a/src/constants/tokenAdress.ts b/src/constants/tokenAdress.ts new file mode 100644 index 0000000..cefdd25 --- /dev/null +++ b/src/constants/tokenAdress.ts @@ -0,0 +1,16 @@ +import { Address } from "viem"; + +export const TOKENS: Record> = { + RIF: { + mainnet: "0x2acc95758f8b5F583470ba265eb685a8f45fc9d5", + testnet: "0xC370cD19517b5A8a9f6dF0958679e8cd4874C048", + }, + rUSDT: { + mainnet: "0xEf213441a85DF4d7acBdAe0Cf78004E1e486BB96", + testnet: "0x31974a4970BAda0ca9bCdE2e2EE6FC15922c5334", + }, + rDoc: { + mainnet: "0x2d919f19D4892381d58EdEbEcA66D5642ceF1A1F", + testnet: "0x7fb303D9806a72563C46aAd8D874B301419c374b", + }, +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index fd2e6e9..32b8f27 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,9 @@ import { Address, isAddress, PublicClient } from "viem"; import chalk from "chalk"; +import fs from "fs"; +import path from "path"; + +const walletFilePath = path.join(process.cwd(), "rootstock-wallet.json"); export function wait(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); @@ -27,3 +31,24 @@ export async function isValidContract( return false; } } + +export function getAddress(address?: Address): Address | undefined { + if (address) { + return validateAndFormatAddress(address); + } + + if (!fs.existsSync(walletFilePath)) { + console.log(chalk.red("🚫 No saved wallet found")); + return undefined; + } + + try { + const { address: savedAddress } = JSON.parse( + fs.readFileSync(walletFilePath, "utf8") + ); + return validateAndFormatAddress(savedAddress); + } catch (error) { + console.log(chalk.red("⚠️ Invalid wallet data")); + return undefined; + } +} diff --git a/src/utils/tokenHelper.ts b/src/utils/tokenHelper.ts index 451cf05..f86357c 100644 --- a/src/utils/tokenHelper.ts +++ b/src/utils/tokenHelper.ts @@ -1,36 +1,50 @@ -import { Address } from "viem"; -import ViemProvider from "./viemProvider"; +import { Address, PublicClient } from "viem"; import { erc20ABI } from "../constants/erc20ABI.js"; +import { TOKENS } from "../constants/tokenAdress"; -interface TokenInfo { - name: string; - symbol: string; - decimals: number; +export function resolveTokenAddress(token: string, testnet: boolean): Address { + return TOKENS[token][ + testnet ? "testnet" : "mainnet" + ].toLowerCase() as Address; } - export async function getTokenInfo( - provider: ViemProvider, - contractAddress: Address -): Promise { - const client = await provider.getPublicClient(); - - const [name, symbol, decimals] = await Promise.all([ + client: PublicClient, + tokenAddress: Address, + holderAddress: Address +): Promise<{ + balance: bigint; + decimals: number; + name: string; + symbol: string; +}> { + const [balance, decimals, name, symbol] = await Promise.all([ client.readContract({ - address: contractAddress, + address: tokenAddress, + abi: erc20ABI, + functionName: "balanceOf", + args: [holderAddress], + }), + client.readContract({ + address: tokenAddress, + abi: erc20ABI, + functionName: "decimals", + }), + client.readContract({ + address: tokenAddress, abi: erc20ABI, functionName: "name", }) as Promise, client.readContract({ - address: contractAddress, + address: tokenAddress, abi: erc20ABI, functionName: "symbol", }) as Promise, - client.readContract({ - address: contractAddress, - abi: erc20ABI, - functionName: "decimals", - }) as Promise, ]); - return { name, symbol, decimals }; + return { + balance: balance as bigint, + decimals: decimals as number, + name: name, + symbol: symbol, + }; } From 73d21a6f32ad2217387c8e06a8625771ba255aaf Mon Sep 17 00:00:00 2001 From: Pratham Date: Fri, 6 Dec 2024 12:40:54 +0530 Subject: [PATCH 20/32] chore: u[date error comment --- src/commands/balance.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commands/balance.ts b/src/commands/balance.ts index cdab365..782794e 100644 --- a/src/commands/balance.ts +++ b/src/commands/balance.ts @@ -22,7 +22,6 @@ export async function balanceCommand( const targetAddress = getAddress(holderAddress); if (!targetAddress) { - console.log(chalk.red("⚠️ No valid aholder ddress found")); return; } const provider = new ViemProvider(testnet); From 7cc11a50410f033f550869f7e8b3af9039380a98 Mon Sep 17 00:00:00 2001 From: Pratham Date: Fri, 6 Dec 2024 16:19:37 +0530 Subject: [PATCH 21/32] fix: wallet address fetch --- src/utils/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index 1fc7454..0265808 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,7 +1,6 @@ import { Address, isAddress, PublicClient } from "viem"; import chalk from "chalk"; import fs from "fs"; -import path from "path"; import { ALLOWED_BRIDGE_METHODS, METHOD_TYPES, @@ -46,9 +45,10 @@ export function getAddress(address?: Address): Address | undefined { } try { - const { address: savedAddress } = JSON.parse( + const { currentWallet, wallets } = JSON.parse( fs.readFileSync(walletFilePath, "utf8") ); + const savedAddress = wallets[currentWallet].address; return validateAndFormatAddress(savedAddress); } catch (error) { console.log(chalk.red("⚠️ Invalid wallet data")); From 7ba62af501d36e916cf543af6a4d95f417c03cd6 Mon Sep 17 00:00:00 2001 From: Pratham Date: Fri, 6 Dec 2024 23:11:30 +0530 Subject: [PATCH 22/32] fix: add erc20 contract check --- src/commands/balance.ts | 14 ++++++++-- src/constants/erc20ABI.ts | 7 +++++ src/utils/index.ts | 3 +++ src/utils/tokenHelper.ts | 54 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/commands/balance.ts b/src/commands/balance.ts index 782794e..16ab39d 100644 --- a/src/commands/balance.ts +++ b/src/commands/balance.ts @@ -1,7 +1,11 @@ import ViemProvider from "../utils/viemProvider.js"; import chalk from "chalk"; import inquirer from "inquirer"; -import { getTokenInfo, resolveTokenAddress } from "../utils/tokenHelper.js"; +import { + getTokenInfo, + isERC20Contract, + resolveTokenAddress, +} from "../utils/tokenHelper.js"; import ora from "ora"; import { console } from "inspector"; import { @@ -78,7 +82,10 @@ export async function balanceCommand( return "🚫 Invalid contract address"; } if (!(await isValidContract(client, formattedContractAddress))) { - return " 🚫 Invalid contract address or contract not found"; + return "🚫 Invalid contract address or contract not found"; + } + if (!(await isERC20Contract(client, formattedContractAddress))) { + return "🚫 Invalid contract address, only ERC20 tokens are supported"; } return true; } catch { @@ -98,6 +105,7 @@ export async function balanceCommand( tokenAddress, targetAddress ); + console.log(name, balance, decimals, symbol); const formattedBalance = formatUnits(balance, decimals); spinner.succeed(chalk.green("Balance retrieved successfully")); @@ -127,5 +135,7 @@ export async function balanceCommand( } else { console.error(chalk.red("🚨 An unknown error occurred.")); } + } finally { + spinner.stop(); } } diff --git a/src/constants/erc20ABI.ts b/src/constants/erc20ABI.ts index fe68871..eaa310f 100644 --- a/src/constants/erc20ABI.ts +++ b/src/constants/erc20ABI.ts @@ -27,6 +27,13 @@ export const erc20ABI = [ outputs: [{ name: "balance", type: "uint256" }], type: "function", }, + { + constant: true, + inputs: [], + name: "totalSupply", + outputs: [{ name: "", type: "uint256" }], + type: "function", + }, { constant: false, inputs: [ diff --git a/src/utils/index.ts b/src/utils/index.ts index 0265808..ea283ac 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -34,6 +34,9 @@ export async function isValidContract( } } + + + export function getAddress(address?: Address): Address | undefined { if (address) { return validateAndFormatAddress(address); diff --git a/src/utils/tokenHelper.ts b/src/utils/tokenHelper.ts index f86357c..1cd5cf6 100644 --- a/src/utils/tokenHelper.ts +++ b/src/utils/tokenHelper.ts @@ -1,4 +1,4 @@ -import { Address, PublicClient } from "viem"; +import { Address, encodeFunctionData, PublicClient } from "viem"; import { erc20ABI } from "../constants/erc20ABI.js"; import { TOKENS } from "../constants/tokenAdress"; @@ -48,3 +48,55 @@ export async function getTokenInfo( symbol: symbol, }; } + +export async function isERC20Contract( + client: PublicClient, + address: Address +): Promise { + try { + const checks = await Promise.all([ + client + .call({ + to: address, + data: encodeFunctionData({ + abi: erc20ABI, + functionName: "totalSupply", + }), + }) + .then(() => true) + .catch(() => false), + client + .call({ + to: address, + data: encodeFunctionData({ + abi: erc20ABI, + functionName: "decimals", + }), + }) + .then(() => true) + .catch(() => false), + + client + .call({ + to: address, + data: encodeFunctionData({ + abi: erc20ABI, + functionName: "symbol", + }), + }) + .then(() => true) + .catch(() => false), + ]); + + const isERC20 = checks.every((check) => check === true); + + if (!isERC20) { + return false; + } + + return true; + } catch (error) { + console.error("Error checking ERC20 contract:", error); + return false; + } +} From 42b69cbcd9df22d3a6c7dc789fb41ce06d487407 Mon Sep 17 00:00:00 2001 From: SarveshLimaye Date: Fri, 6 Dec 2024 23:17:44 +0530 Subject: [PATCH 23/32] feat:show transaction history for current wallet --- README.md | 43 ++++++++++++++++ bin/index.ts | 9 ++++ src/commands/history.ts | 106 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 src/commands/history.ts diff --git a/README.md b/README.md index 0249515..df64a1b 100644 --- a/README.md +++ b/README.md @@ -337,6 +337,49 @@ Output example: 🔗 View on Explorer: https://explorer.testnet.rootstock.io/address/0x0000000000000000000000000000000001000006 ``` +### 9. Fetch Wallet History + +The history command allows you to fetch the transaction history for a wallet on the Rootstock blockchain. This includes transactions such as ERC20, ERC721, and external transfers. You can specify whether to fetch the history from the Mainnet or Testnet by providing the appropriate flag + +#### Mainnet + +```bash +rsk-cli history +``` + +#### Testnet + +```bash +rsk-cli history --testnet +``` + +Output example: + +``` +? 🔒 Enter Alchemy API key to fetch history: ******************************** +🔍 Fetching transaction history for 0x19661D036D4e590948b9c00eef3807b88fBfA8e1 ... +✅ Transaction history fetched successfully: [ + { + "blockNum": "0x57bdd9", + "uniqueId": "0xde678614cd9e20fe5891c25069afef680174456b104f31c9078eb486abd95a64:external", + "hash": "0xde678614cd9e20fe5891c25069afef680174456b104f31c9078eb486abd95a64", + "from": "0x19661d036d4e590948b9c00eef3807b88fbfa8e1", + "to": "0xb45805aead9407f5c7860ff8eccaedd4d0ab36a6", + "value": 0.000003, + "erc721TokenId": null, + "erc1155Metadata": null, + "tokenId": null, + "asset": "ETH", + "category": "external", + "rawContract": { + "value": "0x2ba7def3000", + "address": null, + "decimal": "0x12" + } + } +] +``` + ## Contributing We welcome contributions from the community. Please fork the repository and submit pull requests with your changes. Ensure your code adheres to the project's main objective. diff --git a/bin/index.ts b/bin/index.ts index f240d42..f496c96 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -10,6 +10,7 @@ import { deployCommand } from "../src/commands/deploy.js"; import { verifyCommand } from "../src/commands/verify.js"; import { ReadContract } from "../src/commands/contract.js"; import { bridgeCommand } from "../src/commands/bridge.js"; +import { historyCommand } from "../src/commands/history.js"; interface CommandOptions { testnet?: boolean; @@ -151,4 +152,12 @@ program await bridgeCommand(!!options.testnet); }); +program + .command("history") + .description("Fetch history for current wallet") + .option("-t, --testnet", "History of wallet on the testnet") + .action(async (options: CommandOptions) => { + await historyCommand(!!options.testnet); + }); + program.parse(process.argv); diff --git a/src/commands/history.ts b/src/commands/history.ts new file mode 100644 index 0000000..58b8e3b --- /dev/null +++ b/src/commands/history.ts @@ -0,0 +1,106 @@ +import chalk from "chalk"; +import fs from "fs"; +import { walletFilePath } from "../utils/constants.js"; +import inquirer from "inquirer"; + +type InquirerAnswers = { + apiKey?: string; +}; + +export async function historyCommand(testnet: boolean) { + try { + if (!fs.existsSync(walletFilePath)) { + console.log( + chalk.red("🚫 No saved wallet found. Please create a wallet first.") + ); + return; + } + + 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; + const wallet = wallets[currentWallet]; + const { address: walletAddress } = wallet; + + const apiKeyQuestion: any = [ + { + type: "password", + name: "apiKey", + message: "🔒 Enter Alchemy API key to fetch history:", + mask: "*", + }, + ]; + + const { apiKey } = await inquirer.prompt(apiKeyQuestion); + + console.log( + chalk.blue(`🔍 Fetching transaction history for ${walletAddress} ... `) + ); + + const data = JSON.stringify({ + jsonrpc: "2.0", + id: 0, + method: "alchemy_getAssetTransfers", + params: [ + { + fromBlock: "0x0", + fromAddress: walletAddress, + category: ["external", "erc20", "erc721", "erc1155"], + }, + ], + }); + + const testnetUrl = `https://rootstock-testnet.g.alchemy.com/v2/${apiKey}`; + const mainnetUrl = `https://rootstock-mainnet.g.alchemy.com/v2/${apiKey}`; + const baseURL = testnet ? testnetUrl : mainnetUrl; + + const response = await fetch(baseURL, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: data, + }); + + if (!response.ok) { + // Check if HTTP response is unsuccessful + console.error( + chalk.red(`❌ API request failed with status: ${response.status}`) + ); + return; + } + + const result = await response.json(); + + // Handle Alchemy-specific errors + if (result.error) { + console.error( + chalk.red(`❌ Error from Alchemy: ${result.error.message}`) + ); + return; + } + + // Handle missing or empty transfers + const transfers = result.result?.transfers; + if (!transfers || transfers.length === 0) { + console.log(chalk.yellow("⚠️ No transactions found.")); + return; + } + + console.log( + chalk.green("✅ Transaction history fetched successfully:"), + chalk.blue(JSON.stringify(transfers, null, 2)) + ); + } catch (error: any) { + console.error( + chalk.red(`🚨 An unknown error occurred: ${error.message || error}`) + ); + } +} From 920bd624cc69b6bb406c85a6c1cdca576472759a Mon Sep 17 00:00:00 2001 From: Chandra Bose Date: Sat, 7 Dec 2024 23:17:28 +0530 Subject: [PATCH 24/32] refactor: streamline wallet data handling and improve backup process --- src/commands/wallet.ts | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/src/commands/wallet.ts b/src/commands/wallet.ts index 505ea48..4c44c10 100644 --- a/src/commands/wallet.ts +++ b/src/commands/wallet.ts @@ -513,14 +513,10 @@ export async function walletCommand() { } } -async function writeWalletData(walletFilePath: string, walletsData: any) { +async function writeWalletData(filePath: string, data: any) { try { - fs.writeFileSync( - walletFilePath, - JSON.stringify(walletsData, null, 2), - "utf8" - ); - console.log(chalk.green(`💾 Changes saved at ${walletFilePath}`)); + fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf8"); + console.log(chalk.green(`💾 Changes saved at ${filePath}`)); } catch (error: any) { console.error( chalk.red("❌ Error saving wallet data:"), @@ -546,7 +542,7 @@ async function backupCommand(backupPath: string) { if (fs.existsSync(absoluteBackupPath) && fs.lstatSync(absoluteBackupPath).isDirectory()) { absoluteBackupPath = path.join(absoluteBackupPath, 'wallet_backup.json'); - console.log(chalk.yellow(`⚠️ You provided a directory. Using default file name: wallet_backup.json`)); + console.log(chalk.yellow(`⚠️ Provided a directory. Using default file name: wallet_backup.json`)); } if (!fs.existsSync(backupDir)) { @@ -554,21 +550,13 @@ async function backupCommand(backupPath: string) { console.log(chalk.green(`📂 Created backup directory: ${backupDir}`)); } - const walletData = fs.readFileSync(walletFilePath, "utf8"); - - try { - fs.writeFileSync(absoluteBackupPath, walletData, "utf8"); - console.log( - chalk.green("✅ Wallet backup created successfully!"), - chalk.green(`\n💾 Backup saved successfully at: ${absoluteBackupPath}`) - ); - } catch (writeError: any) { - console.error( - chalk.red("🚨 Error saving the backup file:"), - chalk.yellow(writeError.message) - ); - } + const walletData = JSON.parse(fs.readFileSync(walletFilePath, "utf8")); + writeWalletData(absoluteBackupPath, walletData); + console.log( + chalk.green("✅ Wallet backup created successfully!"), + chalk.green(`\n💾 Backup saved successfully at: ${absoluteBackupPath}`) + ); } catch (error: any) { console.error( chalk.red("🚨 Error during wallet backup:"), From 25e8cdd9c571af0a8d3c6cf0b61f718eb13e5df9 Mon Sep 17 00:00:00 2001 From: Pratham Date: Tue, 10 Dec 2024 14:19:49 +0530 Subject: [PATCH 25/32] chore: update token address --- src/constants/tokenAdress.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/constants/tokenAdress.ts b/src/constants/tokenAdress.ts index cefdd25..fe901d1 100644 --- a/src/constants/tokenAdress.ts +++ b/src/constants/tokenAdress.ts @@ -3,14 +3,14 @@ import { Address } from "viem"; export const TOKENS: Record> = { RIF: { mainnet: "0x2acc95758f8b5F583470ba265eb685a8f45fc9d5", - testnet: "0xC370cD19517b5A8a9f6dF0958679e8cd4874C048", + testnet: "0x19f64674d8a5b4e652319f5e239efd3bc969a1fe", }, rUSDT: { mainnet: "0xEf213441a85DF4d7acBdAe0Cf78004E1e486BB96", - testnet: "0x31974a4970BAda0ca9bCdE2e2EE6FC15922c5334", + testnet: "0x2694785f9c3006edf88df3a66ba7adf106dbd6a0", }, rDoc: { mainnet: "0x2d919f19D4892381d58EdEbEcA66D5642ceF1A1F", - testnet: "0x7fb303D9806a72563C46aAd8D874B301419c374b", + testnet: "0x7fb303d9806a72563c46aad8d874b301419c374b", }, }; From 7749ce255a3279b61c80eb37797470bd65fe44da Mon Sep 17 00:00:00 2001 From: Pratham Date: Tue, 10 Dec 2024 14:28:37 +0530 Subject: [PATCH 26/32] chore: rmv debug console --- src/commands/balance.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commands/balance.ts b/src/commands/balance.ts index 16ab39d..96d9785 100644 --- a/src/commands/balance.ts +++ b/src/commands/balance.ts @@ -105,7 +105,6 @@ export async function balanceCommand( tokenAddress, targetAddress ); - console.log(name, balance, decimals, symbol); const formattedBalance = formatUnits(balance, decimals); spinner.succeed(chalk.green("Balance retrieved successfully")); From ff2e1fd6ed9cc86c7c4fac238db8b05e0d808ddc Mon Sep 17 00:00:00 2001 From: SarveshLimaye Date: Mon, 16 Dec 2024 11:48:20 +0530 Subject: [PATCH 27/32] chore:history command enhancements --- bin/index.ts | 4 +- src/commands/history.ts | 92 ++++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/bin/index.ts b/bin/index.ts index f496c96..3184459 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -19,6 +19,7 @@ interface CommandOptions { txid?: string; abi?: string; bytecode?: string; + apiKey?: string; args?: any; json?: any; name?: string; @@ -155,9 +156,10 @@ program program .command("history") .description("Fetch history for current wallet") + .option("--apiKey { - await historyCommand(!!options.testnet); + await historyCommand(!!options.testnet, options.apiKey!); }); program.parse(process.argv); diff --git a/src/commands/history.ts b/src/commands/history.ts index 58b8e3b..ea9109b 100644 --- a/src/commands/history.ts +++ b/src/commands/history.ts @@ -1,14 +1,23 @@ import chalk from "chalk"; import fs from "fs"; import { walletFilePath } from "../utils/constants.js"; -import inquirer from "inquirer"; -type InquirerAnswers = { - apiKey?: string; -}; - -export async function historyCommand(testnet: boolean) { +export async function historyCommand(testnet: boolean, apiKey: string) { try { + // Check if API key exists in storage or passed as argument + let storedApiKey = getApiKeyFromStorage(); + + if (apiKey && !storedApiKey) { + await writeApiKey(apiKey); + } + + if (!apiKey && !storedApiKey) { + console.log(chalk.red("🔑 Alchemy API key is missing.")); + return; + } + + const finalApiKey = apiKey || storedApiKey; + if (!fs.existsSync(walletFilePath)) { console.log( chalk.red("🚫 No saved wallet found. Please create a wallet first.") @@ -31,17 +40,6 @@ export async function historyCommand(testnet: boolean) { const wallet = wallets[currentWallet]; const { address: walletAddress } = wallet; - const apiKeyQuestion: any = [ - { - type: "password", - name: "apiKey", - message: "🔒 Enter Alchemy API key to fetch history:", - mask: "*", - }, - ]; - - const { apiKey } = await inquirer.prompt(apiKeyQuestion); - console.log( chalk.blue(`🔍 Fetching transaction history for ${walletAddress} ... `) ); @@ -59,8 +57,8 @@ export async function historyCommand(testnet: boolean) { ], }); - const testnetUrl = `https://rootstock-testnet.g.alchemy.com/v2/${apiKey}`; - const mainnetUrl = `https://rootstock-mainnet.g.alchemy.com/v2/${apiKey}`; + const testnetUrl = `https://rootstock-testnet.g.alchemy.com/v2/${finalApiKey}`; + const mainnetUrl = `https://rootstock-mainnet.g.alchemy.com/v2/${finalApiKey}`; const baseURL = testnet ? testnetUrl : mainnetUrl; const response = await fetch(baseURL, { @@ -70,7 +68,6 @@ export async function historyCommand(testnet: boolean) { }); if (!response.ok) { - // Check if HTTP response is unsuccessful console.error( chalk.red(`❌ API request failed with status: ${response.status}`) ); @@ -87,20 +84,65 @@ export async function historyCommand(testnet: boolean) { return; } - // Handle missing or empty transfers const transfers = result.result?.transfers; if (!transfers || transfers.length === 0) { console.log(chalk.yellow("⚠️ No transactions found.")); return; } + for (const transfer of transfers) { + console.log(chalk.green(`✅ Transfer:`)); + console.log(` From: ${transfer.from}`); + console.log(` To: ${transfer.to}`); + console.log(` Token: ${transfer.asset || "N/A"}`); + console.log(` Value: ${transfer.value || "N/A"}`); + console.log(` Tx Hash: ${transfer.hash}`); + } + } catch (error: any) { + console.error( + chalk.red(`🚨 An unknown error occurred: ${error.message || error}`) + ); + } +} - console.log( - chalk.green("✅ Transaction history fetched successfully:"), - chalk.blue(JSON.stringify(transfers, null, 2)) +async function writeApiKey(apiKey: string) { + try { + // Check if wallet file exists + if (!fs.existsSync(walletFilePath)) { + console.error( + chalk.red("🚫 Wallet file not found. Please create a wallet first.") + ); + return; + } + + // 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)); + + console.log(chalk.green(`✅ Alchemy API key updated successfully.`)); + } catch (error: any) { + console.error( + chalk.red("❌ Error updating Alchemy API key:"), + chalk.yellow(error.message || error) ); + } +} + +function getApiKeyFromStorage(): string | undefined { + try { + if (fs.existsSync(walletFilePath)) { + const configData = JSON.parse(fs.readFileSync(walletFilePath, "utf8")); + return configData.alchemyApiKey; + } + return undefined; } catch (error: any) { console.error( - chalk.red(`🚨 An unknown error occurred: ${error.message || error}`) + chalk.red("❌ Error reading alchemy API key:"), + chalk.yellow(error.message || error) ); } } From 5b850289518a3b074871b1a7aeb53282afe3d55b Mon Sep 17 00:00:00 2001 From: Pratham Date: Tue, 17 Dec 2024 12:46:24 +0530 Subject: [PATCH 28/32] chore: remove blank space --- src/utils/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index ea283ac..0265808 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -34,9 +34,6 @@ export async function isValidContract( } } - - - export function getAddress(address?: Address): Address | undefined { if (address) { return validateAndFormatAddress(address); From 9627a62a9b81d16a8e734710a11d329af1b3ce95 Mon Sep 17 00:00:00 2001 From: Pratham Date: Tue, 17 Dec 2024 12:52:45 +0530 Subject: [PATCH 29/32] chore: change token address --- src/constants/tokenAdress.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/constants/tokenAdress.ts b/src/constants/tokenAdress.ts index fe901d1..d3d803d 100644 --- a/src/constants/tokenAdress.ts +++ b/src/constants/tokenAdress.ts @@ -5,12 +5,12 @@ export const TOKENS: Record> = { mainnet: "0x2acc95758f8b5F583470ba265eb685a8f45fc9d5", testnet: "0x19f64674d8a5b4e652319f5e239efd3bc969a1fe", }, - rUSDT: { - mainnet: "0xEf213441a85DF4d7acBdAe0Cf78004E1e486BB96", - testnet: "0x2694785f9c3006edf88df3a66ba7adf106dbd6a0", + USDRIF: { + mainnet: "0x3A15461d8ae0f0fb5fa2629e9da7D66a794a6e37", + testnet: "0xd1b0d1bc03491f49b9aea967ddd07b37f7327e63", }, - rDoc: { - mainnet: "0x2d919f19D4892381d58EdEbEcA66D5642ceF1A1F", - testnet: "0x7fb303d9806a72563c46aad8d874b301419c374b", + DoC: { + mainnet: "0xe700691da7B9851f2f35f8b8182c69c53ccad9db", + testnet: "0xd37a3e5874be2dc6c732ad21c008a1e4032a6040", }, }; From 83a7c434637d3fd0a5a2269458f75dffccc1fda6 Mon Sep 17 00:00:00 2001 From: Pratham Date: Tue, 17 Dec 2024 12:57:40 +0530 Subject: [PATCH 30/32] chore: rmv console import --- src/commands/balance.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commands/balance.ts b/src/commands/balance.ts index 96d9785..cb5edd9 100644 --- a/src/commands/balance.ts +++ b/src/commands/balance.ts @@ -7,7 +7,6 @@ import { resolveTokenAddress, } from "../utils/tokenHelper.js"; import ora from "ora"; -import { console } from "inspector"; import { getAddress, isValidContract, From d97a9b9ec046cee51d73e098ba3ee20ce29da8e9 Mon Sep 17 00:00:00 2001 From: Pratham Date: Tue, 17 Dec 2024 20:02:27 +0530 Subject: [PATCH 31/32] feat: add viem erc20Abi --- src/constants/erc20ABI.ts | 47 --------------------------------------- src/utils/tokenHelper.ts | 17 +++++++------- 2 files changed, 8 insertions(+), 56 deletions(-) delete mode 100644 src/constants/erc20ABI.ts diff --git a/src/constants/erc20ABI.ts b/src/constants/erc20ABI.ts deleted file mode 100644 index eaa310f..0000000 --- a/src/constants/erc20ABI.ts +++ /dev/null @@ -1,47 +0,0 @@ -export const erc20ABI = [ - { - constant: true, - inputs: [], - name: "name", - outputs: [{ name: "", type: "string" }], - type: "function", - }, - { - constant: true, - inputs: [], - name: "symbol", - outputs: [{ name: "", type: "string" }], - type: "function", - }, - { - constant: true, - inputs: [], - name: "decimals", - outputs: [{ name: "", type: "uint8" }], - type: "function", - }, - { - constant: true, - inputs: [{ name: "_owner", type: "address" }], - name: "balanceOf", - outputs: [{ name: "balance", type: "uint256" }], - type: "function", - }, - { - constant: true, - inputs: [], - name: "totalSupply", - outputs: [{ name: "", type: "uint256" }], - type: "function", - }, - { - constant: false, - inputs: [ - { name: "_to", type: "address" }, - { name: "_value", type: "uint256" }, - ], - name: "transfer", - outputs: [{ name: "", type: "bool" }], - type: "function", - }, -] as const; diff --git a/src/utils/tokenHelper.ts b/src/utils/tokenHelper.ts index 1cd5cf6..429e729 100644 --- a/src/utils/tokenHelper.ts +++ b/src/utils/tokenHelper.ts @@ -1,5 +1,4 @@ -import { Address, encodeFunctionData, PublicClient } from "viem"; -import { erc20ABI } from "../constants/erc20ABI.js"; +import { Address, encodeFunctionData, PublicClient, erc20Abi } from "viem"; import { TOKENS } from "../constants/tokenAdress"; export function resolveTokenAddress(token: string, testnet: boolean): Address { @@ -20,23 +19,23 @@ export async function getTokenInfo( const [balance, decimals, name, symbol] = await Promise.all([ client.readContract({ address: tokenAddress, - abi: erc20ABI, + abi: erc20Abi, functionName: "balanceOf", args: [holderAddress], }), client.readContract({ address: tokenAddress, - abi: erc20ABI, + abi: erc20Abi, functionName: "decimals", }), client.readContract({ address: tokenAddress, - abi: erc20ABI, + abi: erc20Abi, functionName: "name", }) as Promise, client.readContract({ address: tokenAddress, - abi: erc20ABI, + abi: erc20Abi, functionName: "symbol", }) as Promise, ]); @@ -59,7 +58,7 @@ export async function isERC20Contract( .call({ to: address, data: encodeFunctionData({ - abi: erc20ABI, + abi: erc20Abi, functionName: "totalSupply", }), }) @@ -69,7 +68,7 @@ export async function isERC20Contract( .call({ to: address, data: encodeFunctionData({ - abi: erc20ABI, + abi: erc20Abi, functionName: "decimals", }), }) @@ -80,7 +79,7 @@ export async function isERC20Contract( .call({ to: address, data: encodeFunctionData({ - abi: erc20ABI, + abi: erc20Abi, functionName: "symbol", }), }) From ce53f72dd34b839e575a4f6fc1f6ecc61f1e36e9 Mon Sep 17 00:00:00 2001 From: SarveshLimaye Date: Wed, 18 Dec 2024 23:34:18 +0530 Subject: [PATCH 32/32] chore:history command enhancements --- README.md | 45 ++++++++++++++++++++++------------------- bin/index.ts | 4 +++- package.json | 3 ++- src/commands/history.ts | 29 ++++++++++++++++---------- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index df64a1b..61157fe 100644 --- a/README.md +++ b/README.md @@ -343,12 +343,28 @@ The history command allows you to fetch the transaction history for a wallet on #### Mainnet +With arguments: + +```bash +rsk-cli history --apiKey --number +``` + +Without arguments: + ```bash rsk-cli history ``` #### Testnet +With arguments: + +```bash +rsk-cli history --testnet --apiKey --number +``` + +Without arguments + ```bash rsk-cli history --testnet ``` @@ -357,27 +373,14 @@ Output example: ``` ? 🔒 Enter Alchemy API key to fetch history: ******************************** -🔍 Fetching transaction history for 0x19661D036D4e590948b9c00eef3807b88fBfA8e1 ... -✅ Transaction history fetched successfully: [ - { - "blockNum": "0x57bdd9", - "uniqueId": "0xde678614cd9e20fe5891c25069afef680174456b104f31c9078eb486abd95a64:external", - "hash": "0xde678614cd9e20fe5891c25069afef680174456b104f31c9078eb486abd95a64", - "from": "0x19661d036d4e590948b9c00eef3807b88fbfa8e1", - "to": "0xb45805aead9407f5c7860ff8eccaedd4d0ab36a6", - "value": 0.000003, - "erc721TokenId": null, - "erc1155Metadata": null, - "tokenId": null, - "asset": "ETH", - "category": "external", - "rawContract": { - "value": "0x2ba7def3000", - "address": null, - "decimal": "0x12" - } - } -] +🔍 Fetching transaction history on Rootstack Testnet for 0x19661D036D4e590948b9c00eef3807b88fBfA8e1 ... +✅ Transfer: + From: 0x19661d036d4e590948b9c00eef3807b88fbfa8e1 + To: 0xb45805aead9407f5c7860ff8eccaedd4d0ab36a6 + Token: ETH + Value: 0.000003 + Tx Hash: 0xde678614cd9e20fe5891c25069afef680174456b104f31c9078eb486abd95a64 + ``` ## Contributing diff --git a/bin/index.ts b/bin/index.ts index 3184459..34a9e60 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -24,6 +24,7 @@ interface CommandOptions { json?: any; name?: string; decodedArgs?: any; + number?: string; } const orange = chalk.rgb(255, 165, 0); @@ -157,9 +158,10 @@ program .command("history") .description("Fetch history for current wallet") .option("--apiKey ", "Number of transactions to fetch") .option("-t, --testnet", "History of wallet on the testnet") .action(async (options: CommandOptions) => { - await historyCommand(!!options.testnet, options.apiKey!); + await historyCommand(!!options.testnet, options.apiKey!, options.number!); }); program.parse(process.argv); diff --git a/package.json b/package.json index f16f391..743c35d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "wallet": "pnpm run build && node dist/bin/index.js wallet", "balance": "pnpm run build && node dist/bin/index.js balance", "transfer": "pnpm run build && node dist/bin/index.js transfer --testnet --address 0xa5f45f5bddefC810C48aCC1D5CdA5e5a4c6BC59E --value 0.001", - "tx-status": "pnpm run build && node dist/bin/index.js tx --testnet --txid 0x876a0a9b167889350c41930a4204e5d9acf5704a7f201447a337094189af961c4" + "tx-status": "pnpm run build && node dist/bin/index.js tx --testnet --txid 0x876a0a9b167889350c41930a4204e5d9acf5704a7f201447a337094189af961c4", + "history": "pnpm run build && node dist/bin/index.js history" }, "keywords": [ "rootstock", diff --git a/src/commands/history.ts b/src/commands/history.ts index ea9109b..4d66a1c 100644 --- a/src/commands/history.ts +++ b/src/commands/history.ts @@ -2,7 +2,11 @@ import chalk from "chalk"; import fs from "fs"; import { walletFilePath } from "../utils/constants.js"; -export async function historyCommand(testnet: boolean, apiKey: string) { +export async function historyCommand( + testnet: boolean, + apiKey: string, + number: string +) { try { // Check if API key exists in storage or passed as argument let storedApiKey = getApiKeyFromStorage(); @@ -41,7 +45,11 @@ export async function historyCommand(testnet: boolean, apiKey: string) { const { address: walletAddress } = wallet; console.log( - chalk.blue(`🔍 Fetching transaction history for ${walletAddress} ... `) + chalk.blue( + `🔍 Fetching transaction history on Rootstack ${ + testnet ? "Testnet" : "Mainnet" + } for ${walletAddress} ... ` + ) ); const data = JSON.stringify({ @@ -53,6 +61,7 @@ export async function historyCommand(testnet: boolean, apiKey: string) { fromBlock: "0x0", fromAddress: walletAddress, category: ["external", "erc20", "erc721", "erc1155"], + withMetadata: true, }, ], }); @@ -84,11 +93,16 @@ export async function historyCommand(testnet: boolean, apiKey: string) { return; } - const transfers = result.result?.transfers; + let transfers = result.result?.transfers; + if (!transfers || transfers.length === 0) { console.log(chalk.yellow("⚠️ No transactions found.")); return; } + + if (number) { + transfers = transfers.slice(0, parseInt(number)); + } for (const transfer of transfers) { console.log(chalk.green(`✅ Transfer:`)); console.log(` From: ${transfer.from}`); @@ -96,6 +110,7 @@ export async function historyCommand(testnet: boolean, apiKey: string) { console.log(` Token: ${transfer.asset || "N/A"}`); console.log(` Value: ${transfer.value || "N/A"}`); console.log(` Tx Hash: ${transfer.hash}`); + console.log(` Time: ${new Date(transfer.metadata.blockTimestamp)}`); } } catch (error: any) { console.error( @@ -106,14 +121,6 @@ export async function historyCommand(testnet: boolean, apiKey: string) { async function writeApiKey(apiKey: string) { try { - // Check if wallet file exists - if (!fs.existsSync(walletFilePath)) { - console.error( - chalk.red("🚫 Wallet file not found. Please create a wallet first.") - ); - return; - } - // Read the existing wallet file const walletsData = JSON.parse(fs.readFileSync(walletFilePath, "utf8"));