use {
crate::types::{
AssetTier, HistoricalIndexData, HistoricalOracleData, InsuranceFund, MarketStatus,
OracleSource, PoolBalance,
},
carbon_core::{
account::AccountMetadata,
postgres::{
metadata::AccountRowMetadata,
primitives::{Pubkey, U128, U16, U32, U64, U8},
},
},
};
#[derive(sqlx::FromRow, Debug, Clone)]
pub struct SpotMarketRow {
#[sqlx(flatten)]
pub account_metadata: AccountRowMetadata,
pub pubkey: Pubkey,
pub oracle: Pubkey,
pub mint: Pubkey,
pub vault: Pubkey,
pub name: Vec<u8>,
pub historical_oracle_data: sqlx::types::Json<HistoricalOracleData>,
pub historical_index_data: sqlx::types::Json<HistoricalIndexData>,
pub revenue_pool: sqlx::types::Json<PoolBalance>,
pub spot_fee_pool: sqlx::types::Json<PoolBalance>,
pub insurance_fund: sqlx::types::Json<InsuranceFund>,
pub total_spot_fee: U128,
pub deposit_balance: U128,
pub borrow_balance: U128,
pub cumulative_deposit_interest: U128,
pub cumulative_borrow_interest: U128,
pub total_social_loss: U128,
pub total_quote_social_loss: U128,
pub withdraw_guard_threshold: U64,
pub max_token_deposits: U64,
pub deposit_token_twap: U64,
pub borrow_token_twap: U64,
pub utilization_twap: U64,
pub last_interest_ts: U64,
pub last_twap_ts: U64,
pub expiry_ts: i64,
pub order_step_size: U64,
pub order_tick_size: U64,
pub min_order_size: U64,
pub max_position_size: U64,
pub next_fill_record_id: U64,
pub next_deposit_record_id: U64,
pub initial_asset_weight: U32,
pub maintenance_asset_weight: U32,
pub initial_liability_weight: U32,
pub maintenance_liability_weight: U32,
pub imf_factor: U32,
pub liquidator_fee: U32,
pub if_liquidation_fee: U32,
pub optimal_utilization: U32,
pub optimal_borrow_rate: U32,
pub max_borrow_rate: U32,
pub decimals: U32,
pub market_index: U16,
pub orders_enabled: bool,
pub oracle_source: sqlx::types::Json<OracleSource>,
pub status: sqlx::types::Json<MarketStatus>,
pub asset_tier: sqlx::types::Json<AssetTier>,
pub paused_operations: U8,
pub if_paused_operations: U8,
pub fee_adjustment: i16,
pub max_token_borrows_fraction: U16,
pub flash_loan_amount: U64,
pub flash_loan_initial_token_amount: U64,
pub total_swap_fee: U64,
pub scale_initial_asset_weight_start: U64,
pub min_borrow_rate: U8,
pub fuel_boost_deposits: U8,
pub fuel_boost_borrows: U8,
pub fuel_boost_taker: U8,
pub fuel_boost_maker: U8,
pub fuel_boost_insurance: U8,
pub token_program_flag: U8,
pub pool_id: U8,
pub padding: Vec<u8>,
}
impl SpotMarketRow {
pub fn from_parts(
source: crate::accounts::spot_market::SpotMarket,
metadata: AccountMetadata,
) -> Self {
Self {
account_metadata: metadata.into(),
pubkey: source.pubkey.into(),
oracle: source.oracle.into(),
mint: source.mint.into(),
vault: source.vault.into(),
name: source.name.to_vec(),
historical_oracle_data: sqlx::types::Json(source.historical_oracle_data),
historical_index_data: sqlx::types::Json(source.historical_index_data),
revenue_pool: sqlx::types::Json(source.revenue_pool),
spot_fee_pool: sqlx::types::Json(source.spot_fee_pool),
insurance_fund: sqlx::types::Json(source.insurance_fund),
total_spot_fee: source.total_spot_fee.into(),
deposit_balance: source.deposit_balance.into(),
borrow_balance: source.borrow_balance.into(),
cumulative_deposit_interest: source.cumulative_deposit_interest.into(),
cumulative_borrow_interest: source.cumulative_borrow_interest.into(),
total_social_loss: source.total_social_loss.into(),
total_quote_social_loss: source.total_quote_social_loss.into(),
withdraw_guard_threshold: source.withdraw_guard_threshold.into(),
max_token_deposits: source.max_token_deposits.into(),
deposit_token_twap: source.deposit_token_twap.into(),
borrow_token_twap: source.borrow_token_twap.into(),
utilization_twap: source.utilization_twap.into(),
last_interest_ts: source.last_interest_ts.into(),
last_twap_ts: source.last_twap_ts.into(),
expiry_ts: source.expiry_ts,
order_step_size: source.order_step_size.into(),
order_tick_size: source.order_tick_size.into(),
min_order_size: source.min_order_size.into(),
max_position_size: source.max_position_size.into(),
next_fill_record_id: source.next_fill_record_id.into(),
next_deposit_record_id: source.next_deposit_record_id.into(),
initial_asset_weight: source.initial_asset_weight.into(),
maintenance_asset_weight: source.maintenance_asset_weight.into(),
initial_liability_weight: source.initial_liability_weight.into(),
maintenance_liability_weight: source.maintenance_liability_weight.into(),
imf_factor: source.imf_factor.into(),
liquidator_fee: source.liquidator_fee.into(),
if_liquidation_fee: source.if_liquidation_fee.into(),
optimal_utilization: source.optimal_utilization.into(),
optimal_borrow_rate: source.optimal_borrow_rate.into(),
max_borrow_rate: source.max_borrow_rate.into(),
decimals: source.decimals.into(),
market_index: source.market_index.into(),
orders_enabled: source.orders_enabled,
oracle_source: sqlx::types::Json(source.oracle_source),
status: sqlx::types::Json(source.status),
asset_tier: sqlx::types::Json(source.asset_tier),
paused_operations: source.paused_operations.into(),
if_paused_operations: source.if_paused_operations.into(),
fee_adjustment: source.fee_adjustment,
max_token_borrows_fraction: source.max_token_borrows_fraction.into(),
flash_loan_amount: source.flash_loan_amount.into(),
flash_loan_initial_token_amount: source.flash_loan_initial_token_amount.into(),
total_swap_fee: source.total_swap_fee.into(),
scale_initial_asset_weight_start: source.scale_initial_asset_weight_start.into(),
min_borrow_rate: source.min_borrow_rate.into(),
fuel_boost_deposits: source.fuel_boost_deposits.into(),
fuel_boost_borrows: source.fuel_boost_borrows.into(),
fuel_boost_taker: source.fuel_boost_taker.into(),
fuel_boost_maker: source.fuel_boost_maker.into(),
fuel_boost_insurance: source.fuel_boost_insurance.into(),
token_program_flag: source.token_program_flag.into(),
pool_id: source.pool_id.into(),
padding: source.padding.to_vec(),
}
}
}
impl TryFrom<SpotMarketRow> for crate::accounts::spot_market::SpotMarket {
type Error = carbon_core::error::Error;
fn try_from(source: SpotMarketRow) -> Result<Self, Self::Error> {
Ok(Self {
pubkey: *source.pubkey,
oracle: *source.oracle,
mint: *source.mint,
vault: *source.vault,
name: source.name.as_slice().try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 32 bytes"
.to_string(),
)
})?,
historical_oracle_data: source.historical_oracle_data.0,
historical_index_data: source.historical_index_data.0,
revenue_pool: source.revenue_pool.0,
spot_fee_pool: source.spot_fee_pool.0,
insurance_fund: source.insurance_fund.0,
total_spot_fee: *source.total_spot_fee,
deposit_balance: *source.deposit_balance,
borrow_balance: *source.borrow_balance,
cumulative_deposit_interest: *source.cumulative_deposit_interest,
cumulative_borrow_interest: *source.cumulative_borrow_interest,
total_social_loss: *source.total_social_loss,
total_quote_social_loss: *source.total_quote_social_loss,
withdraw_guard_threshold: *source.withdraw_guard_threshold,
max_token_deposits: *source.max_token_deposits,
deposit_token_twap: *source.deposit_token_twap,
borrow_token_twap: *source.borrow_token_twap,
utilization_twap: *source.utilization_twap,
last_interest_ts: *source.last_interest_ts,
last_twap_ts: *source.last_twap_ts,
expiry_ts: source.expiry_ts,
order_step_size: *source.order_step_size,
order_tick_size: *source.order_tick_size,
min_order_size: *source.min_order_size,
max_position_size: *source.max_position_size,
next_fill_record_id: *source.next_fill_record_id,
next_deposit_record_id: *source.next_deposit_record_id,
initial_asset_weight: source.initial_asset_weight.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
maintenance_asset_weight: source.maintenance_asset_weight.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
initial_liability_weight: source.initial_liability_weight.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
maintenance_liability_weight: source.maintenance_liability_weight.try_into().map_err(
|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
},
)?,
imf_factor: source.imf_factor.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
liquidator_fee: source.liquidator_fee.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
if_liquidation_fee: source.if_liquidation_fee.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
optimal_utilization: source.optimal_utilization.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
optimal_borrow_rate: source.optimal_borrow_rate.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
max_borrow_rate: source.max_borrow_rate.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
decimals: source.decimals.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
market_index: source.market_index.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
orders_enabled: source.orders_enabled,
oracle_source: source.oracle_source.0,
status: source.status.0,
asset_tier: source.asset_tier.0,
paused_operations: source.paused_operations.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
if_paused_operations: source.if_paused_operations.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
fee_adjustment: source.fee_adjustment,
max_token_borrows_fraction: source.max_token_borrows_fraction.try_into().map_err(
|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
},
)?,
flash_loan_amount: *source.flash_loan_amount,
flash_loan_initial_token_amount: *source.flash_loan_initial_token_amount,
total_swap_fee: *source.total_swap_fee,
scale_initial_asset_weight_start: *source.scale_initial_asset_weight_start,
min_borrow_rate: source.min_borrow_rate.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
fuel_boost_deposits: source.fuel_boost_deposits.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
fuel_boost_borrows: source.fuel_boost_borrows.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
fuel_boost_taker: source.fuel_boost_taker.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
fuel_boost_maker: source.fuel_boost_maker.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
fuel_boost_insurance: source.fuel_boost_insurance.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
token_program_flag: source.token_program_flag.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
pool_id: source.pool_id.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
padding: source.padding.as_slice().try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 40 bytes"
.to_string(),
)
})?,
})
}
}
impl carbon_core::postgres::operations::Table for crate::accounts::spot_market::SpotMarket {
fn table() -> &'static str {
"spot_market_account"
}
fn columns() -> Vec<&'static str> {
vec![
"__pubkey",
"__slot",
"pubkey",
"oracle",
"mint",
"vault",
"name",
"historical_oracle_data",
"historical_index_data",
"revenue_pool",
"spot_fee_pool",
"insurance_fund",
"total_spot_fee",
"deposit_balance",
"borrow_balance",
"cumulative_deposit_interest",
"cumulative_borrow_interest",
"total_social_loss",
"total_quote_social_loss",
"withdraw_guard_threshold",
"max_token_deposits",
"deposit_token_twap",
"borrow_token_twap",
"utilization_twap",
"last_interest_ts",
"last_twap_ts",
"expiry_ts",
"order_step_size",
"order_tick_size",
"min_order_size",
"max_position_size",
"next_fill_record_id",
"next_deposit_record_id",
"initial_asset_weight",
"maintenance_asset_weight",
"initial_liability_weight",
"maintenance_liability_weight",
"imf_factor",
"liquidator_fee",
"if_liquidation_fee",
"optimal_utilization",
"optimal_borrow_rate",
"max_borrow_rate",
"decimals",
"market_index",
"orders_enabled",
"oracle_source",
"status",
"asset_tier",
"paused_operations",
"if_paused_operations",
"fee_adjustment",
"max_token_borrows_fraction",
"flash_loan_amount",
"flash_loan_initial_token_amount",
"total_swap_fee",
"scale_initial_asset_weight_start",
"min_borrow_rate",
"fuel_boost_deposits",
"fuel_boost_borrows",
"fuel_boost_taker",
"fuel_boost_maker",
"fuel_boost_insurance",
"token_program_flag",
"pool_id",
"padding",
]
}
}
#[async_trait::async_trait]
impl carbon_core::postgres::operations::Insert for SpotMarketRow {
async fn insert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(r#"
INSERT INTO spot_market_account (
"pubkey",
"oracle",
"mint",
"vault",
"name",
"historical_oracle_data",
"historical_index_data",
"revenue_pool",
"spot_fee_pool",
"insurance_fund",
"total_spot_fee",
"deposit_balance",
"borrow_balance",
"cumulative_deposit_interest",
"cumulative_borrow_interest",
"total_social_loss",
"total_quote_social_loss",
"withdraw_guard_threshold",
"max_token_deposits",
"deposit_token_twap",
"borrow_token_twap",
"utilization_twap",
"last_interest_ts",
"last_twap_ts",
"expiry_ts",
"order_step_size",
"order_tick_size",
"min_order_size",
"max_position_size",
"next_fill_record_id",
"next_deposit_record_id",
"initial_asset_weight",
"maintenance_asset_weight",
"initial_liability_weight",
"maintenance_liability_weight",
"imf_factor",
"liquidator_fee",
"if_liquidation_fee",
"optimal_utilization",
"optimal_borrow_rate",
"max_borrow_rate",
"decimals",
"market_index",
"orders_enabled",
"oracle_source",
"status",
"asset_tier",
"paused_operations",
"if_paused_operations",
"fee_adjustment",
"max_token_borrows_fraction",
"flash_loan_amount",
"flash_loan_initial_token_amount",
"total_swap_fee",
"scale_initial_asset_weight_start",
"min_borrow_rate",
"fuel_boost_deposits",
"fuel_boost_borrows",
"fuel_boost_taker",
"fuel_boost_maker",
"fuel_boost_insurance",
"token_program_flag",
"pool_id",
"padding",
__pubkey, __slot
) VALUES (
$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
)"#)
.bind(self.pubkey)
.bind(self.oracle)
.bind(self.mint)
.bind(self.vault)
.bind(&self.name)
.bind(&self.historical_oracle_data)
.bind(&self.historical_index_data)
.bind(&self.revenue_pool)
.bind(&self.spot_fee_pool)
.bind(&self.insurance_fund)
.bind(&self.total_spot_fee)
.bind(&self.deposit_balance)
.bind(&self.borrow_balance)
.bind(&self.cumulative_deposit_interest)
.bind(&self.cumulative_borrow_interest)
.bind(&self.total_social_loss)
.bind(&self.total_quote_social_loss)
.bind(&self.withdraw_guard_threshold)
.bind(&self.max_token_deposits)
.bind(&self.deposit_token_twap)
.bind(&self.borrow_token_twap)
.bind(&self.utilization_twap)
.bind(&self.last_interest_ts)
.bind(&self.last_twap_ts)
.bind(self.expiry_ts)
.bind(&self.order_step_size)
.bind(&self.order_tick_size)
.bind(&self.min_order_size)
.bind(&self.max_position_size)
.bind(&self.next_fill_record_id)
.bind(&self.next_deposit_record_id)
.bind(self.initial_asset_weight)
.bind(self.maintenance_asset_weight)
.bind(self.initial_liability_weight)
.bind(self.maintenance_liability_weight)
.bind(self.imf_factor)
.bind(self.liquidator_fee)
.bind(self.if_liquidation_fee)
.bind(self.optimal_utilization)
.bind(self.optimal_borrow_rate)
.bind(self.max_borrow_rate)
.bind(self.decimals)
.bind(self.market_index)
.bind(self.orders_enabled)
.bind(&self.oracle_source)
.bind(&self.status)
.bind(&self.asset_tier)
.bind(self.paused_operations)
.bind(self.if_paused_operations)
.bind(self.fee_adjustment)
.bind(self.max_token_borrows_fraction)
.bind(&self.flash_loan_amount)
.bind(&self.flash_loan_initial_token_amount)
.bind(&self.total_swap_fee)
.bind(&self.scale_initial_asset_weight_start)
.bind(self.min_borrow_rate)
.bind(self.fuel_boost_deposits)
.bind(self.fuel_boost_borrows)
.bind(self.fuel_boost_taker)
.bind(self.fuel_boost_maker)
.bind(self.fuel_boost_insurance)
.bind(self.token_program_flag)
.bind(self.pool_id)
.bind(&self.padding)
.bind(self.account_metadata.pubkey)
.bind(&self.account_metadata.slot)
.execute(pool).await
.map_err(|e| carbon_core::error::Error::Custom(e.to_string()))?;
Ok(())
}
}
#[async_trait::async_trait]
impl carbon_core::postgres::operations::Upsert for SpotMarketRow {
async fn upsert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(r#"INSERT INTO spot_market_account (
"pubkey",
"oracle",
"mint",
"vault",
"name",
"historical_oracle_data",
"historical_index_data",
"revenue_pool",
"spot_fee_pool",
"insurance_fund",
"total_spot_fee",
"deposit_balance",
"borrow_balance",
"cumulative_deposit_interest",
"cumulative_borrow_interest",
"total_social_loss",
"total_quote_social_loss",
"withdraw_guard_threshold",
"max_token_deposits",
"deposit_token_twap",
"borrow_token_twap",
"utilization_twap",
"last_interest_ts",
"last_twap_ts",
"expiry_ts",
"order_step_size",
"order_tick_size",
"min_order_size",
"max_position_size",
"next_fill_record_id",
"next_deposit_record_id",
"initial_asset_weight",
"maintenance_asset_weight",
"initial_liability_weight",
"maintenance_liability_weight",
"imf_factor",
"liquidator_fee",
"if_liquidation_fee",
"optimal_utilization",
"optimal_borrow_rate",
"max_borrow_rate",
"decimals",
"market_index",
"orders_enabled",
"oracle_source",
"status",
"asset_tier",
"paused_operations",
"if_paused_operations",
"fee_adjustment",
"max_token_borrows_fraction",
"flash_loan_amount",
"flash_loan_initial_token_amount",
"total_swap_fee",
"scale_initial_asset_weight_start",
"min_borrow_rate",
"fuel_boost_deposits",
"fuel_boost_borrows",
"fuel_boost_taker",
"fuel_boost_maker",
"fuel_boost_insurance",
"token_program_flag",
"pool_id",
"padding",
__pubkey, __slot
) VALUES (
$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
) ON CONFLICT (
__pubkey
) DO UPDATE SET
"pubkey" = EXCLUDED."pubkey",
"oracle" = EXCLUDED."oracle",
"mint" = EXCLUDED."mint",
"vault" = EXCLUDED."vault",
"name" = EXCLUDED."name",
"historical_oracle_data" = EXCLUDED."historical_oracle_data",
"historical_index_data" = EXCLUDED."historical_index_data",
"revenue_pool" = EXCLUDED."revenue_pool",
"spot_fee_pool" = EXCLUDED."spot_fee_pool",
"insurance_fund" = EXCLUDED."insurance_fund",
"total_spot_fee" = EXCLUDED."total_spot_fee",
"deposit_balance" = EXCLUDED."deposit_balance",
"borrow_balance" = EXCLUDED."borrow_balance",
"cumulative_deposit_interest" = EXCLUDED."cumulative_deposit_interest",
"cumulative_borrow_interest" = EXCLUDED."cumulative_borrow_interest",
"total_social_loss" = EXCLUDED."total_social_loss",
"total_quote_social_loss" = EXCLUDED."total_quote_social_loss",
"withdraw_guard_threshold" = EXCLUDED."withdraw_guard_threshold",
"max_token_deposits" = EXCLUDED."max_token_deposits",
"deposit_token_twap" = EXCLUDED."deposit_token_twap",
"borrow_token_twap" = EXCLUDED."borrow_token_twap",
"utilization_twap" = EXCLUDED."utilization_twap",
"last_interest_ts" = EXCLUDED."last_interest_ts",
"last_twap_ts" = EXCLUDED."last_twap_ts",
"expiry_ts" = EXCLUDED."expiry_ts",
"order_step_size" = EXCLUDED."order_step_size",
"order_tick_size" = EXCLUDED."order_tick_size",
"min_order_size" = EXCLUDED."min_order_size",
"max_position_size" = EXCLUDED."max_position_size",
"next_fill_record_id" = EXCLUDED."next_fill_record_id",
"next_deposit_record_id" = EXCLUDED."next_deposit_record_id",
"initial_asset_weight" = EXCLUDED."initial_asset_weight",
"maintenance_asset_weight" = EXCLUDED."maintenance_asset_weight",
"initial_liability_weight" = EXCLUDED."initial_liability_weight",
"maintenance_liability_weight" = EXCLUDED."maintenance_liability_weight",
"imf_factor" = EXCLUDED."imf_factor",
"liquidator_fee" = EXCLUDED."liquidator_fee",
"if_liquidation_fee" = EXCLUDED."if_liquidation_fee",
"optimal_utilization" = EXCLUDED."optimal_utilization",
"optimal_borrow_rate" = EXCLUDED."optimal_borrow_rate",
"max_borrow_rate" = EXCLUDED."max_borrow_rate",
"decimals" = EXCLUDED."decimals",
"market_index" = EXCLUDED."market_index",
"orders_enabled" = EXCLUDED."orders_enabled",
"oracle_source" = EXCLUDED."oracle_source",
"status" = EXCLUDED."status",
"asset_tier" = EXCLUDED."asset_tier",
"paused_operations" = EXCLUDED."paused_operations",
"if_paused_operations" = EXCLUDED."if_paused_operations",
"fee_adjustment" = EXCLUDED."fee_adjustment",
"max_token_borrows_fraction" = EXCLUDED."max_token_borrows_fraction",
"flash_loan_amount" = EXCLUDED."flash_loan_amount",
"flash_loan_initial_token_amount" = EXCLUDED."flash_loan_initial_token_amount",
"total_swap_fee" = EXCLUDED."total_swap_fee",
"scale_initial_asset_weight_start" = EXCLUDED."scale_initial_asset_weight_start",
"min_borrow_rate" = EXCLUDED."min_borrow_rate",
"fuel_boost_deposits" = EXCLUDED."fuel_boost_deposits",
"fuel_boost_borrows" = EXCLUDED."fuel_boost_borrows",
"fuel_boost_taker" = EXCLUDED."fuel_boost_taker",
"fuel_boost_maker" = EXCLUDED."fuel_boost_maker",
"fuel_boost_insurance" = EXCLUDED."fuel_boost_insurance",
"token_program_flag" = EXCLUDED."token_program_flag",
"pool_id" = EXCLUDED."pool_id",
"padding" = EXCLUDED."padding",
__slot = EXCLUDED.__slot
"#)
.bind(self.pubkey)
.bind(self.oracle)
.bind(self.mint)
.bind(self.vault)
.bind(&self.name)
.bind(&self.historical_oracle_data)
.bind(&self.historical_index_data)
.bind(&self.revenue_pool)
.bind(&self.spot_fee_pool)
.bind(&self.insurance_fund)
.bind(&self.total_spot_fee)
.bind(&self.deposit_balance)
.bind(&self.borrow_balance)
.bind(&self.cumulative_deposit_interest)
.bind(&self.cumulative_borrow_interest)
.bind(&self.total_social_loss)
.bind(&self.total_quote_social_loss)
.bind(&self.withdraw_guard_threshold)
.bind(&self.max_token_deposits)
.bind(&self.deposit_token_twap)
.bind(&self.borrow_token_twap)
.bind(&self.utilization_twap)
.bind(&self.last_interest_ts)
.bind(&self.last_twap_ts)
.bind(self.expiry_ts)
.bind(&self.order_step_size)
.bind(&self.order_tick_size)
.bind(&self.min_order_size)
.bind(&self.max_position_size)
.bind(&self.next_fill_record_id)
.bind(&self.next_deposit_record_id)
.bind(self.initial_asset_weight)
.bind(self.maintenance_asset_weight)
.bind(self.initial_liability_weight)
.bind(self.maintenance_liability_weight)
.bind(self.imf_factor)
.bind(self.liquidator_fee)
.bind(self.if_liquidation_fee)
.bind(self.optimal_utilization)
.bind(self.optimal_borrow_rate)
.bind(self.max_borrow_rate)
.bind(self.decimals)
.bind(self.market_index)
.bind(self.orders_enabled)
.bind(&self.oracle_source)
.bind(&self.status)
.bind(&self.asset_tier)
.bind(self.paused_operations)
.bind(self.if_paused_operations)
.bind(self.fee_adjustment)
.bind(self.max_token_borrows_fraction)
.bind(&self.flash_loan_amount)
.bind(&self.flash_loan_initial_token_amount)
.bind(&self.total_swap_fee)
.bind(&self.scale_initial_asset_weight_start)
.bind(self.min_borrow_rate)
.bind(self.fuel_boost_deposits)
.bind(self.fuel_boost_borrows)
.bind(self.fuel_boost_taker)
.bind(self.fuel_boost_maker)
.bind(self.fuel_boost_insurance)
.bind(self.token_program_flag)
.bind(self.pool_id)
.bind(&self.padding)
.bind(self.account_metadata.pubkey)
.bind(&self.account_metadata.slot)
.execute(pool).await
.map_err(|e| carbon_core::error::Error::Custom(e.to_string()))?;
Ok(())
}
}
#[async_trait::async_trait]
impl carbon_core::postgres::operations::Delete for SpotMarketRow {
type Key = carbon_core::postgres::primitives::Pubkey;
async fn delete(key: Self::Key, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(
r#"DELETE FROM spot_market_account WHERE
__pubkey = $1
"#,
)
.bind(key)
.execute(pool)
.await
.map_err(|e| carbon_core::error::Error::Custom(e.to_string()))?;
Ok(())
}
}
#[async_trait::async_trait]
impl carbon_core::postgres::operations::Lookup for SpotMarketRow {
type Key = carbon_core::postgres::primitives::Pubkey;
async fn lookup(
key: Self::Key,
pool: &sqlx::PgPool,
) -> carbon_core::error::CarbonResult<Option<Self>> {
let row = sqlx::query_as(
r#"SELECT * FROM spot_market_account WHERE
__pubkey = $1
"#,
)
.bind(key)
.fetch_optional(pool)
.await
.map_err(|e| carbon_core::error::Error::Custom(e.to_string()))?;
Ok(row)
}
}
pub struct SpotMarketMigrationOperation;
#[async_trait::async_trait]
impl sqlx_migrator::Operation<sqlx::Postgres> for SpotMarketMigrationOperation {
async fn up(
&self,
connection: &mut sqlx::PgConnection,
) -> Result<(), sqlx_migrator::error::Error> {
sqlx::query(
r#"CREATE TABLE IF NOT EXISTS spot_market_account (
-- Account data
"pubkey" BYTEA NOT NULL,
"oracle" BYTEA NOT NULL,
"mint" BYTEA NOT NULL,
"vault" BYTEA NOT NULL,
"name" BYTEA NOT NULL,
"historical_oracle_data" JSONB NOT NULL,
"historical_index_data" JSONB NOT NULL,
"revenue_pool" JSONB NOT NULL,
"spot_fee_pool" JSONB NOT NULL,
"insurance_fund" JSONB NOT NULL,
"total_spot_fee" NUMERIC(39) NOT NULL,
"deposit_balance" NUMERIC(39) NOT NULL,
"borrow_balance" NUMERIC(39) NOT NULL,
"cumulative_deposit_interest" NUMERIC(39) NOT NULL,
"cumulative_borrow_interest" NUMERIC(39) NOT NULL,
"total_social_loss" NUMERIC(39) NOT NULL,
"total_quote_social_loss" NUMERIC(39) NOT NULL,
"withdraw_guard_threshold" NUMERIC(20) NOT NULL,
"max_token_deposits" NUMERIC(20) NOT NULL,
"deposit_token_twap" NUMERIC(20) NOT NULL,
"borrow_token_twap" NUMERIC(20) NOT NULL,
"utilization_twap" NUMERIC(20) NOT NULL,
"last_interest_ts" NUMERIC(20) NOT NULL,
"last_twap_ts" NUMERIC(20) NOT NULL,
"expiry_ts" INT8 NOT NULL,
"order_step_size" NUMERIC(20) NOT NULL,
"order_tick_size" NUMERIC(20) NOT NULL,
"min_order_size" NUMERIC(20) NOT NULL,
"max_position_size" NUMERIC(20) NOT NULL,
"next_fill_record_id" NUMERIC(20) NOT NULL,
"next_deposit_record_id" NUMERIC(20) NOT NULL,
"initial_asset_weight" INT8 NOT NULL,
"maintenance_asset_weight" INT8 NOT NULL,
"initial_liability_weight" INT8 NOT NULL,
"maintenance_liability_weight" INT8 NOT NULL,
"imf_factor" INT8 NOT NULL,
"liquidator_fee" INT8 NOT NULL,
"if_liquidation_fee" INT8 NOT NULL,
"optimal_utilization" INT8 NOT NULL,
"optimal_borrow_rate" INT8 NOT NULL,
"max_borrow_rate" INT8 NOT NULL,
"decimals" INT8 NOT NULL,
"market_index" INT4 NOT NULL,
"orders_enabled" BOOLEAN NOT NULL,
"oracle_source" JSONB NOT NULL,
"status" JSONB NOT NULL,
"asset_tier" JSONB NOT NULL,
"paused_operations" INT2 NOT NULL,
"if_paused_operations" INT2 NOT NULL,
"fee_adjustment" INT2 NOT NULL,
"max_token_borrows_fraction" INT4 NOT NULL,
"flash_loan_amount" NUMERIC(20) NOT NULL,
"flash_loan_initial_token_amount" NUMERIC(20) NOT NULL,
"total_swap_fee" NUMERIC(20) NOT NULL,
"scale_initial_asset_weight_start" NUMERIC(20) NOT NULL,
"min_borrow_rate" INT2 NOT NULL,
"fuel_boost_deposits" INT2 NOT NULL,
"fuel_boost_borrows" INT2 NOT NULL,
"fuel_boost_taker" INT2 NOT NULL,
"fuel_boost_maker" INT2 NOT NULL,
"fuel_boost_insurance" INT2 NOT NULL,
"token_program_flag" INT2 NOT NULL,
"pool_id" INT2 NOT NULL,
"padding" BYTEA NOT NULL,
-- Account metadata
__pubkey BYTEA NOT NULL,
__slot NUMERIC(20),
PRIMARY KEY (__pubkey)
)"#,
)
.execute(connection)
.await?;
Ok(())
}
async fn down(
&self,
connection: &mut sqlx::PgConnection,
) -> Result<(), sqlx_migrator::error::Error> {
sqlx::query(r#"DROP TABLE IF EXISTS spot_market_account"#)
.execute(connection)
.await?;
Ok(())
}
}