use carbon_core::{
account::AccountMetadata,
postgres::{
metadata::AccountRowMetadata,
primitives::{Pubkey, U16, U32, U64, U8},
},
};
#[derive(sqlx::FromRow, Debug, Clone)]
pub struct MinimalSpotMarketRow {
#[sqlx(flatten)]
pub account_metadata: AccountRowMetadata,
pub pubkey: Pubkey,
pub oracle: Pubkey,
pub mint: Pubkey,
pub vault: Pubkey,
pub padding1: sqlx::types::Json<Vec<Vec<U64>>>,
pub padding2: Vec<u8>,
pub deposit_balance: Vec<u8>,
pub borrow_balance: Vec<u8>,
pub cumulative_deposit_interest: Vec<u8>,
pub cumulative_borrow_interest: Vec<u8>,
pub padding3: Vec<U64>,
pub last_interest_ts: U64,
pub padding4: Vec<U64>,
pub decimals: U32,
pub market_index: U16,
pub padding5: Vec<U16>,
pub padding6: Vec<u8>,
pub pool_id: U8,
pub padding7: Vec<U64>,
}
impl MinimalSpotMarketRow {
pub fn from_parts(
source: crate::accounts::minimal_spot_market::MinimalSpotMarket,
metadata: AccountMetadata,
) -> Self {
Self {
account_metadata: metadata.into(),
pubkey: source.pubkey.into(),
oracle: source.oracle.into(),
mint: source.mint.into(),
vault: source.vault.into(),
padding1: sqlx::types::Json(
source
.padding1
.into_iter()
.map(|element| element.into_iter().map(|element| element.into()).collect())
.collect(),
),
padding2: source.padding2.to_vec(),
deposit_balance: source.deposit_balance.to_vec(),
borrow_balance: source.borrow_balance.to_vec(),
cumulative_deposit_interest: source.cumulative_deposit_interest.to_vec(),
cumulative_borrow_interest: source.cumulative_borrow_interest.to_vec(),
padding3: source
.padding3
.into_iter()
.map(|element| element.into())
.collect(),
last_interest_ts: source.last_interest_ts.into(),
padding4: source
.padding4
.into_iter()
.map(|element| element.into())
.collect(),
decimals: source.decimals.into(),
market_index: source.market_index.into(),
padding5: source
.padding5
.into_iter()
.map(|element| element.into())
.collect(),
padding6: source.padding6.to_vec(),
pool_id: source.pool_id.into(),
padding7: source
.padding7
.into_iter()
.map(|element| element.into())
.collect(),
}
}
}
impl TryFrom<MinimalSpotMarketRow> for crate::accounts::minimal_spot_market::MinimalSpotMarket {
type Error = carbon_core::error::Error;
fn try_from(source: MinimalSpotMarketRow) -> Result<Self, Self::Error> {
Ok(Self {
pubkey: *source.pubkey,
oracle: *source.oracle,
mint: *source.mint,
vault: *source.vault,
padding1: source
.padding1
.0
.into_iter()
.map(|element| {
element
.into_iter()
.map(|element| Ok(*element))
.collect::<Result<Vec<_>, carbon_core::error::Error>>()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to collect array elements".to_string(),
)
})?
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert array element to primitive".to_string(),
)
})
})
.collect::<Result<Vec<_>, carbon_core::error::Error>>()?
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})?,
padding2: source.padding2.as_slice().try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 8 bytes"
.to_string(),
)
})?,
deposit_balance: source.deposit_balance.as_slice().try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 16 bytes"
.to_string(),
)
})?,
borrow_balance: source.borrow_balance.as_slice().try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 16 bytes"
.to_string(),
)
})?,
cumulative_deposit_interest: source
.cumulative_deposit_interest
.as_slice()
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 16 bytes"
.to_string(),
)
})?,
cumulative_borrow_interest: source
.cumulative_borrow_interest
.as_slice()
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 16 bytes"
.to_string(),
)
})?,
padding3: source
.padding3
.into_iter()
.map(|element| Ok(*element))
.collect::<Result<Vec<_>, carbon_core::error::Error>>()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to collect array elements".to_string(),
)
})?
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert array element to primitive".to_string(),
)
})?,
last_interest_ts: *source.last_interest_ts,
padding4: source
.padding4
.into_iter()
.map(|element| Ok(*element))
.collect::<Result<Vec<_>, carbon_core::error::Error>>()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to collect array elements".to_string(),
)
})?
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert array element to 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(),
)
})?,
padding5: source
.padding5
.into_iter()
.map(|element| {
element.try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert value from postgres primitive".to_string(),
)
})
})
.collect::<Result<Vec<_>, carbon_core::error::Error>>()?
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert array element to primitive".to_string(),
)
})?,
padding6: source.padding6.as_slice().try_into().map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert padding from postgres primitive: expected 1 bytes"
.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(),
)
})?,
padding7: source
.padding7
.into_iter()
.map(|element| Ok(*element))
.collect::<Result<Vec<_>, carbon_core::error::Error>>()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to collect array elements".to_string(),
)
})?
.try_into()
.map_err(|_| {
carbon_core::error::Error::Custom(
"Failed to convert array element to primitive".to_string(),
)
})?,
})
}
}
impl carbon_core::postgres::operations::Table
for crate::accounts::minimal_spot_market::MinimalSpotMarket
{
fn table() -> &'static str {
"minimal_spot_market_account"
}
fn columns() -> Vec<&'static str> {
vec![
"__pubkey",
"__slot",
"pubkey",
"oracle",
"mint",
"vault",
"padding1",
"padding2",
"deposit_balance",
"borrow_balance",
"cumulative_deposit_interest",
"cumulative_borrow_interest",
"padding3",
"last_interest_ts",
"padding4",
"decimals",
"market_index",
"padding5",
"padding6",
"pool_id",
"padding7",
]
}
}
#[async_trait::async_trait]
impl carbon_core::postgres::operations::Insert for MinimalSpotMarketRow {
async fn insert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(r#"
INSERT INTO minimal_spot_market_account (
"pubkey",
"oracle",
"mint",
"vault",
"padding1",
"padding2",
"deposit_balance",
"borrow_balance",
"cumulative_deposit_interest",
"cumulative_borrow_interest",
"padding3",
"last_interest_ts",
"padding4",
"decimals",
"market_index",
"padding5",
"padding6",
"pool_id",
"padding7",
__pubkey, __slot
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21
)"#)
.bind(self.pubkey)
.bind(self.oracle)
.bind(self.mint)
.bind(self.vault)
.bind(&self.padding1)
.bind(&self.padding2)
.bind(&self.deposit_balance)
.bind(&self.borrow_balance)
.bind(&self.cumulative_deposit_interest)
.bind(&self.cumulative_borrow_interest)
.bind(&self.padding3)
.bind(&self.last_interest_ts)
.bind(&self.padding4)
.bind(self.decimals)
.bind(self.market_index)
.bind(&self.padding5)
.bind(&self.padding6)
.bind(self.pool_id)
.bind(&self.padding7)
.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 MinimalSpotMarketRow {
async fn upsert(&self, pool: &sqlx::PgPool) -> carbon_core::error::CarbonResult<()> {
sqlx::query(r#"INSERT INTO minimal_spot_market_account (
"pubkey",
"oracle",
"mint",
"vault",
"padding1",
"padding2",
"deposit_balance",
"borrow_balance",
"cumulative_deposit_interest",
"cumulative_borrow_interest",
"padding3",
"last_interest_ts",
"padding4",
"decimals",
"market_index",
"padding5",
"padding6",
"pool_id",
"padding7",
__pubkey, __slot
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21
) ON CONFLICT (
__pubkey
) DO UPDATE SET
"pubkey" = EXCLUDED."pubkey",
"oracle" = EXCLUDED."oracle",
"mint" = EXCLUDED."mint",
"vault" = EXCLUDED."vault",
"padding1" = EXCLUDED."padding1",
"padding2" = EXCLUDED."padding2",
"deposit_balance" = EXCLUDED."deposit_balance",
"borrow_balance" = EXCLUDED."borrow_balance",
"cumulative_deposit_interest" = EXCLUDED."cumulative_deposit_interest",
"cumulative_borrow_interest" = EXCLUDED."cumulative_borrow_interest",
"padding3" = EXCLUDED."padding3",
"last_interest_ts" = EXCLUDED."last_interest_ts",
"padding4" = EXCLUDED."padding4",
"decimals" = EXCLUDED."decimals",
"market_index" = EXCLUDED."market_index",
"padding5" = EXCLUDED."padding5",
"padding6" = EXCLUDED."padding6",
"pool_id" = EXCLUDED."pool_id",
"padding7" = EXCLUDED."padding7",
__slot = EXCLUDED.__slot
"#)
.bind(self.pubkey)
.bind(self.oracle)
.bind(self.mint)
.bind(self.vault)
.bind(&self.padding1)
.bind(&self.padding2)
.bind(&self.deposit_balance)
.bind(&self.borrow_balance)
.bind(&self.cumulative_deposit_interest)
.bind(&self.cumulative_borrow_interest)
.bind(&self.padding3)
.bind(&self.last_interest_ts)
.bind(&self.padding4)
.bind(self.decimals)
.bind(self.market_index)
.bind(&self.padding5)
.bind(&self.padding6)
.bind(self.pool_id)
.bind(&self.padding7)
.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 MinimalSpotMarketRow {
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 minimal_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 MinimalSpotMarketRow {
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 minimal_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 MinimalSpotMarketMigrationOperation;
#[async_trait::async_trait]
impl sqlx_migrator::Operation<sqlx::Postgres> for MinimalSpotMarketMigrationOperation {
async fn up(
&self,
connection: &mut sqlx::PgConnection,
) -> Result<(), sqlx_migrator::error::Error> {
sqlx::query(
r#"CREATE TABLE IF NOT EXISTS minimal_spot_market_account (
-- Account data
"pubkey" BYTEA NOT NULL,
"oracle" BYTEA NOT NULL,
"mint" BYTEA NOT NULL,
"vault" BYTEA NOT NULL,
"padding1" JSONB NOT NULL,
"padding2" BYTEA NOT NULL,
"deposit_balance" BYTEA NOT NULL,
"borrow_balance" BYTEA NOT NULL,
"cumulative_deposit_interest" BYTEA NOT NULL,
"cumulative_borrow_interest" BYTEA NOT NULL,
"padding3" NUMERIC(20)[] NOT NULL,
"last_interest_ts" NUMERIC(20) NOT NULL,
"padding4" NUMERIC(20)[] NOT NULL,
"decimals" INT8 NOT NULL,
"market_index" INT4 NOT NULL,
"padding5" INT4[] NOT NULL,
"padding6" BYTEA NOT NULL,
"pool_id" INT2 NOT NULL,
"padding7" NUMERIC(20)[] 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 minimal_spot_market_account"#)
.execute(connection)
.await?;
Ok(())
}
}