use super::*;
#[derive(
Encode,
Decode,
DecodeWithMemTracking,
Copy,
Clone,
PartialEq,
Eq,
RuntimeDebug,
MaxEncodedLen,
TypeInfo,
)]
pub struct VestingInfo<Balance, BlockNumber> {
locked: Balance,
per_block: Balance,
starting_block: BlockNumber,
}
impl<Balance, BlockNumber> VestingInfo<Balance, BlockNumber>
where
Balance: AtLeast32BitUnsigned + Copy,
BlockNumber: AtLeast32BitUnsigned + Copy + Bounded,
{
pub fn new(
locked: Balance,
per_block: Balance,
starting_block: BlockNumber,
) -> VestingInfo<Balance, BlockNumber> {
VestingInfo { locked, per_block, starting_block }
}
pub fn is_valid(&self) -> bool {
!self.locked.is_zero() && !self.raw_per_block().is_zero()
}
pub fn locked(&self) -> Balance {
self.locked
}
pub fn per_block(&self) -> Balance {
self.per_block.max(One::one())
}
pub(crate) fn raw_per_block(&self) -> Balance {
self.per_block
}
pub fn starting_block(&self) -> BlockNumber {
self.starting_block
}
pub fn locked_at<BlockNumberToBalance: Convert<BlockNumber, Balance>>(
&self,
n: BlockNumber,
) -> Balance {
let vested_block_count = n.saturating_sub(self.starting_block);
let vested_block_count = BlockNumberToBalance::convert(vested_block_count);
vested_block_count
.checked_mul(&self.per_block()) .map(|to_unlock| self.locked.saturating_sub(to_unlock))
.unwrap_or(Zero::zero())
}
pub fn ending_block_as_balance<BlockNumberToBalance: Convert<BlockNumber, Balance>>(
&self,
) -> Balance {
let starting_block = BlockNumberToBalance::convert(self.starting_block);
let duration = if self.per_block() >= self.locked {
One::one()
} else {
self.locked / self.per_block()
+ if (self.locked % self.per_block()).is_zero() {
Zero::zero()
} else {
One::one()
}
};
starting_block.saturating_add(duration)
}
}