diff --git a/Cargo.lock b/Cargo.lock index f24dead..78ff428 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1734,8 +1734,8 @@ dependencies = [ [[package]] name = "holaplex-hub-core" -version = "0.5.1" -source = "git+https://github.com/holaplex/hub-core?branch=master#f436cb38795adec5963f8e6b2eb3b5b1ebbca2cd" +version = "0.5.3" +source = "git+https://github.com/holaplex/hub-core?branch=stable#40a8dfab0dbf2d01b0eda61ff1ce831e1ea4a10b" dependencies = [ "anyhow", "async-trait", @@ -1773,26 +1773,7 @@ dependencies = [ [[package]] name = "holaplex-hub-core-build" version = "0.2.1" -source = "git+https://github.com/holaplex/hub-core?branch=master#f436cb38795adec5963f8e6b2eb3b5b1ebbca2cd" -dependencies = [ - "anyhow", - "dotenv", - "futures-util", - "hex", - "prost-build", - "reqwest", - "serde", - "sha2 0.10.7", - "tempfile", - "tokio", - "toml 0.5.11", - "url", -] - -[[package]] -name = "holaplex-hub-core-build" -version = "0.2.1" -source = "git+https://github.com/holaplex/hub-core?branch=stable#711b8a0c9a1056490dff05acadf5a2b354612f01" +source = "git+https://github.com/holaplex/hub-core?branch=stable#40a8dfab0dbf2d01b0eda61ff1ce831e1ea4a10b" dependencies = [ "anyhow", "dotenv", @@ -1811,7 +1792,7 @@ dependencies = [ [[package]] name = "holaplex-hub-core-macros" version = "0.1.0" -source = "git+https://github.com/holaplex/hub-core?branch=master#f436cb38795adec5963f8e6b2eb3b5b1ebbca2cd" +source = "git+https://github.com/holaplex/hub-core?branch=stable#40a8dfab0dbf2d01b0eda61ff1ce831e1ea4a10b" dependencies = [ "proc-macro2", "quote", @@ -1821,10 +1802,10 @@ dependencies = [ [[package]] name = "holaplex-hub-core-schemas" -version = "0.3.1" -source = "git+https://github.com/holaplex/hub-core?branch=master#f436cb38795adec5963f8e6b2eb3b5b1ebbca2cd" +version = "0.3.2" +source = "git+https://github.com/holaplex/hub-core?branch=stable#40a8dfab0dbf2d01b0eda61ff1ce831e1ea4a10b" dependencies = [ - "holaplex-hub-core-build 0.2.1 (git+https://github.com/holaplex/hub-core?branch=master)", + "holaplex-hub-core-build", "prost", ] @@ -1836,7 +1817,7 @@ dependencies = [ "async-graphql-poem", "async-trait", "holaplex-hub-core", - "holaplex-hub-core-build 0.2.1 (git+https://github.com/holaplex/hub-core?branch=stable)", + "holaplex-hub-core-build", "poem", "prost", "prost-types", diff --git a/api/Cargo.toml b/api/Cargo.toml index 38fcaac..95c168f 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -42,9 +42,9 @@ strum = { version = "0.24.1", features = ["derive"] } [dependencies.hub-core] package = "holaplex-hub-core" -version = "0.5.1" +version = "0.5.3" git = "https://github.com/holaplex/hub-core" -branch = "master" +branch = "stable" features = ["kafka", "credits", "asset_proxy", "sea-orm"] [build-dependencies.hub-core-build] diff --git a/api/src/events.rs b/api/src/events.rs index 4de4978..f0484f3 100644 --- a/api/src/events.rs +++ b/api/src/events.rs @@ -1,9 +1,10 @@ use hub_core::{ - chrono::{DateTime, NaiveDateTime, Utc}, + chrono::{DateTime, NaiveDateTime, Offset, Utc}, credits::{CreditsClient, TransactionId}, prelude::*, producer::Producer, - uuid::Uuid, + thiserror, + uuid::{self, Uuid}, }; use sea_orm::{ sea_query::{Expr, SimpleExpr}, @@ -41,6 +42,68 @@ use crate::{ Actions, Services, }; +#[derive(Debug, thiserror::Error, Triage)] +pub enum ProcessorErrorKind { + #[error("Invalid timestamp in event payload")] + InvalidTimestamp, + #[error("Invalid blockchain in event payload")] + InvalidBlockchain, + #[error("Invalid transaction status in event payload")] + InvalidTransactionStatus, + #[error("No collection metadata found in event payload")] + MissingCollectionMetadata, + #[error("No credit deduction ID found in event payload")] + MissingDeductionId, + #[error("No associated collection found in database")] + DbMissingCollection, + #[error("No associated collection mint found in database")] + DbMissingCollectionMint, + #[error("No associated drop found in database")] + DbMissingDrop, + #[error("No associated mint history found in database")] + DbMissingMintHistory, + #[error("No associated transfer charge found in database")] + DbMissingTransferCharge, + #[error("No associated update history found in database")] + DbMissingUpdateHistory, + + #[error("Database record contains no deduction ID")] + RecordMissingDeductionId, + + #[error("Invalid basis point value for seller fee")] + #[permanent] + InvalidSellerFee(#[source] std::num::TryFromIntError), + #[error("Invalid percent value for creator share")] + #[permanent] + InvalidCreatorShare(#[source] std::num::TryFromIntError), + #[error("Invalid UUID")] + InvalidUuid(#[from] uuid::Error), + #[error("Database error")] + DbError(#[from] sea_orm::DbErr), + #[error("Error sending message")] + SendError(#[from] hub_core::producer::SendError), + #[error("Error handling credit deduction")] + Credits(#[from] hub_core::credits::DeductionError), +} + +#[derive(Debug, thiserror::Error, Triage)] +#[error("Error handling event")] +pub struct ProcessorError { + #[source] + kind: ProcessorErrorKind, + // TODO +} + +impl ProcessorError { + #[inline] + fn new(kind: ProcessorErrorKind) -> Self { + Self { kind } + } +} + +pub type ProcessResult = std::result::Result; +pub type Result = std::result::Result; + #[derive(Clone)] pub struct Processor { pub db: Connection, @@ -215,6 +278,7 @@ impl Processor { None | Some(_) => Ok(()), }, } + .map_err(ProcessorError::new) } async fn index_collection( @@ -223,7 +287,7 @@ impl Processor { project_id: String, created_by: String, payload: SolanaCollectionPayload, - ) -> Result<()> { + ) -> ProcessResult<()> { let SolanaCollectionPayload { supply, mint_address, @@ -234,8 +298,6 @@ impl Processor { .. } = payload; - let metadata = metadata.context("no collection metadata found")?; - let Metadata { name, description, @@ -243,7 +305,7 @@ impl Processor { attributes, uri, image, - } = metadata; + } = metadata.ok_or(ProcessorErrorKind::MissingCollectionMetadata)?; let collection_am = collections::ActiveModel { id: Set(Uuid::from_str(&id)?), @@ -255,7 +317,9 @@ impl Processor { total_mints: Set(0), address: Set(Some(mint_address)), signature: Set(None), - seller_fee_basis_points: Set(seller_fee_basis_points.try_into()?), + seller_fee_basis_points: Set(seller_fee_basis_points + .try_into() + .map_err(ProcessorErrorKind::InvalidSellerFee)?), created_by: Set(created_by.parse()?), created_at: Set(Utc::now().into()), }; @@ -280,7 +344,10 @@ impl Processor { collection_id: Set(id.parse()?), address: Set(creator.address), verified: Set(creator.verified), - share: Set(creator.share.try_into()?), + share: Set(creator + .share + .try_into() + .map_err(ProcessorErrorKind::InvalidCreatorShare)?), }; collection_creator.insert(self.db.get()).await?; } @@ -295,7 +362,7 @@ impl Processor { id: String, created_by: String, payload: SolanaMintPayload, - ) -> Result<()> { + ) -> ProcessResult<()> { let SolanaMintPayload { collection_id, mint_address, @@ -308,8 +375,6 @@ impl Processor { .. } = payload; - let metadata = metadata.context("no collection metadata found")?; - let Metadata { name, description, @@ -317,7 +382,7 @@ impl Processor { attributes, uri, image, - } = metadata; + } = metadata.ok_or(ProcessorErrorKind::MissingCollectionMetadata)?; let mint_am = collection_mints::ActiveModel { id: Set(id.parse()?), @@ -329,7 +394,9 @@ impl Processor { created_at: Set(Utc::now().into()), signature: Set(None), edition: Set(-1), - seller_fee_basis_points: Set(seller_fee_basis_points.try_into()?), + seller_fee_basis_points: Set(seller_fee_basis_points + .try_into() + .map_err(ProcessorErrorKind::InvalidSellerFee)?), credits_deduction_id: Set(None), compressed: Set(compressed), }; @@ -355,7 +422,10 @@ impl Processor { collection_mint_id: Set(mint_model.id), address: Set(creator.address), verified: Set(creator.verified), - share: Set(creator.share.try_into()?), + share: Set(creator + .share + .try_into() + .map_err(ProcessorErrorKind::InvalidCreatorShare)?), }; mint_creator_am.insert(self.db.get()).await?; } @@ -377,15 +447,18 @@ impl Processor { Ok(()) } - async fn update_mint_owner(&self, id: String, payload: MintOwnershipUpdate) -> Result<()> { + async fn update_mint_owner( + &self, + id: String, + payload: MintOwnershipUpdate, + ) -> ProcessResult<()> { let id = Uuid::from_str(&id)?; let db = self.db.get(); let mint = CollectionMints::find_by_id(id) .one(db) - .await - .context("failed to load mint from db")? - .context("mint not found in db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingCollectionMint)?; let mut mint_am: collection_mints::ActiveModel = mint.into(); mint_am.owner = Set(payload.recipient.clone()); @@ -404,7 +477,10 @@ impl Processor { nft_transfer.insert(db).await?; Ok(()) } - async fn update_polygon_mints_owner(&self, payload: MintedTokensOwnershipUpdate) -> Result<()> { + async fn update_polygon_mints_owner( + &self, + payload: MintedTokensOwnershipUpdate, + ) -> ProcessResult<()> { let MintedTokensOwnershipUpdate { mint_ids, new_owner, @@ -412,21 +488,22 @@ impl Processor { transaction_hash, } = payload; - let ts = timestamp.context("No timestamp found")?; - let created_at = DateTime::::from_utc( - NaiveDateTime::from_timestamp_opt(ts.seconds, ts.nanos.try_into()?) - .context("failed to parse to NaiveDateTime")?, - Utc, - ) - .into(); + let created_at = timestamp + .and_then(|t| { + Some(DateTime::from_utc( + NaiveDateTime::from_timestamp_opt(t.seconds, t.nanos.try_into().ok()?)?, + Utc.fix(), + )) + }) + .ok_or(ProcessorErrorKind::InvalidTimestamp)?; let db = self.db.get(); let txn = db.begin().await?; let mint_ids = mint_ids .into_iter() - .map(|s| Uuid::from_str(&s)) - .collect::, _>>()?; + .map(|s| s.parse().map_err(Into::into)) + .collect::>>()?; let mints = CollectionMints::find() .filter(collection_mints::Column::Id.is_in(mint_ids)) @@ -455,13 +532,11 @@ impl Processor { Ok(()) } - async fn project_wallet_created(&self, payload: ProjectWallet) -> Result<()> { + async fn project_wallet_created(&self, payload: ProjectWallet) -> ProcessResult<()> { let conn = self.db.get(); let project_id = Uuid::from_str(&payload.project_id)?; - let blockchain = ProtoBlockchainEnum::from_i32(payload.blockchain) - .context("failed to get blockchain enum variant")?; - + let blockchain = payload.blockchain(); let active_model = project_wallets::ActiveModel { project_id: Set(project_id), wallet_address: Set(payload.wallet_address), @@ -469,20 +544,15 @@ impl Processor { ..Default::default() }; - active_model - .insert(conn) - .await - .context("failed to insert project wallet")?; + active_model.insert(conn).await?; Ok(()) } - async fn customer_wallet_created(&self, payload: CustomerWallet) -> Result<()> { + async fn customer_wallet_created(&self, payload: CustomerWallet) -> ProcessResult<()> { let conn = self.db.get(); - let blockchain = ProtoBlockchainEnum::from_i32(payload.blockchain) - .context("failed to get blockchain enum variant")?; - + let blockchain = payload.blockchain(); let active_model = customer_wallets::ActiveModel { customer_id: Set(payload.customer_id.parse()?), address: Set(payload.wallet_address), @@ -490,15 +560,12 @@ impl Processor { ..Default::default() }; - active_model - .insert(conn) - .await - .context("failed to insert customer wallet")?; + active_model.insert(conn).await?; Ok(()) } - async fn drop_created(&self, id: String, payload: MintResult) -> Result<()> { + async fn drop_created(&self, id: String, payload: MintResult) -> ProcessResult<()> { let conn = self.db.get(); let collection_id = Uuid::from_str(&id)?; @@ -506,10 +573,9 @@ impl Processor { .join(JoinType::InnerJoin, collections::Relation::Drop.def()) .select_also(drops::Entity) .one(conn) - .await - .context("failed to load collection from db")? - .context("collection not found in db")?; - let drop_model = drop.context("failed to get drop from db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingCollection)?; + let drop_model = drop.ok_or(ProcessorErrorKind::DbMissingDrop)?; let mut drops_active_model: drops::ActiveModel = drop_model.clone().into(); let mut collection_active_model: collections::ActiveModel = collection_model.into(); @@ -523,7 +589,7 @@ impl Processor { let deduction_id = drop_model .credits_deduction_id - .context("drop has no deduction id")?; + .ok_or(ProcessorErrorKind::RecordMissingDeductionId)?; self.credits .confirm_deduction(TransactionId(deduction_id)) .await?; @@ -554,15 +620,14 @@ impl Processor { Ok(()) } - async fn collection_created(&self, id: String, payload: MintResult) -> Result<()> { + async fn collection_created(&self, id: String, payload: MintResult) -> ProcessResult<()> { let conn = self.db.get(); let collection_id = Uuid::from_str(&id)?; let collection_model = collections::Entity::find_by_id(collection_id) .one(conn) - .await - .context("failed to load collection from db")? - .context("collection not found in db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingCollection)?; let mut collection_active_model: collections::ActiveModel = collection_model.clone().into(); let mut creation_status = NftCreationStatus::Completed; @@ -574,7 +639,7 @@ impl Processor { let deduction_id = collection_model .credits_deduction_id - .context("drop has no deduction id")?; + .ok_or(ProcessorErrorKind::RecordMissingDeductionId)?; self.credits .confirm_deduction(TransactionId(deduction_id)) .await?; @@ -603,7 +668,7 @@ impl Processor { Ok(()) } - async fn drop_minted(&self, id: String, payload: MintResult) -> Result<()> { + async fn drop_minted(&self, id: String, payload: MintResult) -> ProcessResult<()> { let conn = self.db.get(); let collection_mint_id = Uuid::from_str(&id)?; @@ -611,25 +676,22 @@ impl Processor { collection_mints::Entity::find_by_id(collection_mint_id) .find_also_related(collections::Entity) .one(conn) - .await - .context("failed to load collection mint from db")? - .context("collection mint not found in db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingCollectionMint)?; let mint_history = MintHistory::find() .filter(mint_histories::Column::MintId.eq(collection_mint_id)) .one(conn) - .await - .context("failed to load mint_history from db")? - .context("mint_history not found in db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingMintHistory)?; - let collection = collection.context("collection not found")?; + let collection = collection.ok_or(ProcessorErrorKind::DbMissingCollection)?; let drop = Drops::find() .filter(drops::Column::CollectionId.eq(collection.id)) .one(conn) - .await - .context("failed to load drop from db")? - .context("drop not found in db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingDrop)?; let mut collection_mint_active_model: collection_mints::ActiveModel = collection_mint.clone().into(); @@ -645,7 +707,7 @@ impl Processor { let deduction_id = collection_mint .credits_deduction_id - .context("deduction id not found")?; + .ok_or(ProcessorErrorKind::RecordMissingDeductionId)?; self.credits .confirm_deduction(TransactionId(deduction_id)) @@ -678,25 +740,23 @@ impl Processor { Ok(()) } - async fn minted_to_collection(&self, id: String, payload: MintResult) -> Result<()> { + async fn minted_to_collection(&self, id: String, payload: MintResult) -> ProcessResult<()> { let conn = self.db.get(); let collection_mint_id = Uuid::from_str(&id)?; let (collection_mint, collection) = collection_mints::Entity::find_by_id_with_collection(collection_mint_id) .one(conn) - .await - .context("failed to load collection mint from db")? - .context("collection mint not found in db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingCollectionMint)?; let mint_history = MintHistory::find() .filter(mint_histories::Column::MintId.eq(collection_mint_id)) .one(conn) - .await - .context("failed to load mint_history from db")? - .context("mint_history not found in db")?; + .await? + .ok_or(ProcessorErrorKind::DbMissingMintHistory)?; - let collection = collection.context("collection not found")?; + let collection = collection.ok_or(ProcessorErrorKind::DbMissingCollection)?; let mut collection_mint_active_model: collection_mints::ActiveModel = collection_mint.clone().into(); @@ -712,7 +772,7 @@ impl Processor { let deduction_id = collection_mint .credits_deduction_id - .context("deduction id not found")?; + .ok_or(ProcessorErrorKind::RecordMissingDeductionId)?; self.credits .confirm_deduction(TransactionId(deduction_id)) @@ -745,7 +805,7 @@ impl Processor { Ok(()) } - async fn mint_transferred(&self, id: String, payload: TransferResult) -> Result<()> { + async fn mint_transferred(&self, id: String, payload: TransferResult) -> ProcessResult<()> { let conn = self.db.get(); let transfer_id = Uuid::from_str(&id)?; @@ -753,12 +813,12 @@ impl Processor { .filter(transfer_charges::Column::Id.eq(transfer_id)) .one(conn) .await? - .context("failed to load transfer charge from db")?; + .ok_or(ProcessorErrorKind::DbMissingTransferCharge)?; if let TransferResult::Success(_) = payload { let deduction_id = transfer_charge .credits_deduction_id - .context("deduction id not found")?; + .ok_or(ProcessorErrorKind::RecordMissingDeductionId)?; self.credits .confirm_deduction(TransactionId(deduction_id)) @@ -772,7 +832,7 @@ impl Processor { let update_history = UpdateHistories::find_by_id(Uuid::from_str(&id)?) .one(self.db.get()) .await? - .context("Update history record not found")?; + .ok_or(ProcessorErrorKind::DbMissingUpdateHistory)?; let mut update_history_am: update_histories::ActiveModel = update_history.clone().into(); if let UpdateResult::Success(signature) = payload { @@ -830,11 +890,11 @@ impl Processor { } impl TryFrom for Blockchain { - type Error = Error; + type Error = ProcessorErrorKind; - fn try_from(v: ProtoBlockchainEnum) -> Result { + fn try_from(v: ProtoBlockchainEnum) -> ProcessResult { match v { - ProtoBlockchainEnum::Unspecified => Err(anyhow!("Invalid enum variant")), + ProtoBlockchainEnum::Unspecified => Err(ProcessorErrorKind::InvalidBlockchain), ProtoBlockchainEnum::Solana => Ok(Self::Solana), ProtoBlockchainEnum::Polygon => Ok(Self::Polygon), ProtoBlockchainEnum::Ethereum => Ok(Self::Ethereum), @@ -843,11 +903,11 @@ impl TryFrom for Blockchain { } impl TryFrom for CreationStatus { - type Error = Error; + type Error = ProcessorErrorKind; - fn try_from(i: TransactionStatus) -> Result { + fn try_from(i: TransactionStatus) -> ProcessResult { match i { - TransactionStatus::Unspecified => Err(anyhow!("Invalid enum variant")), + TransactionStatus::Unspecified => Err(ProcessorErrorKind::InvalidTransactionStatus), TransactionStatus::Blocked => Ok(Self::Blocked), TransactionStatus::Failed => Ok(Self::Failed), TransactionStatus::Completed => Ok(Self::Created), @@ -892,7 +952,7 @@ async fn index_attributes( db: &Connection, json_id: Uuid, attributes: Vec, -) -> Result<()> { +) -> ProcessResult<()> { for attr in attributes { let attribute = metadata_json_attributes::ActiveModel { metadata_json_id: Set(json_id), @@ -907,7 +967,7 @@ async fn index_attributes( Ok(()) } -async fn index_files(db: &Connection, json_id: Uuid, files: Vec) -> Result<()> { +async fn index_files(db: &Connection, json_id: Uuid, files: Vec) -> ProcessResult<()> { for file in files { let file_am = metadata_json_files::ActiveModel { metadata_json_id: Set(json_id), diff --git a/api/src/lib.rs b/api/src/lib.rs index 71138cb..7254b3c 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -60,7 +60,7 @@ impl hub_core::producer::Message for proto::NftEvents { type Key = proto::NftEventKey; } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Services { Treasury(proto::TreasuryEventKey, proto::TreasuryEvents), Solana(proto::SolanaNftEventKey, proto::SolanaNftEvents), diff --git a/api/src/main.rs b/api/src/main.rs index c3093c5..15dcc7c 100644 --- a/api/src/main.rs +++ b/api/src/main.rs @@ -1,6 +1,5 @@ //! -use async_graphql::futures_util::StreamExt; use holaplex_hub_nfts::{ blockchains::{polygon::Polygon, solana::Solana}, build_schema, @@ -10,11 +9,7 @@ use holaplex_hub_nfts::{ nft_storage::NftStorageClient, proto, Actions, AppState, Args, Services, }; -use hub_core::{ - anyhow::Context as AnyhowContext, - tokio::{self, task}, - tracing::{info, warn}, -}; +use hub_core::{prelude::*, tokio}; use poem::{get, listener::TcpListener, middleware::AddData, post, EndpointExt, Route, Server}; pub fn main() { @@ -63,25 +58,15 @@ pub fn main() { let cons = common.consumer_cfg.build::().await?; tokio::spawn(async move { - { - let mut stream = cons.stream(); - loop { - let event_processor = event_processor.clone(); - - match stream.next().await { - Some(Ok(msg)) => { - info!(?msg, "message received"); - - tokio::spawn(async move { event_processor.process(msg).await }); - task::yield_now().await; - }, - None => (), - Some(Err(e)) => { - warn!("failed to get message {:?}", e); - }, - } - } - } + cons.consume( + |b| { + b.with_jitter() + .with_min_delay(Duration::from_millis(500)) + .with_max_delay(Duration::from_secs(90)) + }, + |e| async move { event_processor.process(e).await }, + ) + .await }); Server::new(TcpListener::bind(format!("0.0.0.0:{port}"))) diff --git a/api/src/mutations/mint.rs b/api/src/mutations/mint.rs index 4ae39a7..263bd3a 100644 --- a/api/src/mutations/mint.rs +++ b/api/src/mutations/mint.rs @@ -14,7 +14,7 @@ use super::collection::{ use crate::{ blockchains::{polygon::Polygon, solana::Solana, CollectionEvent, DropEvent}, entities::{ - collection_mints, collections, drops, metadata_jsons, mint_creators, mint_histories, + collection_mints, collections, drops, mint_creators, mint_histories, prelude::{CollectionMints, Collections, Drops}, project_wallets, sea_orm_active_enums::{Blockchain as BlockchainEnum, CreationStatus}, @@ -552,8 +552,6 @@ impl Mutation { validate_creators(blockchain, &creators)?; validate_json(blockchain, &input.metadata_json)?; - let seller_fee_basis_points = input.seller_fee_basis_points.unwrap_or_default(); - let owner_address = fetch_owner(conn, collection.project_id, collection.blockchain).await?; if collection.blockchain == BlockchainEnum::Solana { @@ -583,6 +581,19 @@ impl Mutation { ) .await?; + let mut mint_am: collection_mints::ActiveModel = mint.clone().into(); + + let update_history_am = update_histories::ActiveModel { + mint_id: Set(mint.id), + txn_signature: Set(None), + credit_deduction_id: Set(deduction_id.0), + created_by: Set(user_id), + status: Set(CreationStatus::Pending), + ..Default::default() + }; + + let update_history = update_history_am.insert(db.get()).await?; + let sfbp = mint.seller_fee_basis_points.try_into()?; conn.transaction::<_, (), DbErr>(|txn| { Box::pin(async move { mint_creators::Entity::delete_many() @@ -594,13 +605,10 @@ impl Mutation { .exec(txn) .await?; - let metadata_json_model = metadata_jsons::Entity::find() - .filter(metadata_jsons::Column::Id.eq(mint.id)) - .one(txn) - .await? - .ok_or(DbErr::RecordNotFound("Metadata Json not found".to_string()))?; - - metadata_json_model.delete(txn).await?; + if let Some(sfbp) = input.seller_fee_basis_points { + mint_am.seller_fee_basis_points = Set(sfbp.try_into().unwrap_or_default()); + mint_am.update(txn).await?; + } Ok(()) }) @@ -613,17 +621,6 @@ impl Mutation { .save(mint.id, db) .await?; - let update_history_am = update_histories::ActiveModel { - mint_id: Set(mint.id), - txn_signature: Set(None), - credit_deduction_id: Set(deduction_id.0), - created_by: Set(user_id), - status: Set(CreationStatus::Pending), - ..Default::default() - }; - - let update_history = update_history_am.insert(db.get()).await?; - match collection.blockchain { BlockchainEnum::Solana => { solana @@ -640,14 +637,17 @@ impl Mutation { name: metadata_json.name, symbol: metadata_json.symbol, metadata_uri: metadata_json.uri, - seller_fee_basis_points: seller_fee_basis_points.into(), + seller_fee_basis_points: input + .seller_fee_basis_points + .unwrap_or(sfbp) + .try_into()?, creators: creators .into_iter() .map(TryFrom::try_from) .collect::>()?, }), collection_id: collection.id.to_string(), - mint_id: mint.id.to_string(), + mint_id: update_history.mint_id.to_string(), }, ) .await?;