Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit f2de73d

Browse files
spl-token-cli: support ATA in close, balance, and account-info (#1537)
* Use ATA by default in close command * Use ATA by default in balance/account-info queries * Add Aux tag and gc messaging to spl-token account-info * Recommend 'token' only if no args provided
1 parent 19e1161 commit f2de73d

File tree

1 file changed

+112
-35
lines changed

1 file changed

+112
-35
lines changed

token/cli/src/main.rs

Lines changed: 112 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,17 @@ fn command_revoke(config: &Config, account: Pubkey, delegate: Option<Pubkey>) ->
834834
Ok(Some((0, vec![instructions])))
835835
}
836836

837-
fn command_close(config: &Config, account: Pubkey, destination: Pubkey) -> CommandResult {
837+
fn command_close(
838+
config: &Config,
839+
token: Option<Pubkey>,
840+
recipient: Pubkey,
841+
account: Option<Pubkey>,
842+
) -> CommandResult {
843+
let account = if let Some(account) = account {
844+
account
845+
} else {
846+
get_associated_token_address(&config.owner, &token.unwrap())
847+
};
838848
if !config.sign_only {
839849
let source_account = config
840850
.rpc_client
@@ -864,15 +874,27 @@ fn command_close(config: &Config, account: Pubkey, destination: Pubkey) -> Comma
864874
let instructions = vec![close_account(
865875
&spl_token::id(),
866876
&account,
867-
&destination,
877+
&recipient,
868878
&config.owner,
869879
&config.multisigner_pubkeys,
870880
)?];
871881
Ok(Some((0, vec![instructions])))
872882
}
873883

874-
fn command_balance(config: &Config, address: Pubkey) -> CommandResult {
875-
let balance = config.rpc_client.get_token_account_balance(&address)?;
884+
fn command_balance(
885+
config: &Config,
886+
token: Option<Pubkey>,
887+
address: Option<Pubkey>,
888+
) -> CommandResult {
889+
let address = if let Some(address) = address {
890+
address
891+
} else {
892+
get_associated_token_address(&config.owner, &token.unwrap())
893+
};
894+
let balance = config
895+
.rpc_client
896+
.get_token_account_balance(&address)
897+
.map_err(|_| format!("Could not find token account {}", address))?;
876898

877899
if config.verbose {
878900
println!("ui amount: {}", balance.real_number_string_trimmed());
@@ -1027,10 +1049,35 @@ fn command_address(config: &Config, token: Option<Pubkey>) -> CommandResult {
10271049
Ok(None)
10281050
}
10291051

1030-
fn command_account_info(config: &Config, address: Pubkey) -> CommandResult {
1031-
let account = config.rpc_client.get_token_account(&address)?.unwrap();
1052+
fn command_account_info(
1053+
config: &Config,
1054+
token: Option<Pubkey>,
1055+
address: Option<Pubkey>,
1056+
) -> CommandResult {
1057+
let mut is_associated = false;
1058+
let address = if let Some(address) = address {
1059+
address
1060+
} else {
1061+
is_associated = true;
1062+
get_associated_token_address(&config.owner, &token.unwrap())
1063+
};
1064+
let account = config
1065+
.rpc_client
1066+
.get_token_account(&address)
1067+
.map_err(|_| format!("Could not find token account {}", address))?
1068+
.unwrap();
1069+
if !is_associated {
1070+
if let Ok(mint) = Pubkey::from_str(&account.mint) {
1071+
is_associated = get_associated_token_address(&config.owner, &mint) == address;
1072+
}
1073+
}
1074+
let address_message = if is_associated {
1075+
address.to_string()
1076+
} else {
1077+
format!("{} (Aux*)", address)
1078+
};
10321079
println!();
1033-
println_name_value("Address:", &address.to_string());
1080+
println_name_value("Address:", &address_message);
10341081
println_name_value(
10351082
"Balance:",
10361083
&account.token_amount.real_number_string_trimmed(),
@@ -1055,6 +1102,10 @@ fn command_account_info(config: &Config, address: Pubkey) -> CommandResult {
10551102
"Close authority:",
10561103
&account.close_authority.as_ref().unwrap_or(&String::new()),
10571104
);
1105+
if !is_associated {
1106+
println!();
1107+
println!("* Please run `spl-token gc` to clean up Aux accounts");
1108+
}
10581109
Ok(None)
10591110
}
10601111

@@ -1703,37 +1754,57 @@ fn main() {
17031754
SubCommand::with_name("close")
17041755
.about("Close a token account")
17051756
.arg(
1706-
Arg::with_name("account")
1757+
Arg::with_name("token")
17071758
.validator(is_valid_pubkey)
1708-
.value_name("TOKEN_ACCOUNT_ADDRESS")
1759+
.value_name("TOKEN_ADDRESS")
17091760
.takes_value(true)
17101761
.index(1)
1711-
.required(true)
1712-
.help("The address of the token account to close"),
1762+
.required_unless("address")
1763+
.help("Token to close. To close a specific account, use the `--address` parameter instead"),
17131764
)
17141765
.arg(
1715-
Arg::with_name("destination")
1766+
Arg::with_name("recipient")
1767+
.long("recipient")
17161768
.validator(is_valid_pubkey)
17171769
.value_name("REFUND_ACCOUNT_ADDRESS")
17181770
.takes_value(true)
1719-
.index(2)
17201771
.help("The address of the account to receive remaining SOL [default: --owner]"),
17211772
)
1773+
.arg(
1774+
Arg::with_name("address")
1775+
.long("address")
1776+
.validator(is_valid_pubkey)
1777+
.value_name("TOKEN_ACCOUNT_ADDRESS")
1778+
.takes_value(true)
1779+
.conflicts_with("token")
1780+
.help("Specify the token account to close \
1781+
[default: owner's associated token account]"),
1782+
)
17221783
.arg(multisig_signer_arg())
17231784
.nonce_args(true)
17241785
.offline_args(),
17251786
)
17261787
.subcommand(
17271788
SubCommand::with_name("balance")
17281789
.about("Get token account balance")
1790+
.arg(
1791+
Arg::with_name("token")
1792+
.validator(is_valid_pubkey)
1793+
.value_name("TOKEN_ADDRESS")
1794+
.takes_value(true)
1795+
.index(1)
1796+
.required_unless("address")
1797+
.help("Token of associated account. To query a specific account, use the `--address` parameter instead"),
1798+
)
17291799
.arg(
17301800
Arg::with_name("address")
17311801
.validator(is_valid_pubkey)
17321802
.value_name("TOKEN_ACCOUNT_ADDRESS")
17331803
.takes_value(true)
1734-
.index(1)
1735-
.required(true)
1736-
.help("The token account address"),
1804+
.long("address")
1805+
.conflicts_with("token")
1806+
.help("Specify the token account to query \
1807+
[default: owner's associated token account]"),
17371808
),
17381809
)
17391810
.subcommand(
@@ -1777,14 +1848,23 @@ fn main() {
17771848
.subcommand(
17781849
SubCommand::with_name("account-info")
17791850
.about("Query details of an SPL Token account by address")
1851+
.arg(
1852+
Arg::with_name("token")
1853+
.validator(is_valid_pubkey)
1854+
.value_name("TOKEN_ADDRESS")
1855+
.takes_value(true)
1856+
.index(1)
1857+
.required_unless("address")
1858+
.help("Token of associated account. To query a specific account, use the `--address` parameter instead"),
1859+
)
17801860
.arg(
17811861
Arg::with_name("address")
1782-
.validator(is_valid_pubkey)
1783-
.value_name("TOKEN_ACCOUNT_ADDRESS")
1784-
.takes_value(true)
1785-
.index(1)
1786-
.required(true)
1787-
.help("The address of the SPL Token account to query"),
1862+
.validator(is_valid_pubkey)
1863+
.value_name("TOKEN_ACCOUNT_ADDRESS")
1864+
.takes_value(true)
1865+
.long("address")
1866+
.conflicts_with("token")
1867+
.help("Specify the token account to query"),
17881868
),
17891869
)
17901870
.subcommand(
@@ -2146,19 +2226,17 @@ fn main() {
21462226
command_revoke(&config, account, delegate_address)
21472227
}
21482228
("close", Some(arg_matches)) => {
2149-
let account = pubkey_of_signer(arg_matches, "account", &mut wallet_manager)
2150-
.unwrap()
2151-
.unwrap();
2152-
let destination = pubkey_of_signer(arg_matches, "destination", &mut wallet_manager)
2229+
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap();
2230+
let recipient = pubkey_of_signer(arg_matches, "recipient", &mut wallet_manager)
21532231
.unwrap()
21542232
.unwrap_or(config.owner);
2155-
command_close(&config, account, destination)
2233+
let account = pubkey_of_signer(arg_matches, "address", &mut wallet_manager).unwrap();
2234+
command_close(&config, token, recipient, account)
21562235
}
21572236
("balance", Some(arg_matches)) => {
2158-
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager)
2159-
.unwrap()
2160-
.unwrap();
2161-
command_balance(&config, address)
2237+
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap();
2238+
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager).unwrap();
2239+
command_balance(&config, token, address)
21622240
}
21632241
("supply", Some(arg_matches)) => {
21642242
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager)
@@ -2175,10 +2253,9 @@ fn main() {
21752253
command_address(&config, token)
21762254
}
21772255
("account-info", Some(arg_matches)) => {
2178-
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager)
2179-
.unwrap()
2180-
.unwrap();
2181-
command_account_info(&config, address)
2256+
let token = pubkey_of_signer(arg_matches, "token", &mut wallet_manager).unwrap();
2257+
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager).unwrap();
2258+
command_account_info(&config, token, address)
21822259
}
21832260
("multisig-info", Some(arg_matches)) => {
21842261
let address = pubkey_of_signer(arg_matches, "address", &mut wallet_manager)

0 commit comments

Comments
 (0)