use anyhow::Result;
use clap::{Parser, Subcommand};
use forc_tracing::{init_tracing_subscriber, println_error};
use forc_wallet::{
account::{self, Account, Accounts},
balance::{self, Balance},
import::{import_wallet_cli, Import},
list::{list_wallet_cli, List},
network::DEFAULT as DEFAULT_NODE_URL,
new::{new_wallet_cli, New},
sign::{self, Sign},
utils::default_wallet_path,
CliContext,
};
use std::path::PathBuf;
use url::Url;
#[derive(Debug, Parser)]
#[clap(name = "forc wallet", about = ABOUT, after_long_help = EXAMPLES, version)]
struct App {
#[clap(long = "path", default_value_os_t = default_wallet_path() )]
wallet_path: PathBuf,
#[clap(long, default_value_t = Url::parse(DEFAULT_NODE_URL).unwrap())]
node_url: Url,
#[clap(subcommand)]
pub cmd: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
New(New),
List(List),
Import(Import),
Accounts(Accounts),
Account(Account),
Sign(Sign),
Balance(Balance),
}
const ABOUT: &str = "A forc plugin for generating or importing wallets using BIP39 phrases.";
const EXAMPLES: &str = r#"
EXAMPLES:
# Create a new wallet at the default path `~/.fuel/wallets/.wallet`.
forc wallet new
# Create a new wallet and automatically replace the existing wallet if it's at the same path.
forc wallet new --force
# Import a new wallet from a mnemonic phrase.
forc wallet import
# Import a new wallet from a mnemonic phrase and automatically replace the existing wallet if it's at the same path.
forc wallet import --force
# Derive a new account for the default wallet.
forc wallet account new
# Derive a new account for the wallet at the given path.
forc wallet --path /path/to/wallet account new
# Derive (or re-derive) the account at index 5.
forc wallet account 5 new
# Sign a transaction ID with account at index 3.
forc wallet account 3 sign tx-id 0x0bf34feb362608c4171c87115d4a6f63d1cdf4c49b963b464762329488f3ed4f
# Sign an arbitrary string.
forc wallet account 3 sign string "blah blah blah"
# Sign the contents of a file.
forc wallet account 3 sign file /path/to/data-to-sign
# Sign a hex-encoded byte string.
forc wallet account 3 sign hex "0xDEADBEEF"
# You can also use the `sign` subcommand directly. The following gives the same result.
forc wallet sign --account 3 string "blah blah blah"
# Sign directly with a private key.
forc wallet sign --private-key string "blah blah blah"
# Temporarily display the private key of the account at index 0.
forc wallet account 0 private-key
# Show the public key of the account at index 0.
forc wallet account 0 public-key
# Transfer 1 token of the base asset id to a bech32 address at the gas price of 1.
forc wallet account 0 transfer --to fuel1dq2vgftet24u4nkpzmtfus9k689ap5avkm8kdjna8j3d6765yfdsjt6586
--amount 1 --asset-id 0x0000000000000000000000000000000000000000000000000000000000000000 --gas-price 1
# Transfer 1 token of the base asset id to a hex address at the gas price of 1.
forc wallet account 0 transfer --to 0x0b8d0f6a7f271919708530d11bdd9398205137e012424b611e9d97118c180bea
--amount 1 --asset-id 0x0000000000000000000000000000000000000000000000000000000000000000 --gas-price 1
"#;
#[tokio::main]
async fn main() {
init_tracing_subscriber(Default::default());
if let Err(err) = run().await {
println_error(&format!("{}", err));
std::process::exit(1);
}
}
async fn run() -> Result<()> {
let app = App::parse();
let ctx = CliContext {
wallet_path: app.wallet_path,
node_url: app.node_url,
};
match app.cmd {
Command::New(new) => new_wallet_cli(&ctx, new).await?,
Command::List(list) => list_wallet_cli(&ctx, list).await?,
Command::Import(import) => import_wallet_cli(&ctx, import).await?,
Command::Accounts(accounts) => account::print_accounts_cli(&ctx, accounts).await?,
Command::Account(account) => account::cli(&ctx, account).await?,
Command::Sign(sign) => sign::cli(&ctx, sign)?,
Command::Balance(balance) => balance::cli(&ctx, &balance).await?,
}
Ok(())
}