Types

We can't really continue without first defining all the types that will be used in this contract. Let's take a look at these types.

These may be lots of information, but don't worry. You don't necessary have to know all of them at once. You can alway have this page on half of your screen (or another screen), and continue reading the pages on another screen, so you can always refer back to what things are while reading through. This page aims more as a reference than explanations.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}

We don't have 256-bit unsigned integer in the near-sdk, so we need to construct it ourselves.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}

Some basic types that we have declared.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}

This contains the lockup information. The explanation are in the documentation inside the code.

The rest will be here for you to see what information is included, we won't necessary explain what they are as there are documentations to explain in code, unless necessary to clear doubts.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}

For vesting, there include some implementations to assert its validity. What it's checking for is very clear in the code.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}

One actually doesn't know why Deserialize isn't derived from the above enum.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}

Note that the below is deprecated. Actually, they're deprecating the private vesting, so this includes the VestingScheduleWithSalt used only in private vesting.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{Base64VecU8, U128, U64};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{env, AccountId, Balance, require};
use uint::construct_uint;

construct_uint! {
    pub struct U256(4);
}

pub type Duration = u64;  // in nanoseconds
pub type Timestamp = u64;  // nanoseconds. 

// Wrapped into a struct for JSON serialization as string. 
pub type WrappedTimestamp = U64;
pub type WrappedDuration = U64;
pub type WrappedBalance = U128;

/// Hash for Vesting Schedule. 
pub type Hash = Vec<u8>;

/// The result of the transfer poll. 
/// Contains the timestamp when the proposal was voted in. 
pub type PollResult = Option<WrappedTimestamp>;

#[derive(BorshDeserialize, BorshSerialize)]
pub struct LockupInformation {
    pub lockup_amount: Balance,  // yoctoNEAR

    /// Early termination withdrawal. 
    /// Accounted separately from lockup_amount to ensure
    /// linear release not affected. 
    pub termination_withdrawn_tokens: Balance,

    /// [deprecated] lockup duration in nanoseconds. 
    /// Release doesn't start. 
    /// Replaced with `lockup_timestamp` and `release_duration`
    pub lockup_duration: Duration,

    /// If present, the duration when the full lockup amount
    /// be available. The tokens are linearly released from
    /// the moment tokens are unlocked, defined by:
    /// `max(transfer_timestamp + lockup_duration, lockup_timestamp)`.
    /// If absent, tokens aren't locked (vesting logic could
    /// be used, though).
    pub release_duration: Option<Duration>,

    /// Optional absolute lockup timestamp in nanoseconds. 
    /// Lock tokens until timestamp passes; then release starts after.
    /// If absent, `transfers_timestamp` will be used. 
    pub lockup_timestamp: Option<Timestamp>,

    /// Information about transfers. 
    /// If present: contains timestamp of when it was enabled.
    /// If absent: contains AccountId or transfer poll contract.
    pub transfers_information: TransfersInformation,
}

/// Contains information about the transfer, whether they're 
/// enabled or disabled. 
#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum TransfersInformation {

    /// Timestamp when transfers were enabled.
    TransfersEnabled {
        transfers_timestamp: WrappedTimestamp,
    },

    /// AccountId of transfers poll contract, to check if transfers
    /// are enabled. Lockup period starts only after transfer voted
    /// to be enabled. Starts with disabled transfer. Once transfers 
    /// are enabled, they can't be disabled and don't require 
    /// further checking. 
    TransfersDisabled {
        transfer_poll_account_id: AccountId
    },
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, 
  Serialize, PartialEq
)]
#[serde(crate = "near_sdk::serde")]
pub enum TransactionStatus {
    Idle,  // no transaction in progress
    Busy,  // transaction in progress.
}

/// Contains information about current stake and delegation.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct StakingInformation {
    pub staking_pool_account_id: AccountId,

    /// Whether there is a transaction in progress.
    pub status: TransactionStatus,

    /// Amount of token deposited from this account to staking 
    /// pool. NOTE: unstaked amount on staking pool might be 
    /// higher due to staking rewards.
    pub deposit_amount: WrappedBalance,
}

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingSchedule {
    /// vesting starts in nanoseconds
    pub start_timestamp: WrappedTimestamp, 

    /// In nanoseconds, when the FIRST PART of lockup tokens
    /// become vested. The remaining tokens will vest 
    /// continuously until they're fully vested. 
    pub cliff_timestamp: WrappedTimestamp,

    /// vesting ends in nanoseconds
    pub end_timestamp: WrappedTimestamp,
}


impl VestingSchedule {
    pub fn assert_valid(&self) {
      require!(
        self.start_timestamp.0 <= self.cliff_timestamp.0,
        "Cliff timestamp cannot be earlier than start timestamp."
      );

      require!(
        self.cliff_timestamp.0 <= self.end_timestamp.0,
        "Cliff timestamp cannot be later than end timestamp."
      );

      require!(
        self.start_timestamp.0 < self.end_timestamp.0,
        "Total vesting time should be positive."
      );
    }
}

/// Initialization argument type to define vesting schedule
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingScheduleOrHash {
    
    /// [deprecated] Only public schedule is used after transfers
    /// enabled. Vesting schedule is private, and this is the
    /// hash of (vesting_schedule, salt). In JSON, hash has to 
    /// be encoded with base64 to string. 
    VestingHash(Base64VecU8),

    /// Vesting schedule (public)
    VestingSchedule(VestingSchedule),
}

/// Contains information about vesting that contains vesting schedule
/// and termination information.
#[derive(
  Serialize, BorshDeserialize, BorshSerialize, 
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum VestingInformation {
    None,

    /// [deprecated] for private vesting. Hashed for privacy and only
    /// revealed if NEAR foundation terminate vesting. Assumes it
    /// doesn't affect lockup release and duration.
    VestingHash(Base64VecU8),

    /// Explicit vesting schedule
    VestingSchedule(VestingSchedule),

    /// Info about early termination, currently in progress. 
    /// Once unvested amount is transferred out, `VestingInformation`
    /// is removed.
    Terminating(TerminationInformation),
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Copy, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub enum TerminationStatus {
    
    /// Initial stage of termination in case deficit present
    /// on account. 
    VestingTerminatedWithDeficit,

    /// Transaction to unstake everything in progress.
    UnstakingInProgress,

    /// Unstaking from staking pool completed.
    EverythingUnstaked,

    /// Withdraw everything from staking pool, in progress.
    WithdrawingFromStakingPoolInProgress,

    /// Everything out of staking pool. Ready to withdraw 
    /// to wallet. (out of account)
    ReadyToWithdraw,

    /// Withdraw tokens from account (to wallet) in progress.
    WithdrawingFromAccountInProgress,
}

#[derive(
  BorshDeserialize, BorshSerialize, Deserialize, Serialize,
  PartialEq, Clone, Debug
)]
#[serde(crate = "near_sdk::serde")]
pub struct TerminationInformation {

    /// The amount of unvested token has to be transferred back
    /// to NEAR Foundation. These tokens are effectively locked
    /// and can't be transferred out and can't be restaked.
    pub unvested_amount: WrappedBalance,

    /// Status of withdrawal. When unvested amount is in progress
    /// of withdrawal, the status marked as busy, to avoid 
    /// withdrawing the funds twice. 
    pub status: TerminationStatus,
}

#[derive(BorshSerialize, Deserialize, Serialize, Clone, Debug)]
#[serde(crate = "near_sdk::serde")]
pub struct VestingScheduleWithSalt {
    pub vesting_schedule: VestingSchedule,

    /// salt to make hash unique.
    pub salt: Base64VecU8,
}


impl VestingScheduleWithSalt {
    pub fn hash(&self) -> Hash {
      env::sha256(
        &self.try_to_vec().expect("Failed to serialize")
      )
    }
}

Let's move on.