mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 17:21:08 +00:00
Add Balances Locks (#197)
* Add Balances Locks * Pass fmt * Add tests for Balances Locks In order to write this test, I just added the new staking::BondCall :). * . * In case you want to run multiple tests at the same time * Return Result in integration test
This commit is contained in:
+86
-1
@@ -25,7 +25,10 @@ use codec::{
|
||||
Encode,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use frame_support::Parameter;
|
||||
use frame_support::{
|
||||
traits::LockIdentifier,
|
||||
Parameter,
|
||||
};
|
||||
use sp_runtime::traits::{
|
||||
AtLeast32Bit,
|
||||
MaybeSerialize,
|
||||
@@ -80,6 +83,47 @@ pub struct TotalIssuanceStore<T: Balances> {
|
||||
pub _runtime: PhantomData<T>,
|
||||
}
|
||||
|
||||
/// The locks of the balances module.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Store, Encode, Decode)]
|
||||
pub struct LocksStore<'a, T: Balances> {
|
||||
#[store(returns = Vec<BalanceLock<T::Balance>>)]
|
||||
/// Account to retrieve the balance locks for.
|
||||
pub account_id: &'a T::AccountId,
|
||||
}
|
||||
|
||||
/// A single lock on a balance. There can be many of these on an account and they "overlap", so the
|
||||
/// same balance is frozen by multiple locks.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
|
||||
pub struct BalanceLock<Balance> {
|
||||
/// An identifier for this lock. Only one lock may be in existence for each identifier.
|
||||
pub id: LockIdentifier,
|
||||
/// The amount which the free balance may not drop below when this lock is in effect.
|
||||
pub amount: Balance,
|
||||
/// If true, then the lock remains in effect even for payment of transaction fees.
|
||||
pub reasons: Reasons,
|
||||
}
|
||||
|
||||
impl<Balance: Debug> Debug for BalanceLock<Balance> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_struct("BalanceLock")
|
||||
.field("id", &String::from_utf8_lossy(&self.id))
|
||||
.field("amount", &self.amount)
|
||||
.field("reasons", &self.reasons)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Simplified reasons for withdrawing balance.
|
||||
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum Reasons {
|
||||
/// Paying system transaction fees.
|
||||
Fee,
|
||||
/// Any reason other than paying system transaction fees.
|
||||
Misc,
|
||||
/// Any reason at all.
|
||||
All,
|
||||
}
|
||||
|
||||
/// Transfer some liquid free balance to another account.
|
||||
///
|
||||
/// `transfer` will set the `FreeBalance` of the sender and receiver.
|
||||
@@ -181,6 +225,47 @@ mod tests {
|
||||
assert_ne!(info.data.free, 0);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
#[cfg(feature = "integration-tests")]
|
||||
async fn test_state_balance_lock() -> Result<(), crate::Error> {
|
||||
use crate::{
|
||||
frame::staking::{
|
||||
BondCallExt,
|
||||
RewardDestination,
|
||||
},
|
||||
runtimes::KusamaRuntime as RT,
|
||||
ClientBuilder,
|
||||
};
|
||||
|
||||
env_logger::try_init().ok();
|
||||
let bob = PairSigner::<RT, _>::new(AccountKeyring::Bob.pair());
|
||||
let client = ClientBuilder::<RT>::new().build().await?;
|
||||
|
||||
client
|
||||
.bond_and_watch(
|
||||
&bob,
|
||||
AccountKeyring::Charlie.to_account_id(),
|
||||
100_000_000_000,
|
||||
RewardDestination::Stash,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let locks = client
|
||||
.locks(&AccountKeyring::Bob.to_account_id(), None)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
locks,
|
||||
vec![BalanceLock {
|
||||
id: *b"staking ",
|
||||
amount: 100_000_000_000,
|
||||
reasons: Reasons::All,
|
||||
}]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_transfer_error() {
|
||||
env_logger::try_init().ok();
|
||||
|
||||
@@ -196,6 +196,19 @@ pub struct NominateCall<T: Staking> {
|
||||
pub targets: Vec<T::Address>,
|
||||
}
|
||||
|
||||
/// Take the origin account as a stash and lock up `value` of its balance.
|
||||
/// `controller` will be the account that controls it.
|
||||
#[derive(Call, Encode, Debug)]
|
||||
pub struct BondCall<T: Staking> {
|
||||
/// Tٗhe controller account
|
||||
pub contrller: T::AccountId,
|
||||
/// Lock up `value` of its balance.
|
||||
#[codec(compact)]
|
||||
pub value: T::Balance,
|
||||
/// Destination of Staking reward.
|
||||
pub payee: RewardDestination<T::AccountId>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "integration-tests")]
|
||||
mod tests {
|
||||
@@ -324,6 +337,43 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_bond() -> Result<(), Error> {
|
||||
env_logger::try_init().ok();
|
||||
let alice = PairSigner::<RT, _>::new(AccountKeyring::Alice.pair());
|
||||
let client = ClientBuilder::<RT>::new().build().await.unwrap();
|
||||
|
||||
let bond = client
|
||||
.bond_and_watch(
|
||||
&alice,
|
||||
AccountKeyring::Bob.to_account_id(),
|
||||
100_000_000_000,
|
||||
RewardDestination::Stash,
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_matches!(bond, Ok(ExtrinsicSuccess {block: _, extrinsic: _, events}) => {
|
||||
// TOOD: this is unsatisfying – can we do better?
|
||||
assert_eq!(events.len(), 3);
|
||||
});
|
||||
|
||||
let bond_again = client
|
||||
.bond_and_watch(
|
||||
&alice,
|
||||
AccountKeyring::Bob.to_account_id(),
|
||||
100_000_000_000,
|
||||
RewardDestination::Stash,
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_matches!(bond_again, Err(Error::Runtime(RuntimeError::Module(module_err))) => {
|
||||
assert_eq!(module_err.module, "Staking");
|
||||
assert_eq!(module_err.error, "AlreadyBonded");
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_total_issuance_is_okay() -> Result<(), Error> {
|
||||
env_logger::try_init().ok();
|
||||
|
||||
Reference in New Issue
Block a user