use carbon_core::{
account::AccountMetadata,
postgres::{
metadata::AccountRowMetadata,
primitives::{Pubkey, U16, U64, U8},
},
};
#[derive(sqlx::FromRow, Debug, Clone)]
pub struct ConfigRow {
#[sqlx(flatten)]
pub account_metadata: AccountRowMetadata,
pub is_paused: bool,
pub authority: Pubkey,
pub pending_authority: Pubkey,
pub operators: Vec<Pubkey>,
pub protocol_fee_recipient: Pubkey,
pub token_distributor: Pubkey,
pub virtual_sol_reserves: U64,
pub virtual_token_reserves: U64,
pub graduation_target: U64,
pub graduation_fee: U64,
pub damping_term: U8,
pub token_for_stakers_basis_points: U16,
pub swap_fee_basis_points: U8,
pub token_amount_for_raydium_liquidity: U64,
pub max_graduation_price_deviation_basis_points: U16,
pub max_swap_amount_for_pool_price_correction_basis_points: U16,
}
impl ConfigRow {
pub fn from_parts(source: crate::accounts::config::Config, metadata: AccountMetadata) -> Self {
Self {
account_metadata: metadata.into(),
is_paused: source.is_paused,
authority: source.authority.into(),
pending_authority: source.pending_authority.into(),
operators: source
.operators
.into_iter()
.map(|element| element.into())
.collect(),
protocol_fee_recipient: source.protocol_fee_recipient.into(),
token_distributor: source.token_distributor.into(),
virtual_sol_reserves: source.virtual_sol_reserves.into(),
virtual_token_reserves: source.virtual_token_reserves.into(),
graduation_target: source.graduation_target.into(),
graduation_fee: source.graduation_fee.into(),
damping_term: source.damping_term.into(),
token_for_stakers_basis_points: source.token_for_stakers_basis_points.into(),
swap_fee_basis_points: source.swap_fee_basis_points.into(),
token_amount_for_raydium_liquidity: source.token_amount_for_raydium_liquidity.into(),
max_graduation_price_deviation_basis_points: source
.max_graduation_price_deviation_basis_points
.into(),
max_swap_amount_for_pool_price_correction_basis_points: source
.max_swap_amount_for_pool_price_correction_basis_points
.into(),
}
}
}
impl TryFrom<ConfigRow> for crate::accounts::config::Config {
type Error = carbon_core::error::Error;
fn try_from(source: ConfigRow) -> Result<Self, Self::Error> {
Ok(Self {
is_paused: source.is_paused,
authority: *source.authority,
pending_authority: *source.pending_authority,
operators: source
.operators
.into_iter()
.map(|element| *element)
.collect(),
protocol_fee_recipient: *source.protocol_fee_recipient,
token_distributor: *source.token_distributor,
virtual_sol_reserves: *source.virtual_sol_reserves,
virtual_token_reserves: *source.virtual_token_reserves,
graduation_target: *source.graduation_target,
graduation_fee: *source.graduation_fee,
damping_term: source.damping_term.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
token_for_stakers_basis_points: source
.token_for_stakers_basis_points
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
swap_fee_basis_points: source.swap_fee_basis_points.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
token_amount_for_raydium_liquidity: *source.token_amount_for_raydium_liquidity,
max_graduation_price_deviation_basis_points: source
.max_graduation_price_deviation_basis_points
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
max_swap_amount_for_pool_price_correction_basis_points: source
.max_swap_amount_for_pool_price_correction_basis_points
.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::accounts::config::Config {
fn table() -> &'static str {
"config_account"
}
fn columns() -> Vec<&'static str> {
vec![
"__pubkey",
"__slot",
"is_paused",
"authority",
"pending_authority",
"operators",
"protocol_fee_recipient",
"token_distributor",
"virtual_sol_reserves",
"virtual_token_reserves",
"graduation_target",
"graduation_fee",
"damping_term",
"token_for_stakers_basis_points",
"swap_fee_basis_points",
"token_amount_for_raydium_liquidity",
"max_graduation_price_deviation_basis_points",
"max_swap_amount_for_pool_price_correction_basis_points",
]
}
}
#[async_trait::async_trait]
impl carbon_core::postgres::operations::Insert for ConfigRow {
async fn insert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(
r#"
INSERT INTO config_account (
"is_paused",
"authority",
"pending_authority",
"operators",
"protocol_fee_recipient",
"token_distributor",
"virtual_sol_reserves",
"virtual_token_reserves",
"graduation_target",
"graduation_fee",
"damping_term",
"token_for_stakers_basis_points",
"swap_fee_basis_points",
"token_amount_for_raydium_liquidity",
"max_graduation_price_deviation_basis_points",
"max_swap_amount_for_pool_price_correction_basis_points",
__pubkey, __slot
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18
)"#,
)
.bind(self.is_paused)
.bind(self.authority)
.bind(self.pending_authority)
.bind(&self.operators)
.bind(self.protocol_fee_recipient)
.bind(self.token_distributor)
.bind(&self.virtual_sol_reserves)
.bind(&self.virtual_token_reserves)
.bind(&self.graduation_target)
.bind(&self.graduation_fee)
.bind(self.damping_term)
.bind(self.token_for_stakers_basis_points)
.bind(self.swap_fee_basis_points)
.bind(&self.token_amount_for_raydium_liquidity)
.bind(self.max_graduation_price_deviation_basis_points)
.bind(self.max_swap_amount_for_pool_price_correction_basis_points)
.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 ConfigRow {
async fn upsert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(r#"INSERT INTO config_account (
"is_paused",
"authority",
"pending_authority",
"operators",
"protocol_fee_recipient",
"token_distributor",
"virtual_sol_reserves",
"virtual_token_reserves",
"graduation_target",
"graduation_fee",
"damping_term",
"token_for_stakers_basis_points",
"swap_fee_basis_points",
"token_amount_for_raydium_liquidity",
"max_graduation_price_deviation_basis_points",
"max_swap_amount_for_pool_price_correction_basis_points",
__pubkey, __slot
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18
) ON CONFLICT (
__pubkey
) DO UPDATE SET
"is_paused" = EXCLUDED."is_paused",
"authority" = EXCLUDED."authority",
"pending_authority" = EXCLUDED."pending_authority",
"operators" = EXCLUDED."operators",
"protocol_fee_recipient" = EXCLUDED."protocol_fee_recipient",
"token_distributor" = EXCLUDED."token_distributor",
"virtual_sol_reserves" = EXCLUDED."virtual_sol_reserves",
"virtual_token_reserves" = EXCLUDED."virtual_token_reserves",
"graduation_target" = EXCLUDED."graduation_target",
"graduation_fee" = EXCLUDED."graduation_fee",
"damping_term" = EXCLUDED."damping_term",
"token_for_stakers_basis_points" = EXCLUDED."token_for_stakers_basis_points",
"swap_fee_basis_points" = EXCLUDED."swap_fee_basis_points",
"token_amount_for_raydium_liquidity" = EXCLUDED."token_amount_for_raydium_liquidity",
"max_graduation_price_deviation_basis_points" = EXCLUDED."max_graduation_price_deviation_basis_points",
"max_swap_amount_for_pool_price_correction_basis_points" = EXCLUDED."max_swap_amount_for_pool_price_correction_basis_points",
__slot = EXCLUDED.__slot
"#)
.bind(self.is_paused)
.bind(self.authority)
.bind(self.pending_authority)
.bind(&self.operators)
.bind(self.protocol_fee_recipient)
.bind(self.token_distributor)
.bind(&self.virtual_sol_reserves)
.bind(&self.virtual_token_reserves)
.bind(&self.graduation_target)
.bind(&self.graduation_fee)
.bind(self.damping_term)
.bind(self.token_for_stakers_basis_points)
.bind(self.swap_fee_basis_points)
.bind(&self.token_amount_for_raydium_liquidity)
.bind(self.max_graduation_price_deviation_basis_points)
.bind(self.max_swap_amount_for_pool_price_correction_basis_points)
.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 ConfigRow {
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 config_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 ConfigRow {
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 config_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 ConfigMigrationOperation;
#[async_trait::async_trait]
impl sqlx_migrator::Operation<sqlx::Postgres> for ConfigMigrationOperation {
async fn up(
&self,
connection: &mut sqlx::PgConnection,
) -> Result<(), sqlx_migrator::error::Error> {
sqlx::query(
r#"CREATE TABLE IF NOT EXISTS config_account (
-- Account data
"is_paused" BOOLEAN NOT NULL,
"authority" BYTEA NOT NULL,
"pending_authority" BYTEA NOT NULL,
"operators" BYTEA[] NOT NULL,
"protocol_fee_recipient" BYTEA NOT NULL,
"token_distributor" BYTEA NOT NULL,
"virtual_sol_reserves" NUMERIC(20) NOT NULL,
"virtual_token_reserves" NUMERIC(20) NOT NULL,
"graduation_target" NUMERIC(20) NOT NULL,
"graduation_fee" NUMERIC(20) NOT NULL,
"damping_term" INT2 NOT NULL,
"token_for_stakers_basis_points" INT4 NOT NULL,
"swap_fee_basis_points" INT2 NOT NULL,
"token_amount_for_raydium_liquidity" NUMERIC(20) NOT NULL,
"max_graduation_price_deviation_basis_points" INT4 NOT NULL,
"max_swap_amount_for_pool_price_correction_basis_points" INT4 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 config_account"#)
.execute(connection)
.await?;
Ok(())
}
}