From 09d200218380e8bfd79dc903bd46084a5734f432 Mon Sep 17 00:00:00 2001 From: AhzamAkhtar Date: Tue, 24 Dec 2024 21:03:39 +0530 Subject: [PATCH 1/3] fungible tokens skipped when using showFungible option bug fixed in getAssetByOwner --- .../src/dao/extensions/asset.rs | 13 +++++++- digital_asset_types/src/dao/extensions/mod.rs | 1 + .../src/dao/extensions/token_accounts.rs | 25 +++++++++++++++ digital_asset_types/src/dao/scopes/asset.rs | 31 ++++++++++++++----- 4 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 digital_asset_types/src/dao/extensions/token_accounts.rs diff --git a/digital_asset_types/src/dao/extensions/asset.rs b/digital_asset_types/src/dao/extensions/asset.rs index 18525e39e..058f8d135 100644 --- a/digital_asset_types/src/dao/extensions/asset.rs +++ b/digital_asset_types/src/dao/extensions/asset.rs @@ -2,7 +2,7 @@ use sea_orm::{EntityTrait, EnumIter, Related, RelationDef, RelationTrait}; use crate::dao::{ asset, asset_authority, asset_creators, asset_data, asset_grouping, - asset_v1_account_attachments, + asset_v1_account_attachments, token_accounts, sea_orm_active_enums::{OwnerType, RoyaltyTargetType}, }; @@ -13,6 +13,7 @@ pub enum Relation { AssetAuthority, AssetCreators, AssetGrouping, + TokenAccounts, } impl RelationTrait for Relation { @@ -22,6 +23,10 @@ impl RelationTrait for Relation { .from(asset::Column::AssetData) .to(asset_data::Column::Id) .into(), + Self::TokenAccounts => asset::Entity::belongs_to(token_accounts::Entity) + .from(asset::Column::Id) + .to(token_accounts::Column::Mint) + .into(), Self::AssetV1AccountAttachments => { asset::Entity::has_many(asset_v1_account_attachments::Entity).into() } @@ -62,6 +67,12 @@ impl Related for asset::Entity { } } +impl Related for asset::Entity { + fn to() -> RelationDef { + Relation::TokenAccounts.def() + } +} + impl Default for RoyaltyTargetType { fn default() -> Self { Self::Creators diff --git a/digital_asset_types/src/dao/extensions/mod.rs b/digital_asset_types/src/dao/extensions/mod.rs index bcfc3e130..cdc57c34c 100644 --- a/digital_asset_types/src/dao/extensions/mod.rs +++ b/digital_asset_types/src/dao/extensions/mod.rs @@ -5,3 +5,4 @@ pub mod asset_data; pub mod asset_grouping; pub mod asset_v1_account_attachment; pub mod instruction; +pub mod token_accounts; \ No newline at end of file diff --git a/digital_asset_types/src/dao/extensions/token_accounts.rs b/digital_asset_types/src/dao/extensions/token_accounts.rs new file mode 100644 index 000000000..d11ef5c95 --- /dev/null +++ b/digital_asset_types/src/dao/extensions/token_accounts.rs @@ -0,0 +1,25 @@ +use sea_orm::{EntityTrait, EnumIter, Related, RelationDef, RelationTrait}; + +use crate::dao::{asset , token_accounts}; + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Asset, +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Asset => token_accounts::Entity::belongs_to(asset::Entity) + .from(token_accounts::Column::Mint) + .to(asset::Column::Id) + .into(), + } + } +} + +impl Related for token_accounts::Entity { + fn to() -> RelationDef { + Relation::Asset.def() + } +} \ No newline at end of file diff --git a/digital_asset_types/src/dao/scopes/asset.rs b/digital_asset_types/src/dao/scopes/asset.rs index fd7cc6d2e..123fbbfef 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -1,13 +1,10 @@ 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, - tokens, Cursor, FullAsset, GroupingSize, Pagination, + asset::{self}, asset_authority, asset_creators, asset_data, asset_grouping, cl_audits_v2, extensions::{self, instruction::PascalCase}, sea_orm_active_enums::Instruction, token_accounts, tokens, Cursor, FullAsset, GroupingSize, Pagination }, rpc::{filter::AssetSortDirection, options::Options}, }; +use sea_orm::sea_query::{Expr, IntoCondition}; use indexmap::IndexMap; use sea_orm::{entity::*, query::*, ConnectionTrait, DbErr, Order}; use std::collections::HashMap; @@ -151,14 +148,32 @@ pub async fn get_assets_by_owner( limit: u64, options: &Options, ) -> Result, DbErr> { - let cond = Condition::all() - .add(asset::Column::Owner.eq(owner)) + + let mut joins = Vec::new(); + let mut cond = Condition::all() + .add(asset::Column::Owner.eq(owner.clone())) .add(asset::Column::Supply.gt(0)); + if options.show_fungible { + cond = Condition::all() + .add(token_accounts::Column::Owner.eq(owner.clone())); + + let rel = extensions::token_accounts::Relation::Asset + .def() + .rev() + .on_condition(|left,right| { + Expr::tbl(right, token_accounts::Column::Mint) + .eq(Expr::tbl(left, asset::Column::Id)) + .into_condition() + }); + + joins.push(rel); + } + get_assets_by_condition( conn, cond, - vec![], + joins, sort_by, sort_direction, pagination, From 4a0cabad22762eb8e4684fa4d85d15038900200c Mon Sep 17 00:00:00 2001 From: AhzamAkhtar Date: Tue, 24 Dec 2024 21:41:09 +0530 Subject: [PATCH 2/3] test-case and test-snapshot added --- ...RNfDfdq1nKyU1TQiCEQLWyPtD8EwUH9Kt2ahsbidUx | Bin 0 -> 312 bytes ...ajpcYgnxmWK91RhrfsdB3Tm83PcDwPvMC8ZinvtTY6 | Bin 0 -> 824 bytes ...YnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs | Bin 0 -> 224 bytes .../show_fungible_flag_tests.rs | 37 ++++++++++ ..._by_owner_with_show_fungible_scenario.snap | 65 ++++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 integration_tests/tests/data/accounts/get_asset_by_owner_with_show_fungible_scenario/6BRNfDfdq1nKyU1TQiCEQLWyPtD8EwUH9Kt2ahsbidUx create mode 100644 integration_tests/tests/data/accounts/get_asset_by_owner_with_show_fungible_scenario/7BajpcYgnxmWK91RhrfsdB3Tm83PcDwPvMC8ZinvtTY6 create mode 100644 integration_tests/tests/data/accounts/get_asset_by_owner_with_show_fungible_scenario/7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs create mode 100644 integration_tests/tests/integration_tests/snapshots/integration_tests__show_fungible_flag_tests__get_asset_by_owner_with_show_fungible_scenario.snap diff --git a/integration_tests/tests/data/accounts/get_asset_by_owner_with_show_fungible_scenario/6BRNfDfdq1nKyU1TQiCEQLWyPtD8EwUH9Kt2ahsbidUx b/integration_tests/tests/data/accounts/get_asset_by_owner_with_show_fungible_scenario/6BRNfDfdq1nKyU1TQiCEQLWyPtD8EwUH9Kt2ahsbidUx new file mode 100644 index 0000000000000000000000000000000000000000..035a8fc7eb66e42ec8ed229a9c6ca806c5590f51 GIT binary patch literal 312 zcmY#jfB*@G90nE!4+a$=H-NzfNJap00)qsQ^!a+$_0g5xjz_QDue^WuW!dxf{hF%2 zHoA{B?^T}N_F*mC-ER-Cr!Jg)^YlZvbFVAc$ZTnS8y{^x(W>WbYu$f_l^Q@ZKFG=g zNd|`hP@tw&ECk}$TIK$n%m`vJFf0Y)n0a&K7jw3Govm$@xU6PqbFaGXzQn`nlf0NE z^8d}Zt&%!#nz%OPZ=RdVX|D&>|DO4skZJq8<)c^+XGh|Tg%a8f-wNc!z@`xEX`>c+bCn552sJ^VwTANH{Z5O0ccQgW=>9}f=f|i zdVU_rV06F*6bSb8@reXWoB)y;B_##LR{Hwsi6yD!iIsYpMU};R6_r)`0TvNvCI#-L zC6y7Tsg)rGfw_fIMaCW`@jitaxdxt*6-B1Ol~rzTeyQ2$whR!Tk&*EqBQPXK0WCuS E0EE78Hvj+t literal 0 HcmV?d00001 diff --git a/integration_tests/tests/data/accounts/get_asset_by_owner_with_show_fungible_scenario/7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs b/integration_tests/tests/data/accounts/get_asset_by_owner_with_show_fungible_scenario/7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs new file mode 100644 index 0000000000000000000000000000000000000000..07a90f4b0710003caf51f95ec025031b1460aa24 GIT binary patch literal 224 zcmY#jfB*@G34$FTURSP>+0yzpKH7YuRnOPfy8jF-L1zB1-nCp4 zL_>k9RP=7D W*V*pzo2|MdAvog!FDFnBF#rG!K}l%< literal 0 HcmV?d00001 diff --git a/integration_tests/tests/integration_tests/show_fungible_flag_tests.rs b/integration_tests/tests/integration_tests/show_fungible_flag_tests.rs index 113e4ab22..944dea10b 100644 --- a/integration_tests/tests/integration_tests/show_fungible_flag_tests.rs +++ b/integration_tests/tests/integration_tests/show_fungible_flag_tests.rs @@ -82,3 +82,40 @@ async fn test_get_asset_with_show_fungible_scenario_2() { insta::assert_json_snapshot!(name, response); } + +#[tokio::test] +#[serial] +#[named] +async fn test_get_asset_by_owner_with_show_fungible_scenario() { + let name = trim_test_name(function_name!()); + let setup = TestSetup::new_with_options( + name.clone(), + TestSetupOptions { + network: Some(Network::Mainnet), + }, + ) + .await; + + let seeds: Vec = seed_accounts([ + "7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs", + "7BajpcYgnxmWK91RhrfsdB3Tm83PcDwPvMC8ZinvtTY6", + "6BRNfDfdq1nKyU1TQiCEQLWyPtD8EwUH9Kt2ahsbidUx", + ]); + + apply_migrations_and_delete_data(setup.db.clone()).await; + index_seed_events(&setup, seeds.iter().collect_vec()).await; + + let request = r#" + { + "ownerAddress": "2oerfxddTpK5hWAmCMYB6fr9WvNrjEH54CHCWK8sAq7g", + "displayOptions": { + "showFungible": true + } + } + "#; + + let request: api::GetAssetsByOwner = serde_json::from_str(request).unwrap(); + let response = setup.das_api.get_assets_by_owner(request).await.unwrap(); + + insta::assert_json_snapshot!(name, response); +} diff --git a/integration_tests/tests/integration_tests/snapshots/integration_tests__show_fungible_flag_tests__get_asset_by_owner_with_show_fungible_scenario.snap b/integration_tests/tests/integration_tests/snapshots/integration_tests__show_fungible_flag_tests__get_asset_by_owner_with_show_fungible_scenario.snap new file mode 100644 index 000000000..607c278e5 --- /dev/null +++ b/integration_tests/tests/integration_tests/snapshots/integration_tests__show_fungible_flag_tests__get_asset_by_owner_with_show_fungible_scenario.snap @@ -0,0 +1,65 @@ +--- +source: integration_tests/tests/integration_tests/show_fungible_flag_tests.rs +expression: response +snapshot_kind: text +--- +{ + "total": 1, + "limit": 1000, + "cursor": "7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs", + "items": [ + { + "interface": "Custom", + "id": "7EYnhQoR9YM3N7UoaKRoA44Uy8JeaZV3qyouov87awMs", + "content": { + "$schema": "https://schema.metaplex.com/nft1.0.json", + "json_uri": "https://gateway.irys.xyz/P8X64pGutyX5eyTpQmqZr3H4_Lqhm0IYxr5SyzFFNek", + "files": [], + "metadata": { + "name": "Silly Dragon", + "symbol": "SILLY", + "token_standard": "Fungible" + }, + "links": {} + }, + "authorities": [ + { + "address": "38qZKCqcphT5wDrVNJGHYcuenjEtEFPitvrqvMFQkPu7", + "scopes": [ + "full" + ] + } + ], + "compression": { + "eligible": false, + "compressed": false, + "data_hash": "", + "creator_hash": "", + "asset_hash": "", + "tree": "", + "seq": 0, + "leaf_id": 0 + }, + "grouping": [], + "royalty": { + "royalty_model": "creators", + "target": null, + "percent": 0.0, + "basis_points": 0, + "primary_sale_happened": true, + "locked": false + }, + "creators": [], + "ownership": { + "frozen": false, + "delegated": false, + "delegate": null, + "ownership_model": "token", + "owner": "" + }, + "supply": null, + "mutable": true, + "burnt": false + } + ] +} From 93bbfa2583be44949382c135d7a6438b72a28c4c Mon Sep 17 00:00:00 2001 From: AhzamAkhtar Date: Wed, 25 Dec 2024 00:06:31 +0530 Subject: [PATCH 3/3] cleanup --- .../src/dao/extensions/asset.rs | 3 ++- digital_asset_types/src/dao/extensions/mod.rs | 2 +- .../src/dao/extensions/token_accounts.rs | 4 ++-- digital_asset_types/src/dao/scopes/asset.rs | 22 ++++++++++--------- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/digital_asset_types/src/dao/extensions/asset.rs b/digital_asset_types/src/dao/extensions/asset.rs index 058f8d135..3ac3f724f 100644 --- a/digital_asset_types/src/dao/extensions/asset.rs +++ b/digital_asset_types/src/dao/extensions/asset.rs @@ -2,8 +2,9 @@ use sea_orm::{EntityTrait, EnumIter, Related, RelationDef, RelationTrait}; use crate::dao::{ asset, asset_authority, asset_creators, asset_data, asset_grouping, - asset_v1_account_attachments, token_accounts, + asset_v1_account_attachments, sea_orm_active_enums::{OwnerType, RoyaltyTargetType}, + token_accounts, }; #[derive(Copy, Clone, Debug, EnumIter)] diff --git a/digital_asset_types/src/dao/extensions/mod.rs b/digital_asset_types/src/dao/extensions/mod.rs index cdc57c34c..af3baad66 100644 --- a/digital_asset_types/src/dao/extensions/mod.rs +++ b/digital_asset_types/src/dao/extensions/mod.rs @@ -5,4 +5,4 @@ pub mod asset_data; pub mod asset_grouping; pub mod asset_v1_account_attachment; pub mod instruction; -pub mod token_accounts; \ No newline at end of file +pub mod token_accounts; diff --git a/digital_asset_types/src/dao/extensions/token_accounts.rs b/digital_asset_types/src/dao/extensions/token_accounts.rs index d11ef5c95..e48408f74 100644 --- a/digital_asset_types/src/dao/extensions/token_accounts.rs +++ b/digital_asset_types/src/dao/extensions/token_accounts.rs @@ -1,6 +1,6 @@ use sea_orm::{EntityTrait, EnumIter, Related, RelationDef, RelationTrait}; -use crate::dao::{asset , token_accounts}; +use crate::dao::{asset, token_accounts}; #[derive(Copy, Clone, Debug, EnumIter)] pub enum Relation { @@ -22,4 +22,4 @@ impl Related for token_accounts::Entity { fn to() -> RelationDef { Relation::Asset.def() } -} \ No newline at end of file +} diff --git a/digital_asset_types/src/dao/scopes/asset.rs b/digital_asset_types/src/dao/scopes/asset.rs index 123fbbfef..0e4cb699d 100644 --- a/digital_asset_types/src/dao/scopes/asset.rs +++ b/digital_asset_types/src/dao/scopes/asset.rs @@ -1,11 +1,15 @@ 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, token_accounts, tokens, Cursor, FullAsset, GroupingSize, Pagination + asset::{self}, + asset_authority, asset_creators, asset_data, asset_grouping, cl_audits_v2, + extensions::{self, instruction::PascalCase}, + sea_orm_active_enums::Instruction, + token_accounts, tokens, Cursor, FullAsset, GroupingSize, Pagination, }, rpc::{filter::AssetSortDirection, options::Options}, }; -use sea_orm::sea_query::{Expr, IntoCondition}; use indexmap::IndexMap; +use sea_orm::sea_query::{Expr, IntoCondition}; use sea_orm::{entity::*, query::*, ConnectionTrait, DbErr, Order}; use std::collections::HashMap; @@ -148,28 +152,26 @@ pub async fn get_assets_by_owner( limit: u64, options: &Options, ) -> Result, DbErr> { - let mut joins = Vec::new(); let mut cond = Condition::all() .add(asset::Column::Owner.eq(owner.clone())) .add(asset::Column::Supply.gt(0)); if options.show_fungible { - cond = Condition::all() - .add(token_accounts::Column::Owner.eq(owner.clone())); - + cond = Condition::all().add(token_accounts::Column::Owner.eq(owner.clone())); + let rel = extensions::token_accounts::Relation::Asset .def() .rev() - .on_condition(|left,right| { + .on_condition(|left, right| { Expr::tbl(right, token_accounts::Column::Mint) .eq(Expr::tbl(left, asset::Column::Id)) .into_condition() - }); - + }); + joins.push(rel); } - + get_assets_by_condition( conn, cond,