From 9a82a0cfcbbdc4a884e7829d3c918e741dddae02 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Tue, 4 Aug 2026 07:40:21 +0300 Subject: [PATCH 1/3] feat(integration_tests): tests removal + simple retry on fixtures --- .github/workflows/ci.yml | 9 +- integration_tests/tests/amm.rs | 386 ------------ integration_tests/tests/ata.rs | 562 ----------------- integration_tests/tests/pinata.rs | 239 ------- integration_tests/tests/token.rs | 996 ------------------------------ lez/wallet/src/lib.rs | 2 + 6 files changed, 10 insertions(+), 2184 deletions(-) delete mode 100644 integration_tests/tests/amm.rs delete mode 100644 integration_tests/tests/ata.rs delete mode 100644 integration_tests/tests/pinata.rs delete mode 100644 integration_tests/tests/token.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a075d77..1b6250be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -214,7 +214,14 @@ jobs: with: image: ${{ needs.ci-image.outputs.image }} env: RISC0_DEV_MODE=1 - run: cargo nextest archive -p integration_tests --archive-file integration-tests.tar.zst --no-pager + run: | + for i in 1 2 3; do + cargo nextest archive -p integration_tests --archive-file integration-tests.tar.zst --no-pager && break + echo "::warning:: Attempt $i failed, cleaning up and retrying..." >&2 + rm -rf target/debug/deps/*.o target/debug/incremental 2>/dev/null || true + cargo clean -p integration_tests 2>/dev/null || true + sleep 5 + done - name: Upload integration test archive uses: actions/upload-artifact@v4 diff --git a/integration_tests/tests/amm.rs b/integration_tests/tests/amm.rs deleted file mode 100644 index 894d787c..00000000 --- a/integration_tests/tests/amm.rs +++ /dev/null @@ -1,386 +0,0 @@ -#![expect( - clippy::shadow_unrelated, - clippy::tests_outside_test_module, - reason = "We don't care about these in tests" -)] - -use std::time::Duration; - -use anyhow::Result; -use integration_tests::{ - TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, create_token, get_account, new_account, - public_mention, token_send_claiming_new_account, -}; -use log::info; -use tokio::test; -use wallet::{ - account::Label, - cli::{ - Command, SubcommandReturnValue, - account::{AccountSubcommand, NewSubcommand}, - programs::amm::AmmProgramAgnosticSubcommand, - }, -}; - -#[test] -async fn amm_public() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create new account for the token definition - let definition_account_id_1 = new_account(&mut ctx, false, None).await?; - - // Create new account for the token supply holder - let supply_account_id_1 = new_account(&mut ctx, false, None).await?; - - // Create new account for receiving a token transaction - let recipient_account_id_1 = new_account(&mut ctx, false, None).await?; - - // Create new account for the token definition - let definition_account_id_2 = new_account(&mut ctx, false, None).await?; - - // Create new account for the token supply holder - let supply_account_id_2 = new_account(&mut ctx, false, None).await?; - - // Create new account for receiving a token transaction - let recipient_account_id_2 = new_account(&mut ctx, false, None).await?; - - // Create new token - create_token( - &mut ctx, - public_mention(definition_account_id_1), - public_mention(supply_account_id_1), - "A NAM1".to_owned(), - 37, - ) - .await?; - - // Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_1`. - // `recipient_account_id_1` is still unclaimed, so this bypasses the wallet CLI (which never - // signs with the recipient's key) and signs with the recipient's own key directly. - token_send_claiming_new_account(&mut ctx, supply_account_id_1, recipient_account_id_1, 7) - .await?; - - // Create new token - create_token( - &mut ctx, - public_mention(definition_account_id_2), - public_mention(supply_account_id_2), - "A NAM2".to_owned(), - 37, - ) - .await?; - - // Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_2`. - // `recipient_account_id_2` is still unclaimed, so this bypasses the wallet CLI the same way. - token_send_claiming_new_account(&mut ctx, supply_account_id_2, recipient_account_id_2, 7) - .await?; - - info!("=================== SETUP FINISHED ==============="); - - // Create new AMM - - // Setup accounts - // Create new account for the user holding lp - let user_holding_lp = new_account(&mut ctx, false, None).await?; - - // Send creation tx - let subcommand = AmmProgramAgnosticSubcommand::New { - user_holding_a: public_mention(recipient_account_id_1), - user_holding_b: public_mention(recipient_account_id_2), - user_holding_lp: public_mention(user_holding_lp), - balance_a: 3, - balance_b: 3, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?; - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let user_holding_a_acc = get_account(&ctx, recipient_account_id_1).await?; - - let user_holding_b_acc = get_account(&ctx, recipient_account_id_2).await?; - - let user_holding_lp_acc = get_account(&ctx, user_holding_lp).await?; - - assert_eq!( - u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()), - 4 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()), - 4 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()), - 3 - ); - - info!("=================== AMM DEFINITION FINISHED ==============="); - - // Make swap - - let subcommand = AmmProgramAgnosticSubcommand::SwapExactInput { - user_holding_a: public_mention(recipient_account_id_1), - user_holding_b: public_mention(recipient_account_id_2), - amount_in: 2, - min_amount_out: 1, - token_definition: definition_account_id_1, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?; - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let user_holding_a_acc = get_account(&ctx, recipient_account_id_1).await?; - - let user_holding_b_acc = get_account(&ctx, recipient_account_id_2).await?; - - let user_holding_lp_acc = get_account(&ctx, user_holding_lp).await?; - - assert_eq!( - u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()), - 2 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()), - 5 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()), - 3 - ); - - info!("=================== FIRST SWAP FINISHED ==============="); - - // Make swap - - let subcommand = AmmProgramAgnosticSubcommand::SwapExactInput { - user_holding_a: public_mention(recipient_account_id_1), - user_holding_b: public_mention(recipient_account_id_2), - amount_in: 2, - min_amount_out: 1, - token_definition: definition_account_id_2, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?; - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let user_holding_a_acc = get_account(&ctx, recipient_account_id_1).await?; - - let user_holding_b_acc = get_account(&ctx, recipient_account_id_2).await?; - - let user_holding_lp_acc = get_account(&ctx, user_holding_lp).await?; - - assert_eq!( - u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()), - 4 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()), - 3 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()), - 3 - ); - - info!("=================== SECOND SWAP FINISHED ==============="); - - // Add liquidity - - let subcommand = AmmProgramAgnosticSubcommand::AddLiquidity { - user_holding_a: public_mention(recipient_account_id_1), - user_holding_b: public_mention(recipient_account_id_2), - user_holding_lp: public_mention(user_holding_lp), - min_amount_lp: 1, - max_amount_a: 2, - max_amount_b: 2, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?; - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let user_holding_a_acc = get_account(&ctx, recipient_account_id_1).await?; - - let user_holding_b_acc = get_account(&ctx, recipient_account_id_2).await?; - - let user_holding_lp_acc = get_account(&ctx, user_holding_lp).await?; - - assert_eq!( - u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()), - 3 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()), - 1 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()), - 4 - ); - - info!("=================== ADD LIQ FINISHED ==============="); - - // Remove liquidity - - let subcommand = AmmProgramAgnosticSubcommand::RemoveLiquidity { - user_holding_a: public_mention(recipient_account_id_1), - user_holding_b: public_mention(recipient_account_id_2), - user_holding_lp: public_mention(user_holding_lp), - balance_lp: 2, - min_amount_a: 1, - min_amount_b: 1, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?; - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let user_holding_a_acc = get_account(&ctx, recipient_account_id_1).await?; - - let user_holding_b_acc = get_account(&ctx, recipient_account_id_2).await?; - - let user_holding_lp_acc = get_account(&ctx, user_holding_lp).await?; - - assert_eq!( - u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()), - 5 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()), - 4 - ); - - assert_eq!( - u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()), - 2 - ); - - info!("Success!"); - - Ok(()) -} - -#[test] -async fn amm_new_pool_using_labels() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create token 1 accounts - let definition_account_id_1 = new_account(&mut ctx, false, None).await?; - - let supply_account_id_1 = new_account(&mut ctx, false, None).await?; - - // Create holding_a with a label - let holding_a_label = Label::new("amm-holding-a-label"); - let SubcommandReturnValue::RegisterAccount { - account_id: holding_a_id, - } = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Account(AccountSubcommand::New(NewSubcommand::Public { - cci: None, - label: Some(Label::new(holding_a_label.clone())), - })), - ) - .await? - else { - anyhow::bail!("Expected RegisterAccount return value"); - }; - - // Create token 2 accounts - let definition_account_id_2 = new_account(&mut ctx, false, None).await?; - - let supply_account_id_2 = new_account(&mut ctx, false, None).await?; - - // Create holding_b with a label - let holding_b_label = Label::new("amm-holding-b-label"); - let SubcommandReturnValue::RegisterAccount { - account_id: holding_b_id, - } = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Account(AccountSubcommand::New(NewSubcommand::Public { - cci: None, - label: Some(Label::new(holding_b_label.clone())), - })), - ) - .await? - else { - anyhow::bail!("Expected RegisterAccount return value"); - }; - - // Create holding_lp with a label - let holding_lp_label = Label::new("amm-holding-lp-label"); - let SubcommandReturnValue::RegisterAccount { - account_id: holding_lp_id, - } = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Account(AccountSubcommand::New(NewSubcommand::Public { - cci: None, - label: Some(Label::new(holding_lp_label.clone())), - })), - ) - .await? - else { - anyhow::bail!("Expected RegisterAccount return value"); - }; - - // Create token 1 and distribute to holding_a - create_token( - &mut ctx, - public_mention(definition_account_id_1), - public_mention(supply_account_id_1), - "TOKEN1".to_owned(), - 10, - ) - .await?; - - // `holding_a_id` is still unclaimed, so bypass the wallet CLI (see - // `token_send_claiming_new_account`'s docs for why). - token_send_claiming_new_account(&mut ctx, supply_account_id_1, holding_a_id, 5).await?; - - // Create token 2 and distribute to holding_b - create_token( - &mut ctx, - public_mention(definition_account_id_2), - public_mention(supply_account_id_2), - "TOKEN2".to_owned(), - 10, - ) - .await?; - - // `holding_b_id` is still unclaimed, so bypass the wallet CLI the same way. - token_send_claiming_new_account(&mut ctx, supply_account_id_2, holding_b_id, 5).await?; - - // Create AMM pool using account labels instead of IDs - let subcommand = AmmProgramAgnosticSubcommand::New { - user_holding_a: holding_a_label.into(), - user_holding_b: holding_b_label.into(), - user_holding_lp: holding_lp_label.into(), - balance_a: 3, - balance_b: 3, - }; - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?; - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let holding_lp_acc = get_account(&ctx, holding_lp_id).await?; - - // LP balance should be 3 (geometric mean of 3, 3) - assert_eq!( - u128::from_le_bytes(holding_lp_acc.data[33..].try_into().unwrap()), - 3 - ); - - info!("Successfully created AMM pool using account labels"); - - Ok(()) -} diff --git a/integration_tests/tests/ata.rs b/integration_tests/tests/ata.rs deleted file mode 100644 index 21905fb9..00000000 --- a/integration_tests/tests/ata.rs +++ /dev/null @@ -1,562 +0,0 @@ -#![expect( - clippy::shadow_unrelated, - clippy::tests_outside_test_module, - reason = "We don't care about these in tests" -)] - -use std::time::Duration; - -use anyhow::{Context as _, Result}; -use associated_token_account_core::{compute_ata_seed, get_associated_token_account_id}; -use integration_tests::{ - TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, create_token, get_account, new_account, - private_mention, public_mention, token_send, verify_commitment_is_in_state, -}; -use log::info; -use sequencer_service_rpc::RpcClient as _; -use token_core::{TokenDefinition, TokenHolding}; -use tokio::test; -use wallet::cli::{Command, programs::ata::AtaSubcommand}; - -#[test] -async fn create_ata_initializes_holding_account() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let definition_account_id = new_account(&mut ctx, false, None).await?; - let supply_account_id = new_account(&mut ctx, false, None).await?; - let owner_account_id = new_account(&mut ctx, false, None).await?; - - // Create a fungible token - let total_supply = 100_u128; - create_token( - &mut ctx, - public_mention(definition_account_id), - public_mention(supply_account_id), - "TEST".to_owned(), - total_supply, - ) - .await?; - - // Create the ATA for owner + definition - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: public_mention(owner_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Derive expected ATA address and check on-chain state - let ata_program_id = programs::ata().id(); - let ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(owner_account_id, definition_account_id), - ); - - let ata_acc = ctx - .sequencer_client() - .get_account(ata_id) - .await - .context("ATA account not found")?; - - assert_eq!(ata_acc.program_owner, programs::token().id()); - let holding = TokenHolding::try_from(&ata_acc.data)?; - assert_eq!( - holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: 0, - } - ); - - Ok(()) -} - -#[test] -async fn create_ata_is_idempotent() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let definition_account_id = new_account(&mut ctx, false, None).await?; - let supply_account_id = new_account(&mut ctx, false, None).await?; - let owner_account_id = new_account(&mut ctx, false, None).await?; - - // Create a fungible token - create_token( - &mut ctx, - public_mention(definition_account_id), - public_mention(supply_account_id), - "TEST".to_owned(), - 100, - ) - .await?; - - // Create the ATA once - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: public_mention(owner_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Create the ATA a second time — must succeed (idempotent) - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: public_mention(owner_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // State must be unchanged - let ata_program_id = programs::ata().id(); - let ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(owner_account_id, definition_account_id), - ); - - let ata_acc = ctx - .sequencer_client() - .get_account(ata_id) - .await - .context("ATA account not found")?; - - assert_eq!(ata_acc.program_owner, programs::token().id()); - let holding = TokenHolding::try_from(&ata_acc.data)?; - assert_eq!( - holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: 0, - } - ); - - Ok(()) -} - -#[test] -async fn transfer_and_burn_via_ata() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let definition_account_id = new_account(&mut ctx, false, None).await?; - let supply_account_id = new_account(&mut ctx, false, None).await?; - let sender_account_id = new_account(&mut ctx, false, None).await?; - let recipient_account_id = new_account(&mut ctx, false, None).await?; - - let total_supply = 1000_u128; - - // Create a fungible token, supply goes to supply_account_id - create_token( - &mut ctx, - public_mention(definition_account_id), - public_mention(supply_account_id), - "TEST".to_owned(), - total_supply, - ) - .await?; - - // Derive ATA addresses - let ata_program_id = programs::ata().id(); - let sender_ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(sender_account_id, definition_account_id), - ); - let recipient_ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(recipient_account_id, definition_account_id), - ); - - // Create ATAs for sender and recipient - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: public_mention(sender_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: public_mention(recipient_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Fund sender's ATA from the supply account (direct token transfer) - let fund_amount = 200_u128; - token_send( - &mut ctx, - public_mention(supply_account_id), - public_mention(sender_ata_id), - fund_amount, - ) - .await?; - - // Transfer from sender's ATA to recipient's ATA via the ATA program - let transfer_amount = 50_u128; - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Send { - from: public_mention(sender_account_id), - token_definition: definition_account_id, - to: recipient_ata_id, - amount: transfer_amount, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify sender ATA balance decreased - let sender_ata_acc = get_account(&ctx, sender_ata_id).await?; - let sender_holding = TokenHolding::try_from(&sender_ata_acc.data)?; - assert_eq!( - sender_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: fund_amount - transfer_amount, - } - ); - - // Verify recipient ATA balance increased - let recipient_ata_acc = get_account(&ctx, recipient_ata_id).await?; - let recipient_holding = TokenHolding::try_from(&recipient_ata_acc.data)?; - assert_eq!( - recipient_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount, - } - ); - - // Burn from sender's ATA - let burn_amount = 30_u128; - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Burn { - holder: public_mention(sender_account_id), - token_definition: definition_account_id, - amount: burn_amount, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify sender ATA balance after burn - let sender_ata_acc = get_account(&ctx, sender_ata_id).await?; - let sender_holding = TokenHolding::try_from(&sender_ata_acc.data)?; - assert_eq!( - sender_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: fund_amount - transfer_amount - burn_amount, - } - ); - - // Verify the token definition total_supply decreased by burn_amount - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name: "TEST".to_owned(), - total_supply: total_supply - burn_amount, - metadata_id: None, - } - ); - - Ok(()) -} - -#[test] -async fn create_ata_with_private_owner() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let definition_account_id = new_account(&mut ctx, false, None).await?; - let supply_account_id = new_account(&mut ctx, false, None).await?; - let owner_account_id = new_account(&mut ctx, true, None).await?; - - // Create a fungible token - create_token( - &mut ctx, - public_mention(definition_account_id), - public_mention(supply_account_id), - "TEST".to_owned(), - 100, - ) - .await?; - - // Create the ATA for the private owner + definition - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: private_mention(owner_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Derive expected ATA address and check on-chain state - let ata_program_id = programs::ata().id(); - let ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(owner_account_id, definition_account_id), - ); - - let ata_acc = ctx - .sequencer_client() - .get_account(ata_id) - .await - .context("ATA account not found")?; - - assert_eq!(ata_acc.program_owner, programs::token().id()); - let holding = TokenHolding::try_from(&ata_acc.data)?; - assert_eq!( - holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: 0, - } - ); - - // Verify the private owner's commitment is in state - let commitment = ctx - .wallet() - .get_private_account_commitment(owner_account_id) - .context("Private owner commitment not found")?; - assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await); - - Ok(()) -} - -#[test] -async fn transfer_via_ata_private_owner() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let definition_account_id = new_account(&mut ctx, false, None).await?; - let supply_account_id = new_account(&mut ctx, false, None).await?; - let sender_account_id = new_account(&mut ctx, true, None).await?; - let recipient_account_id = new_account(&mut ctx, false, None).await?; - - let total_supply = 1000_u128; - - // Create a fungible token - create_token( - &mut ctx, - public_mention(definition_account_id), - public_mention(supply_account_id), - "TEST".to_owned(), - total_supply, - ) - .await?; - - // Derive ATA addresses - let ata_program_id = programs::ata().id(); - let sender_ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(sender_account_id, definition_account_id), - ); - let recipient_ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(recipient_account_id, definition_account_id), - ); - - // Create ATAs for sender (private owner) and recipient (public owner) - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: private_mention(sender_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: public_mention(recipient_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Fund sender's ATA from the supply account (direct token transfer) - let fund_amount = 200_u128; - token_send( - &mut ctx, - public_mention(supply_account_id), - public_mention(sender_ata_id), - fund_amount, - ) - .await?; - - // Transfer from sender's ATA (private owner) to recipient's ATA - let transfer_amount = 50_u128; - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Send { - from: private_mention(sender_account_id), - token_definition: definition_account_id, - to: recipient_ata_id, - amount: transfer_amount, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify sender ATA balance decreased - let sender_ata_acc = get_account(&ctx, sender_ata_id).await?; - let sender_holding = TokenHolding::try_from(&sender_ata_acc.data)?; - assert_eq!( - sender_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: fund_amount - transfer_amount, - } - ); - - // Verify recipient ATA balance increased - let recipient_ata_acc = get_account(&ctx, recipient_ata_id).await?; - let recipient_holding = TokenHolding::try_from(&recipient_ata_acc.data)?; - assert_eq!( - recipient_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount, - } - ); - - // Verify the private sender's commitment is in state - let commitment = ctx - .wallet() - .get_private_account_commitment(sender_account_id) - .context("Private sender commitment not found")?; - assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await); - - Ok(()) -} - -#[test] -async fn burn_via_ata_private_owner() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let definition_account_id = new_account(&mut ctx, false, None).await?; - let supply_account_id = new_account(&mut ctx, false, None).await?; - let holder_account_id = new_account(&mut ctx, true, None).await?; - - let total_supply = 500_u128; - - // Create a fungible token - create_token( - &mut ctx, - public_mention(definition_account_id), - public_mention(supply_account_id), - "TEST".to_owned(), - total_supply, - ) - .await?; - - // Derive holder's ATA address - let ata_program_id = programs::ata().id(); - let holder_ata_id = get_associated_token_account_id( - &ata_program_id, - &compute_ata_seed(holder_account_id, definition_account_id), - ); - - // Create ATA for the private holder - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Create { - owner: private_mention(holder_account_id), - token_definition: definition_account_id, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Fund holder's ATA from the supply account - let fund_amount = 300_u128; - token_send( - &mut ctx, - public_mention(supply_account_id), - public_mention(holder_ata_id), - fund_amount, - ) - .await?; - - // Burn from holder's ATA (private owner) - let burn_amount = 100_u128; - wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Ata(AtaSubcommand::Burn { - holder: private_mention(holder_account_id), - token_definition: definition_account_id, - amount: burn_amount, - }), - ) - .await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify holder ATA balance after burn - let holder_ata_acc = get_account(&ctx, holder_ata_id).await?; - let holder_holding = TokenHolding::try_from(&holder_ata_acc.data)?; - assert_eq!( - holder_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: fund_amount - burn_amount, - } - ); - - // Verify the token definition total_supply decreased by burn_amount - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name: "TEST".to_owned(), - total_supply: total_supply - burn_amount, - metadata_id: None, - } - ); - - // Verify the private holder's commitment is in state - let commitment = ctx - .wallet() - .get_private_account_commitment(holder_account_id) - .context("Private holder commitment not found")?; - assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await); - - Ok(()) -} diff --git a/integration_tests/tests/pinata.rs b/integration_tests/tests/pinata.rs deleted file mode 100644 index f2c634a2..00000000 --- a/integration_tests/tests/pinata.rs +++ /dev/null @@ -1,239 +0,0 @@ -#![expect( - clippy::shadow_unrelated, - clippy::tests_outside_test_module, - reason = "We don't care about these in tests" -)] - -use std::time::Duration; - -use anyhow::{Context as _, Result}; -use integration_tests::{ - TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, account_balance, new_account, private_mention, - public_mention, sync_private, verify_commitment_is_in_state, wait_for_indexer_to_catch_up, -}; -use log::info; -use tokio::test; -use wallet::cli::{ - Command, SubcommandReturnValue, - programs::{ - native_token_transfer::AuthTransferSubcommand, pinata::PinataProgramAgnosticSubcommand, - }, -}; - -#[test] -async fn claim_pinata_to_uninitialized_public_account_fails_fast() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let winner_account_id = new_account(&mut ctx, false, None).await?; - - let pinata_balance_pre = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - let claim_result = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Pinata(PinataProgramAgnosticSubcommand::Claim { - to: public_mention(winner_account_id), - }), - ) - .await; - - assert!( - claim_result.is_err(), - "Expected uninitialized account error" - ); - let err = claim_result.unwrap_err().to_string(); - assert!( - err.contains("wallet auth-transfer init --account-id Public/"), - "Expected init guidance, got: {err}", - ); - - let pinata_balance_post = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - assert_eq!(pinata_balance_post, pinata_balance_pre); - - Ok(()) -} - -#[test] -async fn claim_pinata_to_uninitialized_private_account_fails_fast() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let winner_account_id = new_account(&mut ctx, true, None).await?; - - let pinata_balance_pre = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - let claim_result = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Pinata(PinataProgramAgnosticSubcommand::Claim { - to: private_mention(winner_account_id), - }), - ) - .await; - - assert!( - claim_result.is_err(), - "Expected uninitialized account error" - ); - let err = claim_result.unwrap_err().to_string(); - assert!( - err.contains("wallet auth-transfer init --account-id Private/"), - "Expected init guidance, got: {err}", - ); - - let pinata_balance_post = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - assert_eq!(pinata_balance_post, pinata_balance_pre); - - Ok(()) -} - -#[test] -async fn claim_pinata_to_existing_public_account() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let pinata_prize = 150; - let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim { - to: public_mention(ctx.existing_public_accounts()[0]), - }); - - let pinata_balance_pre = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), command).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 pinata_balance_post = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - let winner_balance_post = account_balance(&ctx, ctx.existing_public_accounts()[0]).await?; - - assert_eq!(pinata_balance_post, pinata_balance_pre - pinata_prize); - assert_eq!(winner_balance_post, 10000 + pinata_prize); - - info!("Successfully claimed pinata to public account"); - - Ok(()) -} - -#[test] -async fn claim_pinata_indexer_keeps_up() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim { - to: public_mention(ctx.existing_public_accounts()[0]), - }); - - wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - info!("Waiting for indexer to parse blocks"); - wait_for_indexer_to_catch_up(&ctx).await?; - - let winner_ind_state = indexer_service_rpc::RpcClient::get_account( - &**ctx.indexer_client(), - ctx.existing_public_accounts()[0].into(), - ) - .await - .unwrap(); - let winner_seq_state = sequencer_service_rpc::RpcClient::get_account( - ctx.sequencer_client(), - ctx.existing_public_accounts()[0], - ) - .await?; - - assert_eq!(winner_ind_state, winner_seq_state.into()); - - info!("Indexer correctly indexed the pinata claim"); - - Ok(()) -} - -#[test] -async fn claim_pinata_to_existing_private_account() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let pinata_prize = 150; - let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim { - to: private_mention(ctx.existing_private_accounts()[0]), - }); - - let pinata_balance_pre = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; - let SubcommandReturnValue::TransactionExecuted { tx_hash: _ } = result else { - anyhow::bail!("Expected TransactionExecuted return value"); - }; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - info!("Syncing private accounts"); - sync_private(&mut ctx).await?; - - let new_commitment = ctx - .wallet() - .get_private_account_commitment(ctx.existing_private_accounts()[0]) - .context("Failed to get private account commitment")?; - assert!(verify_commitment_is_in_state(new_commitment, ctx.sequencer_client()).await); - - let pinata_balance_post = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - assert_eq!(pinata_balance_post, pinata_balance_pre - pinata_prize); - - info!("Successfully claimed pinata to existing private account"); - - Ok(()) -} - -#[test] -async fn claim_pinata_to_new_private_account() -> Result<()> { - let mut ctx = TestContext::new().await?; - - let pinata_prize = 150; - - // Create new private account - let winner_account_id = new_account(&mut ctx, true, None).await?; - - // Initialize account under auth transfer program - let command = Command::AuthTransfer(AuthTransferSubcommand::Init { - account_id: private_mention(winner_account_id), - }); - wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let new_commitment = ctx - .wallet() - .get_private_account_commitment(winner_account_id) - .context("Failed to get private account commitment")?; - assert!(verify_commitment_is_in_state(new_commitment, ctx.sequencer_client()).await); - - // Claim pinata to the new private account - let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim { - to: private_mention(winner_account_id), - }); - - let pinata_balance_pre = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let new_commitment = ctx - .wallet() - .get_private_account_commitment(winner_account_id) - .context("Failed to get private account commitment")?; - assert!(verify_commitment_is_in_state(new_commitment, ctx.sequencer_client()).await); - - let pinata_balance_post = account_balance(&ctx, system_accounts::pinata_account_id()).await?; - - assert_eq!(pinata_balance_post, pinata_balance_pre - pinata_prize); - - info!("Successfully claimed pinata to new private account"); - - Ok(()) -} diff --git a/integration_tests/tests/token.rs b/integration_tests/tests/token.rs deleted file mode 100644 index 215a1065..00000000 --- a/integration_tests/tests/token.rs +++ /dev/null @@ -1,996 +0,0 @@ -#![expect( - clippy::shadow_unrelated, - clippy::tests_outside_test_module, - reason = "We don't care about these in tests" -)] - -use std::time::Duration; - -use anyhow::{Context as _, Result}; -use integration_tests::{ - TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, get_account, new_account, private_mention, - public_mention, sync_private, token_send_claiming_new_account, verify_commitment_is_in_state, -}; -use key_protocol::key_management::key_tree::chain_index::ChainIndex; -use log::info; -use token_core::{TokenDefinition, TokenHolding}; -use tokio::test; -use wallet::{ - account::Label, - cli::{ - Command, SubcommandReturnValue, - account::{AccountSubcommand, NewSubcommand}, - programs::token::TokenProgramAgnosticSubcommand, - }, -}; - -#[test] -async fn create_and_transfer_public_token() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create new account for the token definition - let definition_account_id = new_account(&mut ctx, false, None).await?; - - // Create new account for the token supply holder - let supply_account_id = new_account(&mut ctx, false, None).await?; - - // Create new account for receiving a token transaction - let recipient_account_id = new_account(&mut ctx, false, None).await?; - - // Create new token - let name = "A NAME".to_owned(); - let total_supply = 37; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: public_mention(definition_account_id), - supply_account_id: public_mention(supply_account_id), - name: name.clone(), - total_supply, - }; - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Check the status of the token definition account - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - - assert_eq!(definition_acc.program_owner, programs::token().id()); - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name: name.clone(), - total_supply, - metadata_id: None - } - ); - - // Check the status of the token holding account with the total supply - let supply_acc = get_account(&ctx, supply_account_id).await?; - - // The account must be owned by the token program - assert_eq!(supply_acc.program_owner, programs::token().id()); - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - } - ); - - // Transfer 7 tokens from supply_acc to recipient_account_id. `recipient_account_id` is - // still unclaimed, so this bypasses the wallet CLI (which never signs with the recipient's - // key) and signs with the recipient's own key directly. - let transfer_amount = 7; - token_send_claiming_new_account( - &mut ctx, - supply_account_id, - recipient_account_id, - transfer_amount, - ) - .await?; - - // Check the status of the supply account after transfer - let supply_acc = get_account(&ctx, supply_account_id).await?; - assert_eq!(supply_acc.program_owner, programs::token().id()); - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - transfer_amount - } - ); - - // Check the status of the recipient account after transfer - let recipient_acc = get_account(&ctx, recipient_account_id).await?; - assert_eq!(recipient_acc.program_owner, programs::token().id()); - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - } - ); - - // Burn 3 tokens from recipient_acc - let burn_amount = 3; - let subcommand = TokenProgramAgnosticSubcommand::Burn { - definition: public_mention(definition_account_id), - holder: public_mention(recipient_account_id), - amount: burn_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Check the status of the token definition account after burn - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name: name.clone(), - total_supply: total_supply - burn_amount, - metadata_id: None - } - ); - - // Check the status of the recipient account after burn - let recipient_acc = get_account(&ctx, recipient_account_id).await?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - burn_amount - } - ); - - // Mint 10 tokens at recipient_acc - let mint_amount = 10; - let subcommand = TokenProgramAgnosticSubcommand::Mint { - definition: public_mention(definition_account_id), - holder: Some(public_mention(recipient_account_id)), - holder_npk: None, - holder_vpk: None, - holder_keys: None, - holder_identifier: None, - amount: mint_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Check the status of the token definition account after mint - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name, - total_supply: total_supply - burn_amount + mint_amount, - metadata_id: None - } - ); - - // Check the status of the recipient account after mint - let recipient_acc = get_account(&ctx, recipient_account_id).await?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - burn_amount + mint_amount - } - ); - - info!("Successfully created and transferred public token"); - - Ok(()) -} - -#[test] -async fn create_and_transfer_token_with_private_supply() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create new account for the token definition (public) - let definition_account_id = new_account(&mut ctx, false, None).await?; - - // Create new account for the token supply holder (private) - let supply_account_id = new_account(&mut ctx, true, None).await?; - - // Create new account for receiving a token transaction (private) - let recipient_account_id = new_account(&mut ctx, true, None).await?; - - // Create new token - let name = "A NAME".to_owned(); - let total_supply = 37; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: public_mention(definition_account_id), - supply_account_id: private_mention(supply_account_id), - name: name.clone(), - total_supply, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Check the status of the token definition account - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - - assert_eq!(definition_acc.program_owner, programs::token().id()); - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name: name.clone(), - total_supply, - metadata_id: None - } - ); - - let new_commitment1 = ctx - .wallet() - .get_private_account_commitment(supply_account_id) - .context("Failed to get supply account commitment")?; - assert!(verify_commitment_is_in_state(new_commitment1, ctx.sequencer_client()).await); - - // Transfer 7 tokens from supply_acc to recipient_account_id - let transfer_amount = 7; - let subcommand = TokenProgramAgnosticSubcommand::Send { - from: private_mention(supply_account_id), - to: Some(private_mention(recipient_account_id)), - to_npk: None, - to_vpk: None, - to_keys: None, - to_identifier: Some(0), - amount: transfer_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let new_commitment1 = ctx - .wallet() - .get_private_account_commitment(supply_account_id) - .context("Failed to get supply account commitment")?; - assert!(verify_commitment_is_in_state(new_commitment1, ctx.sequencer_client()).await); - - let new_commitment2 = ctx - .wallet() - .get_private_account_commitment(recipient_account_id) - .context("Failed to get recipient account commitment")?; - assert!(verify_commitment_is_in_state(new_commitment2, ctx.sequencer_client()).await); - - // Burn 3 tokens from recipient_acc - let burn_amount = 3; - let subcommand = TokenProgramAgnosticSubcommand::Burn { - definition: public_mention(definition_account_id), - holder: private_mention(recipient_account_id), - amount: burn_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Check the token definition account after burn - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name, - total_supply: total_supply - burn_amount, - metadata_id: None - } - ); - - let new_commitment2 = ctx - .wallet() - .get_private_account_commitment(recipient_account_id) - .context("Failed to get recipient account commitment")?; - assert!(verify_commitment_is_in_state(new_commitment2, ctx.sequencer_client()).await); - - // Check the recipient account balance after burn - let recipient_acc = ctx - .wallet() - .get_account_private(recipient_account_id) - .context("Failed to get recipient account")?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - burn_amount - } - ); - - info!("Successfully created and transferred token with private supply"); - - Ok(()) -} - -#[test] -async fn create_token_with_private_definition() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create token definition account (private) - let definition_account_id = new_account(&mut ctx, true, Some(ChainIndex::root())).await?; - - // Create supply account (public) - let supply_account_id = new_account(&mut ctx, false, Some(ChainIndex::root())).await?; - - // Create token with private definition - let name = "A NAME".to_owned(); - let total_supply = 37; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: private_mention(definition_account_id), - supply_account_id: public_mention(supply_account_id), - name: name.clone(), - total_supply, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify private definition commitment - let new_commitment = ctx - .wallet() - .get_private_account_commitment(definition_account_id) - .context("Failed to get definition commitment")?; - assert!(verify_commitment_is_in_state(new_commitment, ctx.sequencer_client()).await); - - // Verify supply account - let supply_acc = get_account(&ctx, supply_account_id).await?; - - assert_eq!(supply_acc.program_owner, programs::token().id()); - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - } - ); - - // Create private recipient account - let recipient_account_id_private = new_account(&mut ctx, true, None).await?; - - // Create public recipient account - let recipient_account_id_public = new_account(&mut ctx, false, None).await?; - - // Mint to public account - let mint_amount_public = 10; - let subcommand = TokenProgramAgnosticSubcommand::Mint { - definition: private_mention(definition_account_id), - holder: Some(public_mention(recipient_account_id_public)), - holder_npk: None, - holder_vpk: None, - holder_keys: None, - holder_identifier: None, - amount: mint_amount_public, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify definition account has updated supply - let definition_acc = ctx - .wallet() - .get_account_private(definition_account_id) - .context("Failed to get definition account")?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name: name.clone(), - total_supply: total_supply + mint_amount_public, - metadata_id: None - } - ); - - // Verify public recipient received tokens - let recipient_acc = get_account(&ctx, recipient_account_id_public).await?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: mint_amount_public - } - ); - - // Mint to private account - let mint_amount_private = 5; - let subcommand = TokenProgramAgnosticSubcommand::Mint { - definition: private_mention(definition_account_id), - holder: Some(private_mention(recipient_account_id_private)), - holder_npk: None, - holder_vpk: None, - holder_keys: None, - holder_identifier: None, - amount: mint_amount_private, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify private recipient commitment - let new_commitment = ctx - .wallet() - .get_private_account_commitment(recipient_account_id_private) - .context("Failed to get recipient commitment")?; - assert!(verify_commitment_is_in_state(new_commitment, ctx.sequencer_client()).await); - - // Verify private recipient balance - let recipient_acc_private = ctx - .wallet() - .get_account_private(recipient_account_id_private) - .context("Failed to get private recipient account")?; - let token_holding = TokenHolding::try_from(&recipient_acc_private.data)?; - - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: mint_amount_private - } - ); - - info!("Successfully created token with private definition and minted to both account types"); - - Ok(()) -} - -#[test] -async fn create_token_with_private_definition_and_supply() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create token definition account (private) - let definition_account_id = new_account(&mut ctx, true, None).await?; - - // Create supply account (private) - let supply_account_id = new_account(&mut ctx, true, None).await?; - - // Create token with both private definition and supply - let name = "A NAME".to_owned(); - let total_supply = 37; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: private_mention(definition_account_id), - supply_account_id: private_mention(supply_account_id), - name, - total_supply, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify definition commitment - let definition_commitment = ctx - .wallet() - .get_private_account_commitment(definition_account_id) - .context("Failed to get definition commitment")?; - assert!(verify_commitment_is_in_state(definition_commitment, ctx.sequencer_client()).await); - - // Verify supply commitment - let supply_commitment = ctx - .wallet() - .get_private_account_commitment(supply_account_id) - .context("Failed to get supply commitment")?; - assert!(verify_commitment_is_in_state(supply_commitment, ctx.sequencer_client()).await); - - // Verify supply balance - let supply_acc = ctx - .wallet() - .get_account_private(supply_account_id) - .context("Failed to get supply account")?; - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - } - ); - - // Create recipient account - let recipient_account_id = new_account(&mut ctx, true, None).await?; - - // Transfer tokens - let transfer_amount = 7; - let subcommand = TokenProgramAgnosticSubcommand::Send { - from: private_mention(supply_account_id), - to: Some(private_mention(recipient_account_id)), - to_npk: None, - to_vpk: None, - to_keys: None, - to_identifier: Some(0), - amount: transfer_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify both commitments updated - let supply_commitment = ctx - .wallet() - .get_private_account_commitment(supply_account_id) - .context("Failed to get supply commitment")?; - assert!(verify_commitment_is_in_state(supply_commitment, ctx.sequencer_client()).await); - - let recipient_commitment = ctx - .wallet() - .get_private_account_commitment(recipient_account_id) - .context("Failed to get recipient commitment")?; - assert!(verify_commitment_is_in_state(recipient_commitment, ctx.sequencer_client()).await); - - // Verify balances - let supply_acc = ctx - .wallet() - .get_account_private(supply_account_id) - .context("Failed to get supply account")?; - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - transfer_amount - } - ); - - let recipient_acc = ctx - .wallet() - .get_account_private(recipient_account_id) - .context("Failed to get recipient account")?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - } - ); - - info!("Successfully created and transferred token with both private definition and supply"); - - Ok(()) -} - -#[test] -async fn shielded_token_transfer() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create token definition account (public) - let definition_account_id = new_account(&mut ctx, false, None).await?; - - // Create supply account (public) - let supply_account_id = new_account(&mut ctx, false, None).await?; - - // Create recipient account (private) for shielded transfer - let recipient_account_id = new_account(&mut ctx, true, None).await?; - - // Create token - let name = "A NAME".to_owned(); - let total_supply = 37; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: public_mention(definition_account_id), - supply_account_id: public_mention(supply_account_id), - name, - total_supply, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Perform shielded transfer: public supply -> private recipient - let transfer_amount = 7; - let subcommand = TokenProgramAgnosticSubcommand::Send { - from: public_mention(supply_account_id), - to: Some(private_mention(recipient_account_id)), - to_npk: None, - to_vpk: None, - to_keys: None, - to_identifier: Some(0), - amount: transfer_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify supply account balance - let supply_acc = get_account(&ctx, supply_account_id).await?; - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - transfer_amount - } - ); - - // Verify recipient commitment exists - let new_commitment = ctx - .wallet() - .get_private_account_commitment(recipient_account_id) - .context("Failed to get recipient commitment")?; - assert!(verify_commitment_is_in_state(new_commitment, ctx.sequencer_client()).await); - - // Verify recipient balance - let recipient_acc = ctx - .wallet() - .get_account_private(recipient_account_id) - .context("Failed to get recipient account")?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - } - ); - - info!("Successfully performed shielded token transfer"); - - Ok(()) -} - -#[test] -async fn deshielded_token_transfer() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create token definition account (public) - let definition_account_id = new_account(&mut ctx, false, None).await?; - - // Create supply account (private) - let supply_account_id = new_account(&mut ctx, true, None).await?; - - // Create recipient account (public) for deshielded transfer - let recipient_account_id = new_account(&mut ctx, false, None).await?; - - // Create token with private supply - let name = "A NAME".to_owned(); - let total_supply = 37; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: public_mention(definition_account_id), - supply_account_id: private_mention(supply_account_id), - name, - total_supply, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Perform deshielded transfer: private supply -> public recipient - let transfer_amount = 7; - let subcommand = TokenProgramAgnosticSubcommand::Send { - from: private_mention(supply_account_id), - to: Some(public_mention(recipient_account_id)), - to_npk: None, - to_vpk: None, - to_keys: None, - to_identifier: Some(0), - amount: transfer_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Verify supply account commitment exists - let new_commitment = ctx - .wallet() - .get_private_account_commitment(supply_account_id) - .context("Failed to get supply commitment")?; - assert!(verify_commitment_is_in_state(new_commitment, ctx.sequencer_client()).await); - - // Verify supply balance - let supply_acc = ctx - .wallet() - .get_account_private(supply_account_id) - .context("Failed to get supply account")?; - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - transfer_amount - } - ); - - // Verify recipient balance - let recipient_acc = get_account(&ctx, recipient_account_id).await?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - } - ); - - info!("Successfully performed deshielded token transfer"); - - Ok(()) -} - -#[test] -async fn token_claiming_path_with_private_accounts() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create token definition account (private) - let definition_account_id = new_account(&mut ctx, true, None).await?; - - // Create supply account (private) - let supply_account_id = new_account(&mut ctx, true, None).await?; - - // Create token - let name = "A NAME".to_owned(); - let total_supply = 37; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: private_mention(definition_account_id), - supply_account_id: private_mention(supply_account_id), - name, - total_supply, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Create new private account for claiming path - let recipient_account_id = new_account(&mut ctx, true, None).await?; - - // Get keys for foreign mint (claiming path) - let holder = ctx - .wallet() - .storage() - .key_chain() - .private_account(recipient_account_id) - .context("Failed to get private account keys")?; - - let holder_keys = holder.key_chain; - let holder_identifier = holder.kind.identifier(); - - // Mint using claiming path (foreign account) - let mint_amount = 9; - let subcommand = TokenProgramAgnosticSubcommand::Mint { - definition: private_mention(definition_account_id), - holder: None, - holder_npk: Some(hex::encode(holder_keys.nullifier_public_key.0)), - holder_vpk: Some(hex::encode(holder_keys.viewing_public_key.to_bytes())), - holder_keys: None, - holder_identifier: Some(holder_identifier), - amount: mint_amount, - }; - - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Sync to claim the account - sync_private(&mut ctx).await?; - - // Verify commitment exists - let recipient_commitment = ctx - .wallet() - .get_private_account_commitment(recipient_account_id) - .context("Failed to get recipient commitment")?; - assert!(verify_commitment_is_in_state(recipient_commitment, ctx.sequencer_client()).await); - - // Verify balance - let recipient_acc = ctx - .wallet() - .get_account_private(recipient_account_id) - .context("Failed to get recipient account")?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: mint_amount - } - ); - - info!("Successfully minted tokens using claiming path"); - - Ok(()) -} - -#[test] -async fn create_token_using_labels() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create definition and supply accounts with labels - let def_label = Label::new("token-definition-label"); - let supply_label = Label::new("token-supply-label"); - - let result = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Account(AccountSubcommand::New(NewSubcommand::Public { - cci: None, - label: Some(def_label.clone()), - })), - ) - .await?; - let SubcommandReturnValue::RegisterAccount { - account_id: definition_account_id, - } = result - else { - anyhow::bail!("Expected RegisterAccount return value"); - }; - - let result = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Account(AccountSubcommand::New(NewSubcommand::Public { - cci: None, - label: Some(Label::new(supply_label.clone())), - })), - ) - .await?; - let SubcommandReturnValue::RegisterAccount { - account_id: supply_account_id, - } = result - else { - anyhow::bail!("Expected RegisterAccount return value"); - }; - - // Create token using account labels instead of IDs - let name = "LABELED TOKEN".to_owned(); - let total_supply = 100; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: def_label.into(), - supply_account_id: supply_label.into(), - name: name.clone(), - total_supply, - }; - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - let definition_acc = get_account(&ctx, definition_account_id).await?; - let token_definition = TokenDefinition::try_from(&definition_acc.data)?; - - assert_eq!(definition_acc.program_owner, programs::token().id()); - assert_eq!( - token_definition, - TokenDefinition::Fungible { - name, - total_supply, - metadata_id: None - } - ); - - let supply_acc = get_account(&ctx, supply_account_id).await?; - let token_holding = TokenHolding::try_from(&supply_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: total_supply - } - ); - - info!("Successfully created token using definition and supply account labels"); - - Ok(()) -} - -#[test] -async fn transfer_token_using_from_label() -> Result<()> { - let mut ctx = TestContext::new().await?; - - // Create definition account - let definition_account_id = new_account(&mut ctx, false, None).await?; - - // Create supply account with a label - let supply_label = Label::new("token-supply-sender"); - let result = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Account(AccountSubcommand::New(NewSubcommand::Public { - cci: None, - label: Some(supply_label.clone()), - })), - ) - .await?; - let SubcommandReturnValue::RegisterAccount { - account_id: supply_account_id, - } = result - else { - anyhow::bail!("Expected RegisterAccount return value"); - }; - - // Create recipient account - let recipient_account_id = new_account(&mut ctx, false, None).await?; - - // Create token - let total_supply = 50; - let subcommand = TokenProgramAgnosticSubcommand::New { - definition_account_id: public_mention(definition_account_id), - supply_account_id: public_mention(supply_account_id), - name: "LABEL TEST TOKEN".to_owned(), - total_supply, - }; - wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - - // Confirm the label resolves to the account created for it. - let resolved_sender = ctx - .wallet() - .storage() - .resolve_label(&supply_label) - .context("supply_label should resolve to an account")?; - assert_eq!( - resolved_sender, - wallet::account::AccountIdWithPrivacy::Public(supply_account_id) - ); - - // Transfer token from the label-resolved account. `recipient_account_id` is still - // unclaimed, so this bypasses the wallet CLI (which never signs with the recipient's key) - // and signs with the recipient's own key directly. - let transfer_amount = 20; - token_send_claiming_new_account( - &mut ctx, - supply_account_id, - recipient_account_id, - transfer_amount, - ) - .await?; - - let recipient_acc = get_account(&ctx, recipient_account_id).await?; - let token_holding = TokenHolding::try_from(&recipient_acc.data)?; - assert_eq!( - token_holding, - TokenHolding::Fungible { - definition_id: definition_account_id, - balance: transfer_amount - } - ); - - info!("Successfully transferred token using from_label"); - - Ok(()) -} diff --git a/lez/wallet/src/lib.rs b/lez/wallet/src/lib.rs index f54fd551..8fcab669 100644 --- a/lez/wallet/src/lib.rs +++ b/lez/wallet/src/lib.rs @@ -67,6 +67,8 @@ pub struct SharedAccountInfo { pub vpk: lee_core::encryption::ViewingPublicKey, } +// + #[derive(Debug, thiserror::Error)] pub enum ExecutionFailureKind { #[error("Failed to get data from sequencer")] From 8f0a3032cb9e4d9564f58ce9b5bb43f5ef04bfd3 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Tue, 4 Aug 2026 07:54:29 +0300 Subject: [PATCH 2/3] fix(ci): machete fix --- Cargo.lock | 2 -- integration_tests/Cargo.toml | 2 -- 2 files changed, 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 634cd99e..8f8344f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4372,7 +4372,6 @@ name = "integration_tests" version = "0.1.0" dependencies = [ "anyhow", - "associated_token_account_core", "authenticated_transfer_core", "bridge_core", "bridge_lock_core", @@ -4402,7 +4401,6 @@ dependencies = [ "test_fixtures", "test_programs", "testnet_initial_state", - "token_core", "tokio", "vault_core", "wallet", diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 4d078550..225d75d4 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -17,8 +17,6 @@ wallet.workspace = true common.workspace = true key_protocol.workspace = true serde_json.workspace = true -token_core.workspace = true -associated_token_account_core.workspace = true vault_core.workspace = true faucet_core.workspace = true bridge_core.workspace = true From 7b9e323dd2229b485ee4960be888e4ffecdd626d Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Tue, 4 Aug 2026 15:43:52 +0300 Subject: [PATCH 3/3] fix: suggestion fix 1 --- lez/wallet/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/lez/wallet/src/lib.rs b/lez/wallet/src/lib.rs index 8fcab669..f54fd551 100644 --- a/lez/wallet/src/lib.rs +++ b/lez/wallet/src/lib.rs @@ -67,8 +67,6 @@ pub struct SharedAccountInfo { pub vpk: lee_core::encryption::ViewingPublicKey, } -// - #[derive(Debug, thiserror::Error)] pub enum ExecutionFailureKind { #[error("Failed to get data from sequencer")]