extern crate alloc;
use anyhow::Result;
use miden_protocol::account::AccountId;
use miden_protocol::account::auth::AuthScheme;
use miden_protocol::asset::{Asset, FungibleAsset};
use miden_protocol::note::{Note, NoteType};
use miden_protocol::transaction::{ExecutedTransaction, RawOutputNote};
use miden_testing::{Auth, MockChain, assert_note_created};
async fn execute_with_output(
output_assets: &[Asset],
) -> Result<(AccountId, Note, MockChain, ExecutedTransaction)> {
let mut builder = MockChain::builder();
let sender = builder.add_existing_wallet_with_assets(
Auth::BasicAuth {
auth_scheme: AuthScheme::Falcon512Poseidon2,
},
output_assets.iter().copied(),
)?;
let target = builder.create_new_wallet(Auth::BasicAuth {
auth_scheme: AuthScheme::Falcon512Poseidon2,
})?;
let sender_id = sender.id();
let output = builder.add_p2id_note(sender_id, target.id(), output_assets, NoteType::Public)?;
let spawn = builder.add_spawn_note([&output])?;
let chain = builder.build()?;
let executed = chain
.build_tx_context(sender, &[spawn.id()], &[])?
.extend_expected_output_notes(vec![RawOutputNote::Full(output)])
.build()?
.execute()
.await?;
Ok((sender_id, spawn, chain, executed))
}
#[tokio::test]
async fn note_lifecycle_full_flow() -> Result<()> {
let asset: Asset = FungibleAsset::mock(7);
let (sender_id, spawn, mut chain, executed) = execute_with_output(&[asset]).await?;
assert!(chain.is_note_committed(&spawn.id()));
assert!(chain.is_note_unspent(&spawn.nullifier()));
assert!(executed.consumes_note(&spawn.id()));
assert_note_created!(
executed,
note_type: NoteType::Public,
sender: sender_id,
assets: [asset],
);
chain.add_pending_executed_transaction(&executed)?;
chain.prove_next_block()?;
assert!(chain.is_note_consumed(&spawn.nullifier()));
Ok(())
}
#[tokio::test]
async fn assert_note_created_partial_specs_match() -> Result<()> {
let asset: Asset = FungibleAsset::mock(7);
let (sender_id, _spawn, _chain, executed) = execute_with_output(&[asset]).await?;
assert_note_created!(executed, note_type: NoteType::Public);
assert_note_created!(executed, sender: sender_id);
assert_note_created!(executed, assets: [asset]);
assert_note_created!(executed, note_type: NoteType::Public, assets: [asset]);
Ok(())
}
#[tokio::test]
#[should_panic(expected = "no output note matches")]
async fn assert_note_created_panics_on_sender_mismatch() {
let asset: Asset = FungibleAsset::mock(7);
let (_sender_id, _spawn, _chain, executed) = execute_with_output(&[asset]).await.unwrap();
assert_note_created!(executed, sender: FungibleAsset::mock_issuer());
}
#[tokio::test]
#[should_panic(expected = "no output note matches")]
async fn assert_note_created_panics_on_asset_count_mismatch() {
let asset: Asset = FungibleAsset::mock(7);
let (_sender_id, _spawn, _chain, executed) = execute_with_output(&[asset]).await.unwrap();
assert_note_created!(executed, assets: [asset, asset]);
}