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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// Copyright (C) 2022 JET PROTOCOL HOLDINGS, LLC.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use anchor_lang::prelude::*;
use bytemuck::Contiguous;
use crate::ErrorCode;
/// Description of the token's usage
#[derive(AnchorSerialize, AnchorDeserialize, Contiguous, Eq, PartialEq, Clone, Copy, Debug)]
#[repr(u32)]
pub enum TokenKind {
/// The token can be used as collateral
Collateral = 1,
/// The token represents a debt that needs to be repaid
Claim,
/// The token balance is managed by a trusted adapter to represent the amount of collateral
/// custodied by that adapter. The token account is owned by the adapter. Collateral
/// is accessed through instructions to the adapter.
AdapterCollateral,
}
impl Default for TokenKind {
fn default() -> TokenKind {
Self::Collateral
}
}
impl From<jet_metadata::TokenKind> for TokenKind {
fn from(kind: jet_metadata::TokenKind) -> Self {
match kind {
jet_metadata::TokenKind::NonCollateral => Self::Collateral,
jet_metadata::TokenKind::Collateral => Self::Collateral,
jet_metadata::TokenKind::Claim => Self::Claim,
jet_metadata::TokenKind::AdapterCollateral => Self::AdapterCollateral,
}
}
}
/// The configuration account specifying parameters for a token when used
/// in a position within a margin account.
#[account]
#[derive(Debug, Eq, PartialEq)]
pub struct TokenConfig {
/// The mint for the token
pub mint: Pubkey,
/// The mint for the underlying token represented, if any
pub underlying_mint: Pubkey,
/// The space this config is valid within
pub airspace: Pubkey,
/// The administrator of this token, which has the authority to provide information
/// about (e.g. prices) and otherwise modify position states for these tokens.
pub admin: TokenAdmin,
/// Description of this token
///
/// This determines the way the margin program values a token as a position in a
/// margin account.
pub token_kind: TokenKind,
/// A modifier to adjust the token value, based on the kind of token
pub value_modifier: u16,
/// The maximum staleness (seconds) that's acceptable for balances of this token
pub max_staleness: u64,
}
impl TokenConfig {
pub const SPACE: usize = 8 + 2 + std::mem::size_of::<Self>();
pub fn validate(&self) -> Result<()> {
if self.underlying_mint == Pubkey::default() {
msg!("the underlying mint must be set");
return err!(ErrorCode::InvalidConfig);
}
Ok(())
}
pub fn adapter_program(&self) -> Option<Pubkey> {
match self.admin {
TokenAdmin::Adapter(address) => Some(address),
_ => None,
}
}
pub fn oracle(&self) -> Option<TokenOracle> {
match self.admin {
TokenAdmin::Margin { oracle } => Some(oracle),
_ => None,
}
}
}
/// Information about where to find the oracle data for a token
#[derive(AnchorSerialize, AnchorDeserialize, Debug, Eq, PartialEq, Clone, Copy)]
pub enum TokenOracle {
Pyth {
/// The pyth address containing price information for a token.
price: Pubkey,
/// The pyth address with product information for a token
product: Pubkey,
},
}
/// Description of which program administers a token
#[derive(AnchorSerialize, AnchorDeserialize, Debug, Eq, PartialEq, Clone, Copy)]
pub enum TokenAdmin {
/// This margin program administers the token directly
Margin {
/// An oracle that can be used to collect price information for a token
oracle: TokenOracle,
},
/// The token is administered by the given adapter program
///
/// The adapter is responsible for providing price information for the token.
Adapter(Pubkey),
}
/// Configuration for allowed liquidators
#[account]
#[derive(Default, Debug, Eq, PartialEq)]
pub struct LiquidatorConfig {
/// The airspace this liquidator is being configured to act within
pub airspace: Pubkey,
/// The address of the liquidator allowed to act
pub liquidator: Pubkey,
}
impl LiquidatorConfig {
pub const SPACE: usize = 8 + std::mem::size_of::<Self>();
}
/// Configuration for allowed adapters
#[account]
#[derive(Default, Debug, Eq, PartialEq)]
pub struct AdapterConfig {
/// The airspace this adapter can be used in
pub airspace: Pubkey,
/// The program address allowed to be called as an adapter
pub adapter_program: Pubkey,
}
impl AdapterConfig {
pub const SPACE: usize = 8 + std::mem::size_of::<Self>();
}