spl-token-cli: Consolidate TX construction/signing
This commit is contained in:
parent
e0fb75d134
commit
748ff6c7d8
|
@ -8,14 +8,15 @@ use solana_account_decoder::{
|
||||||
UiAccountData,
|
UiAccountData,
|
||||||
};
|
};
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
input_parsers::pubkey_of_signer,
|
input_parsers::{pubkey_of_signer, signer_of},
|
||||||
input_validators::{is_amount, is_url, is_valid_pubkey, is_valid_signer},
|
input_validators::{is_amount, is_url, is_valid_pubkey, is_valid_signer},
|
||||||
keypair::signer_from_path,
|
keypair::DefaultSigner,
|
||||||
};
|
};
|
||||||
use solana_cli_output::display::println_name_value;
|
use solana_cli_output::display::println_name_value;
|
||||||
use solana_client::{rpc_client::RpcClient, rpc_request::TokenAccountsFilter};
|
use solana_client::{rpc_client::RpcClient, rpc_request::TokenAccountsFilter};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
commitment_config::CommitmentConfig,
|
commitment_config::CommitmentConfig,
|
||||||
|
instruction::Instruction,
|
||||||
native_token::*,
|
native_token::*,
|
||||||
program_pack::Pack,
|
program_pack::Pack,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
|
@ -36,27 +37,27 @@ static WARNING: Emoji = Emoji("⚠️", "!");
|
||||||
struct Config {
|
struct Config {
|
||||||
rpc_client: RpcClient,
|
rpc_client: RpcClient,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
owner: Box<dyn Signer>,
|
owner: Pubkey,
|
||||||
fee_payer: Box<dyn Signer>,
|
fee_payer: Pubkey,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
|
default_signer: DefaultSigner,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Error = Box<dyn std::error::Error>;
|
type Error = Box<dyn std::error::Error>;
|
||||||
type CommandResult = Result<Option<Transaction>, Error>;
|
type CommandResult = Result<Option<(u64, Vec<Instruction>)>, Error>;
|
||||||
|
|
||||||
macro_rules! unique_signers {
|
fn new_throwaway_signer() -> (Option<Box<dyn Signer>>, Option<Pubkey>) {
|
||||||
($vec:ident) => {
|
let keypair = Keypair::new();
|
||||||
$vec.sort_by_key(|l| l.pubkey());
|
let pubkey = keypair.pubkey();
|
||||||
$vec.dedup();
|
(Some(Box::new(keypair) as Box<dyn Signer>), Some(pubkey))
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_fee_payer_balance(config: &Config, required_balance: u64) -> Result<(), Error> {
|
fn check_fee_payer_balance(config: &Config, required_balance: u64) -> Result<(), Error> {
|
||||||
let balance = config.rpc_client.get_balance(&config.fee_payer.pubkey())?;
|
let balance = config.rpc_client.get_balance(&config.fee_payer)?;
|
||||||
if balance < required_balance {
|
if balance < required_balance {
|
||||||
Err(format!(
|
Err(format!(
|
||||||
"Fee payer, {}, has insufficient balance: {} required, {} available",
|
"Fee payer, {}, has insufficient balance: {} required, {} available",
|
||||||
config.fee_payer.pubkey(),
|
config.fee_payer,
|
||||||
lamports_to_sol(required_balance),
|
lamports_to_sol(required_balance),
|
||||||
lamports_to_sol(balance)
|
lamports_to_sol(balance)
|
||||||
)
|
)
|
||||||
|
@ -67,11 +68,11 @@ fn check_fee_payer_balance(config: &Config, required_balance: u64) -> Result<(),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_owner_balance(config: &Config, required_balance: u64) -> Result<(), Error> {
|
fn check_owner_balance(config: &Config, required_balance: u64) -> Result<(), Error> {
|
||||||
let balance = config.rpc_client.get_balance(&config.owner.pubkey())?;
|
let balance = config.rpc_client.get_balance(&config.owner)?;
|
||||||
if balance < required_balance {
|
if balance < required_balance {
|
||||||
Err(format!(
|
Err(format!(
|
||||||
"Owner, {}, has insufficient balance: {} required, {} available",
|
"Owner, {}, has insufficient balance: {} required, {} available",
|
||||||
config.owner.pubkey(),
|
config.owner,
|
||||||
lamports_to_sol(required_balance),
|
lamports_to_sol(required_balance),
|
||||||
lamports_to_sol(balance)
|
lamports_to_sol(balance)
|
||||||
)
|
)
|
||||||
|
@ -84,90 +85,57 @@ fn check_owner_balance(config: &Config, required_balance: u64) -> Result<(), Err
|
||||||
fn command_create_token(
|
fn command_create_token(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
decimals: u8,
|
decimals: u8,
|
||||||
token: Box<dyn Signer>,
|
token: Pubkey,
|
||||||
enable_freeze: bool,
|
enable_freeze: bool,
|
||||||
) -> CommandResult {
|
) -> CommandResult {
|
||||||
println!("Creating token {}", token.pubkey());
|
println!("Creating token {}", token);
|
||||||
|
|
||||||
let minimum_balance_for_rent_exemption = config
|
let minimum_balance_for_rent_exemption = config
|
||||||
.rpc_client
|
.rpc_client
|
||||||
.get_minimum_balance_for_rent_exemption(Mint::LEN)?;
|
.get_minimum_balance_for_rent_exemption(Mint::LEN)?;
|
||||||
let freeze_authority_pubkey = if enable_freeze {
|
let freeze_authority_pubkey = if enable_freeze {
|
||||||
Some(config.owner.pubkey())
|
Some(config.owner)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![
|
||||||
&[
|
|
||||||
system_instruction::create_account(
|
system_instruction::create_account(
|
||||||
&config.fee_payer.pubkey(),
|
&config.fee_payer,
|
||||||
&token.pubkey(),
|
&token,
|
||||||
minimum_balance_for_rent_exemption,
|
minimum_balance_for_rent_exemption,
|
||||||
Mint::LEN as u64,
|
Mint::LEN as u64,
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
),
|
),
|
||||||
initialize_mint(
|
initialize_mint(
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&token.pubkey(),
|
&token,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
freeze_authority_pubkey.as_ref(),
|
freeze_authority_pubkey.as_ref(),
|
||||||
decimals,
|
decimals,
|
||||||
)?,
|
)?,
|
||||||
],
|
];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((minimum_balance_for_rent_exemption, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
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()),
|
|
||||||
)?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), token.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_create_account(
|
fn command_create_account(config: &Config, token: Pubkey, account: Pubkey) -> CommandResult {
|
||||||
config: &Config,
|
println!("Creating account {}", account);
|
||||||
token: Pubkey,
|
|
||||||
account: Box<dyn Signer>,
|
|
||||||
) -> CommandResult {
|
|
||||||
println!("Creating account {}", account.pubkey());
|
|
||||||
|
|
||||||
let minimum_balance_for_rent_exemption = config
|
let minimum_balance_for_rent_exemption = config
|
||||||
.rpc_client
|
.rpc_client
|
||||||
.get_minimum_balance_for_rent_exemption(Account::LEN)?;
|
.get_minimum_balance_for_rent_exemption(Account::LEN)?;
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![
|
||||||
&[
|
|
||||||
system_instruction::create_account(
|
system_instruction::create_account(
|
||||||
&config.fee_payer.pubkey(),
|
&config.fee_payer,
|
||||||
&account.pubkey(),
|
&account,
|
||||||
minimum_balance_for_rent_exemption,
|
minimum_balance_for_rent_exemption,
|
||||||
Account::LEN as u64,
|
Account::LEN as u64,
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
),
|
),
|
||||||
initialize_account(
|
initialize_account(&spl_token::id(), &account, &token, &config.owner)?,
|
||||||
&spl_token::id(),
|
];
|
||||||
&account.pubkey(),
|
Ok(Some((minimum_balance_for_rent_exemption, instructions)))
|
||||||
&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()),
|
|
||||||
)?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), account.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_authorize(
|
fn command_authorize(
|
||||||
|
@ -186,31 +154,22 @@ fn command_authorize(
|
||||||
"Updating {}\n Current {}: {}\n New {}: {}",
|
"Updating {}\n Current {}: {}\n New {}: {}",
|
||||||
account,
|
account,
|
||||||
auth_str,
|
auth_str,
|
||||||
config.owner.pubkey(),
|
config.owner,
|
||||||
auth_str,
|
auth_str,
|
||||||
new_owner
|
new_owner
|
||||||
.map(|pubkey| pubkey.to_string())
|
.map(|pubkey| pubkey.to_string())
|
||||||
.unwrap_or_else(|| "disabled".to_string())
|
.unwrap_or_else(|| "disabled".to_string())
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![set_authority(
|
||||||
&[set_authority(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&account,
|
&account,
|
||||||
new_owner.as_ref(),
|
new_owner.as_ref(),
|
||||||
authority_type,
|
authority_type,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_transfer(
|
fn command_transfer(
|
||||||
|
@ -232,26 +191,17 @@ fn command_transfer(
|
||||||
let mint_pubkey = Pubkey::from_str(&source_account.mint)?;
|
let mint_pubkey = Pubkey::from_str(&source_account.mint)?;
|
||||||
let amount = spl_token::ui_amount_to_amount(ui_amount, source_account.token_amount.decimals);
|
let amount = spl_token::ui_amount_to_amount(ui_amount, source_account.token_amount.decimals);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![transfer_checked(
|
||||||
&[transfer_checked(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&sender,
|
&sender,
|
||||||
&mint_pubkey,
|
&mint_pubkey,
|
||||||
&recipient,
|
&recipient,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
amount,
|
amount,
|
||||||
source_account.token_amount.decimals,
|
source_account.token_amount.decimals,
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_burn(config: &Config, source: Pubkey, ui_amount: f64) -> CommandResult {
|
fn command_burn(config: &Config, source: Pubkey, ui_amount: f64) -> CommandResult {
|
||||||
|
@ -265,25 +215,16 @@ fn command_burn(config: &Config, source: Pubkey, ui_amount: f64) -> CommandResul
|
||||||
let mint_pubkey = Pubkey::from_str(&source_account.mint)?;
|
let mint_pubkey = Pubkey::from_str(&source_account.mint)?;
|
||||||
let amount = spl_token::ui_amount_to_amount(ui_amount, source_account.token_amount.decimals);
|
let amount = spl_token::ui_amount_to_amount(ui_amount, source_account.token_amount.decimals);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![burn_checked(
|
||||||
&[burn_checked(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&source,
|
&source,
|
||||||
&mint_pubkey,
|
&mint_pubkey,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
amount,
|
amount,
|
||||||
source_account.token_amount.decimals,
|
source_account.token_amount.decimals,
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_mint(
|
fn command_mint(
|
||||||
|
@ -303,25 +244,16 @@ fn command_mint(
|
||||||
.value;
|
.value;
|
||||||
let amount = spl_token::ui_amount_to_amount(ui_amount, recipient_token_balance.decimals);
|
let amount = spl_token::ui_amount_to_amount(ui_amount, recipient_token_balance.decimals);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![mint_to_checked(
|
||||||
&[mint_to_checked(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&token,
|
&token,
|
||||||
&recipient,
|
&recipient,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
amount,
|
amount,
|
||||||
recipient_token_balance.decimals,
|
recipient_token_balance.decimals,
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_freeze(config: &Config, account: Pubkey) -> CommandResult {
|
fn command_freeze(config: &Config, account: Pubkey) -> CommandResult {
|
||||||
|
@ -334,23 +266,14 @@ fn command_freeze(config: &Config, account: Pubkey) -> CommandResult {
|
||||||
|
|
||||||
println!("Freezing account: {}\n Token: {}", account, token);
|
println!("Freezing account: {}\n Token: {}", account, token);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![freeze_account(
|
||||||
&[freeze_account(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&account,
|
&account,
|
||||||
&token,
|
&token,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_thaw(config: &Config, account: Pubkey) -> CommandResult {
|
fn command_thaw(config: &Config, account: Pubkey) -> CommandResult {
|
||||||
|
@ -363,56 +286,37 @@ fn command_thaw(config: &Config, account: Pubkey) -> CommandResult {
|
||||||
|
|
||||||
println!("Freezing account: {}\n Token: {}", account, token);
|
println!("Freezing account: {}\n Token: {}", account, token);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![thaw_account(
|
||||||
&[thaw_account(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&account,
|
&account,
|
||||||
&token,
|
&token,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_wrap(config: &Config, sol: f64) -> CommandResult {
|
fn command_wrap(config: &Config, sol: f64, account: Pubkey) -> CommandResult {
|
||||||
let account = Keypair::new();
|
|
||||||
let lamports = sol_to_lamports(sol);
|
let lamports = sol_to_lamports(sol);
|
||||||
println!("Wrapping {} SOL into {}", sol, account.pubkey());
|
println!("Wrapping {} SOL into {}", sol, account);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![
|
||||||
&[
|
|
||||||
system_instruction::create_account(
|
system_instruction::create_account(
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&account.pubkey(),
|
&account,
|
||||||
lamports,
|
lamports,
|
||||||
Account::LEN as u64,
|
Account::LEN as u64,
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
),
|
),
|
||||||
initialize_account(
|
initialize_account(
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&account.pubkey(),
|
&account,
|
||||||
&native_mint::id(),
|
&native_mint::id(),
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
)?,
|
)?,
|
||||||
],
|
];
|
||||||
Some(&config.fee_payer.pubkey()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_owner_balance(config, lamports)?;
|
check_owner_balance(config, lamports)?;
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
Ok(Some((0, instructions)))
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref(), &account];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_unwrap(config: &Config, address: Pubkey) -> CommandResult {
|
fn command_unwrap(config: &Config, address: Pubkey) -> CommandResult {
|
||||||
|
@ -425,26 +329,17 @@ fn command_unwrap(config: &Config, address: Pubkey) -> CommandResult {
|
||||||
.get_balance_with_commitment(&address, config.commitment_config)?
|
.get_balance_with_commitment(&address, config.commitment_config)?
|
||||||
.value
|
.value
|
||||||
),
|
),
|
||||||
config.owner.pubkey()
|
&config.owner,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![close_account(
|
||||||
&[close_account(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&address,
|
&address,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_approve(
|
fn command_approve(
|
||||||
|
@ -466,26 +361,17 @@ fn command_approve(
|
||||||
let mint_pubkey = Pubkey::from_str(&source_account.mint)?;
|
let mint_pubkey = Pubkey::from_str(&source_account.mint)?;
|
||||||
let amount = spl_token::ui_amount_to_amount(ui_amount, source_account.token_amount.decimals);
|
let amount = spl_token::ui_amount_to_amount(ui_amount, source_account.token_amount.decimals);
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![approve_checked(
|
||||||
&[approve_checked(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&account,
|
&account,
|
||||||
&mint_pubkey,
|
&mint_pubkey,
|
||||||
&delegate,
|
&delegate,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
amount,
|
amount,
|
||||||
source_account.token_amount.decimals,
|
source_account.token_amount.decimals,
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_revoke(config: &Config, account: Pubkey) -> CommandResult {
|
fn command_revoke(config: &Config, account: Pubkey) -> CommandResult {
|
||||||
|
@ -505,22 +391,8 @@ fn command_revoke(config: &Config, account: Pubkey) -> CommandResult {
|
||||||
return Err(format!("No delegate on account {}", account).into());
|
return Err(format!("No delegate on account {}", account).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![revoke(&spl_token::id(), &account, &config.owner, &[])?];
|
||||||
&[revoke(
|
Ok(Some((0, instructions)))
|
||||||
&spl_token::id(),
|
|
||||||
&account,
|
|
||||||
&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()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_close(config: &Config, account: Pubkey, destination: Pubkey) -> CommandResult {
|
fn command_close(config: &Config, account: Pubkey, destination: Pubkey) -> CommandResult {
|
||||||
|
@ -538,23 +410,14 @@ fn command_close(config: &Config, account: Pubkey, destination: Pubkey) -> Comma
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut transaction = Transaction::new_with_payer(
|
let instructions = vec![close_account(
|
||||||
&[close_account(
|
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&account,
|
&account,
|
||||||
&destination,
|
&destination,
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
&[],
|
&[],
|
||||||
)?],
|
)?];
|
||||||
Some(&config.fee_payer.pubkey()),
|
Ok(Some((0, instructions)))
|
||||||
);
|
|
||||||
|
|
||||||
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
|
|
||||||
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
|
|
||||||
let mut signers = vec![config.fee_payer.as_ref(), config.owner.as_ref()];
|
|
||||||
unique_signers!(signers);
|
|
||||||
transaction.sign(&signers, recent_blockhash);
|
|
||||||
Ok(Some(transaction))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_balance(config: &Config, address: Pubkey) -> CommandResult {
|
fn command_balance(config: &Config, address: Pubkey) -> CommandResult {
|
||||||
|
@ -587,7 +450,7 @@ fn command_accounts(config: &Config, token: Option<Pubkey>) -> CommandResult {
|
||||||
let accounts = config
|
let accounts = config
|
||||||
.rpc_client
|
.rpc_client
|
||||||
.get_token_accounts_by_owner_with_commitment(
|
.get_token_accounts_by_owner_with_commitment(
|
||||||
&config.owner.pubkey(),
|
&config.owner,
|
||||||
match token {
|
match token {
|
||||||
Some(token) => TokenAccountsFilter::Mint(token),
|
Some(token) => TokenAccountsFilter::Mint(token),
|
||||||
None => TokenAccountsFilter::ProgramId(spl_token::id()),
|
None => TokenAccountsFilter::ProgramId(spl_token::id()),
|
||||||
|
@ -1116,6 +979,7 @@ fn main() {
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let mut wallet_manager = None;
|
let mut wallet_manager = None;
|
||||||
|
let mut bulk_signers: Vec<Option<Box<dyn Signer>>> = Vec::new();
|
||||||
|
|
||||||
let config = {
|
let config = {
|
||||||
let cli_config = if let Some(config_file) = matches.value_of("config_file") {
|
let cli_config = if let Some(config_file) = matches.value_of("config_file") {
|
||||||
|
@ -1128,30 +992,31 @@ fn main() {
|
||||||
.unwrap_or(&cli_config.json_rpc_url)
|
.unwrap_or(&cli_config.json_rpc_url)
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let owner = signer_from_path(
|
let default_signer_arg_name = "owner".to_string();
|
||||||
&matches,
|
let default_signer_path = matches
|
||||||
matches
|
.value_of(&default_signer_arg_name)
|
||||||
.value_of("owner")
|
.map(|s| s.to_string())
|
||||||
.unwrap_or(&cli_config.keypair_path),
|
.unwrap_or(cli_config.keypair_path);
|
||||||
"owner",
|
let default_signer = DefaultSigner {
|
||||||
&mut wallet_manager,
|
path: default_signer_path,
|
||||||
)
|
arg_name: default_signer_arg_name,
|
||||||
.unwrap_or_else(|e| {
|
};
|
||||||
eprintln!("error: {}", e);
|
let owner = default_signer
|
||||||
exit(1);
|
.signer_from_path(&matches, &mut wallet_manager)
|
||||||
});
|
.unwrap_or_else(|e| {
|
||||||
let fee_payer = signer_from_path(
|
eprintln!("error: {}", e);
|
||||||
&matches,
|
exit(1);
|
||||||
matches
|
})
|
||||||
.value_of("fee_payer")
|
.pubkey();
|
||||||
.unwrap_or(&cli_config.keypair_path),
|
bulk_signers.push(None);
|
||||||
"fee_payer",
|
let (signer, fee_payer) = signer_of(&matches, "fee_payer", &mut wallet_manager)
|
||||||
&mut wallet_manager,
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
eprintln!("error: {}", e);
|
eprintln!("error: {}", e);
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
|
let fee_payer = fee_payer.unwrap_or(owner);
|
||||||
|
bulk_signers.push(signer);
|
||||||
|
|
||||||
let verbose = matches.is_present("verbose");
|
let verbose = matches.is_present("verbose");
|
||||||
|
|
||||||
Config {
|
Config {
|
||||||
|
@ -1160,6 +1025,7 @@ fn main() {
|
||||||
owner,
|
owner,
|
||||||
fee_payer,
|
fee_payer,
|
||||||
commitment_config: CommitmentConfig::single_gossip(),
|
commitment_config: CommitmentConfig::single_gossip(),
|
||||||
|
default_signer,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1168,20 +1034,16 @@ fn main() {
|
||||||
let _ = match matches.subcommand() {
|
let _ = match matches.subcommand() {
|
||||||
("create-token", Some(arg_matches)) => {
|
("create-token", Some(arg_matches)) => {
|
||||||
let decimals = value_t_or_exit!(arg_matches, "decimals", u8);
|
let decimals = value_t_or_exit!(arg_matches, "decimals", u8);
|
||||||
let token = if arg_matches.is_present("token_keypair") {
|
let (signer, token) = if arg_matches.is_present("token_keypair") {
|
||||||
signer_from_path(
|
signer_of(&arg_matches, "token_keypair", &mut wallet_manager).unwrap_or_else(|e| {
|
||||||
&matches,
|
|
||||||
&value_t_or_exit!(arg_matches, "token_keypair", String),
|
|
||||||
"token_keypair",
|
|
||||||
&mut wallet_manager,
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|e| {
|
|
||||||
eprintln!("error: {}", e);
|
eprintln!("error: {}", e);
|
||||||
exit(1);
|
exit(1);
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Box::new(Keypair::new())
|
new_throwaway_signer()
|
||||||
};
|
};
|
||||||
|
let token = token.unwrap();
|
||||||
|
bulk_signers.push(signer);
|
||||||
|
|
||||||
command_create_token(
|
command_create_token(
|
||||||
&config,
|
&config,
|
||||||
|
@ -1194,20 +1056,18 @@ fn main() {
|
||||||
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager)
|
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let account = if arg_matches.is_present("account_keypair") {
|
let (signer, account) = if arg_matches.is_present("account_keypair") {
|
||||||
signer_from_path(
|
signer_of(&arg_matches, "account_keypair", &mut wallet_manager).unwrap_or_else(
|
||||||
&matches,
|
|e| {
|
||||||
&value_t_or_exit!(arg_matches, "account_keypair", String),
|
|
||||||
"account_keypair",
|
|
||||||
&mut wallet_manager,
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|e| {
|
|
||||||
eprintln!("error: {}", e);
|
eprintln!("error: {}", e);
|
||||||
exit(1);
|
exit(1);
|
||||||
})
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Box::new(Keypair::new())
|
new_throwaway_signer()
|
||||||
};
|
};
|
||||||
|
let account = account.unwrap();
|
||||||
|
bulk_signers.push(signer);
|
||||||
|
|
||||||
command_create_account(&config, token, account)
|
command_create_account(&config, token, account)
|
||||||
}
|
}
|
||||||
|
@ -1268,7 +1128,10 @@ fn main() {
|
||||||
}
|
}
|
||||||
("wrap", Some(arg_matches)) => {
|
("wrap", Some(arg_matches)) => {
|
||||||
let amount = value_t_or_exit!(arg_matches, "amount", f64);
|
let amount = value_t_or_exit!(arg_matches, "amount", f64);
|
||||||
command_wrap(&config, amount)
|
let (signer, account) = new_throwaway_signer();
|
||||||
|
let account = account.unwrap();
|
||||||
|
bulk_signers.push(signer);
|
||||||
|
command_wrap(&config, amount, account)
|
||||||
}
|
}
|
||||||
("unwrap", Some(arg_matches)) => {
|
("unwrap", Some(arg_matches)) => {
|
||||||
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager)
|
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager)
|
||||||
|
@ -1325,8 +1188,31 @@ fn main() {
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
.and_then(|transaction| {
|
.and_then(|transaction_info| {
|
||||||
if let Some(transaction) = transaction {
|
if let Some((minimum_balance_for_rent_exemption, instructions)) = transaction_info {
|
||||||
|
let mut transaction =
|
||||||
|
Transaction::new_with_payer(&instructions, Some(&config.fee_payer));
|
||||||
|
let (recent_blockhash, fee_calculator) = config
|
||||||
|
.rpc_client
|
||||||
|
.get_recent_blockhash()
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
eprintln!("error: {}", e);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
check_fee_payer_balance(
|
||||||
|
&config,
|
||||||
|
minimum_balance_for_rent_exemption
|
||||||
|
+ fee_calculator.calculate_fee(&transaction.message()),
|
||||||
|
)?;
|
||||||
|
let signer_info = config
|
||||||
|
.default_signer
|
||||||
|
.generate_unique_signers(bulk_signers, &matches, &mut wallet_manager)
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
eprintln!("error: {}", e);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
transaction.sign(&signer_info.signers, recent_blockhash);
|
||||||
|
|
||||||
let signature = config
|
let signature = config
|
||||||
.rpc_client
|
.rpc_client
|
||||||
.send_and_confirm_transaction_with_spinner_and_commitment(
|
.send_and_confirm_transaction_with_spinner_and_commitment(
|
||||||
|
|
Loading…
Reference in New Issue