diff --git a/book/src/cli.md b/book/src/cli.md index 526237af0..63f663766 100644 --- a/book/src/cli.md +++ b/book/src/cli.md @@ -14,14 +14,20 @@ $ solana address ``` -#### Airdrop Lamports +#### Airdrop SOL/Lamports ```sh // Command -$ solana airdrop 123 +$ solana airdrop 2 // Return -"Your balance is: 123" +"2.00000000 SOL" + +// Command +$ solana airdrop 123 --lamports + +// Return +"123 lamports" ``` #### Get Balance @@ -31,7 +37,7 @@ $ solana airdrop 123 $ solana balance // Return -"Your balance is: 123" +"3.00050001 SOL" ``` #### Confirm Transaction @@ -175,29 +181,46 @@ USAGE: FLAGS: -h, --help Prints help information - --rpc-tls Enable TLS for the RPC endpoint -V, --version Prints version information OPTIONS: - --drone-host Drone host to use [default: same as --host] - --drone-port Drone port to use [default: 9900] - -n, --host Host to use for both RPC and drone [default: 127.0.0.1] - -k, --keypair /path/to/id.json - --rpc-host RPC host to use [default: same as --host] - --rpc-port RPC port to use [default: 8899] + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json SUBCOMMANDS: - address Get your public key - airdrop Request a batch of lamports - balance Get your balance - cancel Cancel a transfer - confirm Confirm transaction by signature - deploy Deploy a program - get-transaction-count Get current transaction count - help Prints this message or the help of the given subcommand(s) - pay Send a payment - send-signature Send a signature to authorize a transfer - send-timestamp Send a timestamp to unlock a transfer + address Get your public key + airdrop Request lamports + authorize-voter Authorize a new vote signing keypair for the given vote account + balance Get your balance + cancel Cancel a transfer + claim-storage-reward Redeem storage reward credits + cluster-version Get the version of the cluster entrypoint + confirm Confirm transaction by signature + create-replicator-storage-account Create a replicator storage account + create-storage-mining-pool-account Create mining pool account + create-validator-storage-account Create a validator storage account + create-vote-account Create a vote account + deactivate-stake Deactivate the delegated stake from the stake account + delegate-stake Delegate stake to a vote account + deploy Deploy a program + fees Display current cluster fees + get Get wallet config settings + get-slot Get current slot + get-transaction-count Get current transaction count + help Prints this message or the help of the given subcommand(s) + pay Send a payment + ping Submit transactions sequentially + redeem-vote-credits Redeem credits in the stake account + send-signature Send a signature to authorize a transfer + send-timestamp Send a timestamp to unlock a transfer + set Set a wallet config setting + show-account Show the contents of an account + show-stake-account Show the contents of a stake account + show-storage-account Show the contents of a storage account + show-vote-account Show the contents of a vote account + validator-info Publish/get Validator info on Solana + withdraw-stake Withdraw the unstaked lamports from the stake account ``` ```manpage @@ -205,11 +228,16 @@ solana-address Get your public key USAGE: - solana address + solana address [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json ``` ```manpage @@ -217,14 +245,46 @@ solana-airdrop Request a batch of lamports USAGE: - solana airdrop + solana airdrop [OPTIONS] [unit] FLAGS: -h, --help Prints help information -V, --version Prints version information +OPTIONS: + -C, --config Configuration file to use [default: /Users/tyeraeulberg/.config/solana/wallet/config.yml] + --drone-host Drone host to use [default: the --url host] + --drone-port Drone port to use [default: 9900] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + ARGS: - The number of lamports to request + The airdrop amount to request (default unit SOL) + Specify unit to use for request and balance display [possible values: SOL, lamports] + +``` + +```manpage +solana-authorize-voter +Authorize a new vote signing keypair for the given vote account + +USAGE: + solana authorize-voter [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Vote account in which to set the authorized voter + Keypair file for the currently authorized vote signer + New vote signer to authorize + ``` ```manpage @@ -232,11 +292,20 @@ solana-balance Get your balance USAGE: - solana balance + solana balance [FLAGS] [OPTIONS] [PUBKEY] FLAGS: - -h, --help Prints help information - -V, --version Prints version information + -h, --help Prints help information + --lamports Display balance in lamports instead of SOL + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + The public key of the balance to check ``` ```manpage @@ -244,14 +313,57 @@ solana-cancel Cancel a transfer USAGE: - solana cancel + solana cancel [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + ARGS: - The process id of the transfer to cancel + The process id of the transfer to cancel +``` + +```manpage +solana-claim-storage-reward +Redeem storage reward credits + +USAGE: + solana claim-storage-reward [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + The node account to credit the rewards to + Storage account address to redeem credits for +``` + +```manpage +solana-cluster-version +Get the version of the cluster entrypoint + +USAGE: + solana cluster-version [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json ``` ```manpage @@ -259,29 +371,170 @@ solana-confirm Confirm transaction by signature USAGE: - solana confirm + solana confirm [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + ARGS: The transaction signature to confirm ``` +```manpage +solana-create-replicator-storage-account +Create a replicator storage account + +USAGE: + solana create-replicator-storage-account [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + + +``` + +```manpage +solana-create-storage-mining-pool-account +Create mining pool account + +USAGE: + solana create-storage-mining-pool-account [OPTIONS] [unit] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: /Users/tyeraeulberg/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Storage mining pool account address to fund + The amount to assign to the storage mining pool account (default unit SOL) + Specify unit to use for request [possible values: SOL, lamports] +``` + +```manpage +solana-create-validator-storage-account +Create a validator storage account + +USAGE: + solana create-validator-storage-account [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + + +``` + +```manpage +solana-create-vote-account +Create a vote account + +USAGE: + solana create-vote-account [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + --commission The commission taken on reward redemption (0-255), default: 0 + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Vote account address to fund + Validator that will vote with this account + The amount of lamports to send to the vote account +``` + +```manpage +solana-deactivate-stake +Deactivate the delegated stake from the stake account + +USAGE: + solana deactivate-stake [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Keypair file for the stake account, for signing the delegate transaction. + The vote account to which the stake is currently delegated +``` + +```manpage +solana-delegate-stake +Delegate stake to a vote account + +USAGE: + solana delegate-stake [OPTIONS] [unit] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: /Users/tyeraeulberg/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Keypair file for the new stake account + The vote account to which the stake will be delegated + The amount to delegate (default unit SOL) + Specify unit to use for request [possible values: SOL, lamports] +``` + ```manpage solana-deploy Deploy a program USAGE: - solana deploy + solana deploy [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + ARGS: - /path/to/program.o + /path/to/program.o ``` ```manpage @@ -289,11 +542,53 @@ solana-fees Display current cluster fees USAGE: - solana fees + solana fees [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json +``` + +```manpage +solana-get +Get wallet config settings + +USAGE: + solana get [OPTIONS] [CONFIG_FIELD] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Return a specific config setting [possible values: url, keypair] +``` + +```manpage +solana-get-slot +Get current slot + +USAGE: + solana get-slot [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json ``` ```manpage @@ -301,11 +596,16 @@ solana-get-transaction-count Get current transaction count USAGE: - solana get-transaction-count + solana get-transaction-count [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json ``` ```manpage @@ -313,7 +613,7 @@ solana-pay Send a payment USAGE: - solana pay [FLAGS] [OPTIONS] + solana pay [FLAGS] [OPTIONS] [--] [unit] FLAGS: --cancelable @@ -321,13 +621,60 @@ FLAGS: -V, --version Prints version information OPTIONS: + -C, --config Configuration file to use [default: + /Users/tyeraeulberg/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json --after A timestamp after which transaction will execute --require-timestamp-from Require timestamp from this third party --require-signature-from ... Any third party signatures required to unlock the lamports ARGS: The pubkey of recipient - The number of lamports to send + The amount to send (default unit SOL) + Specify unit to use for request [possible values: SOL, lamports] +``` + +```manpage +solana-ping +Submit transactions sequentially + +USAGE: + solana ping [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: + ~/.config/solana/wallet/config.yml] + -c, --count Stop after submitting count transactions + -i, --interval Wait interval seconds between submitting the next transaction [default: 2] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + -t, --timeout Wait up to timeout seconds for transaction confirmation [default: 10] +``` + +```manpage +solana-redeem-vote-credits +Redeem credits in the stake account + +USAGE: + solana redeem-vote-credits [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Staking account address to redeem credits for + The vote account to which the stake was previously delegated. ``` ```manpage @@ -335,15 +682,20 @@ solana-send-signature Send a signature to authorize a transfer USAGE: - solana send-signature + solana send-signature [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + ARGS: The pubkey of recipient - The process id of the transfer to authorize + The process id of the transfer to authorize ``` ```manpage @@ -351,16 +703,163 @@ solana-send-timestamp Send a timestamp to unlock a transfer USAGE: - solana send-timestamp [OPTIONS] + solana send-timestamp [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] --date Optional arbitrary timestamp to apply + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json ARGS: The pubkey of recipient - The process id of the transfer to unlock + The process id of the transfer to unlock +``` + +```manpage +solana-set +Set a wallet config setting + +USAGE: + solana set [OPTIONS] <--url |--keypair > + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json +``` + +```manpage +solana-show-account +Show the contents of an account + +USAGE: + solana show-account [FLAGS] [OPTIONS] + +FLAGS: + -h, --help Prints help information + --lamports Display balance in lamports instead of SOL + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + -o, --output Write the account data to this file + +ARGS: + Account pubkey +``` + +```manpage +solana-show-stake-account +Show the contents of a stake account + +USAGE: + solana show-stake-account [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Stake account pubkey +``` + +```manpage +solana-show-storage-account +Show the contents of a storage account + +USAGE: + solana show-storage-account [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Storage account pubkey +``` + +```manpage +solana-show-vote-account +Show the contents of a vote account + +USAGE: + solana show-vote-account [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Vote account pubkey +``` + +```manpage +solana-validator-info +Publish/get Validator info on Solana + +USAGE: + solana validator-info [OPTIONS] [SUBCOMMAND] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: ~/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +SUBCOMMANDS: + get Get and parse Solana Validator info + help Prints this message or the help of the given subcommand(s) + publish Publish Validator info on Solana +``` + +```manpage +solana-withdraw-stake +Withdraw the unstaked lamports from the stake account + +USAGE: + solana withdraw-stake [OPTIONS] [unit] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -C, --config Configuration file to use [default: /Users/tyeraeulberg/.config/solana/wallet/config.yml] + -u, --url JSON RPC URL for the solana cluster + -k, --keypair /path/to/id.json + +ARGS: + Keypair file for the stake account, for signing the withdraw transaction. + The account where the lamports should be transfered + The amount to withdraw from the stake account (default unit SOL) + Specify unit to use for request [possible values: SOL, lamports] ``` diff --git a/book/src/running-replicator.md b/book/src/running-replicator.md index a7ef0da6e..4cd88d295 100644 --- a/book/src/running-replicator.md +++ b/book/src/running-replicator.md @@ -129,7 +129,7 @@ $ export STORAGE_IDENTITY=$(solana-keygen pubkey storage-keypair.json) ``` Then set up the storage accounts for your replicator by running: ```bash -$ solana --keypair replicator-keypair.json airdrop 100000 +$ solana --keypair replicator-keypair.json airdrop 100000 lamports $ solana --keypair replicator-keypair.json create-replicator-storage-account $REPLICATOR_IDENTITY $STORAGE_IDENTITY ``` Note: Every time the testnet restarts, run the steps to setup the replicator accounts again. diff --git a/book/src/validator-monitor.md b/book/src/validator-monitor.md index 02856f613..ad287057b 100644 --- a/book/src/validator-monitor.md +++ b/book/src/validator-monitor.md @@ -25,10 +25,11 @@ $ solana show-vote-account 2ozWvfaXQd1X6uKh8jERoRGApDqSqcEy6fF1oN13LL2G ``` ## Check Your Balance -Your lamport balance should decrease by the transaction fee amount as your -validator submits votes, and increase after serving as the leader: +Your account balance should decrease by the transaction fee amount as your +validator submits votes, and increase after serving as the leader. Pass the +`--lamports` are to observe in finer detail: ```bash -$ solana balance +$ solana balance --lamports ``` ## Check Slot Number diff --git a/book/src/validator-stake.md b/book/src/validator-stake.md index c239e9665..2aae02d6c 100644 --- a/book/src/validator-stake.md +++ b/book/src/validator-stake.md @@ -10,7 +10,7 @@ $ solana-keygen new -o ~/validator-config/stake-keypair.json ``` and use the cli's `delegate-stake` command to stake your validator with 42 lamports: ```bash -$ solana delegate-stake ~/validator-config/stake-keypair.json ~/validator-vote-keypair.json 42 +$ solana delegate-stake ~/validator-config/stake-keypair.json ~/validator-vote-keypair.json 42 lamports ``` Note that stakes need to warm up, and warmup increments are applied at Epoch boundaries, so it can take an hour @@ -20,7 +20,7 @@ Assuming your node is voting, now you're up and running and generating validator to periodically redeem/claim your rewards: ```bash -$ solana-wallet redeem-vote-credits ~/validator-config/stake-keypair.json ~/validator-vote-keypair.json +$ solana redeem-vote-credits ~/validator-config/stake-keypair.json ~/validator-vote-keypair.json ``` The rewards lamports earned are split between your stake account and the vote account according to the diff --git a/book/src/validator-start.md b/book/src/validator-start.md index a75f28ac6..558cd1c7a 100644 --- a/book/src/validator-start.md +++ b/book/src/validator-start.md @@ -24,8 +24,8 @@ airdrop of lamports from the testnet drone: ```bash $ solana set --url http://testnet.solana.com:8899 $ solana get -$ solana airdrop 123 -$ solana balance +$ solana airdrop 123 lamports +$ solana balance --lamports ``` Also try running following command to join the gossip network and view all the @@ -52,7 +52,7 @@ $ solana set --keypair ~/validator-keypair.json **your validator identity keypair.** If you haven't, you will need to add the `--keypair` argument to each command, like: ```bash -$ solana --keypair ~/validator-keypair.json airdrop 1000 +$ solana --keypair ~/validator-keypair.json airdrop 1000 lamports ``` (You can always override the set configuration by explicitly passing the `--keypair` argument with a command.) @@ -60,7 +60,7 @@ $ solana --keypair ~/validator-keypair.json airdrop 1000 ### Validator Start Airdrop yourself some lamports to get started: ```bash -$ solana airdrop 1000 +$ solana airdrop 1000 lamports ``` Your validator will need a vote account. Create it now with the following diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 1c8d73328..e26b513d7 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -10,3 +10,7 @@ pub mod wallet; pub(crate) fn lamports_to_sol(lamports: u64) -> f64 { lamports as f64 / 2u64.pow(34) as f64 } + +pub(crate) fn sol_to_lamports(sol: f64) -> u64 { + (sol * 2u64.pow(34) as f64) as u64 +} diff --git a/cli/src/wallet.rs b/cli/src/wallet.rs index b6d889c3b..1d7f1523c 100644 --- a/cli/src/wallet.rs +++ b/cli/src/wallet.rs @@ -1,4 +1,7 @@ -use crate::{display::println_name_value, input_validators::*, lamports_to_sol, validator_info::*}; +use crate::{ + display::println_name_value, input_validators::*, lamports_to_sol, sol_to_lamports, + validator_info::*, +}; use chrono::prelude::*; use clap::{value_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand}; use console::{style, Emoji}; @@ -56,6 +59,7 @@ pub enum WalletCommand { drone_host: Option, drone_port: u16, lamports: u64, + use_lamports_unit: bool, }, Balance { pubkey: Pubkey, @@ -84,14 +88,14 @@ pub enum WalletCommand { GetSlot, GetTransactionCount, GetVersion, - Pay( - u64, // lamports - Pubkey, // to - Option>, // timestamp - Option, // timestamp_pubkey - Option>, // witness(es) - Option, // cancelable - ), + Pay { + lamports: u64, + to: Pubkey, + timestamp: Option>, + timestamp_pubkey: Option, + witnesses: Option>, + cancelable: Option, + }, Ping { interval: Duration, count: Option, @@ -223,11 +227,17 @@ pub fn parse_command( } else { None }; - let lamports = airdrop_matches.value_of("lamports").unwrap().parse()?; + let lamports = parse_amount_lamports( + airdrop_matches.value_of("amount").unwrap(), + airdrop_matches.value_of("unit"), + )?; + let use_lamports_unit = airdrop_matches.value_of("unit").is_some() + && airdrop_matches.value_of("unit").unwrap() == "lamports"; Ok(WalletCommand::Airdrop { drone_host, drone_port, lamports, + use_lamports_unit, }) } ("balance", Some(balance_matches)) => { @@ -297,12 +307,15 @@ pub fn parse_command( ("delegate-stake", Some(matches)) => { let stake_account_keypair = keypair_of(matches, "stake_account_keypair_file").unwrap(); let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap(); - let lamports_to_stake = matches.value_of("lamports_to_stake").unwrap().parse()?; + let lamports = parse_amount_lamports( + matches.value_of("amount").unwrap(), + matches.value_of("unit"), + )?; let force = matches.is_present("force"); Ok(WalletCommand::DelegateStake( stake_account_keypair, vote_account_pubkey, - lamports_to_stake, + lamports, force, )) } @@ -310,7 +323,10 @@ pub fn parse_command( let stake_account_keypair = keypair_of(matches, "stake_account_keypair_file").unwrap(); let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap(); - let lamports = matches.value_of("lamports").unwrap().parse()?; + let lamports = parse_amount_lamports( + matches.value_of("amount").unwrap(), + matches.value_of("unit"), + )?; Ok(WalletCommand::WithdrawStake( stake_account_keypair, destination_account_pubkey, @@ -374,7 +390,10 @@ pub fn parse_command( ("get-slot", Some(_matches)) => Ok(WalletCommand::GetSlot), ("get-transaction-count", Some(_matches)) => Ok(WalletCommand::GetTransactionCount), ("pay", Some(pay_matches)) => { - let lamports = pay_matches.value_of("lamports").unwrap().parse()?; + let lamports = parse_amount_lamports( + pay_matches.value_of("amount").unwrap(), + pay_matches.value_of("unit"), + )?; let to = value_of(&pay_matches, "to").unwrap_or(*pubkey); let timestamp = if pay_matches.is_present("timestamp") { // Parse input for serde_json @@ -388,21 +407,21 @@ pub fn parse_command( None }; let timestamp_pubkey = value_of(&pay_matches, "timestamp_pubkey"); - let witness_vec = values_of(&pay_matches, "witness"); + let witnesses = values_of(&pay_matches, "witness"); let cancelable = if pay_matches.is_present("cancelable") { Some(*pubkey) } else { None }; - Ok(WalletCommand::Pay( + Ok(WalletCommand::Pay { lamports, to, timestamp, timestamp_pubkey, - witness_vec, + witnesses, cancelable, - )) + }) } ("ping", Some(ping_matches)) => { let interval = Duration::from_secs(value_t_or_exit!(ping_matches, "interval", u64)); @@ -524,6 +543,7 @@ fn process_airdrop( config: &WalletConfig, drone_addr: &SocketAddr, lamports: u64, + use_lamports_unit: bool, ) -> ProcessResult { println!( "Requesting airdrop of {:?} lamports from {}", @@ -542,11 +562,7 @@ fn process_airdrop( .retry_get_balance(&config.keypair.pubkey(), 5)? .unwrap_or(previous_balance); - let ess = if current_balance == 1 { "" } else { "s" }; - Ok(format!( - "Your balance is: {:?} lamport{}", - current_balance, ess - )) + Ok(build_balance_message(current_balance, use_lamports_unit)) } fn process_balance( @@ -1409,6 +1425,7 @@ pub fn process_command(config: &WalletConfig) -> ProcessResult { drone_host, drone_port, lamports, + use_lamports_unit, } => { let drone_addr = SocketAddr::new( drone_host.unwrap_or_else(|| { @@ -1424,7 +1441,13 @@ pub fn process_command(config: &WalletConfig) -> ProcessResult { *drone_port, ); - process_airdrop(&rpc_client, config, &drone_addr, *lamports) + process_airdrop( + &rpc_client, + config, + &drone_addr, + *lamports, + *use_lamports_unit, + ) } // Check client balance @@ -1572,14 +1595,14 @@ pub fn process_command(config: &WalletConfig) -> ProcessResult { WalletCommand::GetTransactionCount => process_get_transaction_count(&rpc_client), // If client has positive balance, pay lamports to another address - WalletCommand::Pay( + WalletCommand::Pay { lamports, to, timestamp, timestamp_pubkey, ref witnesses, cancelable, - ) => process_pay( + } => process_pay( &rpc_client, config, *lamports, @@ -1713,6 +1736,17 @@ fn build_balance_message(lamports: u64, use_lamports_unit: bool) -> String { } } +fn parse_amount_lamports( + amount: &str, + use_lamports_unit: Option<&str>, +) -> Result> { + if use_lamports_unit.is_some() && use_lamports_unit.unwrap() == "lamports" { + Ok(amount.parse()?) + } else { + Ok(sol_to_lamports(amount.parse()?)) + } +} + pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, 'v> { App::new(name) .about(about) @@ -1739,12 +1773,19 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .help("Drone port to use"), ) .arg( - Arg::with_name("lamports") + Arg::with_name("amount") .index(1) - .value_name("LAMPORTS") + .value_name("AMOUNT") .takes_value(true) .required(true) - .help("The number of lamports to request"), + .help("The airdrop amount to request (default unit SOL)"), + ) + .arg( + Arg::with_name("unit") + .index(2) + .takes_value(true) + .possible_values(&["SOL", "lamports"]) + .help("Specify unit to use for request and balance display"), ), ) .subcommand( @@ -1848,7 +1889,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .value_name("LAMPORTS") .takes_value(true) .required(true) - .help("The number of lamports to send to the vote account"), + .help("The amount of lamports to send to the vote account"), ) .arg( Arg::with_name("commission") @@ -1927,12 +1968,19 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .help("The vote account to which the stake will be delegated"), ) .arg( - Arg::with_name("lamports_to_stake") + Arg::with_name("amount") .index(3) - .value_name("LAMPORTS") + .value_name("AMOUNT") .takes_value(true) .required(true) - .help("The number of lamports to stake"), + .help("The amount to delegate (default unit SOL)"), + ) + .arg( + Arg::with_name("unit") + .index(4) + .takes_value(true) + .possible_values(&["SOL", "lamports"]) + .help("Specify unit to use for request"), ), ) .subcommand( @@ -1978,12 +2026,19 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .help("The account where the lamports should be transfered"), ) .arg( - Arg::with_name("lamports") + Arg::with_name("amount") .index(3) - .value_name("LAMPORTS") + .value_name("AMOUNT") .takes_value(true) .required(true) - .help("The number of lamports to withdraw from the stake account."), + .help("The amount to withdraw from the stake account (default unit SOL)"), + ) + .arg( + Arg::with_name("unit") + .index(4) + .takes_value(true) + .possible_values(&["SOL", "lamports"]) + .help("Specify unit to use for request"), ), ) .subcommand( @@ -2034,12 +2089,19 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .help("Storage mining pool account address to fund"), ) .arg( - Arg::with_name("lamports") + Arg::with_name("amount") .index(2) - .value_name("LAMPORTS") + .value_name("AMOUNT") .takes_value(true) .required(true) - .help("The number of lamports to assign to the storage mining pool account"), + .help("The amount to assign to the storage mining pool account (default unit SOL)"), + ) + .arg( + Arg::with_name("unit") + .index(3) + .takes_value(true) + .possible_values(&["SOL", "lamports"]) + .help("Specify unit to use for request"), ), ) .subcommand( @@ -2149,12 +2211,19 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .help("The pubkey of recipient"), ) .arg( - Arg::with_name("lamports") + Arg::with_name("amount") .index(2) - .value_name("LAMPORTS") + .value_name("AMOUNT") .takes_value(true) .required(true) - .help("The number of lamports to send"), + .help("The amount to send (default unit SOL)"), + ) + .arg( + Arg::with_name("unit") + .index(3) + .takes_value(true) + .possible_values(&["SOL", "lamports"]) + .help("Specify unit to use for request"), ) .arg( Arg::with_name("timestamp") @@ -2369,13 +2438,14 @@ mod tests { // Test Airdrop Subcommand let test_airdrop = test_commands .clone() - .get_matches_from(vec!["test", "airdrop", "50"]); + .get_matches_from(vec!["test", "airdrop", "50", "lamports"]); assert_eq!( parse_command(&pubkey, &test_airdrop).unwrap(), WalletCommand::Airdrop { drone_host: None, drone_port: solana_drone::drone::DRONE_PORT, - lamports: 50 + lamports: 50, + use_lamports_unit: true, } ); let test_bad_airdrop = test_commands @@ -2509,6 +2579,7 @@ mod tests { &keypair_file, &pubkey_string, "42", + "lamports", ]); assert_eq!( parse_command(&pubkey, &test_delegate_stake).unwrap(), @@ -2523,6 +2594,7 @@ mod tests { &keypair_file, &pubkey_string, "42", + "lamports", ]); assert_eq!( parse_command(&pubkey, &test_delegate_stake).unwrap(), @@ -2536,6 +2608,7 @@ mod tests { &keypair_file, &pubkey_string, "42", + "lamports", ]); let keypair = read_keypair(&keypair_file).unwrap(); assert_eq!( @@ -2569,13 +2642,23 @@ mod tests { ); // Test Simple Pay Subcommand - let test_pay = - test_commands - .clone() - .get_matches_from(vec!["test", "pay", &pubkey_string, "50"]); + let test_pay = test_commands.clone().get_matches_from(vec![ + "test", + "pay", + &pubkey_string, + "50", + "lamports", + ]); assert_eq!( parse_command(&pubkey, &test_pay).unwrap(), - WalletCommand::Pay(50, pubkey, None, None, None, None) + WalletCommand::Pay { + lamports: 50, + to: pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: None, + cancelable: None + } ); // Test Pay Subcommand w/ Witness @@ -2584,6 +2667,7 @@ mod tests { "pay", &pubkey_string, "50", + "lamports", "--require-signature-from", &witness0_string, "--require-signature-from", @@ -2591,19 +2675,34 @@ mod tests { ]); assert_eq!( parse_command(&pubkey, &test_pay_multiple_witnesses).unwrap(), - WalletCommand::Pay(50, pubkey, None, None, Some(vec![witness0, witness1]), None) + WalletCommand::Pay { + lamports: 50, + to: pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: Some(vec![witness0, witness1]), + cancelable: None + } ); let test_pay_single_witness = test_commands.clone().get_matches_from(vec![ "test", "pay", &pubkey_string, "50", + "lamports", "--require-signature-from", &witness0_string, ]); assert_eq!( parse_command(&pubkey, &test_pay_single_witness).unwrap(), - WalletCommand::Pay(50, pubkey, None, None, Some(vec![witness0]), None) + WalletCommand::Pay { + lamports: 50, + to: pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: Some(vec![witness0]), + cancelable: None + } ); // Test Pay Subcommand w/ Timestamp @@ -2612,6 +2711,7 @@ mod tests { "pay", &pubkey_string, "50", + "lamports", "--after", "2018-09-19T17:30:59", "--require-timestamp-from", @@ -2619,7 +2719,14 @@ mod tests { ]); assert_eq!( parse_command(&pubkey, &test_pay_timestamp).unwrap(), - WalletCommand::Pay(50, pubkey, Some(dt), Some(witness0), None, None) + WalletCommand::Pay { + lamports: 50, + to: pubkey, + timestamp: Some(dt), + timestamp_pubkey: Some(witness0), + witnesses: None, + cancelable: None + } ); // Test Send-Signature Subcommand @@ -2638,6 +2745,7 @@ mod tests { "pay", &pubkey_string, "50", + "lamports", "--after", "2018-09-19T17:30:59", "--require-signature-from", @@ -2649,14 +2757,14 @@ mod tests { ]); assert_eq!( parse_command(&pubkey, &test_pay_multiple_witnesses).unwrap(), - WalletCommand::Pay( - 50, - pubkey, - Some(dt), - Some(witness0), - Some(vec![witness0, witness1]), - None - ) + WalletCommand::Pay { + lamports: 50, + to: pubkey, + timestamp: Some(dt), + timestamp_pubkey: Some(witness0), + witnesses: Some(vec![witness0, witness1]), + cancelable: None + } ); // Test Send-Timestamp Subcommand @@ -2756,20 +2864,27 @@ mod tests { config.command = WalletCommand::GetTransactionCount; assert_eq!(process_command(&config).unwrap(), "1234"); - config.command = WalletCommand::Pay(10, bob_pubkey, None, None, None, None); + config.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: None, + cancelable: None, + }; let signature = process_command(&config); assert_eq!(signature.unwrap(), SIGNATURE.to_string()); let date_string = "\"2018-09-19T17:30:59Z\""; let dt: DateTime = serde_json::from_str(&date_string).unwrap(); - config.command = WalletCommand::Pay( - 10, - bob_pubkey, - Some(dt), - Some(config.keypair.pubkey()), - None, - None, - ); + config.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: Some(dt), + timestamp_pubkey: Some(config.keypair.pubkey()), + witnesses: None, + cancelable: None, + }; let result = process_command(&config); let json: Value = serde_json::from_str(&result.unwrap()).unwrap(); assert_eq!( @@ -2783,14 +2898,14 @@ mod tests { ); let witness = Pubkey::new_rand(); - config.command = WalletCommand::Pay( - 10, - bob_pubkey, - None, - None, - Some(vec![witness]), - Some(config.keypair.pubkey()), - ); + config.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: Some(vec![witness]), + cancelable: Some(config.keypair.pubkey()), + }; let result = process_command(&config); let json: Value = serde_json::from_str(&result.unwrap()).unwrap(); assert_eq!( @@ -2818,6 +2933,7 @@ mod tests { drone_host: None, drone_port: 1234, lamports: 50, + use_lamports_unit: true, }; assert!(process_command(&config).is_ok()); @@ -2856,6 +2972,7 @@ mod tests { drone_host: None, drone_port: 1234, lamports: 50, + use_lamports_unit: true, }; assert!(process_command(&config).is_err()); @@ -2877,27 +2994,34 @@ mod tests { config.command = WalletCommand::GetTransactionCount; assert!(process_command(&config).is_err()); - config.command = WalletCommand::Pay(10, bob_pubkey, None, None, None, None); + config.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: None, + cancelable: None, + }; assert!(process_command(&config).is_err()); - config.command = WalletCommand::Pay( - 10, - bob_pubkey, - Some(dt), - Some(config.keypair.pubkey()), - None, - None, - ); + config.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: Some(dt), + timestamp_pubkey: Some(config.keypair.pubkey()), + witnesses: None, + cancelable: None, + }; assert!(process_command(&config).is_err()); - config.command = WalletCommand::Pay( - 10, - bob_pubkey, - None, - None, - Some(vec![witness]), - Some(config.keypair.pubkey()), - ); + config.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: Some(vec![witness]), + cancelable: Some(config.keypair.pubkey()), + }; assert!(process_command(&config).is_err()); config.command = WalletCommand::TimeElapsed(bob_pubkey, process_id, dt); diff --git a/cli/tests/deploy.rs b/cli/tests/deploy.rs index 5450d1702..c96b3f8dd 100644 --- a/cli/tests/deploy.rs +++ b/cli/tests/deploy.rs @@ -34,6 +34,7 @@ fn test_wallet_deploy_program() { drone_host: None, drone_port: drone_addr.port(), lamports: 50, + use_lamports_unit: true, }; process_command(&config).unwrap(); diff --git a/cli/tests/pay.rs b/cli/tests/pay.rs index e83a334cc..781d8ad34 100644 --- a/cli/tests/pay.rs +++ b/cli/tests/pay.rs @@ -66,14 +66,14 @@ fn test_wallet_timestamp_tx() { // Make transaction (from config_payer to bob_pubkey) requiring timestamp from config_witness let date_string = "\"2018-09-19T17:30:59Z\""; let dt: DateTime = serde_json::from_str(&date_string).unwrap(); - config_payer.command = WalletCommand::Pay( - 10, - bob_pubkey, - Some(dt), - Some(config_witness.keypair.pubkey()), - None, - None, - ); + config_payer.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: Some(dt), + timestamp_pubkey: Some(config_witness.keypair.pubkey()), + witnesses: None, + cancelable: None, + }; let sig_response = process_command(&config_payer); let object: Value = serde_json::from_str(&sig_response.unwrap()).unwrap(); @@ -133,14 +133,14 @@ fn test_wallet_witness_tx() { .unwrap(); // Make transaction (from config_payer to bob_pubkey) requiring witness signature from config_witness - config_payer.command = WalletCommand::Pay( - 10, - bob_pubkey, - None, - None, - Some(vec![config_witness.keypair.pubkey()]), - None, - ); + config_payer.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: Some(vec![config_witness.keypair.pubkey()]), + cancelable: None, + }; let sig_response = process_command(&config_payer); let object: Value = serde_json::from_str(&sig_response.unwrap()).unwrap(); @@ -193,14 +193,14 @@ fn test_wallet_cancel_tx() { .unwrap(); // Make transaction (from config_payer to bob_pubkey) requiring witness signature from config_witness - config_payer.command = WalletCommand::Pay( - 10, - bob_pubkey, - None, - None, - Some(vec![config_witness.keypair.pubkey()]), - Some(config_payer.keypair.pubkey()), - ); + config_payer.command = WalletCommand::Pay { + lamports: 10, + to: bob_pubkey, + timestamp: None, + timestamp_pubkey: None, + witnesses: Some(vec![config_witness.keypair.pubkey()]), + cancelable: Some(config_payer.keypair.pubkey()), + }; let sig_response = process_command(&config_payer).unwrap(); let object: Value = serde_json::from_str(&sig_response).unwrap(); diff --git a/cli/tests/request_airdrop.rs b/cli/tests/request_airdrop.rs index da56a227a..5a84f86f2 100644 --- a/cli/tests/request_airdrop.rs +++ b/cli/tests/request_airdrop.rs @@ -19,6 +19,7 @@ fn test_wallet_request_airdrop() { drone_host: None, drone_port: drone_addr.port(), lamports: 50, + use_lamports_unit: true, }; let sig_response = process_command(&bob_config); diff --git a/multinode-demo/delegate-stake.sh b/multinode-demo/delegate-stake.sh index a25407d12..185d5a35e 100755 --- a/multinode-demo/delegate-stake.sh +++ b/multinode-demo/delegate-stake.sh @@ -95,7 +95,7 @@ fi if ((airdrops_enabled)); then declare fees=100 # TODO: No hardcoded transaction fees, fetch the current cluster fees - $solana_cli "${common_args[@]}" airdrop $((stake_lamports+fees)) + $solana_cli "${common_args[@]}" airdrop $((stake_lamports+fees)) lamports fi $solana_keygen new -o "$stake_keypair_path" @@ -104,6 +104,5 @@ set -x $solana_cli "${common_args[@]}" \ show-vote-account "$vote_keypair_path" $solana_cli "${common_args[@]}" \ - delegate-stake $maybe_force "$stake_keypair_path" "$vote_keypair_path" "$stake_lamports" + delegate-stake $maybe_force "$stake_keypair_path" "$vote_keypair_path" "$stake_lamports" lamports $solana_cli "${common_args[@]}" show-stake-account "$stake_keypair_path" - diff --git a/multinode-demo/replicator.sh b/multinode-demo/replicator.sh index 01f0541d3..3d3db0780 100755 --- a/multinode-demo/replicator.sh +++ b/multinode-demo/replicator.sh @@ -63,7 +63,7 @@ if [[ ! -r $identity_keypair ]]; then # TODO: https://github.com/solana-labs/solminer/blob/9cd2289/src/replicator.js#L17-L18 $solana_cli --keypair "$identity_keypair" --url "$rpc_url" \ - airdrop 100000 + airdrop 100000 lamports fi identity_pubkey=$($solana_keygen pubkey "$identity_keypair") diff --git a/multinode-demo/validator.sh b/multinode-demo/validator.sh index e05739010..084a51ca3 100755 --- a/multinode-demo/validator.sh +++ b/multinode-demo/validator.sh @@ -273,11 +273,11 @@ setup_validator_accounts() { echo "Adding $node_lamports to validator identity account:" ( declare fees=100 # TODO: No hardcoded transaction fees, fetch the current cluster fees - wallet airdrop $((node_lamports+fees)) + wallet airdrop $((node_lamports+fees)) lamports ) || return $? else echo "Validator identity account balance:" - wallet balance || return $? + wallet balance --lamports || return $? fi if ! wallet show-vote-account "$voting_keypair_path"; then diff --git a/scripts/solana-install-deploy.sh b/scripts/solana-install-deploy.sh index 62ba841e3..f3e49e3a5 100755 --- a/scripts/solana-install-deploy.sh +++ b/scripts/solana-install-deploy.sh @@ -72,10 +72,10 @@ PATH="$SOLANA_ROOT"/target/debug:$PATH set -x # shellcheck disable=SC2086 # Don't want to double quote $maybeKeypair -balance=$(solana $maybeKeypair --url "$URL" balance) +balance=$(solana $maybeKeypair --url "$URL" balance --lamports) if [[ $balance = "0 lamports" ]]; then # shellcheck disable=SC2086 # Don't want to double quote $maybeKeypair - solana $maybeKeypair --url "$URL" airdrop 42 + solana $maybeKeypair --url "$URL" airdrop 42 lamports fi # shellcheck disable=SC2086 # Don't want to double quote $maybeKeypair diff --git a/scripts/wallet-sanity.sh b/scripts/wallet-sanity.sh index 6fb8721d8..1b0b2e145 100755 --- a/scripts/wallet-sanity.sh +++ b/scripts/wallet-sanity.sh @@ -63,11 +63,11 @@ fi $solana_cli "${entrypoint[@]}" address check_balance_output "0 lamports" -$solana_cli "${entrypoint[@]}" airdrop 600 +$solana_cli "${entrypoint[@]}" airdrop 600 lamports check_balance_output "600 lamports" -$solana_cli "${entrypoint[@]}" airdrop 400 +$solana_cli "${entrypoint[@]}" airdrop 400 lamports check_balance_output "1000 lamports" -pay_and_confirm $garbage_address 50 +pay_and_confirm $garbage_address 50 lamports check_balance_output "lamports" # <-- exact number of lamports here depends on the current cluster fees echo PASS