solana/cli: strip down to deploy_bridge

Delete all non-Wormhole commands. Users should use the official
spl_token CLI to interact with tokens.

Removes the --owner argument and defaults to the fee payer.

Change-Id: I728766131cd697feff5f16ae5aa991c3d87e40cb
This commit is contained in:
Leo 2021-04-15 21:24:32 +02:00 committed by Leopold Schabel
parent c405ec9f98
commit 33f39d30fa
2 changed files with 15 additions and 844 deletions

View File

@ -1,74 +0,0 @@
use std::{error, net::SocketAddr, thread::sleep, time::Duration};
use solana_client::rpc_client::RpcClient;
use solana_faucet::faucet::request_airdrop_transaction;
use solana_sdk::{
hash::Hash,
pubkey::Pubkey,
signature::{Signature, Signer, SignerError},
transaction::Transaction,
};
use crate::CommmandResult;
// Quick and dirty Keypair that assumes the client will do retries but not update the
// blockhash. If the client updates the blockhash, the signature will be invalid.
struct FaucetKeypair {
transaction: Transaction,
}
impl FaucetKeypair {
fn new_keypair(
faucet_addr: &SocketAddr,
to_pubkey: &Pubkey,
lamports: u64,
blockhash: Hash,
) -> Result<Self, Box<dyn error::Error>> {
let transaction = request_airdrop_transaction(faucet_addr, to_pubkey, lamports, blockhash)?;
Ok(Self { transaction })
}
fn airdrop_transaction(&self) -> Transaction {
self.transaction.clone()
}
}
impl Signer for FaucetKeypair {
/// Return the public key of the keypair used to sign votes
fn pubkey(&self) -> Pubkey {
self.transaction.message().account_keys[0]
}
fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
Ok(self.pubkey())
}
fn sign_message(&self, _msg: &[u8]) -> Signature {
self.transaction.signatures[0]
}
fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
Ok(self.sign_message(message))
}
}
pub fn request_and_confirm_airdrop(
rpc_client: &RpcClient,
faucet_addr: &SocketAddr,
to_pubkey: &Pubkey,
lamports: u64,
) -> CommmandResult {
let (blockhash, _fee_calculator) = rpc_client.get_recent_blockhash()?;
let keypair = {
let mut retries = 5;
loop {
let result = FaucetKeypair::new_keypair(faucet_addr, to_pubkey, lamports, blockhash);
if result.is_ok() || retries == 0 {
break result;
}
retries -= 1;
sleep(Duration::from_secs(1));
}
}?;
Ok(Some(keypair.airdrop_transaction()))
}

View File

@ -1,15 +1,15 @@
use std::{fmt::Display, mem::size_of, net::ToSocketAddrs, ops::Deref, process::exit};
use clap::{
crate_description, crate_name, crate_version, value_t, value_t_or_exit, App, AppSettings, Arg,
ArgMatches, SubCommand,
App, AppSettings, Arg, ArgMatches, crate_description, crate_name, crate_version, SubCommand,
value_t, value_t_or_exit,
};
use hex;
use primitive_types::U256;
use rand::{
CryptoRng,
prelude::StdRng,
rngs::{mock::StepRng, ThreadRng},
CryptoRng, RngCore,
RngCore, rngs::{mock::StepRng, ThreadRng},
};
use solana_account_decoder::{parse_token::TokenAccountType, UiAccountData};
use solana_clap_utils::{
@ -23,39 +23,30 @@ use solana_sdk::{
commitment_config::CommitmentConfig,
native_token::*,
pubkey::Pubkey,
signature::{read_keypair_file, Keypair, Signer},
signature::{Keypair, read_keypair_file, Signer},
system_instruction,
transaction::Transaction,
};
use spl_token::{
self,
instruction::*,
native_mint,
state::{Account, Mint},
};
use solana_sdk::program_pack::Pack;
use spl_token::native_mint;
use spl_token::state::Mint;
use spl_bridge::{instruction::*, state::*};
use crate::faucet::request_and_confirm_airdrop;
use solana_sdk::program_pack::Pack;
mod faucet;
struct Config {
rpc_client: RpcClient,
owner: Keypair,
fee_payer: Keypair,
commitment_config: CommitmentConfig,
}
type Error = Box<dyn std::error::Error>;
type CommmandResult = Result<Option<Transaction>, Error>;
type CommandResult = Result<Option<Transaction>, Error>;
fn command_deploy_bridge(
config: &Config,
bridge: &Pubkey,
initial_guardian: Vec<[u8; 20]>,
) -> CommmandResult {
) -> CommandResult {
println!("Deploying bridge program {}", bridge);
let minimum_balance_for_rent_exemption = config
@ -64,7 +55,7 @@ fn command_deploy_bridge(
let ix = initialize(
bridge,
&config.owner.pubkey(),
&config.fee_payer.pubkey(),
initial_guardian,
&BridgeConfig {
guardian_set_expiration_time: 200000000,
@ -80,7 +71,7 @@ fn command_deploy_bridge(
minimum_balance_for_rent_exemption
+ fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(&[&config.fee_payer, &config.owner], recent_blockhash);
transaction.sign(&[&config.fee_payer], recent_blockhash);
Ok(Some(transaction))
}
@ -99,381 +90,9 @@ fn check_fee_payer_balance(config: &Config, required_balance: u64) -> Result<(),
}
}
fn check_owner_balance(config: &Config, required_balance: u64) -> Result<(), Error> {
let balance = config.rpc_client.get_balance(&config.owner.pubkey())?;
if balance < required_balance {
Err(format!(
"Owner, {}, has insufficient balance: {} required, {} available",
config.owner.pubkey(),
lamports_to_sol(required_balance),
lamports_to_sol(balance)
)
.into())
} else {
Ok(())
}
}
fn command_create_token(config: &Config, decimals: u8, token: Keypair) -> CommmandResult {
println!("Creating token {}", token.pubkey());
let minimum_balance_for_rent_exemption = config
.rpc_client
.get_minimum_balance_for_rent_exemption(Mint::LEN)?;
let mut transaction = Transaction::new_with_payer(
&[
system_instruction::create_account(
&config.fee_payer.pubkey(),
&token.pubkey(),
minimum_balance_for_rent_exemption,
Mint::LEN as u64,
&spl_token::id(),
),
initialize_mint(
&spl_token::id(),
&token.pubkey(),
&config.owner.pubkey(),
None,
decimals,
)?,
],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_fee_payer_balance(
config,
minimum_balance_for_rent_exemption
+ fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(
&[&config.fee_payer, &config.owner, &token],
recent_blockhash,
);
Ok(Some(transaction))
}
fn command_create_account(config: &Config, token: Pubkey, account: Keypair) -> CommmandResult {
println!("Creating account {}", account.pubkey());
let minimum_balance_for_rent_exemption = config
.rpc_client
.get_minimum_balance_for_rent_exemption(Account::LEN)?;
let mut transaction = Transaction::new_with_payer(
&[
system_instruction::create_account(
&config.fee_payer.pubkey(),
&account.pubkey(),
minimum_balance_for_rent_exemption,
Account::LEN as u64,
&spl_token::id(),
),
initialize_account(
&spl_token::id(),
&account.pubkey(),
&token,
&config.owner.pubkey(),
)?,
],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_fee_payer_balance(
config,
minimum_balance_for_rent_exemption
+ fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(
&[&config.fee_payer, &config.owner, &account],
recent_blockhash,
);
Ok(Some(transaction))
}
fn command_assign(config: &Config, account: Pubkey, new_owner: Pubkey) -> CommmandResult {
println!(
"Assigning {}\n Current owner: {}\n New owner: {}",
account,
config.owner.pubkey(),
new_owner
);
let mut transaction = Transaction::new_with_payer(
&[spl_token::instruction::set_authority(
&spl_token::id(),
&account,
Some(&new_owner),
AuthorityType::AccountOwner,
&config.owner.pubkey(),
&[],
)?],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_fee_payer_balance(
config,
fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(&[&config.fee_payer, &config.owner], recent_blockhash);
Ok(Some(transaction))
}
fn command_transfer(
config: &Config,
sender: Pubkey,
ui_amount: f64,
recipient: Pubkey,
) -> CommmandResult {
println!(
"Transfer {} tokens\n Sender: {}\n Recipient: {}",
ui_amount, sender, recipient
);
let sender_token_balance = config
.rpc_client
.get_token_account_balance_with_commitment(&sender, config.commitment_config)?
.value;
let amount = spl_token::ui_amount_to_amount(ui_amount, sender_token_balance.decimals);
let mut transaction = Transaction::new_with_payer(
&[transfer(
&spl_token::id(),
&sender,
&recipient,
&config.owner.pubkey(),
&[],
amount,
)?],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_fee_payer_balance(
config,
fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(&[&config.fee_payer, &config.owner], recent_blockhash);
Ok(Some(transaction))
}
fn command_burn(config: &Config, source: Pubkey, ui_amount: f64) -> CommmandResult {
println!("Burn {} tokens\n Source: {}", ui_amount, source);
let source_token_balance = config
.rpc_client
.get_token_account_balance_with_commitment(&source, config.commitment_config)?
.value;
let source_account = config
.rpc_client
.get_account_with_commitment(&source, config.commitment_config)?
.value
.unwrap_or_default();
let data = source_account.data.to_vec();
let mint_pubkey = Account::unpack_from_slice(&data)?.mint;
let amount = spl_token::ui_amount_to_amount(ui_amount, source_token_balance.decimals);
let mut transaction = Transaction::new_with_payer(
&[burn(
&spl_token::id(),
&source,
&mint_pubkey,
&config.owner.pubkey(),
&[],
amount,
)?],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_fee_payer_balance(
config,
fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(&[&config.fee_payer, &config.owner], recent_blockhash);
Ok(Some(transaction))
}
fn command_mint(
config: &Config,
token: Pubkey,
ui_amount: f64,
recipient: Pubkey,
) -> CommmandResult {
println!(
"Minting {} tokens\n Token: {}\n Recipient: {}",
ui_amount, token, recipient
);
let recipient_token_balance = config
.rpc_client
.get_token_account_balance_with_commitment(&recipient, config.commitment_config)?
.value;
let amount = spl_token::ui_amount_to_amount(ui_amount, recipient_token_balance.decimals);
let mut transaction = Transaction::new_with_payer(
&[mint_to(
&spl_token::id(),
&token,
&recipient,
&config.owner.pubkey(),
&[],
amount,
)?],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_fee_payer_balance(
config,
fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(&[&config.fee_payer, &config.owner], recent_blockhash);
Ok(Some(transaction))
}
fn command_wrap(config: &Config, sol: f64) -> CommmandResult {
let account = Keypair::new();
let lamports = sol_to_lamports(sol);
println!("Wrapping {} SOL into {}", sol, account.pubkey());
let mut transaction = Transaction::new_with_payer(
&[
system_instruction::create_account(
&config.owner.pubkey(),
&account.pubkey(),
lamports,
size_of::<Account>() as u64,
&spl_token::id(),
),
initialize_account(
&spl_token::id(),
&account.pubkey(),
&native_mint::id(),
&config.owner.pubkey(),
)?,
],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_owner_balance(config, lamports)?;
check_fee_payer_balance(
config,
fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(
&[&config.fee_payer, &config.owner, &account],
recent_blockhash,
);
Ok(Some(transaction))
}
fn command_unwrap(config: &Config, address: Pubkey) -> CommmandResult {
println!("Unwrapping {}", address);
println!(
" Amount: {} SOL\n Recipient: {}",
lamports_to_sol(
config
.rpc_client
.get_balance_with_commitment(&address, config.commitment_config)?
.value
),
config.owner.pubkey()
);
let mut transaction = Transaction::new_with_payer(
&[close_account(
&spl_token::id(),
&address,
&config.owner.pubkey(),
&config.owner.pubkey(),
&[],
)?],
Some(&config.fee_payer.pubkey()),
);
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
check_fee_payer_balance(
config,
fee_calculator.calculate_fee(&transaction.message()),
)?;
transaction.sign(&[&config.fee_payer, &config.owner], recent_blockhash);
Ok(Some(transaction))
}
fn command_balance(config: &Config, address: Pubkey) -> CommmandResult {
let balance = config
.rpc_client
.get_token_account_balance_with_commitment(&address, config.commitment_config)?
.value;
println!("ui amount: {}", balance.ui_amount);
println!("decimals: {}", balance.decimals);
println!("amount: {}", balance.amount);
Ok(None)
}
fn command_supply(config: &Config, address: Pubkey) -> CommmandResult {
let supply = config
.rpc_client
.get_token_supply_with_commitment(&address, config.commitment_config)?
.value;
println!("{}", supply.ui_amount);
Ok(None)
}
fn command_accounts(config: &Config, token: Option<Pubkey>) -> CommmandResult {
let accounts = config
.rpc_client
.get_token_accounts_by_owner_with_commitment(
&config.owner.pubkey(),
match token {
Some(token) => TokenAccountsFilter::Mint(token),
None => TokenAccountsFilter::ProgramId(spl_token::id()),
},
config.commitment_config,
)?
.value;
if accounts.is_empty() {
println!("None");
}
println!("Account Token Balance");
println!("-------------------------------------------------------------------------------------------------");
for keyed_account in accounts {
let address = keyed_account.pubkey;
if let UiAccountData::Json(parsed_account) = keyed_account.account.data {
if parsed_account.program != "spl-token" {
println!(
"{:<44} Unsupported account program: {}",
address, parsed_account.program
);
} else {
match serde_json::from_value(parsed_account.parsed) {
Ok(TokenAccountType::Account(ui_token_account)) => println!(
"{:<44} {:<44} {}",
address, ui_token_account.mint, ui_token_account.token_amount.ui_amount
),
Ok(_) => println!("{:<44} Unsupported token account", address),
Err(err) => println!("{:<44} Account parse failure: {}", address, err),
}
}
} else {
println!("{:<44} Unsupported account data format", address);
}
}
Ok(None)
}
fn main() {
let default_decimals = &format!("{}", native_mint::DECIMALS);
let matches = App::new(crate_name!())
.about(crate_description!())
.version(crate_version!())
@ -498,19 +117,7 @@ fn main() {
.value_name("URL")
.takes_value(true)
.validator(is_url)
.help("JSON RPC URL for the cluster. Default from the configuration file."),
)
.arg(
Arg::with_name("owner")
.long("owner")
.value_name("KEYPAIR")
.validator(is_keypair)
.takes_value(true)
.help(
"Specify the token owner account. \
This may be a keypair file, the ASK keyword. \
Defaults to the client keypair.",
),
.help("JSON RPC URL for the cluster. Default from the configuration file."),
)
.arg(
Arg::with_name("fee_payer")
@ -524,266 +131,6 @@ fn main() {
Defaults to the client keypair.",
),
)
.subcommand(SubCommand::with_name("create-token").about("Create a new token")
.arg(
Arg::with_name("decimals")
.long("decimals")
.validator(|s| {
s.parse::<u8>().map_err(|e| format!("{}", e))?;
Ok(())
})
.value_name("DECIMALS")
.takes_value(true)
.default_value(&default_decimals)
.help("Number of base 10 digits to the right of the decimal place"),
)
.arg(
Arg::with_name("seed")
.long("seed")
.validator(|s| {
s.parse::<u64>().map_err(|e| format!("{}", e))?;
Ok(())
})
.value_name("SEED")
.takes_value(true)
.help("Numeric seed for deterministic account creation (debug only)"),
)
)
.subcommand(
SubCommand::with_name("create-account")
.about("Create a new token account")
.arg(
Arg::with_name("token")
.validator(is_pubkey_or_keypair)
.value_name("TOKEN_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The token that the account will hold"),
)
.arg(
Arg::with_name("seed")
.long("seed")
.validator(|s| {
s.parse::<u64>().map_err(|e| format!("{}", e))?;
Ok(())
})
.value_name("SEED")
.takes_value(true)
.help("Numeric seed for deterministic account creation (debug only)"),
),
)
.subcommand(
SubCommand::with_name("assign")
.about("Assign a token or token account to a new owner")
.arg(
Arg::with_name("address")
.validator(is_pubkey_or_keypair)
.value_name("TOKEN_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The address of the token account"),
)
.arg(
Arg::with_name("new_owner")
.validator(is_pubkey_or_keypair)
.value_name("OWNER_ADDRESS")
.takes_value(true)
.index(2)
.required(true)
.help("The address of the new owner"),
),
)
.subcommand(
SubCommand::with_name("transfer")
.about("Transfer tokens between accounts")
.arg(
Arg::with_name("sender")
.validator(is_pubkey_or_keypair)
.value_name("SENDER_TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The token account address of the sender"),
)
.arg(
Arg::with_name("amount")
.validator(is_amount)
.value_name("TOKEN_AMOUNT")
.takes_value(true)
.index(2)
.required(true)
.help("Amount to send, in tokens"),
)
.arg(
Arg::with_name("recipient")
.validator(is_pubkey_or_keypair)
.value_name("RECIPIENT_TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(3)
.required(true)
.help("The token account address of recipient"),
),
)
.subcommand(
SubCommand::with_name("approve")
.about("Approve token sprending")
.arg(
Arg::with_name("sender")
.validator(is_pubkey_or_keypair)
.value_name("SENDER_TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The token account address of the sender"),
)
.arg(
Arg::with_name("amount")
.validator(is_amount)
.value_name("TOKEN_AMOUNT")
.takes_value(true)
.index(2)
.required(true)
.help("Amount to send, in tokens"),
)
.arg(
Arg::with_name("recipient")
.validator(is_pubkey_or_keypair)
.value_name("RECIPIENT_TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(3)
.required(true)
.help("The token account address of recipient"),
),
)
.subcommand(
SubCommand::with_name("burn")
.about("Burn tokens from an account")
.arg(
Arg::with_name("source")
.validator(is_pubkey_or_keypair)
.value_name("SOURCE_TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The token account address to burn from"),
)
.arg(
Arg::with_name("amount")
.validator(is_amount)
.value_name("TOKEN_AMOUNT")
.takes_value(true)
.index(2)
.required(true)
.help("Amount to burn, in tokens"),
),
)
.subcommand(
SubCommand::with_name("mint")
.about("Mint new tokens")
.arg(
Arg::with_name("token")
.validator(is_pubkey_or_keypair)
.value_name("TOKEN_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The token to mint"),
)
.arg(
Arg::with_name("amount")
.validator(is_amount)
.value_name("TOKEN_AMOUNT")
.takes_value(true)
.index(2)
.required(true)
.help("Amount to mint, in tokens"),
)
.arg(
Arg::with_name("recipient")
.validator(is_pubkey_or_keypair)
.value_name("RECIPIENT_TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(3)
.required(true)
.help("The token account address of recipient"),
),
)
.subcommand(
SubCommand::with_name("balance")
.about("Get token account balance")
.arg(
Arg::with_name("address")
.validator(is_pubkey_or_keypair)
.value_name("TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The token account address"),
),
)
.subcommand(
SubCommand::with_name("supply")
.about("Get token supply")
.arg(
Arg::with_name("address")
.validator(is_pubkey_or_keypair)
.value_name("TOKEN_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The token address"),
),
)
.subcommand(
SubCommand::with_name("accounts")
.about("List all token accounts by owner")
.arg(
Arg::with_name("token")
.validator(is_pubkey_or_keypair)
.value_name("TOKEN_ADDRESS")
.takes_value(true)
.index(1)
.help("Limit results to the given token. [Default: list accounts for all tokens]"),
),
)
.subcommand(
SubCommand::with_name("wrap")
.about("Wrap native SOL in a SOL token account")
.arg(
Arg::with_name("amount")
.validator(is_amount)
.value_name("AMOUNT")
.takes_value(true)
.index(1)
.required(true)
.help("Amount of SOL to wrap"),
),
)
.subcommand(
SubCommand::with_name("unwrap")
.about("Unwrap a SOL token account")
.arg(
Arg::with_name("address")
.validator(is_pubkey_or_keypair)
.value_name("TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.index(1)
.required(true)
.help("The address of the token account to unwrap"),
),
)
.subcommand(SubCommand::with_name("airdrop")
.arg(
Arg::with_name("faucet_url")
.value_name("FAUCET_URL")
.takes_value(true)
.index(1)
.required(true)
.help("The address of the faucet"),
)
.about("Request an airdrop of 100 SOL"))
.subcommand(SubCommand::with_name("create-bridge")
.about("Create a new bridge")
.arg(
@ -801,7 +148,7 @@ fn main() {
.arg(
Arg::with_name("guardian")
.validator(is_hex)
.value_name("GUADIAN_ADDRESS")
.value_name("GUARDIAN_ADDRESS")
.takes_value(true)
.index(2)
.required(true)
@ -825,12 +172,10 @@ fn main() {
})
};
let owner = keypair_of(&matches, "owner").unwrap_or_else(client_keypair);
let fee_payer = keypair_of(&matches, "fee_payer").unwrap_or_else(client_keypair);
Config {
rpc_client: RpcClient::new(json_rpc_url),
owner,
fee_payer,
commitment_config: CommitmentConfig::processed(),
}
@ -839,67 +184,6 @@ fn main() {
solana_logger::setup_with_default("solana=info");
let _ = match matches.subcommand() {
("create-token", Some(arg_matches)) => {
let decimals = value_t_or_exit!(arg_matches, "decimals", u8);
let keypair = keypair_from_seed_arg(arg_matches);
command_create_token(&config, decimals, keypair)
}
("create-account", Some(arg_matches)) => {
let token = pubkey_of(arg_matches, "token").unwrap();
let keypair = keypair_from_seed_arg(arg_matches);
command_create_account(&config, token, keypair)
}
("assign", Some(arg_matches)) => {
let address = pubkey_of(arg_matches, "address").unwrap();
let new_owner = pubkey_of(arg_matches, "new_owner").unwrap();
command_assign(&config, address, new_owner)
}
("transfer", Some(arg_matches)) => {
let sender = pubkey_of(arg_matches, "sender").unwrap();
let amount = value_t_or_exit!(arg_matches, "amount", f64);
let recipient = pubkey_of(arg_matches, "recipient").unwrap();
command_transfer(&config, sender, amount, recipient)
}
("burn", Some(arg_matches)) => {
let source = pubkey_of(arg_matches, "source").unwrap();
let amount = value_t_or_exit!(arg_matches, "amount", f64);
command_burn(&config, source, amount)
}
("mint", Some(arg_matches)) => {
let token = pubkey_of(arg_matches, "token").unwrap();
let amount = value_t_or_exit!(arg_matches, "amount", f64);
let recipient = pubkey_of(arg_matches, "recipient").unwrap();
command_mint(&config, token, amount, recipient)
}
("wrap", Some(arg_matches)) => {
let amount = value_t_or_exit!(arg_matches, "amount", f64);
command_wrap(&config, amount)
}
("unwrap", Some(arg_matches)) => {
let address = pubkey_of(arg_matches, "address").unwrap();
command_unwrap(&config, address)
}
("balance", Some(arg_matches)) => {
let address = pubkey_of(arg_matches, "address").unwrap();
command_balance(&config, address)
}
("supply", Some(arg_matches)) => {
let address = pubkey_of(arg_matches, "address").unwrap();
command_supply(&config, address)
}
("accounts", Some(arg_matches)) => {
let token = pubkey_of(arg_matches, "token");
command_accounts(&config, token)
}
("airdrop", Some(arg_matches)) => {
let faucet_addr = value_t_or_exit!(arg_matches, "faucet_url", String);
request_and_confirm_airdrop(
&config.rpc_client,
&faucet_addr.to_socket_addrs().unwrap().next().unwrap(),
&config.owner.pubkey(),
100 * LAMPORTS_PER_SOL,
)
}
("create-bridge", Some(arg_matches)) => {
let bridge = pubkey_of(arg_matches, "bridge").unwrap();
let initial_guardian: String = value_of(arg_matches, "guardian").unwrap();
@ -938,45 +222,6 @@ fn main() {
});
}
fn keypair_from_seed_arg(arg_matches: &ArgMatches) -> Keypair {
match value_t!(arg_matches, "seed", u64) {
Ok(v) => {
let mut sk_bytes = [0u8; 32];
StepRng::new(v, 1).fill_bytes(&mut sk_bytes);
solana_sdk::signature::keypair_from_seed(&sk_bytes).unwrap()
}
Err(_) => Keypair::new(),
}
}
pub fn is_u8<T>(amount: T) -> Result<(), String>
where
T: AsRef<str> + Display,
{
if amount.as_ref().parse::<u8>().is_ok() {
Ok(())
} else {
Err(format!(
"Unable to parse input amount as integer, provided: {}",
amount
))
}
}
pub fn is_u32<T>(amount: T) -> Result<(), String>
where
T: AsRef<str> + Display,
{
if amount.as_ref().parse::<u32>().is_ok() {
Ok(())
} else {
Err(format!(
"Unable to parse input amount as integer, provided: {}",
amount
))
}
}
pub fn is_hex<T>(value: T) -> Result<(), String>
where
T: AsRef<str> + Display,