1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use anchor_lang::prelude::*;
use crate::{orderbook::state::OrderTag, FixedTermErrorCode};
/// A `ClaimTicket` represents a claim of tickets that have been staked with the program
/// This account is generated by the `StakeTickets` program instruction
#[account]
#[derive(Debug)]
pub struct ClaimTicket {
/// The account registered as owner of this claim
pub owner: Pubkey,
/// The `TicketManager` this claim ticket was established under
/// Determines the asset this ticket will be redeemed for
pub market: Pubkey,
/// The slot after which this claim can be redeemed for the underlying value
pub maturation_timestamp: i64,
/// The number of tokens this claim is redeemable for
pub redeemable: u64,
}
/// A split ticket represents a claim of underlying tokens as the result of a lending action.
///
/// The split ticket is generated when a user places a matched order with the `auto_stake` flag set to true.
/// By taking the difference between the matched base and quote quantities, the split ticket assigns principal and
/// interest values.
#[account]
#[derive(Debug)]
pub struct SplitTicket {
/// The account registered as owner of this claim
pub owner: Pubkey,
/// The `TicketManager` this claim ticket was established under
/// Determines the asset this ticket will be redeemed for
pub market: Pubkey,
/// The `OrderTag` associated with the creation of this struct
pub order_tag: OrderTag,
/// The time slot during which the ticket was struck
pub struck_timestamp: i64,
/// The slot after which this claim can be redeemed for the underlying value
pub maturation_timestamp: i64,
/// The total number of principal tokens the ticket was struck for
pub principal: u64,
/// The total number of interest tokens struck for this ticket
/// same underlying asset as the principal token
pub interest: u64,
}
impl SplitTicket {
pub fn make_seeds<'a>(user: &'a [u8], bytes: &'a [u8]) -> [&'a [u8]; 3] {
[crate::seeds::SPLIT_TICKET, user, bytes]
}
}
/// Enum used for pattern matching a ticket deserialization
pub(crate) enum TicketKind<'info> {
Claim(Account<'info, ClaimTicket>),
Split(Account<'info, SplitTicket>),
}
/// Deserializes an ambiguous `AccountInfo` into the correct `TicketKind`
pub(crate) fn deserialize_ticket(info: AccountInfo) -> Result<TicketKind> {
if let Ok(ticket) = Account::<ClaimTicket>::try_from(&info) {
return Ok(TicketKind::Claim(ticket));
} else if let Ok(ticket) = Account::<SplitTicket>::try_from(&info) {
return Ok(TicketKind::Split(ticket));
}
err!(FixedTermErrorCode::FailedToDeserializeTicket)
}
make_verification!(ClaimTicket);
make_verification!(SplitTicket);
macro_rules! make_verification {
($ticket:ty) => {
impl $ticket {
/// Verify ticket ownership, takes owner and manager pubkeys
pub fn verify_owner_manager(&self, owner: &Pubkey, market: &Pubkey) -> Result<()> {
if self.owner != *owner {
return err!(FixedTermErrorCode::DoesNotOwnTicket);
}
if self.market != *market {
return err!(FixedTermErrorCode::TicketNotFromManager);
}
Ok(())
}
/// Verify ticket ownership, takes owner pubkey
pub fn verify_owner(&self, owner: &Pubkey) -> Result<()> {
if self.owner != *owner {
return err!(FixedTermErrorCode::DoesNotOwnTicket);
}
Ok(())
}
}
};
}
pub(crate) use make_verification;