use crate::frame::system::{
System,
SystemEventsDecoder,
};
use codec::{
Decode,
Encode,
};
use core::marker::PhantomData;
use frame_support::Parameter;
use sp_runtime::traits::{
AtLeast32Bit,
MaybeSerialize,
Member,
};
use std::fmt::Debug;
#[module]
pub trait Balances: System {
type Balance: Parameter
+ Member
+ AtLeast32Bit
+ codec::Codec
+ Default
+ Copy
+ MaybeSerialize
+ Debug
+ From<<Self as System>::BlockNumber>;
}
#[derive(Clone, Debug, Eq, PartialEq, Default, Decode, Encode)]
pub struct AccountData<Balance> {
pub free: Balance,
pub reserved: Balance,
pub misc_frozen: Balance,
pub fee_frozen: Balance,
}
#[derive(Clone, Debug, Eq, PartialEq, Store, Encode)]
pub struct TotalIssuanceStore<T: Balances> {
#[store(returns = T::Balance)]
pub _runtime: PhantomData<T>,
}
#[derive(Clone, Debug, PartialEq, Call, Encode)]
pub struct TransferCall<'a, T: Balances> {
pub to: &'a <T as System>::Address,
#[codec(compact)]
pub amount: T::Balance,
}
#[derive(Clone, Debug, Eq, PartialEq, Event, Decode)]
pub struct TransferEvent<T: Balances> {
pub from: <T as System>::AccountId,
pub to: <T as System>::AccountId,
pub amount: T::Balance,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
error::{
Error,
ModuleError,
RuntimeError,
},
events::EventsDecoder,
extrinsic::{
PairSigner,
Signer,
},
subscription::EventSubscription,
system::AccountStoreExt,
tests::{
test_client,
TestRuntime,
},
};
use sp_core::{
sr25519::Pair,
Pair as _,
};
use sp_keyring::AccountKeyring;
#[async_std::test]
async fn test_basic_transfer() {
env_logger::try_init().ok();
let alice = PairSigner::<TestRuntime, _>::new(AccountKeyring::Alice.pair());
let bob = PairSigner::<TestRuntime, _>::new(AccountKeyring::Bob.pair());
let (client, _) = test_client().await;
let alice_pre = client.account(alice.account_id(), None).await.unwrap();
let bob_pre = client.account(bob.account_id(), None).await.unwrap();
let event = client
.transfer_and_watch(&alice, &bob.account_id(), 10_000)
.await
.unwrap()
.transfer()
.unwrap()
.unwrap();
let expected_event = TransferEvent {
from: alice.account_id().clone(),
to: bob.account_id().clone(),
amount: 10_000,
};
assert_eq!(event, expected_event);
let alice_post = client.account(alice.account_id(), None).await.unwrap();
let bob_post = client.account(bob.account_id(), None).await.unwrap();
assert!(alice_pre.data.free - 10_000 >= alice_post.data.free);
assert_eq!(bob_pre.data.free + 10_000, bob_post.data.free);
}
#[async_std::test]
async fn test_state_total_issuance() {
env_logger::try_init().ok();
let (client, _) = test_client().await;
let total_issuance = client.total_issuance(None).await.unwrap();
assert_ne!(total_issuance, 0);
}
#[async_std::test]
async fn test_state_read_free_balance() {
env_logger::try_init().ok();
let (client, _) = test_client().await;
let account = AccountKeyring::Alice.to_account_id();
let info = client.account(&account, None).await.unwrap();
assert_ne!(info.data.free, 0);
}
#[async_std::test]
async fn test_transfer_error() {
env_logger::try_init().ok();
let alice = PairSigner::new(AccountKeyring::Alice.pair());
let hans = PairSigner::new(Pair::generate().0);
let (client, _) = test_client().await;
client
.transfer_and_watch(&alice, hans.account_id(), 100_000_000_000)
.await
.unwrap();
let res = client
.transfer_and_watch(&hans, alice.account_id(), 100_000_000_000)
.await;
if let Err(Error::Runtime(RuntimeError::Module(error))) = res {
let error2 = ModuleError {
module: "Balances".into(),
error: "InsufficientBalance".into(),
};
assert_eq!(error, error2);
} else {
panic!("expected an error");
}
}
#[async_std::test]
async fn test_transfer_subscription() {
env_logger::try_init().ok();
let alice = PairSigner::new(AccountKeyring::Alice.pair());
let bob = AccountKeyring::Bob.to_account_id();
let (client, _) = test_client().await;
let sub = client.subscribe_events().await.unwrap();
let mut decoder = EventsDecoder::<TestRuntime>::new(client.metadata().clone());
decoder.with_balances();
let mut sub = EventSubscription::<TestRuntime>::new(sub, decoder);
sub.filter_event::<TransferEvent<_>>();
client.transfer(&alice, &bob, 10_000).await.unwrap();
let raw = sub.next().await.unwrap().unwrap();
let event = TransferEvent::<TestRuntime>::decode(&mut &raw.data[..]).unwrap();
assert_eq!(
event,
TransferEvent {
from: alice.account_id().clone(),
to: bob.clone(),
amount: 10_000,
}
);
}
}