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

Commit 37280ce

Browse files
authored
token-cli: Move everything to async (#3353)
1 parent d3cbe36 commit 37280ce

File tree

5 files changed

+772
-634
lines changed

5 files changed

+772
-634
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

token/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ spl-associated-token-account = { version = "1.0.5", path="../../associated-token
3232
spl-memo = { version = "3.0.1", path="../../memo/program", features = ["no-entrypoint"] }
3333
strum = "0.24"
3434
strum_macros = "0.24"
35+
tokio = "1.14"
3536

3637
[dev-dependencies]
3738
solana-test-validator = "=1.10.29"

token/cli/src/bench.rs

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@ use {
77
input_validators::{is_amount, is_parsable, is_valid_pubkey},
88
},
99
solana_client::{
10-
rpc_client::RpcClient,
11-
tpu_client::{TpuClient, TpuClientConfig},
10+
nonblocking::rpc_client::RpcClient, rpc_client::RpcClient as BlockingRpcClient,
11+
tpu_client::TpuClient, tpu_client::TpuClientConfig,
1212
},
1313
solana_remote_wallet::remote_wallet::RemoteWalletManager,
1414
solana_sdk::{
1515
message::Message, native_token::Sol, program_pack::Pack, pubkey::Pubkey, signature::Signer,
1616
system_instruction,
1717
},
1818
spl_associated_token_account::*,
19+
spl_token::{
20+
instruction,
21+
state::{Account, Mint},
22+
},
1923
std::{sync::Arc, time::Instant},
2024
};
2125

@@ -160,9 +164,9 @@ impl BenchSubCommand for App<'_, '_> {
160164
}
161165
}
162166

163-
pub(crate) fn bench_process_command(
167+
pub(crate) async fn bench_process_command(
164168
matches: &ArgMatches<'_>,
165-
config: &Config,
169+
config: &Config<'_>,
166170
mut signers: Vec<Box<dyn Signer>>,
167171
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
168172
) -> CommandResult {
@@ -179,7 +183,7 @@ pub(crate) fn bench_process_command(
179183
config.signer_or_default(arg_matches, "owner", wallet_manager);
180184
signers.push(owner_signer);
181185

182-
command_create_accounts(config, signers, &token, n, &owner)?;
186+
command_create_accounts(config, signers, &token, n, &owner).await?;
183187
}
184188
("close-accounts", Some(arg_matches)) => {
185189
let token = pubkey_of_signer(arg_matches, "token", wallet_manager)
@@ -190,7 +194,7 @@ pub(crate) fn bench_process_command(
190194
config.signer_or_default(arg_matches, "owner", wallet_manager);
191195
signers.push(owner_signer);
192196

193-
command_close_accounts(config, signers, &token, n, &owner)?;
197+
command_close_accounts(config, signers, &token, n, &owner).await?;
194198
}
195199
("deposit-into", Some(arg_matches)) => {
196200
let token = pubkey_of_signer(arg_matches, "token", wallet_manager)
@@ -209,7 +213,8 @@ pub(crate) fn bench_process_command(
209213

210214
command_deposit_into_or_withdraw_from(
211215
config, signers, &token, n, &owner, ui_amount, &from, true,
212-
)?;
216+
)
217+
.await?;
213218
}
214219
("withdraw-from", Some(arg_matches)) => {
215220
let token = pubkey_of_signer(arg_matches, "token", wallet_manager)
@@ -228,7 +233,8 @@ pub(crate) fn bench_process_command(
228233

229234
command_deposit_into_or_withdraw_from(
230235
config, signers, &token, n, &owner, ui_amount, &to, false,
231-
)?;
236+
)
237+
.await?;
232238
}
233239
_ => unreachable!(),
234240
}
@@ -260,18 +266,19 @@ fn get_token_addresses_with_seed(
260266
.collect()
261267
}
262268

263-
fn is_valid_token(rpc_client: &RpcClient, token: &Pubkey) -> Result<(), Error> {
264-
let mint_account_data = rpc_client
269+
async fn is_valid_token(rpc_client: &RpcClient, token: &Pubkey) -> Result<(), Error> {
270+
let mint_account = rpc_client
265271
.get_account_data(token)
272+
.await
266273
.map_err(|err| format!("Token mint {} does not exist: {}", token, err))?;
267274

268-
spl_token::state::Mint::unpack(&mint_account_data)
275+
Mint::unpack(&mint_account)
269276
.map(|_| ())
270277
.map_err(|err| format!("Invalid token mint {}: {}", token, err).into())
271278
}
272279

273-
fn command_create_accounts(
274-
config: &Config,
280+
async fn command_create_accounts(
281+
config: &Config<'_>,
275282
signers: Vec<Box<dyn Signer>>,
276283
token: &Pubkey,
277284
n: usize,
@@ -280,10 +287,11 @@ fn command_create_accounts(
280287
let rpc_client = &config.rpc_client;
281288

282289
println!("Scanning accounts...");
283-
is_valid_token(rpc_client, token)?;
290+
is_valid_token(rpc_client, token).await?;
284291

285292
let minimum_balance_for_rent_exemption = rpc_client
286-
.get_minimum_balance_for_rent_exemption(spl_token::state::Account::get_packed_len())?;
293+
.get_minimum_balance_for_rent_exemption(Account::get_packed_len())
294+
.await?;
287295

288296
let mut lamports_required = 0;
289297

@@ -292,7 +300,8 @@ fn command_create_accounts(
292300
let mut messages = vec![];
293301
for address_chunk in token_addresses_with_seed.chunks(100) {
294302
let accounts_chunk = rpc_client
295-
.get_multiple_accounts(&address_chunk.iter().map(|x| x.0).collect::<Vec<_>>())?;
303+
.get_multiple_accounts(&address_chunk.iter().map(|x| x.0).collect::<Vec<_>>())
304+
.await?;
296305

297306
for (account, (address, seed)) in accounts_chunk.iter().zip(address_chunk) {
298307
if account.is_none() {
@@ -305,27 +314,22 @@ fn command_create_accounts(
305314
owner,
306315
seed,
307316
minimum_balance_for_rent_exemption,
308-
spl_token::state::Account::get_packed_len() as u64,
317+
Account::get_packed_len() as u64,
309318
&config.program_id,
310319
),
311-
spl_token::instruction::initialize_account(
312-
&config.program_id,
313-
address,
314-
token,
315-
owner,
316-
)?,
320+
instruction::initialize_account(&config.program_id, address, token, owner)?,
317321
],
318322
Some(&config.fee_payer),
319323
));
320324
}
321325
}
322326
}
323327

324-
send_messages(config, &messages, lamports_required, signers)
328+
send_messages(config, &messages, lamports_required, signers).await
325329
}
326330

327-
fn command_close_accounts(
328-
config: &Config,
331+
async fn command_close_accounts(
332+
config: &Config<'_>,
329333
signers: Vec<Box<dyn Signer>>,
330334
token: &Pubkey,
331335
n: usize,
@@ -334,18 +338,19 @@ fn command_close_accounts(
334338
let rpc_client = &config.rpc_client;
335339

336340
println!("Scanning accounts...");
337-
is_valid_token(rpc_client, token)?;
341+
is_valid_token(rpc_client, token).await?;
338342

339343
let token_addresses_with_seed =
340344
get_token_addresses_with_seed(&config.program_id, token, owner, n);
341345
let mut messages = vec![];
342346
for address_chunk in token_addresses_with_seed.chunks(100) {
343347
let accounts_chunk = rpc_client
344-
.get_multiple_accounts(&address_chunk.iter().map(|x| x.0).collect::<Vec<_>>())?;
348+
.get_multiple_accounts(&address_chunk.iter().map(|x| x.0).collect::<Vec<_>>())
349+
.await?;
345350

346351
for (account, (address, _seed)) in accounts_chunk.iter().zip(address_chunk) {
347352
if let Some(account) = account {
348-
match spl_token::state::Account::unpack(&account.data) {
353+
match Account::unpack(&account.data) {
349354
Ok(token_account) => {
350355
if token_account.amount != 0 {
351356
eprintln!(
@@ -354,7 +359,7 @@ fn command_close_accounts(
354359
);
355360
} else {
356361
messages.push(Message::new(
357-
&[spl_token::instruction::close_account(
362+
&[instruction::close_account(
358363
&config.program_id,
359364
address,
360365
owner,
@@ -373,12 +378,12 @@ fn command_close_accounts(
373378
}
374379
}
375380

376-
send_messages(config, &messages, 0, signers)
381+
send_messages(config, &messages, 0, signers).await
377382
}
378383

379384
#[allow(clippy::too_many_arguments)]
380-
fn command_deposit_into_or_withdraw_from(
381-
config: &Config,
385+
async fn command_deposit_into_or_withdraw_from(
386+
config: &Config<'_>,
382387
signers: Vec<Box<dyn Signer>>,
383388
token: &Pubkey,
384389
n: usize,
@@ -390,9 +395,10 @@ fn command_deposit_into_or_withdraw_from(
390395
let rpc_client = &config.rpc_client;
391396

392397
println!("Scanning accounts...");
393-
is_valid_token(rpc_client, token)?;
398+
is_valid_token(rpc_client, token).await?;
394399

395-
let (mint_pubkey, decimals) = crate::resolve_mint_info(config, from_or_to, Some(*token), None)?;
400+
let (mint_pubkey, decimals) =
401+
crate::resolve_mint_info(config, from_or_to, Some(*token), None).await?;
396402
if mint_pubkey != *token {
397403
return Err(format!("Source account {} is not a {} token", from_or_to, token).into());
398404
}
@@ -403,12 +409,13 @@ fn command_deposit_into_or_withdraw_from(
403409
let mut messages = vec![];
404410
for address_chunk in token_addresses_with_seed.chunks(100) {
405411
let accounts_chunk = rpc_client
406-
.get_multiple_accounts(&address_chunk.iter().map(|x| x.0).collect::<Vec<_>>())?;
412+
.get_multiple_accounts(&address_chunk.iter().map(|x| x.0).collect::<Vec<_>>())
413+
.await?;
407414

408415
for (account, (address, _seed)) in accounts_chunk.iter().zip(address_chunk) {
409416
if account.is_some() {
410417
messages.push(Message::new(
411-
&[spl_token::instruction::transfer_checked(
418+
&[instruction::transfer_checked(
412419
&config.program_id,
413420
if deposit_into { from_or_to } else { address },
414421
token,
@@ -426,11 +433,11 @@ fn command_deposit_into_or_withdraw_from(
426433
}
427434
}
428435

429-
send_messages(config, &messages, 0, signers)
436+
send_messages(config, &messages, 0, signers).await
430437
}
431438

432-
fn send_messages(
433-
config: &Config,
439+
async fn send_messages(
440+
config: &Config<'_>,
434441
messages: &[Message],
435442
mut lamports_required: u64,
436443
signers: Vec<Box<dyn Signer>>,
@@ -442,7 +449,8 @@ fn send_messages(
442449

443450
let (_blockhash, fee_calculator, _last_valid_block_height) = config
444451
.rpc_client
445-
.get_recent_blockhash_with_commitment(config.rpc_client.commitment())?
452+
.get_recent_blockhash_with_commitment(config.rpc_client.commitment())
453+
.await?
446454
.value;
447455

448456
lamports_required += messages
@@ -456,17 +464,18 @@ fn send_messages(
456464
Sol(lamports_required)
457465
);
458466

459-
crate::check_fee_payer_balance(config, lamports_required)?;
467+
crate::check_fee_payer_balance(config, lamports_required).await?;
460468

469+
// TODO use async tpu client once it's available in 1.11
461470
let start = Instant::now();
471+
let rpc_client = BlockingRpcClient::new(config.rpc_client.url());
462472
let tpu_client = TpuClient::new(
463-
config.rpc_client.clone(),
473+
Arc::new(rpc_client),
464474
&config.websocket_url,
465475
TpuClientConfig::default(),
466476
)?;
467477
let transaction_errors =
468478
tpu_client.send_and_confirm_messages_with_spinner(messages, &signers)?;
469-
470479
for (i, transaction_error) in transaction_errors.into_iter().enumerate() {
471480
if let Some(transaction_error) = transaction_error {
472481
println!("Message {} failed with {:?}", i, transaction_error);

token/cli/src/config.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use solana_clap_utils::{
44
keypair::{pubkey_from_path, signer_from_path_with_config, SignerFromPathConfig},
55
};
66
use solana_cli_output::OutputFormat;
7-
use solana_client::{blockhash_query::BlockhashQuery, rpc_client::RpcClient};
7+
use solana_client::nonblocking::rpc_client::RpcClient;
88
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
99
use solana_sdk::{pubkey::Pubkey, signature::Signer};
1010
use spl_associated_token_account::*;
@@ -29,7 +29,6 @@ pub(crate) struct Config<'a> {
2929
pub(crate) default_keypair: KeypairOrPath,
3030
pub(crate) nonce_account: Option<Pubkey>,
3131
pub(crate) nonce_authority: Option<Pubkey>,
32-
pub(crate) blockhash_query: BlockhashQuery,
3332
pub(crate) sign_only: bool,
3433
pub(crate) dump_transaction_message: bool,
3534
pub(crate) multisigner_pubkeys: Vec<&'a Pubkey>,
@@ -39,9 +38,9 @@ pub(crate) struct Config<'a> {
3938
impl<'a> Config<'a> {
4039
// Check if an explicit token account address was provided, otherwise
4140
// return the associated token address for the default address.
42-
pub(crate) fn associated_token_address_or_override(
41+
pub(crate) async fn associated_token_address_or_override(
4342
&self,
44-
arg_matches: &ArgMatches,
43+
arg_matches: &ArgMatches<'_>,
4544
override_name: &str,
4645
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
4746
) -> Pubkey {
@@ -52,13 +51,14 @@ impl<'a> Config<'a> {
5251
wallet_manager,
5352
token,
5453
)
54+
.await
5555
}
5656

5757
// Check if an explicit token account address was provided, otherwise
5858
// return the associated token address for the default address.
59-
pub(crate) fn associated_token_address_for_token_or_override(
59+
pub(crate) async fn associated_token_address_for_token_or_override(
6060
&self,
61-
arg_matches: &ArgMatches,
61+
arg_matches: &ArgMatches<'_>,
6262
override_name: &str,
6363
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
6464
token: Option<Pubkey>,

0 commit comments

Comments
 (0)