use rand_core::{RngCore, OsRng}; use blake2::{ digest::{consts::U32, Digest}, Blake2b, }; use scale::Encode; use serai_runtime::coins::primitives::OutInstructionWithBalance; use sp_core::Pair; use serai_client::{ primitives::{ Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress, Data, ExternalAddress, insecure_pair_from_name, }, in_instructions::{ InInstructionsEvent, primitives::{InInstruction, InInstructionWithBalance, Batch}, }, coins::{primitives::OutInstruction, CoinsEvent}, PairSigner, Serai, SeraiCoins, }; mod common; use common::{tx::publish_tx, in_instructions::provide_batch}; serai_test!( burn: (|serai: Serai| async move { let network = NetworkId::Bitcoin; let id = 0; let mut block_hash = BlockHash([0; 32]); OsRng.fill_bytes(&mut block_hash.0); let pair = insecure_pair_from_name("Dave"); let public = pair.public(); let address = SeraiAddress::from(public); let coin = Coin::Bitcoin; let amount = Amount(OsRng.next_u64().saturating_add(1)); let balance = Balance { coin, amount }; let batch = Batch { network, id, block: block_hash, instructions: vec![InInstructionWithBalance { instruction: InInstruction::Transfer(address), balance, }], }; let block = provide_batch(&serai, batch.clone()).await; let serai = serai.as_of(block); let batches = serai.in_instructions().batch_events().await.unwrap(); assert_eq!( batches, vec![InInstructionsEvent::Batch { network, id, block: block_hash, instructions_hash: Blake2b::::digest(batch.instructions.encode()).into(), }] ); assert_eq!( serai.coins().mint_events().await.unwrap(), vec![CoinsEvent::Mint { to: address.into(), balance }] ); assert_eq!(serai.coins().coin_supply(coin).await.unwrap(), amount); assert_eq!(serai.coins().coin_balance(coin, address).await.unwrap(), amount); // Now burn it let mut rand_bytes = vec![0; 32]; OsRng.fill_bytes(&mut rand_bytes); let external_address = ExternalAddress::new(rand_bytes).unwrap(); let mut rand_bytes = vec![0; 32]; OsRng.fill_bytes(&mut rand_bytes); let data = Data::new(rand_bytes).unwrap(); let instruction = OutInstructionWithBalance { balance, instruction: OutInstruction { address: external_address, data: Some(data) }, }; let serai = serai.into_inner(); let block = publish_tx( serai, &serai .sign( &PairSigner::new(pair), &SeraiCoins::burn_with_instruction(instruction.clone()), 0, Default::default(), ) ) .await; let serai = serai.as_of(block).coins(); let events = serai.burn_with_instruction_events().await.unwrap(); assert_eq!(events, vec![CoinsEvent::BurnWithInstruction { from: address.into(), instruction }]); assert_eq!(serai.coin_supply(coin).await.unwrap(), Amount(0)); assert_eq!(serai.coin_balance(coin, address).await.unwrap(), Amount(0)); }) );