use tape_rpc::Rpc;
use solana_program::program_pack::Pack;
use tape_api::state::Tape;
use tape_core::tape::{remaining_tape_epochs, tape_reservation_cost};
use tape_core::types::coin::{Coin, SOL, TAPE};
use tape_core::types::StorageUnits;
use tape_protocol::Api;
use crate::balance::{get_rent, rent_exempt_minimum};
use crate::error::TapedriveError;
use crate::tapedrive::Tapedrive;
pub const LAMPORTS_PER_SIGNATURE: u64 = 5_000;
const RESERVE_SIGNATURES: u64 = 2;
impl<Blockchain: Rpc, Cluster: Api> Tapedrive<Blockchain, Cluster> {
pub async fn estimate_cost(
&self,
capacity: StorageUnits,
epochs: u64,
) -> Result<Coin<TAPE>, TapedriveError> {
let archive = self.rpc().get_archive().await?;
reservation_cost(archive.storage_price, capacity, epochs)
}
pub async fn estimate_extend_expiry_cost(
&self,
tape: &Tape,
extra_epochs: u64,
) -> Result<Coin<TAPE>, TapedriveError> {
let archive = self.rpc().get_archive().await?;
reservation_cost(archive.storage_price, tape.capacity, extra_epochs)
}
pub async fn estimate_extend_capacity_cost(
&self,
tape: &Tape,
extra: StorageUnits,
) -> Result<Coin<TAPE>, TapedriveError> {
let system = self.rpc().get_system().await?;
let archive = self.rpc().get_archive().await?;
let epochs = remaining_tape_epochs(system.current_epoch, tape.active_epoch, tape.expiry_epoch)
.ok_or_else(|| TapedriveError::InvalidArgument("tape has expired".to_string()))?;
reservation_cost(archive.storage_price, extra, epochs)
}
pub async fn estimate_reserve_lamports(&self) -> Result<Coin<SOL>, TapedriveError> {
let rent = get_rent(self.rpc()).await?;
let tape_rent = rent_exempt_minimum(&rent, Tape::get_size())?;
let token_rent = rent_exempt_minimum(&rent, spl_token::state::Account::LEN)?;
Ok(SOL(tape_rent.lamports() + token_rent.lamports() + RESERVE_SIGNATURES * LAMPORTS_PER_SIGNATURE))
}
}
pub fn reservation_cost(
price_per_unit: Coin<TAPE>,
capacity: StorageUnits,
epochs: u64,
) -> Result<Coin<TAPE>, TapedriveError> {
tape_reservation_cost(price_per_unit, capacity, epochs)
.ok_or_else(|| TapedriveError::InvalidArgument("tape reservation cost overflow".to_string()))
}