use {
crate::types::{ContractTier, OracleSource},
carbon_core::{
instruction::InstructionMetadata,
postgres::{
metadata::InstructionRowMetadata,
primitives::{U128, U16, U32, U64, U8},
},
},
};
#[derive(sqlx::FromRow, Debug, Clone)]
pub struct InitializePerpMarketRow {
#[sqlx(flatten)]
pub instruction_metadata: InstructionRowMetadata,
pub market_index: U16,
pub amm_base_asset_reserve: U128,
pub amm_quote_asset_reserve: U128,
pub amm_periodicity: i64,
pub amm_peg_multiplier: U128,
pub oracle_source: sqlx::types::Json<OracleSource>,
pub contract_tier: sqlx::types::Json<ContractTier>,
pub margin_ratio_initial: U32,
pub margin_ratio_maintenance: U32,
pub liquidator_fee: U32,
pub if_liquidation_fee: U32,
pub imf_factor: U32,
pub active_status: bool,
pub base_spread: U32,
pub max_spread: U32,
pub max_open_interest: U128,
pub max_revenue_withdraw_per_period: U64,
pub quote_max_insurance: U64,
pub order_step_size: U64,
pub order_tick_size: U64,
pub min_order_size: U64,
pub concentration_coef_scale: U128,
pub curve_update_intensity: U8,
pub amm_jit_intensity: U8,
pub name: Vec<u8>,
pub lp_pool_id: U8,
#[sqlx(rename = "__accounts")]
pub accounts: sqlx::types::Json<Vec<solana_instruction::AccountMeta>>,
}
impl InitializePerpMarketRow {
pub fn from_parts(
source: crate::instructions::initialize_perp_market::InitializePerpMarket,
metadata: InstructionMetadata,
accounts: Vec<solana_instruction::AccountMeta>,
) -> Self {
Self {
instruction_metadata: metadata.into(),
market_index: source.market_index.into(),
amm_base_asset_reserve: source.amm_base_asset_reserve.into(),
amm_quote_asset_reserve: source.amm_quote_asset_reserve.into(),
amm_periodicity: source.amm_periodicity,
amm_peg_multiplier: source.amm_peg_multiplier.into(),
oracle_source: sqlx::types::Json(source.oracle_source),
contract_tier: sqlx::types::Json(source.contract_tier),
margin_ratio_initial: source.margin_ratio_initial.into(),
margin_ratio_maintenance: source.margin_ratio_maintenance.into(),
liquidator_fee: source.liquidator_fee.into(),
if_liquidation_fee: source.if_liquidation_fee.into(),
imf_factor: source.imf_factor.into(),
active_status: source.active_status,
base_spread: source.base_spread.into(),
max_spread: source.max_spread.into(),
max_open_interest: source.max_open_interest.into(),
max_revenue_withdraw_per_period: source.max_revenue_withdraw_per_period.into(),
quote_max_insurance: source.quote_max_insurance.into(),
order_step_size: source.order_step_size.into(),
order_tick_size: source.order_tick_size.into(),
min_order_size: source.min_order_size.into(),
concentration_coef_scale: source.concentration_coef_scale.into(),
curve_update_intensity: source.curve_update_intensity.into(),
amm_jit_intensity: source.amm_jit_intensity.into(),
name: source.name.to_vec(),
lp_pool_id: source.lp_pool_id.into(),
accounts: sqlx::types::Json(accounts),
}
}
}
impl TryFrom<InitializePerpMarketRow>
for crate::instructions::initialize_perp_market::InitializePerpMarket
{
type Error = carbon_core::error::Error;
fn try_from(source: InitializePerpMarketRow) -> Result<Self, Self::Error> {
Ok(Self {
market_index: source.market_index.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
amm_base_asset_reserve: *source.amm_base_asset_reserve,
amm_quote_asset_reserve: *source.amm_quote_asset_reserve,
amm_periodicity: source.amm_periodicity,
amm_peg_multiplier: *source.amm_peg_multiplier,
oracle_source: source.oracle_source.0,
contract_tier: source.contract_tier.0,
margin_ratio_initial: source.margin_ratio_initial.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
margin_ratio_maintenance: source.margin_ratio_maintenance.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(),
)
})?,
imf_factor: source.imf_factor.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
active_status: source.active_status,
base_spread: source.base_spread.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
max_spread: source.max_spread.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
max_open_interest: *source.max_open_interest,
max_revenue_withdraw_per_period: *source.max_revenue_withdraw_per_period,
quote_max_insurance: *source.quote_max_insurance,
order_step_size: *source.order_step_size,
order_tick_size: *source.order_tick_size,
min_order_size: *source.min_order_size,
concentration_coef_scale: *source.concentration_coef_scale,
curve_update_intensity: source.curve_update_intensity.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
amm_jit_intensity: source.amm_jit_intensity.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
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(),
)
})?,
lp_pool_id: source.lp_pool_id.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
})
}
}
impl carbon_core::postgres::operations::Table
for crate::instructions::initialize_perp_market::InitializePerpMarket
{
fn table() -> &'static str {
"initialize_perp_market_instruction"
}
fn columns() -> Vec<&'static str> {
vec![
"__signature",
"__instruction_index",
"__stack_height",
"__slot",
"market_index",
"amm_base_asset_reserve",
"amm_quote_asset_reserve",
"amm_periodicity",
"amm_peg_multiplier",
"oracle_source",
"contract_tier",
"margin_ratio_initial",
"margin_ratio_maintenance",
"liquidator_fee",
"if_liquidation_fee",
"imf_factor",
"active_status",
"base_spread",
"max_spread",
"max_open_interest",
"max_revenue_withdraw_per_period",
"quote_max_insurance",
"order_step_size",
"order_tick_size",
"min_order_size",
"concentration_coef_scale",
"curve_update_intensity",
"amm_jit_intensity",
"name",
"lp_pool_id",
"__accounts",
]
}
}
#[async_trait::async_trait]
impl carbon_core::postgres::operations::Insert for InitializePerpMarketRow {
async fn insert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(r#"
INSERT INTO initialize_perp_market_instruction (
"market_index",
"amm_base_asset_reserve",
"amm_quote_asset_reserve",
"amm_periodicity",
"amm_peg_multiplier",
"oracle_source",
"contract_tier",
"margin_ratio_initial",
"margin_ratio_maintenance",
"liquidator_fee",
"if_liquidation_fee",
"imf_factor",
"active_status",
"base_spread",
"max_spread",
"max_open_interest",
"max_revenue_withdraw_per_period",
"quote_max_insurance",
"order_step_size",
"order_tick_size",
"min_order_size",
"concentration_coef_scale",
"curve_update_intensity",
"amm_jit_intensity",
"name",
"lp_pool_id",
__signature, __instruction_index, __stack_height, __slot, __accounts
) 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
)"#)
.bind(self.market_index)
.bind(&self.amm_base_asset_reserve)
.bind(&self.amm_quote_asset_reserve)
.bind(self.amm_periodicity)
.bind(&self.amm_peg_multiplier)
.bind(&self.oracle_source)
.bind(&self.contract_tier)
.bind(self.margin_ratio_initial)
.bind(self.margin_ratio_maintenance)
.bind(self.liquidator_fee)
.bind(self.if_liquidation_fee)
.bind(self.imf_factor)
.bind(self.active_status)
.bind(self.base_spread)
.bind(self.max_spread)
.bind(&self.max_open_interest)
.bind(&self.max_revenue_withdraw_per_period)
.bind(&self.quote_max_insurance)
.bind(&self.order_step_size)
.bind(&self.order_tick_size)
.bind(&self.min_order_size)
.bind(&self.concentration_coef_scale)
.bind(self.curve_update_intensity)
.bind(self.amm_jit_intensity)
.bind(&self.name)
.bind(self.lp_pool_id)
.bind(&self.instruction_metadata.signature)
.bind(self.instruction_metadata.instruction_index)
.bind(self.instruction_metadata.stack_height)
.bind(&self.instruction_metadata.slot)
.bind(&self.accounts)
.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 InitializePerpMarketRow {
async fn upsert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(r#"INSERT INTO initialize_perp_market_instruction (
"market_index",
"amm_base_asset_reserve",
"amm_quote_asset_reserve",
"amm_periodicity",
"amm_peg_multiplier",
"oracle_source",
"contract_tier",
"margin_ratio_initial",
"margin_ratio_maintenance",
"liquidator_fee",
"if_liquidation_fee",
"imf_factor",
"active_status",
"base_spread",
"max_spread",
"max_open_interest",
"max_revenue_withdraw_per_period",
"quote_max_insurance",
"order_step_size",
"order_tick_size",
"min_order_size",
"concentration_coef_scale",
"curve_update_intensity",
"amm_jit_intensity",
"name",
"lp_pool_id",
__signature, __instruction_index, __stack_height, __slot, __accounts
) 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
) ON CONFLICT (
__signature, __instruction_index, __stack_height
) DO UPDATE SET
"market_index" = EXCLUDED."market_index",
"amm_base_asset_reserve" = EXCLUDED."amm_base_asset_reserve",
"amm_quote_asset_reserve" = EXCLUDED."amm_quote_asset_reserve",
"amm_periodicity" = EXCLUDED."amm_periodicity",
"amm_peg_multiplier" = EXCLUDED."amm_peg_multiplier",
"oracle_source" = EXCLUDED."oracle_source",
"contract_tier" = EXCLUDED."contract_tier",
"margin_ratio_initial" = EXCLUDED."margin_ratio_initial",
"margin_ratio_maintenance" = EXCLUDED."margin_ratio_maintenance",
"liquidator_fee" = EXCLUDED."liquidator_fee",
"if_liquidation_fee" = EXCLUDED."if_liquidation_fee",
"imf_factor" = EXCLUDED."imf_factor",
"active_status" = EXCLUDED."active_status",
"base_spread" = EXCLUDED."base_spread",
"max_spread" = EXCLUDED."max_spread",
"max_open_interest" = EXCLUDED."max_open_interest",
"max_revenue_withdraw_per_period" = EXCLUDED."max_revenue_withdraw_per_period",
"quote_max_insurance" = EXCLUDED."quote_max_insurance",
"order_step_size" = EXCLUDED."order_step_size",
"order_tick_size" = EXCLUDED."order_tick_size",
"min_order_size" = EXCLUDED."min_order_size",
"concentration_coef_scale" = EXCLUDED."concentration_coef_scale",
"curve_update_intensity" = EXCLUDED."curve_update_intensity",
"amm_jit_intensity" = EXCLUDED."amm_jit_intensity",
"name" = EXCLUDED."name",
"lp_pool_id" = EXCLUDED."lp_pool_id",
__instruction_index = EXCLUDED.__instruction_index,
__stack_height = EXCLUDED.__stack_height,
__slot = EXCLUDED.__slot,
__accounts = EXCLUDED.__accounts
"#)
.bind(self.market_index)
.bind(&self.amm_base_asset_reserve)
.bind(&self.amm_quote_asset_reserve)
.bind(self.amm_periodicity)
.bind(&self.amm_peg_multiplier)
.bind(&self.oracle_source)
.bind(&self.contract_tier)
.bind(self.margin_ratio_initial)
.bind(self.margin_ratio_maintenance)
.bind(self.liquidator_fee)
.bind(self.if_liquidation_fee)
.bind(self.imf_factor)
.bind(self.active_status)
.bind(self.base_spread)
.bind(self.max_spread)
.bind(&self.max_open_interest)
.bind(&self.max_revenue_withdraw_per_period)
.bind(&self.quote_max_insurance)
.bind(&self.order_step_size)
.bind(&self.order_tick_size)
.bind(&self.min_order_size)
.bind(&self.concentration_coef_scale)
.bind(self.curve_update_intensity)
.bind(self.amm_jit_intensity)
.bind(&self.name)
.bind(self.lp_pool_id)
.bind(&self.instruction_metadata.signature)
.bind(self.instruction_metadata.instruction_index)
.bind(self.instruction_metadata.stack_height)
.bind(&self.instruction_metadata.slot)
.bind(&self.accounts)
.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 InitializePerpMarketRow {
type Key = (
String,
carbon_core::postgres::primitives::U32,
carbon_core::postgres::primitives::U32,
);
async fn delete(key: Self::Key, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(
r#"DELETE FROM initialize_perp_market_instruction WHERE
__signature = $1 AND __instruction_index = $2 AND __stack_height = $3
"#,
)
.bind(key.0)
.bind(key.1)
.bind(key.2)
.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 InitializePerpMarketRow {
type Key = (
String,
carbon_core::postgres::primitives::U32,
carbon_core::postgres::primitives::U32,
);
async fn lookup(
key: Self::Key,
pool: &sqlx::PgPool,
) -> carbon_core::error::CarbonResult<Option<Self>> {
let row = sqlx::query_as(
r#"SELECT * FROM initialize_perp_market_instruction WHERE
__signature = $1 AND __instruction_index = $2 AND __stack_height = $3
"#,
)
.bind(key.0)
.bind(key.1)
.bind(key.2)
.fetch_optional(pool)
.await
.map_err(|e| carbon_core::error::Error::Custom(e.to_string()))?;
Ok(row)
}
}
pub struct InitializePerpMarketMigrationOperation;
#[async_trait::async_trait]
impl sqlx_migrator::Operation<sqlx::Postgres> for InitializePerpMarketMigrationOperation {
async fn up(
&self,
connection: &mut sqlx::PgConnection,
) -> Result<(), sqlx_migrator::error::Error> {
sqlx::query(
r#"CREATE TABLE IF NOT EXISTS initialize_perp_market_instruction (
-- Instruction data
"market_index" INT4 NOT NULL,
"amm_base_asset_reserve" NUMERIC(39) NOT NULL,
"amm_quote_asset_reserve" NUMERIC(39) NOT NULL,
"amm_periodicity" INT8 NOT NULL,
"amm_peg_multiplier" NUMERIC(39) NOT NULL,
"oracle_source" JSONB NOT NULL,
"contract_tier" JSONB NOT NULL,
"margin_ratio_initial" INT8 NOT NULL,
"margin_ratio_maintenance" INT8 NOT NULL,
"liquidator_fee" INT8 NOT NULL,
"if_liquidation_fee" INT8 NOT NULL,
"imf_factor" INT8 NOT NULL,
"active_status" BOOLEAN NOT NULL,
"base_spread" INT8 NOT NULL,
"max_spread" INT8 NOT NULL,
"max_open_interest" NUMERIC(39) NOT NULL,
"max_revenue_withdraw_per_period" NUMERIC(20) NOT NULL,
"quote_max_insurance" NUMERIC(20) NOT NULL,
"order_step_size" NUMERIC(20) NOT NULL,
"order_tick_size" NUMERIC(20) NOT NULL,
"min_order_size" NUMERIC(20) NOT NULL,
"concentration_coef_scale" NUMERIC(39) NOT NULL,
"curve_update_intensity" INT2 NOT NULL,
"amm_jit_intensity" INT2 NOT NULL,
"name" BYTEA NOT NULL,
"lp_pool_id" INT2 NOT NULL,
-- Instruction metadata
__signature TEXT NOT NULL,
__instruction_index BIGINT NOT NULL,
__stack_height BIGINT NOT NULL,
__slot NUMERIC(20),
__accounts JSONB NOT NULL,
PRIMARY KEY (__signature, __instruction_index, __stack_height)
)"#,
)
.execute(connection)
.await?;
Ok(())
}
async fn down(
&self,
connection: &mut sqlx::PgConnection,
) -> Result<(), sqlx_migrator::error::Error> {
sqlx::query(r#"DROP TABLE IF EXISTS initialize_perp_market_instruction"#)
.execute(connection)
.await?;
Ok(())
}
}