refactor(integration_bench): ScenarioOutput::step closure helper

This commit is contained in:
moudyellaz 2026-05-20 12:19:43 +02:00
parent 0119b38c1b
commit ab77c5d26a
7 changed files with 383 additions and 418 deletions

View File

@ -77,12 +77,29 @@ impl ScenarioOutput {
self.total = self.total.saturating_add(step.total);
self.steps.push(step);
}
/// Run a single timed step against `ctx`: capture pre-block, run `submit`,
/// finalize timings, push a `StepResult` onto `self.steps`. Returns the
/// `SubcommandReturnValue` from `submit` so the caller can match on it.
pub async fn step(
&mut self,
ctx: &mut TestContext,
label: impl Into<String>,
submit: impl AsyncFnOnce(&mut TestContext) -> Result<SubcommandReturnValue>,
) -> Result<SubcommandReturnValue> {
let pre_block = begin_step(ctx).await?;
let started = Instant::now();
let ret = submit(ctx).await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
self.push(step);
Ok(ret)
}
}
/// Begin a timed step. Capture this *before* submitting the wallet operation
/// so we can later subtract it from the post-submit block height to detect
/// when the chain has advanced past the tx's block.
pub async fn begin_step(ctx: &TestContext) -> Result<u64> {
async fn begin_step(ctx: &TestContext) -> Result<u64> {
Ok(ctx.sequencer_client().get_last_block_id().await?)
}
@ -90,14 +107,7 @@ pub async fn begin_step(ctx: &TestContext) -> Result<u64> {
/// being captured and `ret` being received) and, if `ret` is a
/// [`SubcommandReturnValue::PrivacyPreservingTransfer`], polls the sequencer
/// for inclusion and records the inclusion latency. Returns a [`StepResult`].
///
/// Usage:
/// ```ignore
/// let started = Instant::now();
/// let ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), cmd).await?;
/// let step = finalize_step("label", started, pre_block_id, &ret, ctx).await?;
/// ```
pub async fn finalize_step(
async fn finalize_step(
label: impl Into<String>,
started: Instant,
pre_block_id: u64,

View File

@ -22,10 +22,12 @@
clippy::arithmetic_side_effects,
clippy::print_stderr,
clippy::print_stdout,
clippy::shadow_unrelated,
clippy::wildcard_enum_match_arm,
reason = "Bench tool: stderr/stdout output is the deliverable; small Duration / iterator-sum \
arithmetic is safe at bench scale; bench scenarios bail loudly on any unexpected \
return variant, which is preferable to maintaining an exhaustive list in five files."
return variant, which is preferable to maintaining an exhaustive list in five files; \
the step() closure helper canonically rebinds `ctx` inside the closure body."
)]
use std::{path::PathBuf, time::Duration};

View File

@ -1,18 +1,16 @@
//! AMM swap flow: setup two tokens, create pool, swap, add liquidity, remove liquidity.
use std::time::Instant;
use anyhow::{Result, bail};
use test_fixtures::public_mention;
use test_fixtures::{TestContext, public_mention};
use wallet::cli::{
Command, SubcommandReturnValue,
account::{AccountSubcommand, NewSubcommand},
programs::{amm::AmmProgramAgnosticSubcommand, token::TokenProgramAgnosticSubcommand},
};
use crate::harness::{ScenarioOutput, finalize_step};
use crate::harness::ScenarioOutput;
pub async fn run(ctx: &mut test_fixtures::TestContext) -> Result<ScenarioOutput> {
pub async fn run(ctx: &mut TestContext) -> Result<ScenarioOutput> {
let mut output = ScenarioOutput::new("amm_swap_flow");
let def_a = new_public_account(ctx, &mut output, "create_acc_def_a").await?;
@ -26,121 +24,97 @@ pub async fn run(ctx: &mut test_fixtures::TestContext) -> Result<ScenarioOutput>
let user_lp = new_public_account(ctx, &mut output, "create_acc_user_lp").await?;
timed_token_new(ctx, &mut output, "token_a_new", def_a, supply_a, "TokA").await?;
timed_token_send(
ctx,
&mut output,
"token_a_fund_user",
supply_a,
user_a,
1_000,
)
.await?;
timed_token_send(ctx, &mut output, "token_a_fund_user", supply_a, user_a, 1_000).await?;
timed_token_new(ctx, &mut output, "token_b_new", def_b, supply_b, "TokB").await?;
timed_token_send(
ctx,
&mut output,
"token_b_fund_user",
supply_b,
user_b,
1_000,
)
.await?;
timed_token_send(ctx, &mut output, "token_b_fund_user", supply_b, user_b, 1_000).await?;
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::New {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
user_holding_lp: public_mention(user_lp),
balance_a: 300,
balance_b: 300,
}),
)
output
.step(ctx, "amm_new_pool", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::New {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
user_holding_lp: public_mention(user_lp),
balance_a: 300,
balance_b: 300,
}),
)
.await
})
.await?;
let step = finalize_step("amm_new_pool", started, pre_block, &ret, ctx).await?;
output.push(step);
}
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::SwapExactInput {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
amount_in: 50,
min_amount_out: 1,
token_definition: def_a,
}),
)
output
.step(ctx, "amm_swap_exact_input", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::SwapExactInput {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
amount_in: 50,
min_amount_out: 1,
token_definition: def_a,
}),
)
.await
})
.await?;
let step = finalize_step("amm_swap_exact_input", started, pre_block, &ret, ctx).await?;
output.push(step);
}
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::AddLiquidity {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
user_holding_lp: public_mention(user_lp),
min_amount_lp: 1,
max_amount_a: 100,
max_amount_b: 100,
}),
)
output
.step(ctx, "amm_add_liquidity", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::AddLiquidity {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
user_holding_lp: public_mention(user_lp),
min_amount_lp: 1,
max_amount_a: 100,
max_amount_b: 100,
}),
)
.await
})
.await?;
let step = finalize_step("amm_add_liquidity", started, pre_block, &ret, ctx).await?;
output.push(step);
}
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::RemoveLiquidity {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
user_holding_lp: public_mention(user_lp),
balance_lp: 50,
min_amount_a: 1,
min_amount_b: 1,
}),
)
output
.step(ctx, "amm_remove_liquidity", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::AMM(AmmProgramAgnosticSubcommand::RemoveLiquidity {
user_holding_a: public_mention(user_a),
user_holding_b: public_mention(user_b),
user_holding_lp: public_mention(user_lp),
balance_lp: 50,
min_amount_a: 1,
min_amount_b: 1,
}),
)
.await
})
.await?;
let step = finalize_step("amm_remove_liquidity", started, pre_block, &ret, ctx).await?;
output.push(step);
}
Ok(output)
}
async fn new_public_account(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
) -> Result<nssa::AccountId> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let ret = output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await
})
.await?;
match ret {
SubcommandReturnValue::RegisterAccount { account_id } => Ok(account_id),
other => bail!("expected RegisterAccount, got {other:?}"),
@ -148,53 +122,54 @@ async fn new_public_account(
}
async fn timed_token_new(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
def_id: nssa::AccountId,
supply_id: nssa::AccountId,
name: &str,
) -> Result<()> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(supply_id),
name: name.to_owned(),
total_supply: 10_000,
}),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let name = name.to_owned();
output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(supply_id),
name,
total_supply: 10_000,
}),
)
.await
})
.await?;
Ok(())
}
async fn timed_token_send(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
from_id: nssa::AccountId,
to_id: nssa::AccountId,
amount: u128,
) -> Result<()> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(from_id),
to: Some(public_mention(to_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount,
}),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(from_id),
to: Some(public_mention(to_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount,
}),
)
.await
})
.await?;
Ok(())
}

View File

@ -1,42 +1,38 @@
//! Multi-recipient fanout: one funded supply pays 10 distinct recipients.
use std::time::Instant;
use anyhow::{Result, bail};
use test_fixtures::public_mention;
use test_fixtures::{TestContext, public_mention};
use wallet::cli::{
Command, SubcommandReturnValue,
account::{AccountSubcommand, NewSubcommand},
programs::token::TokenProgramAgnosticSubcommand,
};
use crate::harness::{ScenarioOutput, finalize_step};
use crate::harness::ScenarioOutput;
const FANOUT_COUNT: usize = 10;
const AMOUNT_PER_TRANSFER: u128 = 100;
pub async fn run(ctx: &mut test_fixtures::TestContext) -> Result<ScenarioOutput> {
pub async fn run(ctx: &mut TestContext) -> Result<ScenarioOutput> {
let mut output = ScenarioOutput::new("multi_recipient_fanout");
let def_id = new_public_account(ctx, &mut output, "create_acc_def").await?;
let supply_id = new_public_account(ctx, &mut output, "create_acc_supply").await?;
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(supply_id),
name: "FanoutToken".to_owned(),
total_supply: 10_000_000,
}),
)
output
.step(ctx, "token_new_fungible", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(supply_id),
name: "FanoutToken".to_owned(),
total_supply: 10_000_000,
}),
)
.await
})
.await?;
let step = finalize_step("token_new_fungible", started, pre_block, &ret, ctx).await?;
output.push(step);
}
let mut recipients = Vec::with_capacity(FANOUT_COUNT);
for i in 0..FANOUT_COUNT {
@ -44,45 +40,45 @@ pub async fn run(ctx: &mut test_fixtures::TestContext) -> Result<ScenarioOutput>
recipients.push(id);
}
for (i, recipient_id) in recipients.iter().enumerate() {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(public_mention(*recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: AMOUNT_PER_TRANSFER,
}),
)
.await?;
let step = finalize_step(format!("transfer_{i:02}"), started, pre_block, &ret, ctx).await?;
output.push(step);
for (i, recipient_id) in recipients.iter().copied().enumerate() {
output
.step(ctx, format!("transfer_{i:02}"), async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(public_mention(recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: AMOUNT_PER_TRANSFER,
}),
)
.await
})
.await?;
}
Ok(output)
}
async fn new_public_account(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
) -> Result<nssa::AccountId> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let ret = output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await
})
.await?;
match ret {
SubcommandReturnValue::RegisterAccount { account_id } => Ok(account_id),
other => bail!("expected RegisterAccount, got {other:?}"),

View File

@ -15,7 +15,7 @@ use wallet::cli::{
programs::token::TokenProgramAgnosticSubcommand,
};
use crate::harness::{BlockSize, ScenarioOutput, StepResult, finalize_step};
use crate::harness::{BlockSize, ScenarioOutput, StepResult};
const PARALLEL_FANOUT_N: usize = 10;
const AMOUNT_PER_TRANSFER: u128 = 100;
@ -43,47 +43,47 @@ pub async fn run(ctx: &mut TestContext) -> Result<ScenarioOutput> {
.expect("usize fits u128")
.saturating_mul(AMOUNT_PER_TRANSFER)
.saturating_mul(10);
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(master_id),
name: "ParToken".to_owned(),
total_supply: total_mint,
}),
)
output
.step(ctx, "token_new_fungible", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(master_id),
name: "ParToken".to_owned(),
total_supply: total_mint,
}),
)
.await
})
.await?;
let step = finalize_step("token_new_fungible", started, pre_block, &ret, ctx).await?;
output.push(step);
}
// Fund each sender from master. Serial; this is setup, not measured throughput.
for (i, sender_id) in senders.iter().enumerate() {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(master_id),
to: Some(public_mention(*sender_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: AMOUNT_PER_TRANSFER * 5,
}),
)
.await?;
let step =
finalize_step(format!("fund_sender_{i:02}"), started, pre_block, &ret, ctx).await?;
output.push(step);
for (i, sender_id) in senders.iter().copied().enumerate() {
output
.step(ctx, format!("fund_sender_{i:02}"), async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(master_id),
to: Some(public_mention(sender_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: AMOUNT_PER_TRANSFER * 5,
}),
)
.await
})
.await?;
}
// The measured phase: submit N transfers as fast as possible, do not wait
// for chain advance between submits. The sequencer batches whatever lands in
// its mempool before block_create_timeout.
// its mempool before block_create_timeout. The burst step is captured
// manually rather than via the `step()` helper because we need to time
// submit-and-inclusion as two separate intervals over a synthesised batch
// rather than per-tx.
let pre_block_burst = ctx.sequencer_client().get_last_block_id().await?;
let burst_started = Instant::now();
@ -169,18 +169,18 @@ async fn new_public_account(
output: &mut ScenarioOutput,
label: &str,
) -> Result<nssa::AccountId> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let ret = output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await
})
.await?;
match ret {
SubcommandReturnValue::RegisterAccount { account_id } => Ok(account_id),
other => bail!("expected RegisterAccount, got {other:?}"),

View File

@ -1,18 +1,16 @@
//! Private chained flow: shielded, deshielded, and private-to-private transfers.
use std::time::Instant;
use anyhow::{Result, bail};
use test_fixtures::{private_mention, public_mention};
use test_fixtures::{TestContext, private_mention, public_mention};
use wallet::cli::{
Command, SubcommandReturnValue,
account::{AccountSubcommand, NewSubcommand},
programs::token::TokenProgramAgnosticSubcommand,
};
use crate::harness::{ScenarioOutput, finalize_step};
use crate::harness::ScenarioOutput;
pub async fn run(ctx: &mut test_fixtures::TestContext) -> Result<ScenarioOutput> {
pub async fn run(ctx: &mut TestContext) -> Result<ScenarioOutput> {
let mut output = ScenarioOutput::new("private_chained_flow");
let def_id = new_public_account(ctx, &mut output, "create_acc_def").await?;
@ -23,103 +21,95 @@ pub async fn run(ctx: &mut test_fixtures::TestContext) -> Result<ScenarioOutput>
let private_b = new_private_account(ctx, &mut output, "create_acc_priv_b").await?;
// Mint into public supply.
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(supply_id),
name: "PrivToken".to_owned(),
total_supply: 1_000_000,
}),
)
output
.step(ctx, "token_new_fungible", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(def_id),
supply_account_id: public_mention(supply_id),
name: "PrivToken".to_owned(),
total_supply: 1_000_000,
}),
)
.await
})
.await?;
let step = finalize_step("token_new_fungible", started, pre_block, &ret, ctx).await?;
output.push(step);
}
// Shielded transfer: public supply -> private_a.
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(private_mention(private_a)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 1_000,
}),
)
output
.step(ctx, "shielded_transfer", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(private_mention(private_a)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 1_000,
}),
)
.await
})
.await?;
let step = finalize_step("shielded_transfer", started, pre_block, &ret, ctx).await?;
output.push(step);
}
// Deshielded transfer: private_a -> public_recipient.
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: private_mention(private_a),
to: Some(public_mention(public_recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 100,
}),
)
output
.step(ctx, "deshielded_transfer", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: private_mention(private_a),
to: Some(public_mention(public_recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 100,
}),
)
.await
})
.await?;
let step = finalize_step("deshielded_transfer", started, pre_block, &ret, ctx).await?;
output.push(step);
}
// Private-to-private transfer: private_a -> private_b.
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: private_mention(private_a),
to: Some(private_mention(private_b)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 200,
}),
)
output
.step(ctx, "private_to_private", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: private_mention(private_a),
to: Some(private_mention(private_b)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 200,
}),
)
.await
})
.await?;
let step = finalize_step("private_to_private", started, pre_block, &ret, ctx).await?;
output.push(step);
}
Ok(output)
}
async fn new_public_account(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
) -> Result<nssa::AccountId> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let ret = output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await
})
.await?;
match ret {
SubcommandReturnValue::RegisterAccount { account_id } => Ok(account_id),
other => bail!("expected RegisterAccount, got {other:?}"),
@ -127,22 +117,22 @@ async fn new_public_account(
}
async fn new_private_account(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
) -> Result<nssa::AccountId> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Private {
cci: None,
label: None,
})),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let ret = output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Private {
cci: None,
label: None,
})),
)
.await
})
.await?;
match ret {
SubcommandReturnValue::RegisterAccount { account_id } => Ok(account_id),
other => bail!("expected RegisterAccount, got {other:?}"),

View File

@ -1,102 +1,94 @@
//! Token onboarding scenario: create accounts, mint, public transfer, private transfer.
use std::time::Instant;
use anyhow::{Result, bail};
use test_fixtures::{private_mention, public_mention};
use test_fixtures::{TestContext, private_mention, public_mention};
use wallet::cli::{
Command, SubcommandReturnValue,
account::{AccountSubcommand, NewSubcommand},
programs::token::TokenProgramAgnosticSubcommand,
};
use crate::harness::{ScenarioOutput, finalize_step};
use crate::harness::ScenarioOutput;
pub async fn run(ctx: &mut test_fixtures::TestContext) -> Result<ScenarioOutput> {
pub async fn run(ctx: &mut TestContext) -> Result<ScenarioOutput> {
let mut output = ScenarioOutput::new("token_onboarding");
let definition_id = new_public_account(ctx, &mut output, "create_pub_definition").await?;
let supply_id = new_public_account(ctx, &mut output, "create_pub_supply").await?;
let recipient_id = new_public_account(ctx, &mut output, "create_pub_recipient").await?;
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(definition_id),
supply_account_id: public_mention(supply_id),
name: "BenchToken".to_owned(),
total_supply: 1_000_000,
}),
)
output
.step(ctx, "token_new_fungible", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::New {
definition_account_id: public_mention(definition_id),
supply_account_id: public_mention(supply_id),
name: "BenchToken".to_owned(),
total_supply: 1_000_000,
}),
)
.await
})
.await?;
let step = finalize_step("token_new_fungible", started, pre_block, &ret, ctx).await?;
output.push(step);
}
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(public_mention(recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 1_000,
}),
)
output
.step(ctx, "token_public_transfer", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(public_mention(recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 1_000,
}),
)
.await
})
.await?;
let step = finalize_step("token_public_transfer", started, pre_block, &ret, ctx).await?;
output.push(step);
}
let private_recipient_id =
new_private_account(ctx, &mut output, "create_priv_recipient").await?;
{
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(private_mention(private_recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 500,
}),
)
output
.step(ctx, "token_shielded_transfer", async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Token(TokenProgramAgnosticSubcommand::Send {
from: public_mention(supply_id),
to: Some(private_mention(private_recipient_id)),
to_npk: None,
to_vpk: None,
to_identifier: Some(0),
amount: 500,
}),
)
.await
})
.await?;
let step = finalize_step("token_shielded_transfer", started, pre_block, &ret, ctx).await?;
output.push(step);
}
Ok(output)
}
async fn new_public_account(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
) -> Result<nssa::AccountId> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let ret = output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
cci: None,
label: None,
})),
)
.await
})
.await?;
match ret {
SubcommandReturnValue::RegisterAccount { account_id } => Ok(account_id),
other => bail!("expected RegisterAccount, got {other:?}"),
@ -104,22 +96,22 @@ async fn new_public_account(
}
async fn new_private_account(
ctx: &mut test_fixtures::TestContext,
ctx: &mut TestContext,
output: &mut ScenarioOutput,
label: &str,
) -> Result<nssa::AccountId> {
let pre_block = crate::harness::begin_step(ctx).await?;
let started = Instant::now();
let ret = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Private {
cci: None,
label: None,
})),
)
.await?;
let step = finalize_step(label, started, pre_block, &ret, ctx).await?;
output.push(step);
let ret = output
.step(ctx, label, async |ctx| {
wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Private {
cci: None,
label: None,
})),
)
.await
})
.await?;
match ret {
SubcommandReturnValue::RegisterAccount { account_id } => Ok(account_id),
other => bail!("expected RegisterAccount, got {other:?}"),