From 0bfcfc2773be0a4da86e01444a44b929175ec7e9 Mon Sep 17 00:00:00 2001 From: imabdulbasit Date: Mon, 28 Aug 2023 19:06:24 +0500 Subject: [PATCH] Switch collection history field in mint object --- api/src/dataloaders/collection_mints.rs | 8 +- api/src/dataloaders/mod.rs | 2 + .../switch_collection_histories.rs | 50 ++++++ api/src/entities/collection_mints.rs | 154 +--------------- api/src/entities/mint_histories.rs | 4 +- .../entities/switch_collection_histories.rs | 5 +- api/src/events.rs | 16 +- api/src/lib.rs | 8 +- api/src/mutations/collection.rs | 12 +- api/src/mutations/mint.rs | 12 +- api/src/mutations/transfer.rs | 3 +- api/src/objects/collection.rs | 9 +- api/src/objects/collection_mint.rs | 168 ++++++++++++++++++ api/src/objects/customer.rs | 11 +- api/src/objects/mod.rs | 2 + api/src/objects/wallet.rs | 8 +- api/src/queries/mint.rs | 2 +- 17 files changed, 278 insertions(+), 196 deletions(-) create mode 100644 api/src/dataloaders/switch_collection_histories.rs create mode 100644 api/src/objects/collection_mint.rs diff --git a/api/src/dataloaders/collection_mints.rs b/api/src/dataloaders/collection_mints.rs index c456f78..1e37b6f 100644 --- a/api/src/dataloaders/collection_mints.rs +++ b/api/src/dataloaders/collection_mints.rs @@ -4,7 +4,7 @@ use async_graphql::{dataloader::Loader as DataLoader, FieldError, Result}; use poem::async_trait; use sea_orm::prelude::*; -use crate::{db::Connection, entities::collection_mints}; +use crate::{db::Connection, entities::collection_mints, objects::CollectionMint}; #[derive(Debug, Clone)] pub struct Loader { @@ -21,7 +21,7 @@ impl Loader { #[async_trait] impl DataLoader for Loader { type Error = FieldError; - type Value = Vec; + type Value = Vec; async fn load(&self, keys: &[Uuid]) -> Result, Self::Error> { let collection_mints = collection_mints::Entity::find() @@ -60,7 +60,7 @@ impl OwnerLoader { #[async_trait] impl DataLoader for OwnerLoader { type Error = FieldError; - type Value = Vec; + type Value = Vec; async fn load(&self, keys: &[String]) -> Result, Self::Error> { let collection_mints = collection_mints::Entity::find() @@ -100,7 +100,7 @@ impl CollectionMintLoader { #[async_trait] impl DataLoader for CollectionMintLoader { type Error = FieldError; - type Value = collection_mints::CollectionMint; + type Value = CollectionMint; async fn load(&self, keys: &[Uuid]) -> Result, Self::Error> { let collection_mints = collection_mints::Entity::find() diff --git a/api/src/dataloaders/mod.rs b/api/src/dataloaders/mod.rs index 2bf0b1e..b2244cb 100644 --- a/api/src/dataloaders/mod.rs +++ b/api/src/dataloaders/mod.rs @@ -11,6 +11,7 @@ mod mint_histories; mod nft_transfers; mod project_collection; mod project_collections; +mod switch_collection_histories; mod update_histories; pub use collection::Loader as CollectionLoader; @@ -34,4 +35,5 @@ pub use mint_histories::{ pub use nft_transfers::CollectionMintTransfersLoader; pub use project_collection::ProjectCollectionLoader; pub use project_collections::ProjectCollectionsLoader; +pub use switch_collection_histories::SwitchCollectionHistoryLoader; pub use update_histories::UpdateMintHistoryLoader; diff --git a/api/src/dataloaders/switch_collection_histories.rs b/api/src/dataloaders/switch_collection_histories.rs new file mode 100644 index 0000000..c1653bf --- /dev/null +++ b/api/src/dataloaders/switch_collection_histories.rs @@ -0,0 +1,50 @@ +use std::collections::HashMap; + +use async_graphql::{dataloader::Loader as DataLoader, FieldError, Result}; +use poem::async_trait; +use sea_orm::{prelude::*, Order, QueryOrder}; + +use crate::{db::Connection, entities::switch_collection_histories}; + +#[derive(Debug, Clone)] +pub struct SwitchCollectionHistoryLoader { + pub db: Connection, +} + +impl SwitchCollectionHistoryLoader { + #[must_use] + pub fn new(db: Connection) -> Self { + Self { db } + } +} + +#[async_trait] +impl DataLoader for SwitchCollectionHistoryLoader { + type Error = FieldError; + type Value = Vec; + + async fn load(&self, keys: &[Uuid]) -> Result, Self::Error> { + let conn = self.db.get(); + let switch_histories = switch_collection_histories::Entity::find() + .filter( + switch_collection_histories::Column::CollectionMintId + .is_in(keys.iter().map(ToOwned::to_owned)), + ) + .order_by(switch_collection_histories::Column::CreatedAt, Order::Desc) + .all(conn) + .await?; + + Ok(switch_histories.into_iter().fold( + HashMap::new(), + |mut acc: HashMap>, switch_history| { + acc.entry(switch_history.collection_mint_id.clone()) + .or_insert_with(Vec::new); + + acc.entry(switch_history.collection_mint_id.clone()) + .and_modify(|switch_histories| switch_histories.push(switch_history.into())); + + acc + }, + )) + } +} diff --git a/api/src/entities/collection_mints.rs b/api/src/entities/collection_mints.rs index f10d6e8..940ab90 100644 --- a/api/src/entities/collection_mints.rs +++ b/api/src/entities/collection_mints.rs @@ -1,17 +1,9 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.0 -use async_graphql::{ComplexObject, Context, Error, Result, SimpleObject}; +use async_graphql::Result; use sea_orm::{entity::prelude::*, JoinType, QuerySelect, SelectTwo}; -use super::{ - collections, mint_creators, mint_histories, nft_transfers, - sea_orm_active_enums::{Blockchain, CreationStatus}, - update_histories, -}; -use crate::{ - objects::{Collection, MetadataJson}, - AppContext, -}; +use super::{collections, sea_orm_active_enums::CreationStatus}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "collection_mints")] @@ -34,148 +26,6 @@ pub struct Model { pub compressed: bool, } -/// Represents a single NFT minted from a collection. -#[derive(Clone, Debug, PartialEq, Eq, SimpleObject)] -#[graphql(complex)] -pub struct CollectionMint { - /// The unique ID of the minted NFT. - pub id: Uuid, - /// The ID of the collection the NFT was minted from. - pub collection_id: Uuid, - /// The address of the NFT - /// On Solana this is the mint address. - /// On EVM chains it is the concatenation of the contract address and the token id `{contractAddress}:{tokenId}`. - pub address: Option, - /// The wallet address of the owner of the NFT. - pub owner: String, - /// The status of the NFT creation. - pub creation_status: CreationStatus, - /// The unique ID of the creator of the NFT. - pub created_by: Uuid, - /// The date and time when the NFT was created. - pub created_at: DateTimeWithTimeZone, - /// The transaction signature associated with the NFT. - pub signature: Option, - /// The unique edition number of the NFT. - pub edition: i64, - /// The seller fee basis points (ie royalties) for the NFT. - pub seller_fee_basis_points: i16, - /// credits deduction id - pub credits_deduction_id: Option, - /// Indicates if the NFT is compressed. Compression is only supported on Solana. - pub compressed: bool, -} - -#[ComplexObject] -impl CollectionMint { - /// The collection the NFT was minted from. - async fn collection(&self, ctx: &Context<'_>) -> Result> { - let AppContext { - collection_loader, .. - } = ctx.data::()?; - - collection_loader.load_one(self.collection_id).await - } - - /// The metadata json associated to the collection. - /// [Metaplex v1.1.0 Standard](https://docs.metaplex.com/programs/token-metadata/token-standard) - async fn metadata_json(&self, ctx: &Context<'_>) -> Result> { - let AppContext { - metadata_json_loader, - .. - } = ctx.data::()?; - let collection = self.collection(ctx).await?.ok_or(Error::new(format!( - "Collection not found for collection mint {:?}", - &self.id - )))?; - - match collection.blockchain { - Blockchain::Solana => metadata_json_loader.load_one(self.id).await, - Blockchain::Polygon => metadata_json_loader.load_one(self.collection_id).await, - Blockchain::Ethereum => Err(Error::new("Ethereum not supported")), - } - } - - /// The update history of the mint. - async fn update_histories( - &self, - ctx: &Context<'_>, - ) -> Result>> { - let AppContext { - update_mint_history_loader, - .. - } = ctx.data::()?; - - update_mint_history_loader.load_one(self.id).await - } - /// The creators of the mint. Includes the creator addresses and their shares. - async fn creators(&self, ctx: &Context<'_>) -> Result>> { - let AppContext { - mint_creators_loader, - .. - } = ctx.data::()?; - - mint_creators_loader.load_one(self.id).await - } - - /// The record of the original mint. - async fn mint_history(&self, ctx: &Context<'_>) -> Result> { - let AppContext { - collection_mint_mint_history_loader, - .. - } = ctx.data::()?; - - collection_mint_mint_history_loader.load_one(self.id).await - } - - /// The history of transfers for the mint. - async fn transfer_histories( - &self, - ctx: &Context<'_>, - ) -> Result>> { - let AppContext { - collection_mint_transfers_loader, - .. - } = ctx.data::()?; - - collection_mint_transfers_loader.load_one(self.id).await - } -} - -impl From for CollectionMint { - fn from( - Model { - id, - collection_id, - address, - owner, - creation_status, - created_by, - created_at, - signature, - edition, - seller_fee_basis_points, - credits_deduction_id, - compressed, - }: Model, - ) -> Self { - Self { - id, - collection_id, - address, - owner, - creation_status, - created_by, - created_at, - signature, - edition, - seller_fee_basis_points, - credits_deduction_id, - compressed, - } - } -} - #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( diff --git a/api/src/entities/mint_histories.rs b/api/src/entities/mint_histories.rs index 435a05a..9cd5799 100644 --- a/api/src/entities/mint_histories.rs +++ b/api/src/entities/mint_histories.rs @@ -3,8 +3,8 @@ use async_graphql::{ComplexObject, Context, Result, SimpleObject}; use sea_orm::entity::prelude::*; -use super::{collection_mints::CollectionMint, sea_orm_active_enums::CreationStatus}; -use crate::AppContext; +use super::sea_orm_active_enums::CreationStatus; +use crate::{objects::CollectionMint, AppContext}; /// A record of a minted NFT. #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, SimpleObject)] diff --git a/api/src/entities/switch_collection_histories.rs b/api/src/entities/switch_collection_histories.rs index 2907648..35733f7 100644 --- a/api/src/entities/switch_collection_histories.rs +++ b/api/src/entities/switch_collection_histories.rs @@ -1,11 +1,12 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 - +use async_graphql::SimpleObject; use sea_orm::entity::prelude::*; use super::sea_orm_active_enums::CreationStatus; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, SimpleObject)] #[sea_orm(table_name = "switch_collection_histories")] +#[graphql(concrete(name = "SwitchCollectionHistory", params()))] pub struct Model { #[sea_orm(primary_key, auto_increment = false)] pub id: Uuid, diff --git a/api/src/events.rs b/api/src/events.rs index b4ab669..695b042 100644 --- a/api/src/events.rs +++ b/api/src/events.rs @@ -66,6 +66,8 @@ pub enum ProcessorErrorKind { DbMissingTransferCharge, #[error("No associated update history found in database")] DbMissingUpdateHistory, + #[error("No associated switch collection history found in database")] + DbMissingSwitchCollectionHistory, #[error("Database record contains no deduction ID")] RecordMissingDeductionId, @@ -251,6 +253,10 @@ impl Processor { SolanaNftsEvent::UpdateCollectionMintFailed(_) | SolanaNftsEvent::RetryUpdateMintFailed(_), ) => self.mint_updated(id, UpdateResult::Failure).await, + Some(SolanaNftsEvent::SwitchMintCollectionFailed(_)) => { + self.switch_collection_submitted(id, SwitchCollectionResult::Failure) + .await + }, Some(SolanaNftsEvent::UpdateMintOwner(e)) => self.update_mint_owner(id, e).await, Some(SolanaNftsEvent::ImportedExternalCollection(e)) => { self.index_collection(id, project_id, user_id, e).await @@ -304,10 +310,10 @@ impl Processor { } = metadata.ok_or(ProcessorErrorKind::MissingCollectionMetadata)?; let collection_am = collections::ActiveModel { - id: Set(id.parse()?), + id: Set(Uuid::from_str(&id)?), blockchain: Set(Blockchain::Solana), supply: Set(supply.map(Into::into)), - project_id: Set(project_id.parse()?), + project_id: Set(Uuid::from_str(&project_id)?), credits_deduction_id: Set(None), creation_status: Set(CreationStatus::Created), total_mints: Set(0), @@ -851,17 +857,17 @@ impl Processor { &self, id: String, payload: SwitchCollectionResult, - ) -> Result<()> { + ) -> ProcessResult<()> { let history_id = Uuid::from_str(&id)?; let history = SwitchCollectionHistories::find_by_id(history_id) .one(self.db.get()) .await? - .context("Switch collection history record not found")?; + .ok_or(ProcessorErrorKind::DbMissingSwitchCollectionHistory)?; let mint = CollectionMints::find_by_id(history.collection_mint_id) .one(self.db.get()) .await? - .context("Mint record not found")?; + .ok_or(ProcessorErrorKind::DbMissingCollectionMint)?; let mut history_am: switch_collection_histories::ActiveModel = history.clone().into(); diff --git a/api/src/lib.rs b/api/src/lib.rs index 3aa4bfd..7254b3c 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -26,7 +26,8 @@ use dataloaders::{ CollectionMintMintHistoryLoader, CollectionMintTransfersLoader, CollectionMintsLoader, CollectionMintsOwnerLoader, CreatorsLoader, DropLoader, DropMintHistoryLoader, HoldersLoader, MetadataJsonAttributesLoader, MetadataJsonLoader, MintCreatorsLoader, MinterMintHistoryLoader, - ProjectCollectionLoader, ProjectCollectionsLoader, ProjectDropsLoader, UpdateMintHistoryLoader, + ProjectCollectionLoader, ProjectCollectionsLoader, ProjectDropsLoader, + SwitchCollectionHistoryLoader, UpdateMintHistoryLoader, }; use db::Connection; use hub_core::{ @@ -286,6 +287,7 @@ pub struct AppContext { mint_creators_loader: DataLoader, collection_mint_mint_history_loader: DataLoader, collection_mint_transfers_loader: DataLoader, + switch_collection_history_loader: DataLoader, } impl AppContext { @@ -334,7 +336,8 @@ impl AppContext { ); let collection_mint_transfers_loader = DataLoader::new(CollectionMintTransfersLoader::new(db.clone()), tokio::spawn); - + let switch_collection_history_loader = + DataLoader::new(SwitchCollectionHistoryLoader::new(db.clone()), tokio::spawn); Self { db, user_id, @@ -360,6 +363,7 @@ impl AppContext { mint_creators_loader, collection_mint_mint_history_loader, collection_mint_transfers_loader, + switch_collection_history_loader, } } } diff --git a/api/src/mutations/collection.rs b/api/src/mutations/collection.rs index 7aeeac6..d3ea2ab 100644 --- a/api/src/mutations/collection.rs +++ b/api/src/mutations/collection.rs @@ -22,7 +22,7 @@ use crate::{ switch_collection_histories, }, metadata_json::MetadataJson, - objects::{Collection as CollectionObject, Creator, MetadataJsonInput}, + objects::{Collection as CollectionObject, CollectionMint, Creator, MetadataJsonInput}, proto::{ nft_events::Event as NftEvent, CollectionCreation, CollectionImport, CreationStatus as NftCreationStatus, Creator as ProtoCreator, MasterEdition, @@ -462,6 +462,10 @@ impl Mutation { }) } + /// This mutation allows you to change the collection to which a mint belongs. + /// For Solana, the mint specified by `input` must already belong to a Metaplex Certified Collection. + /// The collection you are aiming to switch to must also be Metaplex Certified Collection. + pub async fn switch_collection( &self, ctx: &Context<'_>, @@ -576,11 +580,13 @@ pub async fn fetch_owner( Ok(owner) } +/// Result of a successful create collection mutation. #[derive(Debug, Clone, SimpleObject)] pub struct CreateCollectionPayload { collection: CollectionObject, } +/// Input object for creating a collection. #[derive(Debug, Clone, Serialize, Deserialize, InputObject)] pub struct CreateCollectionInput { pub project: Uuid, @@ -782,13 +788,15 @@ pub struct ImportCollectionPayload { status: CreationStatus, } +/// Input object for switching a mint's collection. #[derive(Debug, Clone, Serialize, Deserialize, InputObject)] pub struct SwitchCollectionInput { mint: Uuid, collection_address: String, } +/// Represents the result of a successful switch collection mutation. #[derive(Debug, Clone, SimpleObject)] pub struct SwitchCollectionPayload { - collection_mint: collection_mints::CollectionMint, + collection_mint: CollectionMint, } diff --git a/api/src/mutations/mint.rs b/api/src/mutations/mint.rs index db02144..263bd3a 100644 --- a/api/src/mutations/mint.rs +++ b/api/src/mutations/mint.rs @@ -21,7 +21,7 @@ use crate::{ update_histories, }, metadata_json::MetadataJson, - objects::{Creator, MetadataJsonInput}, + objects::{CollectionMint, Creator, MetadataJsonInput}, proto::{ self, nft_events::Event as NftEvent, CreationStatus as NftCreationStatus, MetaplexMetadata, MintCollectionCreation, MintCreation, NftEventKey, NftEvents, RetryUpdateSolanaMintPayload, @@ -890,7 +890,7 @@ pub struct MintDropInput { /// Represents payload data for the `mint_edition` mutation #[derive(Debug, Clone, SimpleObject)] pub struct MintEditionPayload { - collection_mint: collection_mints::CollectionMint, + collection_mint: CollectionMint, } /// Represents input data for `retry_mint` mutation with an ID as a field of type UUID @@ -902,7 +902,7 @@ pub struct RetryMintEditionInput { /// Represents payload data for `retry_mint` mutation #[derive(Debug, Clone, SimpleObject)] pub struct RetryMintEditionPayload { - collection_mint: collection_mints::CollectionMint, + collection_mint: CollectionMint, } /// Represents input data for `mint_to_collection` mutation with a collection ID, recipient, metadata, and optional seller fee basis points as fields @@ -941,12 +941,12 @@ pub struct UpdateMintInput { #[derive(Debug, Clone, SimpleObject)] pub struct MintToCollectionPayload { /// The minted NFT - collection_mint: collection_mints::CollectionMint, + collection_mint: CollectionMint, } #[derive(Debug, Clone, SimpleObject)] pub struct UpdateMintPayload { - collection_mint: collection_mints::CollectionMint, + collection_mint: CollectionMint, } /// Represents input data for `retry_mint_to_collection` mutation with an ID as a field of type UUID @@ -960,7 +960,7 @@ pub struct RetryMintToCollectionInput { #[derive(Debug, Clone, SimpleObject)] pub struct RetryMintToCollectionPayload { /// The retried minted NFT - collection_mint: collection_mints::CollectionMint, + collection_mint: CollectionMint, } #[derive(Debug, Clone, InputObject)] diff --git a/api/src/mutations/transfer.rs b/api/src/mutations/transfer.rs index 2601bb4..98ea103 100644 --- a/api/src/mutations/transfer.rs +++ b/api/src/mutations/transfer.rs @@ -7,11 +7,12 @@ use super::collection::{validate_evm_address, validate_solana_address}; use crate::{ blockchains::{polygon::Polygon, solana::Solana, TransferEvent}, entities::{ - collection_mints::{self, CollectionMint}, + collection_mints, prelude::CustomerWallets, sea_orm_active_enums::{Blockchain, CreationStatus}, transfer_charges, }, + objects::CollectionMint, proto::{self, NftEventKey, TransferPolygonAsset}, Actions, AppContext, OrganizationId, UserID, }; diff --git a/api/src/objects/collection.rs b/api/src/objects/collection.rs index e86b2e8..e0d2c3d 100644 --- a/api/src/objects/collection.rs +++ b/api/src/objects/collection.rs @@ -1,10 +1,10 @@ use async_graphql::{Context, Object, Result}; use sea_orm::entity::prelude::*; -use super::{metadata_json::MetadataJson, Drop, Holder}; +use super::{metadata_json::MetadataJson, CollectionMint, Drop, Holder}; use crate::{ entities::{ - collection_creators, collection_mints, + collection_creators, collections::Model, mint_histories, sea_orm_active_enums::{Blockchain, CreationStatus}, @@ -119,10 +119,7 @@ impl Collection { } /// The list of minted NFTs from the collection including the NFTs address and current owner's wallet address. - async fn mints( - &self, - ctx: &Context<'_>, - ) -> Result>> { + async fn mints(&self, ctx: &Context<'_>) -> Result>> { let AppContext { collection_mints_loader, .. diff --git a/api/src/objects/collection_mint.rs b/api/src/objects/collection_mint.rs new file mode 100644 index 0000000..a7c6b21 --- /dev/null +++ b/api/src/objects/collection_mint.rs @@ -0,0 +1,168 @@ +use async_graphql::{ComplexObject, Context, Error, Result, SimpleObject}; +use sea_orm::entity::prelude::*; + +use crate::{ + entities::{ + collection_mints::Model, + mint_creators, mint_histories, nft_transfers, + sea_orm_active_enums::{Blockchain, CreationStatus}, + switch_collection_histories, update_histories, + }, + objects::{Collection, MetadataJson}, + AppContext, +}; + +/// Represents a single NFT minted from a collection. +#[derive(Clone, Debug, PartialEq, Eq, SimpleObject)] +#[graphql(complex)] +pub struct CollectionMint { + /// The unique ID of the minted NFT. + pub id: Uuid, + /// The ID of the collection the NFT was minted from. + pub collection_id: Uuid, + /// The address of the NFT + /// On Solana this is the mint address. + /// On EVM chains it is the concatenation of the contract address and the token id `{contractAddress}:{tokenId}`. + pub address: Option, + /// The wallet address of the owner of the NFT. + pub owner: String, + /// The status of the NFT creation. + pub creation_status: CreationStatus, + /// The unique ID of the creator of the NFT. + pub created_by: Uuid, + /// The date and time when the NFT was created. + pub created_at: DateTimeWithTimeZone, + /// The transaction signature associated with the NFT. + pub signature: Option, + /// The unique edition number of the NFT. + pub edition: i64, + /// The seller fee basis points (ie royalties) for the NFT. + pub seller_fee_basis_points: i16, + /// credits deduction id + pub credits_deduction_id: Option, + /// Indicates if the NFT is compressed. Compression is only supported on Solana. + pub compressed: bool, +} + +#[ComplexObject] +impl CollectionMint { + /// The collection the NFT was minted from. + async fn collection(&self, ctx: &Context<'_>) -> Result> { + let AppContext { + collection_loader, .. + } = ctx.data::()?; + + collection_loader.load_one(self.collection_id).await + } + + /// The metadata json associated to the collection. + /// [Metaplex v1.1.0 Standard](https://docs.metaplex.com/programs/token-metadata/token-standard) + async fn metadata_json(&self, ctx: &Context<'_>) -> Result> { + let AppContext { + metadata_json_loader, + .. + } = ctx.data::()?; + let collection = self.collection(ctx).await?.ok_or(Error::new(format!( + "Collection not found for collection mint {:?}", + &self.id + )))?; + + match collection.blockchain { + Blockchain::Solana => metadata_json_loader.load_one(self.id).await, + Blockchain::Polygon => metadata_json_loader.load_one(self.collection_id).await, + Blockchain::Ethereum => Err(Error::new("Ethereum not supported")), + } + } + + /// The update history of the mint. + async fn update_histories( + &self, + ctx: &Context<'_>, + ) -> Result>> { + let AppContext { + update_mint_history_loader, + .. + } = ctx.data::()?; + + update_mint_history_loader.load_one(self.id).await + } + /// The creators of the mint. Includes the creator addresses and their shares. + async fn creators(&self, ctx: &Context<'_>) -> Result>> { + let AppContext { + mint_creators_loader, + .. + } = ctx.data::()?; + + mint_creators_loader.load_one(self.id).await + } + + /// The record of the original mint. + async fn mint_history(&self, ctx: &Context<'_>) -> Result> { + let AppContext { + collection_mint_mint_history_loader, + .. + } = ctx.data::()?; + + collection_mint_mint_history_loader.load_one(self.id).await + } + + /// The history of transfers for the mint. + async fn transfer_histories( + &self, + ctx: &Context<'_>, + ) -> Result>> { + let AppContext { + collection_mint_transfers_loader, + .. + } = ctx.data::()?; + + collection_mint_transfers_loader.load_one(self.id).await + } + + /// The history of switched collections for the mint. + async fn switch_collection_histories( + &self, + ctx: &Context<'_>, + ) -> Result>> { + let AppContext { + switch_collection_history_loader, + .. + } = ctx.data::()?; + + switch_collection_history_loader.load_one(self.id).await + } +} + +impl From for CollectionMint { + fn from( + Model { + id, + collection_id, + address, + owner, + creation_status, + created_by, + created_at, + signature, + edition, + seller_fee_basis_points, + credits_deduction_id, + compressed, + }: Model, + ) -> Self { + Self { + id, + collection_id, + address, + owner, + creation_status, + created_by, + created_at, + signature, + edition, + seller_fee_basis_points, + credits_deduction_id, + compressed, + } + } +} diff --git a/api/src/objects/customer.rs b/api/src/objects/customer.rs index bf44f0c..c5a59eb 100644 --- a/api/src/objects/customer.rs +++ b/api/src/objects/customer.rs @@ -1,10 +1,8 @@ use async_graphql::{ComplexObject, Context, Result, SimpleObject}; use hub_core::uuid::Uuid; -use crate::{ - entities::{collection_mints, mint_histories}, - AppContext, -}; +use super::CollectionMint; +use crate::{entities::mint_histories, AppContext}; /// A project customer. #[derive(SimpleObject, Debug, Clone)] @@ -21,10 +19,7 @@ pub struct Customer { impl Customer { /// The NFTs owned by any of the customers' wallets. #[graphql(requires = "addresses")] - async fn mints( - &self, - ctx: &Context<'_>, - ) -> Result>> { + async fn mints(&self, ctx: &Context<'_>) -> Result>> { let AppContext { collection_mints_owner_loader, .. diff --git a/api/src/objects/mod.rs b/api/src/objects/mod.rs index 242986e..380f69b 100644 --- a/api/src/objects/mod.rs +++ b/api/src/objects/mod.rs @@ -1,6 +1,7 @@ #![allow(clippy::unused_async)] mod collection; +mod collection_mint; mod creator; mod customer; mod drop; @@ -10,6 +11,7 @@ mod project; mod wallet; pub use collection::Collection; +pub use collection_mint::CollectionMint; pub use creator::Creator; pub use customer::Customer; pub use drop::Drop; diff --git a/api/src/objects/wallet.rs b/api/src/objects/wallet.rs index f52931e..b6293a7 100644 --- a/api/src/objects/wallet.rs +++ b/api/src/objects/wallet.rs @@ -1,6 +1,7 @@ use async_graphql::{ComplexObject, Context, Result, SimpleObject}; -use crate::{entities::collection_mints, AppContext}; +use super::CollectionMint; +use crate::AppContext; /// A blockchain wallet is a digital wallet that allows users to securely store, manage, and transfer their cryptocurrencies or other digital assets on a blockchain network. #[derive(SimpleObject, Debug, Clone)] @@ -14,10 +15,7 @@ pub struct Wallet { #[ComplexObject] impl Wallet { /// The NFTs that were minted from Holaplex and are owned by the wallet's address. - async fn mints( - &self, - ctx: &Context<'_>, - ) -> Result>> { + async fn mints(&self, ctx: &Context<'_>) -> Result>> { let AppContext { collection_mints_owner_loader, .. diff --git a/api/src/queries/mint.rs b/api/src/queries/mint.rs index 43cb649..cb0ec76 100644 --- a/api/src/queries/mint.rs +++ b/api/src/queries/mint.rs @@ -1,7 +1,7 @@ use async_graphql::{Context, Object, Result}; use hub_core::uuid::Uuid; -use crate::{entities::collection_mints::CollectionMint, AppContext}; +use crate::{objects::CollectionMint, AppContext}; #[derive(Debug, Clone, Copy, Default)] pub struct Query;