From 2e01bac1524221623273dc920011b7e9d01bb3e0 Mon Sep 17 00:00:00 2001 From: Nagaprasadvr Date: Fri, 15 Nov 2024 12:28:09 +0530 Subject: [PATCH] feat: add showInscription filter --- digital_asset_types/src/dao/full_asset.rs | 4 + digital_asset_types/src/dao/scopes/asset.rs | 132 +++++++++++------- .../src/dapi/assets_by_authority.rs | 2 +- .../src/dapi/assets_by_creator.rs | 2 +- .../src/dapi/assets_by_group.rs | 2 +- digital_asset_types/src/dapi/common/asset.rs | 44 ++++++ digital_asset_types/src/dapi/search_assets.rs | 2 +- digital_asset_types/src/rpc/asset.rs | 27 ++++ digital_asset_types/src/rpc/options.rs | 2 + 9 files changed, 163 insertions(+), 54 deletions(-) diff --git a/digital_asset_types/src/dao/full_asset.rs b/digital_asset_types/src/dao/full_asset.rs index fda932d21..53a23dfd6 100644 --- a/digital_asset_types/src/dao/full_asset.rs +++ b/digital_asset_types/src/dao/full_asset.rs @@ -1,12 +1,16 @@ use crate::dao::{asset, asset_authority, asset_creators, asset_data, asset_grouping}; +use super::{asset_v1_account_attachments, tokens}; + #[derive(Clone, Debug, PartialEq)] pub struct FullAsset { pub asset: asset::Model, pub data: asset_data::Model, + pub token_info: Option, pub authorities: Vec, pub creators: Vec, pub groups: Vec, + pub inscription: Option, } #[derive(Clone, Debug, PartialEq)] pub struct AssetRelated { diff --git a/digital_asset_types/src/dao/scopes/asset.rs b/digital_asset_types/src/dao/scopes/asset.rs index 60e01abc2..f7f820c15 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -1,12 +1,16 @@ use crate::{ dao::{ asset::{self}, - asset_authority, asset_creators, asset_data, asset_grouping, cl_audits_v2, - extensions::{self, instruction::PascalCase}, - sea_orm_active_enums::{Instruction, SpecificationAssetClass}, - Cursor, FullAsset, GroupingSize, Pagination, + asset_authority, asset_creators, asset_data, asset_grouping, asset_v1_account_attachments, + cl_audits_v2, + extensions::{self, asset_v1_account_attachment, instruction::PascalCase}, + sea_orm_active_enums::Instruction, + tokens, Cursor, FullAsset, GroupingSize, Pagination, + }, + rpc::{ + filter::AssetSortDirection, + options::{self, Options}, }, - rpc::{filter::AssetSortDirection, options::Options}, }; use indexmap::IndexMap; use sea_orm::{entity::*, query::*, ConnectionTrait, DbErr, Order}; @@ -60,7 +64,7 @@ pub async fn get_by_creator( sort_direction: Order, pagination: &Pagination, limit: u64, - show_unverified_collections: bool, + options: &Options, ) -> Result, DbErr> { let mut condition = Condition::all() .add(asset_creators::Column::Creator.eq(creator.clone())) @@ -76,7 +80,7 @@ pub async fn get_by_creator( sort_direction, pagination, limit, - show_unverified_collections, + options, Some(creator), ) .await @@ -112,13 +116,13 @@ pub async fn get_by_grouping( sort_direction: Order, pagination: &Pagination, limit: u64, - show_unverified_collections: bool, + options: &Options, ) -> Result, DbErr> { let mut condition = asset_grouping::Column::GroupKey .eq(group_key) .and(asset_grouping::Column::GroupValue.eq(group_value)); - if !show_unverified_collections { + if !options.show_unverified_collections { condition = condition.and( asset_grouping::Column::Verified .eq(true) @@ -136,7 +140,7 @@ pub async fn get_by_grouping( sort_direction, pagination, limit, - show_unverified_collections, + options, None, ) .await @@ -151,19 +155,10 @@ pub async fn get_assets_by_owner( limit: u64, options: &Options, ) -> Result, DbErr> { - let mut cond = Condition::all() + let cond = Condition::all() .add(asset::Column::Owner.eq(owner)) .add(asset::Column::Supply.gt(0)); - if options.show_fungible { - cond = cond.add( - asset::Column::SpecificationAssetClass - .eq(SpecificationAssetClass::FungibleToken) - .or(asset::Column::SpecificationAssetClass - .eq(SpecificationAssetClass::FungibleAsset)), - ); - } - get_assets_by_condition( conn, cond, @@ -172,7 +167,7 @@ pub async fn get_assets_by_owner( sort_direction, pagination, limit, - options.show_unverified_collections, + options, ) .await } @@ -184,19 +179,10 @@ pub async fn get_assets( limit: u64, options: &Options, ) -> Result, DbErr> { - let mut cond = Condition::all() + let cond = Condition::all() .add(asset::Column::Id.is_in(asset_ids)) .add(asset::Column::Supply.gt(0)); - if options.show_fungible { - cond = cond.add( - asset::Column::SpecificationAssetClass - .eq(SpecificationAssetClass::FungibleToken) - .or(asset::Column::SpecificationAssetClass - .eq(SpecificationAssetClass::FungibleAsset)), - ); - } - get_assets_by_condition( conn, cond, @@ -206,7 +192,7 @@ pub async fn get_assets( Order::Asc, pagination, limit, - false, + options, ) .await } @@ -218,7 +204,7 @@ pub async fn get_by_authority( sort_direction: Order, pagination: &Pagination, limit: u64, - show_unverified_collections: bool, + options: &Options, ) -> Result, DbErr> { let cond = Condition::all() .add(asset_authority::Column::Authority.eq(authority)) @@ -231,7 +217,7 @@ pub async fn get_by_authority( sort_direction, pagination, limit, - show_unverified_collections, + options, None, ) .await @@ -246,7 +232,7 @@ async fn get_by_related_condition( sort_direction: Order, pagination: &Pagination, limit: u64, - show_unverified_collections: bool, + options: &Options, required_creator: Option>, ) -> Result, DbErr> where @@ -265,19 +251,19 @@ where let assets = paginate(pagination, limit, stmt, sort_direction, asset::Column::Id) .all(conn) .await?; - get_related_for_assets(conn, assets, show_unverified_collections, required_creator).await + get_related_for_assets(conn, assets, options, required_creator).await } pub async fn get_related_for_assets( conn: &impl ConnectionTrait, assets: Vec, - show_unverified_collections: bool, + options: &Options, required_creator: Option>, ) -> Result, DbErr> { let asset_ids = assets.iter().map(|a| a.id.clone()).collect::>(); let asset_data: Vec = asset_data::Entity::find() - .filter(asset_data::Column::Id.is_in(asset_ids)) + .filter(asset_data::Column::Id.is_in(asset_ids.clone())) .all(conn) .await?; let asset_data_map = asset_data.into_iter().fold(HashMap::new(), |mut acc, ad| { @@ -299,6 +285,8 @@ pub async fn get_related_for_assets( authorities: vec![], creators: vec![], groups: vec![], + token_info: None, + inscription: None, }; acc.insert(id, fa); }; @@ -346,7 +334,7 @@ pub async fn get_related_for_assets( } } - let cond = if show_unverified_collections { + let cond = if options.show_unverified_collections { Condition::all() } else { Condition::any() @@ -363,6 +351,20 @@ pub async fn get_related_for_assets( .order_by_asc(asset_grouping::Column::AssetId) .all(conn) .await?; + + if options.show_inscription { + let attachments = asset_v1_account_attachments::Entity::find() + .filter(asset_v1_account_attachments::Column::AssetId.is_in(asset_ids.clone())) + .all(conn) + .await?; + + for a in attachments.into_iter() { + if let Some(asset) = assets_map.get_mut(&a.id) { + asset.inscription = Some(a); + } + } + } + for g in grouping.into_iter() { if let Some(asset) = assets_map.get_mut(&g.asset_id) { asset.groups.push(g); @@ -381,7 +383,7 @@ pub async fn get_assets_by_condition( sort_direction: Order, pagination: &Pagination, limit: u64, - show_unverified_collections: bool, + options: &Options, ) -> Result, DbErr> { let mut stmt = asset::Entity::find(); for def in joins { @@ -397,8 +399,7 @@ pub async fn get_assets_by_condition( let assets = paginate(pagination, limit, stmt, sort_direction, asset::Column::Id) .all(conn) .await?; - let full_assets = - get_related_for_assets(conn, assets, show_unverified_collections, None).await?; + let full_assets = get_related_for_assets(conn, assets, options, None).await?; Ok(full_assets) } @@ -414,14 +415,17 @@ pub async fn get_by_id( asset_data = asset_data.filter(Condition::all().add(asset::Column::Supply.gt(0))); } - if options.show_fungible { - asset_data = asset_data.filter( - asset::Column::SpecificationAssetClass - .eq(SpecificationAssetClass::FungibleToken) - .or(asset::Column::SpecificationAssetClass - .eq(SpecificationAssetClass::FungibleAsset)), - ); - } + let token_info = if options.show_fungible { + get_token_by_id(conn, asset_id.clone()).await.ok() + } else { + None + }; + + let inscription = if options.show_inscription { + get_inscription_by_id(conn, asset_id.clone()).await.ok() + } else { + None + }; let asset_data: (asset::Model, asset_data::Model) = asset_data.one(conn).await.and_then(|o| match o { @@ -462,6 +466,8 @@ pub async fn get_by_id( authorities, creators, groups: grouping, + token_info, + inscription, }) } @@ -585,3 +591,29 @@ fn filter_out_stale_creators(creators: &mut Vec) { } } } + +pub async fn get_token_by_id( + conn: &impl ConnectionTrait, + id: Vec, +) -> Result { + tokens::Entity::find_by_id(id) + .one(conn) + .await + .and_then(|o| match o { + Some(t) => Ok(t), + _ => Err(DbErr::RecordNotFound("Token Not Found".to_string())), + }) +} + +pub async fn get_inscription_by_id( + conn: &impl ConnectionTrait, + id: Vec, +) -> Result { + asset_v1_account_attachments::Entity::find_by_id(id) + .one(conn) + .await + .and_then(|o| match o { + Some(t) => Ok(t), + _ => Err(DbErr::RecordNotFound("Inscription Not Found".to_string())), + }) +} diff --git a/digital_asset_types/src/dapi/assets_by_authority.rs b/digital_asset_types/src/dapi/assets_by_authority.rs index 59404f3e0..b52891062 100644 --- a/digital_asset_types/src/dapi/assets_by_authority.rs +++ b/digital_asset_types/src/dapi/assets_by_authority.rs @@ -24,7 +24,7 @@ pub async fn get_assets_by_authority( sort_direction, &pagination, page_options.limit, - options.show_unverified_collections, + options, ) .await?; Ok(build_asset_response( diff --git a/digital_asset_types/src/dapi/assets_by_creator.rs b/digital_asset_types/src/dapi/assets_by_creator.rs index 9ce5de591..3a2b1e53e 100644 --- a/digital_asset_types/src/dapi/assets_by_creator.rs +++ b/digital_asset_types/src/dapi/assets_by_creator.rs @@ -27,7 +27,7 @@ pub async fn get_assets_by_creator( sort_direction, &pagination, page_options.limit, - options.show_unverified_collections, + options, ) .await?; Ok(build_asset_response( diff --git a/digital_asset_types/src/dapi/assets_by_group.rs b/digital_asset_types/src/dapi/assets_by_group.rs index 68784b9f4..36f4ae534 100644 --- a/digital_asset_types/src/dapi/assets_by_group.rs +++ b/digital_asset_types/src/dapi/assets_by_group.rs @@ -27,7 +27,7 @@ pub async fn get_assets_by_group( sort_direction, &pagination, page_options.limit, - options.show_unverified_collections, + options, ) .await?; Ok(build_asset_response( diff --git a/digital_asset_types/src/dapi/common/asset.rs b/digital_asset_types/src/dapi/common/asset.rs index c9a9dd486..be11dc03f 100644 --- a/digital_asset_types/src/dapi/common/asset.rs +++ b/digital_asset_types/src/dapi/common/asset.rs @@ -7,10 +7,13 @@ use crate::rpc::filter::{AssetSortBy, AssetSortDirection, AssetSorting}; use crate::rpc::options::Options; use crate::rpc::response::TransactionSignatureList; use crate::rpc::response::{AssetError, AssetList}; +use crate::rpc::TokenInfo; +use crate::rpc::TokenInscriptionInfo; use crate::rpc::{ Asset as RpcAsset, Authority, Compression, Content, Creator, File, Group, Interface, MetadataMap, MplCoreInfo, Ownership, Royalty, Scope, Supply, Uses, }; +use blockbuster::programs::token_inscriptions::InscriptionData; use jsonpath_lib::JsonPathError; use log::warn; use mime_guess::Mime; @@ -355,6 +358,8 @@ pub fn asset_to_rpc(asset: FullAsset, options: &Options) -> Result Result None, }; + let token_info = if options.show_fungible && token_info.is_some() { + let token_info = token_info.unwrap(); + Some(TokenInfo { + supply: token_info.supply.try_into().unwrap_or(0), + decimals: token_info.decimals as u8, + mint_authority: token_info + .mint_authority + .map(|s| bs58::encode(s).into_string()), + freeze_authority: token_info + .freeze_authority + .map(|s| bs58::encode(s).into_string()), + token_program: bs58::encode(token_info.token_program).into_string(), + }) + } else { + None + }; + + let inscription = if options.show_inscription && inscription.is_some() { + let inscription = inscription.unwrap(); + + inscription.data.map(|d| { + let deserialized_data: InscriptionData = serde_json::from_value(d).unwrap(); + TokenInscriptionInfo { + authority: deserialized_data.authority, + root: deserialized_data.root, + content: deserialized_data.content, + encoding: deserialized_data.encoding, + inscription_data: deserialized_data.inscription_data, + order: deserialized_data.order, + size: deserialized_data.size, + validation_hash: deserialized_data.validation_hash, + } + }) + } else { + None + }; + Ok(RpcAsset { interface: interface.clone(), id: bs58::encode(asset.id).into_string(), @@ -444,6 +486,8 @@ pub fn asset_to_rpc(asset: FullAsset, options: &Options) -> Result, } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct TokenInfo { + pub supply: u64, + pub decimals: u8, + pub token_program: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub mint_authority: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub freeze_authority: Option, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct TokenInscriptionInfo { + pub authority: String, + pub root: String, + pub inscription_data: String, + pub content: String, + pub encoding: String, + pub order: u64, + pub size: u32, + pub validation_hash: Option, +} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Asset { pub interface: Interface, @@ -389,6 +412,10 @@ pub struct Asset { pub mutable: bool, pub burnt: bool, #[serde(skip_serializing_if = "Option::is_none")] + pub token_info: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub inscription: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub plugins: Option, #[serde(skip_serializing_if = "Option::is_none")] pub unknown_plugins: Option, diff --git a/digital_asset_types/src/rpc/options.rs b/digital_asset_types/src/rpc/options.rs index 161ffba8b..8c389c60e 100644 --- a/digital_asset_types/src/rpc/options.rs +++ b/digital_asset_types/src/rpc/options.rs @@ -8,4 +8,6 @@ pub struct Options { pub show_unverified_collections: bool, #[serde(default)] pub show_fungible: bool, + #[serde(default)] + pub show_inscription: bool, }