Marvin Jones 456a2fe159 refactor(integration_tests): apply shared helpers to remaining test files
Use account_balance, get_account, new_account, send, and sync_private
helpers in public.rs, pinata.rs, private_pda.rs, program_deployment.rs,
and token.rs to reduce boilerplate and improve consistency.
2026-06-25 17:22:43 -04:00

410 lines
13 KiB
Rust

use std::time::Duration;
use anyhow::Result;
use common::transaction::LeeTransaction;
use integration_tests::{
TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, account_balance, get_account, new_account,
public_mention, send,
};
use lee::public_transaction;
use log::info;
use sequencer_service_rpc::RpcClient as _;
use tokio::test;
use wallet::{
account::Label,
cli::{
CliAccountMention, Command, account::AccountSubcommand,
programs::native_token_transfer::AuthTransferSubcommand,
},
};
#[test]
async fn successful_transfer_to_existing_account() -> Result<()> {
let mut ctx = TestContext::new().await?;
let sender = ctx.existing_public_accounts()[0];
let receiver = ctx.existing_public_accounts()[1];
send(
&mut ctx,
public_mention(sender),
public_mention(receiver),
100,
)
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("Checking correct balance move");
let acc_1_balance = account_balance(&ctx, sender).await?;
let acc_2_balance = account_balance(&ctx, receiver).await?;
info!("Balance of sender: {acc_1_balance:#?}");
info!("Balance of receiver: {acc_2_balance:#?}");
assert_eq!(acc_1_balance, 9900);
assert_eq!(acc_2_balance, 20100);
Ok(())
}
#[test]
pub async fn successful_transfer_to_new_account() -> Result<()> {
let mut ctx = TestContext::new().await?;
let new_persistent_account_id = new_account(&mut ctx, false, None).await?;
let sender = ctx.existing_public_accounts()[0];
send(
&mut ctx,
public_mention(sender),
public_mention(new_persistent_account_id),
100,
)
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("Checking correct balance move");
let acc_1_balance = account_balance(&ctx, sender).await?;
let acc_2_balance = account_balance(&ctx, new_persistent_account_id).await?;
info!("Balance of sender: {acc_1_balance:#?}");
info!("Balance of receiver: {acc_2_balance:#?}");
assert_eq!(acc_1_balance, 9900);
assert_eq!(acc_2_balance, 100);
Ok(())
}
#[test]
async fn failed_transfer_with_insufficient_balance() -> Result<()> {
let mut ctx = TestContext::new().await?;
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
from: public_mention(ctx.existing_public_accounts()[0]),
to: Some(public_mention(ctx.existing_public_accounts()[1])),
to_npk: None,
to_vpk: None,
to_keys: None,
to_identifier: Some(0),
amount: 1_000_000,
});
let failed_send = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await;
assert!(failed_send.is_err());
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("Checking balances unchanged");
let acc_1_balance = account_balance(&ctx, ctx.existing_public_accounts()[0]).await?;
let acc_2_balance = account_balance(&ctx, ctx.existing_public_accounts()[1]).await?;
info!("Balance of sender: {acc_1_balance:#?}");
info!("Balance of receiver: {acc_2_balance:#?}");
assert_eq!(acc_1_balance, 10000);
assert_eq!(acc_2_balance, 20000);
Ok(())
}
#[test]
async fn two_consecutive_successful_transfers() -> Result<()> {
let mut ctx = TestContext::new().await?;
let sender = ctx.existing_public_accounts()[0];
let receiver = ctx.existing_public_accounts()[1];
// First transfer
send(
&mut ctx,
public_mention(sender),
public_mention(receiver),
100,
)
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("Checking correct balance move after first transfer");
let acc_1_balance = account_balance(&ctx, sender).await?;
let acc_2_balance = account_balance(&ctx, receiver).await?;
info!("Balance of sender: {acc_1_balance:#?}");
info!("Balance of receiver: {acc_2_balance:#?}");
assert_eq!(acc_1_balance, 9900);
assert_eq!(acc_2_balance, 20100);
info!("First TX Success!");
// Second transfer
send(
&mut ctx,
public_mention(sender),
public_mention(receiver),
100,
)
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("Checking correct balance move after second transfer");
let acc_1_balance = account_balance(&ctx, sender).await?;
let acc_2_balance = account_balance(&ctx, receiver).await?;
info!("Balance of sender: {acc_1_balance:#?}");
info!("Balance of receiver: {acc_2_balance:#?}");
assert_eq!(acc_1_balance, 9800);
assert_eq!(acc_2_balance, 20200);
info!("Second TX Success!");
Ok(())
}
#[test]
async fn initialize_public_account() -> Result<()> {
let mut ctx = TestContext::new().await?;
let account_id = new_account(&mut ctx, false, None).await?;
let command = Command::AuthTransfer(AuthTransferSubcommand::Init {
account_id: public_mention(account_id),
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
info!("Checking correct execution");
let account = get_account(&ctx, account_id).await?;
assert_eq!(
account.program_owner,
programs::authenticated_transfer().id()
);
assert_eq!(account.balance, 0);
assert_eq!(account.nonce.0, 1);
assert!(account.data.is_empty());
info!("Successfully initialized public account");
Ok(())
}
#[test]
async fn successful_transfer_using_from_label() -> Result<()> {
let mut ctx = TestContext::new().await?;
// Assign a label to the sender account
let label = Label::new("sender-label");
let command = Command::Account(AccountSubcommand::Label {
account_id: public_mention(ctx.existing_public_accounts()[0]),
label: label.clone(),
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
// Send using the label instead of account ID
let sender = ctx.existing_public_accounts()[0];
let receiver = ctx.existing_public_accounts()[1];
send(
&mut ctx,
CliAccountMention::Label(label),
public_mention(receiver),
100,
)
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("Checking correct balance move");
let acc_1_balance = account_balance(&ctx, sender).await?;
let acc_2_balance = account_balance(&ctx, receiver).await?;
assert_eq!(acc_1_balance, 9900);
assert_eq!(acc_2_balance, 20100);
info!("Successfully transferred using from_label");
Ok(())
}
#[test]
async fn successful_transfer_using_to_label() -> Result<()> {
let mut ctx = TestContext::new().await?;
// Assign a label to the receiver account
let label = Label::new("receiver-label");
let command = Command::Account(AccountSubcommand::Label {
account_id: public_mention(ctx.existing_public_accounts()[1]),
label: label.clone(),
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
// Send using the label for the recipient
let sender = ctx.existing_public_accounts()[0];
let receiver = ctx.existing_public_accounts()[1];
send(
&mut ctx,
public_mention(sender),
CliAccountMention::Label(label),
100,
)
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("Checking correct balance move");
let acc_1_balance = account_balance(&ctx, sender).await?;
let acc_2_balance = account_balance(&ctx, receiver).await?;
assert_eq!(acc_1_balance, 9900);
assert_eq!(acc_2_balance, 20100);
info!("Successfully transferred using to_label");
Ok(())
}
#[test]
async fn cannot_transfer_funds_from_system_faucet_account() -> Result<()> {
let ctx = TestContext::new().await?;
let faucet_account_id = system_accounts::faucet_account_id();
let recipient = ctx.existing_public_accounts()[0];
let recipient_balance_before = account_balance(&ctx, recipient).await?;
let faucet_balance_before = account_balance(&ctx, faucet_account_id).await?;
let amount = 1_u128;
let message = public_transaction::Message::try_new(
programs::authenticated_transfer().id(),
vec![faucet_account_id, recipient],
vec![],
authenticated_transfer_core::Instruction::Transfer { amount },
)?;
let tx = lee::PublicTransaction::new(
message,
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
);
let tx_hash = ctx
.sequencer_client()
.send_transaction(LeeTransaction::Public(tx))
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let recipient_balance_after = account_balance(&ctx, recipient).await?;
let faucet_balance_after = account_balance(&ctx, faucet_account_id).await?;
let tx_on_chain = ctx.sequencer_client().get_transaction(tx_hash).await?;
assert_eq!(recipient_balance_after, recipient_balance_before);
assert_eq!(faucet_balance_after, faucet_balance_before);
assert!(tx_on_chain.is_none());
Ok(())
}
#[test]
async fn cannot_execute_faucet_program() -> Result<()> {
let ctx = TestContext::new().await?;
let faucet_account_id = system_accounts::faucet_account_id();
let recipient = ctx.existing_public_accounts()[0];
let vault_program_id = programs::vault().id();
let recipient_vault_id = vault_core::compute_vault_account_id(vault_program_id, recipient);
let recipient_balance_before = account_balance(&ctx, recipient).await?;
let faucet_balance_before = account_balance(&ctx, faucet_account_id).await?;
let amount = 1_u128;
let message = public_transaction::Message::try_new(
programs::faucet().id(),
vec![faucet_account_id, recipient_vault_id],
vec![],
faucet_core::Instruction::GenesisTransferVault {
vault_program_id,
recipient_id: recipient,
amount,
},
)?;
let tx = lee::PublicTransaction::new(
message,
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
);
let tx_hash = ctx
.sequencer_client()
.send_transaction(LeeTransaction::Public(tx))
.await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let recipient_balance_after = account_balance(&ctx, recipient).await?;
let faucet_balance_after = account_balance(&ctx, faucet_account_id).await?;
let tx_on_chain = ctx.sequencer_client().get_transaction(tx_hash).await?;
assert_eq!(recipient_balance_after, recipient_balance_before);
assert_eq!(faucet_balance_after, faucet_balance_before);
assert!(tx_on_chain.is_none());
Ok(())
}
#[test]
async fn user_tx_that_chain_calls_faucet_is_dropped() -> Result<()> {
let ctx = TestContext::new().await?;
let faucet_chain_caller = test_programs::faucet_chain_caller();
let deploy_tx = LeeTransaction::ProgramDeployment(lee::ProgramDeploymentTransaction::new(
lee::program_deployment_transaction::Message::new(faucet_chain_caller.elf().to_owned()),
));
ctx.sequencer_client().send_transaction(deploy_tx).await?;
info!("Waiting for deploy block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let faucet_account_id = system_accounts::faucet_account_id();
let attacker = ctx.existing_public_accounts()[0];
let faucet_program_id = programs::faucet().id();
let vault_program_id = programs::vault().id();
let attacker_vault_id = vault_core::compute_vault_account_id(vault_program_id, attacker);
let amount: u128 = 1;
let message = public_transaction::Message::try_new(
faucet_chain_caller.id(),
vec![faucet_account_id, attacker_vault_id],
vec![],
(faucet_program_id, vault_program_id, attacker, amount),
)?;
let attack_tx = LeeTransaction::Public(lee::PublicTransaction::new(
message,
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
));
let faucet_balance_before = account_balance(&ctx, faucet_account_id).await?;
let vault_balance_before = account_balance(&ctx, attacker_vault_id).await?;
let tx_hash = ctx.sequencer_client().send_transaction(attack_tx).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let faucet_balance_after = account_balance(&ctx, faucet_account_id).await?;
let vault_balance_after = account_balance(&ctx, attacker_vault_id).await?;
let tx_on_chain = ctx.sequencer_client().get_transaction(tx_hash).await?;
assert_eq!(faucet_balance_after, faucet_balance_before);
assert_eq!(vault_balance_after, vault_balance_before);
assert!(tx_on_chain.is_none());
Ok(())
}