diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 4efcce8e9..35ff93505 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -848,6 +848,26 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "const_format" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "cookie" version = "0.17.0" @@ -3331,6 +3351,7 @@ dependencies = [ "canonical_json", "chrono", "clap", + "const_format", "diesel", "diesel-async", "diesel_migrations", @@ -5200,6 +5221,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" +[[package]] +name = "unicode-xid" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" + [[package]] name = "untrusted" version = "0.7.1" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 9ba106d11..b9a2588e7 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -42,6 +42,7 @@ bigdecimal = { version = "0.4.0", features = ["serde"] } bitflags = "2.5.0" chrono = { version = "0.4.19", features = ["clock", "serde"] } clap = { version = "4.3.5", features = ["derive", "unstable-styles"] } +const_format = "0.2.33" # Do NOT enable the postgres feature here, it is conditionally enabled in a feature # block in the Cargo.toml file for the processor crate. # https://github.com/aptos-labs/aptos-indexer-processors/pull/325 diff --git a/rust/processor/Cargo.toml b/rust/processor/Cargo.toml index 32c87ad6a..964e6fb63 100644 --- a/rust/processor/Cargo.toml +++ b/rust/processor/Cargo.toml @@ -27,6 +27,7 @@ bitflags = { workspace = true } canonical_json = { workspace = true } chrono = { workspace = true } clap = { workspace = true } +const_format = { workspace = true } diesel = { workspace = true } diesel-async = { workspace = true } diesel_migrations = { workspace = true } diff --git a/rust/processor/src/db/common/models/account_transaction_models/account_transactions.rs b/rust/processor/src/db/common/models/account_transaction_models/account_transactions.rs index 385d1e010..611e16652 100644 --- a/rust/processor/src/db/common/models/account_transaction_models/account_transactions.rs +++ b/rust/processor/src/db/common/models/account_transaction_models/account_transactions.rs @@ -7,7 +7,7 @@ use crate::{ db::common::models::{ - object_models::v2_object_utils::ObjectWithMetadata, + object_models::v2_object_utils::ObjectWithMetadata, resources::FromWriteResource, user_transactions_models::user_transactions::UserTransaction, }, schema::account_transactions, @@ -98,9 +98,7 @@ impl AccountTransaction { // owner as well. // This handles partial deletes as well. accounts.insert(standardize_address(res.address.as_str())); - if let Some(inner) = - &ObjectWithMetadata::from_write_resource(res, txn_version).unwrap() - { + if let Some(inner) = &ObjectWithMetadata::from_write_resource(res).unwrap() { accounts.insert(inner.object_core.get_owner_address()); } }, diff --git a/rust/processor/src/db/common/models/coin_models/coin_utils.rs b/rust/processor/src/db/common/models/coin_models/coin_utils.rs index ec46f532c..b8a378156 100644 --- a/rust/processor/src/db/common/models/coin_models/coin_utils.rs +++ b/rust/processor/src/db/common/models/coin_models/coin_utils.rs @@ -5,7 +5,7 @@ #![allow(clippy::extra_unused_lifetimes)] use crate::{ - db::common::models::default_models::move_resources::MoveResource, + db::common::models::{default_models::move_resources::MoveResource, resources::COIN_ADDR}, utils::util::{deserialize_from_string, hash_str, standardize_address, truncate_str}, }; use anyhow::{bail, Context, Result}; @@ -16,7 +16,6 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use tracing::error; -pub const COIN_ADDR: &str = "0x0000000000000000000000000000000000000000000000000000000000000001"; const COIN_TYPE_HASH_LENGTH: usize = 5000; const COIN_TYPE_MAX: usize = 1000; diff --git a/rust/processor/src/db/common/models/fungible_asset_models/parquet_v2_fungible_asset_balances.rs b/rust/processor/src/db/common/models/fungible_asset_models/parquet_v2_fungible_asset_balances.rs index d5140e92f..3418e663a 100644 --- a/rust/processor/src/db/common/models/fungible_asset_models/parquet_v2_fungible_asset_balances.rs +++ b/rust/processor/src/db/common/models/fungible_asset_models/parquet_v2_fungible_asset_balances.rs @@ -17,6 +17,7 @@ use crate::{ v2_fungible_asset_utils::FungibleAssetStore, }, object_models::v2_object_utils::ObjectAggregatedDataMapping, + resources::FromWriteResource, token_v2_models::v2_token_utils::TokenStandard, }, utils::util::standardize_address, @@ -76,8 +77,7 @@ impl FungibleAssetBalance { txn_timestamp: chrono::NaiveDateTime, object_metadatas: &ObjectAggregatedDataMapping, ) -> anyhow::Result> { - if let Some(inner) = &FungibleAssetStore::from_write_resource(write_resource, txn_version)? - { + if let Some(inner) = &FungibleAssetStore::from_write_resource(write_resource)? { let storage_id = standardize_address(write_resource.address.as_str()); // Need to get the object of the store if let Some(object_data) = object_metadatas.get(&storage_id) { diff --git a/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_balances.rs b/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_balances.rs index 3bf244824..de16146dc 100644 --- a/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_balances.rs +++ b/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_balances.rs @@ -12,6 +12,7 @@ use crate::{ db::common::models::{ coin_models::coin_utils::{CoinInfoType, CoinResource}, object_models::v2_object_utils::ObjectAggregatedDataMapping, + resources::FromWriteResource, token_v2_models::v2_token_utils::{TokenStandard, V2_STANDARD}, }, schema::{ @@ -157,8 +158,7 @@ impl FungibleAssetBalance { txn_timestamp: chrono::NaiveDateTime, object_metadatas: &ObjectAggregatedDataMapping, ) -> anyhow::Result> { - if let Some(inner) = &FungibleAssetStore::from_write_resource(write_resource, txn_version)? - { + if let Some(inner) = &FungibleAssetStore::from_write_resource(write_resource)? { let storage_id = standardize_address(write_resource.address.as_str()); // Need to get the object of the store if let Some(object_data) = object_metadatas.get(&storage_id) { diff --git a/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_utils.rs b/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_utils.rs index 3e5bc5fbe..0ae413f03 100644 --- a/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_utils.rs +++ b/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_asset_utils.rs @@ -6,7 +6,6 @@ use crate::{ db::common::models::{ - coin_models::coin_utils::COIN_ADDR, default_models::move_resources::MoveResource, token_models::token_utils::URI_LENGTH, token_v2_models::v2_token_utils::ResourceReference, }, utils::util::{deserialize_from_string, truncate_str, Aggregator}, @@ -54,35 +53,15 @@ pub struct FungibleAssetMetadata { project_uri: String, } -impl FungibleAssetMetadata { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2FungibleAssetResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2FungibleAssetResource::FungibleAssetMetadata(inner) = - V2FungibleAssetResource::from_resource( - &type_str, - resource.data.as_ref().unwrap(), - txn_version, - )? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for FungibleAssetMetadata { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } +} +impl FungibleAssetMetadata { pub fn get_name(&self) -> String { truncate_str(&self.name, FUNGIBLE_ASSET_LENGTH) } @@ -108,33 +87,11 @@ pub struct FungibleAssetStore { pub frozen: bool, } -impl FungibleAssetStore { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2FungibleAssetResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2FungibleAssetResource::FungibleAssetStore(inner) = - V2FungibleAssetResource::from_resource( - &type_str, - resource.data.as_ref().unwrap(), - txn_version, - )? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for FungibleAssetStore { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -153,35 +110,15 @@ pub struct OptionalBigDecimal { #[derive(Serialize, Deserialize, Debug, Clone)] struct BigDecimalWrapper(#[serde(deserialize_with = "deserialize_from_string")] pub BigDecimal); -impl FungibleAssetSupply { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str: String = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2FungibleAssetResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2FungibleAssetResource::FungibleAssetSupply(inner) = - V2FungibleAssetResource::from_resource( - &type_str, - resource.data.as_ref().unwrap(), - txn_version, - )? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for FungibleAssetSupply { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } +} +impl FungibleAssetSupply { pub fn get_maximum(&self) -> Option { self.maximum.vec.first().map(|x| x.0.clone()) } @@ -192,33 +129,11 @@ pub struct ConcurrentFungibleAssetSupply { pub current: Aggregator, } -impl ConcurrentFungibleAssetSupply { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str: String = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2FungibleAssetResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2FungibleAssetResource::ConcurrentFungibleAssetSupply(inner) = - V2FungibleAssetResource::from_resource( - &type_str, - resource.data.as_ref().unwrap(), - txn_version, - )? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for ConcurrentFungibleAssetSupply { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -227,33 +142,11 @@ pub struct ConcurrentFungibleAssetBalance { pub balance: Aggregator, } -impl ConcurrentFungibleAssetBalance { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str: String = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2FungibleAssetResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2FungibleAssetResource::ConcurrentFungibleAssetBalance(inner) = - V2FungibleAssetResource::from_resource( - &type_str, - resource.data.as_ref().unwrap(), - txn_version, - )? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for ConcurrentFungibleAssetBalance { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -294,66 +187,6 @@ pub struct FrozenEventV2 { pub frozen: bool, } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum V2FungibleAssetResource { - FungibleAssetMetadata(FungibleAssetMetadata), - FungibleAssetStore(FungibleAssetStore), - FungibleAssetSupply(FungibleAssetSupply), - ConcurrentFungibleAssetSupply(ConcurrentFungibleAssetSupply), - ConcurrentFungibleAssetBalance(ConcurrentFungibleAssetBalance), -} - -impl V2FungibleAssetResource { - pub fn is_resource_supported(data_type: &str) -> bool { - [ - format!("{}::fungible_asset::Supply", COIN_ADDR), - format!("{}::fungible_asset::ConcurrentSupply", COIN_ADDR), - format!("{}::fungible_asset::Metadata", COIN_ADDR), - format!("{}::fungible_asset::FungibleStore", COIN_ADDR), - format!("{}::fungible_asset::ConcurrentFungibleBalance", COIN_ADDR), - ] - .contains(&data_type.to_string()) - } - - pub fn from_resource( - data_type: &str, - data: &serde_json::Value, - txn_version: i64, - ) -> Result { - match data_type { - x if x == format!("{}::fungible_asset::Supply", COIN_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::FungibleAssetSupply(inner))) - }, - x if x == format!("{}::fungible_asset::ConcurrentSupply", COIN_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::ConcurrentFungibleAssetSupply(inner))) - }, - x if x == format!("{}::fungible_asset::Metadata", COIN_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::FungibleAssetMetadata(inner))) - }, - x if x == format!("{}::fungible_asset::FungibleStore", COIN_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::FungibleAssetStore(inner))) - }, - x if x == format!("{}::fungible_asset::ConcurrentFungibleBalance", COIN_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::ConcurrentFungibleAssetBalance(inner))) - }, - _ => Ok(None), - } - .context(format!( - "version {} failed! failed to parse type {}, data {:?}", - txn_version, data_type, data - ))? - .context(format!( - "Resource unsupported! Call is_resource_supported first. version {} type {}", - txn_version, data_type - )) - } -} - pub enum FungibleAssetEvent { DepositEvent(DepositEvent), WithdrawEvent(WithdrawEvent), @@ -396,6 +229,7 @@ impl FungibleAssetEvent { #[cfg(test)] mod tests { use super::*; + use crate::db::common::models::resources::V2FungibleAssetResource; #[test] fn test_fungible_asset_supply_null() { diff --git a/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_metadata.rs b/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_metadata.rs index bcb1df18d..6e89fd6a8 100644 --- a/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_metadata.rs +++ b/rust/processor/src/db/common/models/fungible_asset_models/v2_fungible_metadata.rs @@ -10,6 +10,7 @@ use crate::{ db::common::models::{ coin_models::coin_utils::{CoinInfoType, CoinResource}, object_models::v2_object_utils::ObjectAggregatedDataMapping, + resources::FromWriteResource, token_v2_models::v2_token_utils::TokenStandard, }, schema::fungible_asset_metadata, @@ -56,9 +57,7 @@ impl FungibleAssetMetadataModel { txn_timestamp: chrono::NaiveDateTime, object_metadatas: &ObjectAggregatedDataMapping, ) -> anyhow::Result> { - if let Some(inner) = - &FungibleAssetMetadata::from_write_resource(write_resource, txn_version)? - { + if let Some(inner) = &FungibleAssetMetadata::from_write_resource(write_resource)? { // the new coin type let asset_type = standardize_address(&write_resource.address.to_string()); if let Some(object_metadata) = object_metadatas.get(&asset_type) { diff --git a/rust/processor/src/db/common/models/mod.rs b/rust/processor/src/db/common/models/mod.rs index cf80f3fc0..6cd0614c1 100644 --- a/rust/processor/src/db/common/models/mod.rs +++ b/rust/processor/src/db/common/models/mod.rs @@ -11,6 +11,7 @@ pub mod ledger_info; pub mod object_models; pub mod processor_status; pub mod property_map; +pub mod resources; pub mod stake_models; pub mod token_models; pub mod token_v2_models; diff --git a/rust/processor/src/db/common/models/object_models/v2_object_utils.rs b/rust/processor/src/db/common/models/object_models/v2_object_utils.rs index 617e98f00..135409bce 100644 --- a/rust/processor/src/db/common/models/object_models/v2_object_utils.rs +++ b/rust/processor/src/db/common/models/object_models/v2_object_utils.rs @@ -7,14 +7,14 @@ use crate::{ db::common::models::{ - default_models::move_resources::MoveResource, fungible_asset_models::v2_fungible_asset_utils::{ ConcurrentFungibleAssetBalance, ConcurrentFungibleAssetSupply, FungibleAssetMetadata, FungibleAssetStore, FungibleAssetSupply, }, + resources::FromWriteResource, token_v2_models::v2_token_utils::{ AptosCollection, ConcurrentSupply, FixedSupply, PropertyMapModel, TokenIdentifiers, - TokenV2, TransferEvent, UnlimitedSupply, V2TokenResource, + TokenV2, TransferEvent, UnlimitedSupply, }, }, utils::util::{deserialize_from_string, standardize_address}, @@ -100,67 +100,49 @@ impl ObjectCore { } } +impl TryFrom<&WriteResource> for ObjectCore { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) + } +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ObjectWithMetadata { pub object_core: ObjectCore, pub state_key_hash: String, } -impl ObjectWithMetadata { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - if let V2TokenResource::ObjectCore(inner) = V2TokenResource::from_resource( - &type_str, - &serde_json::from_str(write_resource.data.as_str()).unwrap(), - txn_version, - )? { - Ok(Some(Self { - object_core: inner, - state_key_hash: standardize_address( +impl FromWriteResource<'_> for ObjectWithMetadata { + fn from_write_resource(write_resource: &WriteResource) -> anyhow::Result> { + Ok( + ObjectCore::from_write_resource(write_resource)?.map(|object_core| { + let state_key_hash = standardize_address( hex::encode(write_resource.state_key_hash.as_slice()).as_str(), - ), - })) - } else { - Ok(None) - } + ); + Self { + object_core, + state_key_hash, + } + }), + ) } +} +impl ObjectWithMetadata { pub fn get_state_key_hash(&self) -> String { standardize_address(&self.state_key_hash) } } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Untransferable {} - -impl Untransferable { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::Untransferable(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - Ok(Some(inner)) - } else { - Ok(None) - } +pub struct Untransferable; + +impl TryFrom<&WriteResource> for Untransferable { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } diff --git a/rust/processor/src/db/common/models/resources.rs b/rust/processor/src/db/common/models/resources.rs new file mode 100644 index 000000000..6a24a877f --- /dev/null +++ b/rust/processor/src/db/common/models/resources.rs @@ -0,0 +1,212 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::db::common::models::{ + default_models::move_resources::MoveResource, + fungible_asset_models::v2_fungible_asset_utils::{ + ConcurrentFungibleAssetBalance, ConcurrentFungibleAssetSupply, FungibleAssetMetadata, + FungibleAssetStore, FungibleAssetSupply, + }, + object_models::v2_object_utils::{ObjectCore, Untransferable}, + token_v2_models::v2_token_utils::{ + AptosCollection, Collection, ConcurrentSupply, FixedSupply, PropertyMapModel, + TokenIdentifiers, TokenV2, UnlimitedSupply, + }, +}; +use anyhow::Result; +use aptos_protos::transaction::v1::WriteResource; +use const_format::formatcp; + +pub const COIN_ADDR: &str = "0x0000000000000000000000000000000000000000000000000000000000000001"; +pub const TOKEN_ADDR: &str = "0x0000000000000000000000000000000000000000000000000000000000000003"; +pub const TOKEN_V2_ADDR: &str = + "0x0000000000000000000000000000000000000000000000000000000000000004"; + +pub const TYPE_FUNGIBLE_ASSET_SUPPLY: &str = formatcp!("{COIN_ADDR}::fungible_asset::Supply"); +pub const TYPE_CONCURRENT_FUNGIBLE_ASSET_SUPPLY: &str = + formatcp!("{COIN_ADDR}::fungible_asset::ConcurrentSupply"); +pub const TYPE_FUNGIBLE_ASSET_METADATA: &str = formatcp!("{COIN_ADDR}::fungible_asset::Metadata"); +pub const TYPE_FUNGIBLE_ASSET_STORE: &str = formatcp!("{COIN_ADDR}::fungible_asset::FungibleStore"); +pub const TYPE_CONCURRENT_FUNGIBLE_ASSET_BALANCE: &str = + formatcp!("{COIN_ADDR}::fungible_asset::ConcurrentFungibleAssetBalance"); + +pub const TYPE_OBJECT_CORE: &str = formatcp!("{COIN_ADDR}::object::ObjectCore"); +pub const TYPE_UNTRANSFERABLE: &str = formatcp!("{COIN_ADDR}::object::Untransferable"); +pub const TYPE_COLLECTION: &str = formatcp!("{TOKEN_V2_ADDR}::collection::Collection"); +pub const TYPE_CONCURRENT_SUPPLY: &str = formatcp!("{TOKEN_V2_ADDR}::collection::ConcurrentSupply"); +pub const TYPE_FIXED_SUPPLY: &str = formatcp!("{TOKEN_V2_ADDR}::collection::FixedSupply"); +pub const TYPE_UNLIMITED_SUPPLY: &str = formatcp!("{TOKEN_V2_ADDR}::collection::UnlimitedSupply"); +pub const TYPE_APOTS_COLLECTION: &str = formatcp!("{TOKEN_V2_ADDR}::aptos_token::AptosCollection"); +pub const TYPE_TOKEN_V2: &str = formatcp!("{TOKEN_V2_ADDR}::token::Token"); +pub const TYPE_TOKEN_IDENTIFIERS: &str = formatcp!("{TOKEN_V2_ADDR}::token::TokenIdentifiers"); +pub const TYPE_PROPERTY_MAP: &str = formatcp!("{TOKEN_V2_ADDR}::property_map::PropertyMap"); + +pub trait Resource { + fn type_str() -> &'static str; +} + +pub trait FromWriteResource<'a> { + fn from_write_resource(write_resource: &'a WriteResource) -> Result> + where + Self: Sized; +} + +impl<'a, T> FromWriteResource<'a> for T +where + T: TryFrom<&'a WriteResource, Error = anyhow::Error> + Resource, +{ + fn from_write_resource(write_resource: &'a WriteResource) -> Result> { + if MoveResource::get_outer_type_from_write_resource(write_resource) != Self::type_str() { + return Ok(None); + } + Ok(Some(write_resource.try_into()?)) + } +} + +pub enum V2FungibleAssetResource { + ConcurrentFungibleAssetBalance(ConcurrentFungibleAssetBalance), + ConcurrentFungibleAssetSupply(ConcurrentFungibleAssetSupply), + FungibleAssetMetadata(FungibleAssetMetadata), + FungibleAssetStore(FungibleAssetStore), + FungibleAssetSupply(FungibleAssetSupply), +} + +impl Resource for ConcurrentFungibleAssetBalance { + fn type_str() -> &'static str { + TYPE_CONCURRENT_FUNGIBLE_ASSET_BALANCE + } +} + +impl Resource for ConcurrentFungibleAssetSupply { + fn type_str() -> &'static str { + TYPE_CONCURRENT_FUNGIBLE_ASSET_SUPPLY + } +} + +impl Resource for FungibleAssetMetadata { + fn type_str() -> &'static str { + TYPE_FUNGIBLE_ASSET_METADATA + } +} + +impl Resource for FungibleAssetStore { + fn type_str() -> &'static str { + TYPE_FUNGIBLE_ASSET_STORE + } +} + +impl Resource for FungibleAssetSupply { + fn type_str() -> &'static str { + TYPE_FUNGIBLE_ASSET_SUPPLY + } +} + +impl V2FungibleAssetResource { + pub fn from_write_resource(write_resource: &WriteResource) -> Result> { + let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); + Ok(Some(match type_str.as_str() { + TYPE_CONCURRENT_FUNGIBLE_ASSET_BALANCE => { + Self::ConcurrentFungibleAssetBalance(write_resource.try_into()?) + }, + TYPE_CONCURRENT_FUNGIBLE_ASSET_SUPPLY => { + Self::ConcurrentFungibleAssetSupply(write_resource.try_into()?) + }, + TYPE_FUNGIBLE_ASSET_METADATA => Self::FungibleAssetMetadata(write_resource.try_into()?), + TYPE_FUNGIBLE_ASSET_STORE => Self::FungibleAssetStore(write_resource.try_into()?), + TYPE_FUNGIBLE_ASSET_SUPPLY => Self::FungibleAssetSupply(write_resource.try_into()?), + _ => return Ok(None), + })) + } +} + +pub enum V2TokenResource { + AptosCollection(AptosCollection), + Collection(Collection), + ConcurrentSupply(ConcurrentSupply), + FixedSupply(FixedSupply), + ObjectCore(ObjectCore), + PropertyMapModel(PropertyMapModel), + TokenIdentifiers(TokenIdentifiers), + TokenV2(TokenV2), + UnlimitedSupply(UnlimitedSupply), + Untransferable(Untransferable), +} + +impl Resource for AptosCollection { + fn type_str() -> &'static str { + TYPE_APOTS_COLLECTION + } +} + +impl Resource for Collection { + fn type_str() -> &'static str { + TYPE_COLLECTION + } +} + +impl Resource for ConcurrentSupply { + fn type_str() -> &'static str { + TYPE_CONCURRENT_SUPPLY + } +} + +impl Resource for FixedSupply { + fn type_str() -> &'static str { + TYPE_FIXED_SUPPLY + } +} + +impl Resource for ObjectCore { + fn type_str() -> &'static str { + TYPE_OBJECT_CORE + } +} + +impl Resource for PropertyMapModel { + fn type_str() -> &'static str { + TYPE_PROPERTY_MAP + } +} + +impl Resource for TokenIdentifiers { + fn type_str() -> &'static str { + TYPE_TOKEN_IDENTIFIERS + } +} + +impl Resource for TokenV2 { + fn type_str() -> &'static str { + TYPE_TOKEN_V2 + } +} + +impl Resource for UnlimitedSupply { + fn type_str() -> &'static str { + TYPE_UNLIMITED_SUPPLY + } +} + +impl Resource for Untransferable { + fn type_str() -> &'static str { + TYPE_UNTRANSFERABLE + } +} + +impl V2TokenResource { + pub fn from_write_resource(write_resource: &WriteResource) -> Result> { + let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); + Ok(Some(match type_str.as_str() { + TYPE_APOTS_COLLECTION => Self::AptosCollection(write_resource.try_into()?), + TYPE_COLLECTION => Self::Collection(write_resource.try_into()?), + TYPE_CONCURRENT_SUPPLY => Self::ConcurrentSupply(write_resource.try_into()?), + TYPE_FIXED_SUPPLY => Self::FixedSupply(write_resource.try_into()?), + TYPE_OBJECT_CORE => Self::ObjectCore(write_resource.try_into()?), + TYPE_PROPERTY_MAP => Self::PropertyMapModel(write_resource.try_into()?), + TYPE_TOKEN_IDENTIFIERS => Self::TokenIdentifiers(write_resource.try_into()?), + TYPE_TOKEN_V2 => Self::TokenV2(write_resource.try_into()?), + TYPE_UNLIMITED_SUPPLY => Self::UnlimitedSupply(write_resource.try_into()?), + TYPE_UNTRANSFERABLE => Self::Untransferable(write_resource.try_into()?), + _ => return Ok(None), + })) + } +} diff --git a/rust/processor/src/db/common/models/token_models/token_utils.rs b/rust/processor/src/db/common/models/token_models/token_utils.rs index aa2d74c18..5b9f1e1dd 100644 --- a/rust/processor/src/db/common/models/token_models/token_utils.rs +++ b/rust/processor/src/db/common/models/token_models/token_utils.rs @@ -4,16 +4,18 @@ // This is required because a diesel macro makes clippy sad #![allow(clippy::extra_unused_lifetimes)] -use crate::utils::util::{ - deserialize_from_string, deserialize_property_map_from_bcs_hexstring, - deserialize_string_from_hexstring, hash_str, standardize_address, truncate_str, +use crate::{ + db::common::models::resources::TOKEN_ADDR, + utils::util::{ + deserialize_from_string, deserialize_property_map_from_bcs_hexstring, + deserialize_string_from_hexstring, hash_str, standardize_address, truncate_str, + }, }; use anyhow::{Context, Result}; use bigdecimal::BigDecimal; use serde::{Deserialize, Serialize}; use std::fmt::{self, Formatter}; -pub const TOKEN_ADDR: &str = "0x0000000000000000000000000000000000000000000000000000000000000003"; pub const NAME_LENGTH: usize = 128; pub const URI_LENGTH: usize = 512; diff --git a/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_datas.rs b/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_datas.rs index 0f06fc1d6..5ea635c52 100644 --- a/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_datas.rs +++ b/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_datas.rs @@ -9,6 +9,7 @@ use crate::{ bq_analytics::generic_parquet_processor::{GetTimeStamp, HasVersion, NamedTable}, db::common::models::{ object_models::v2_object_utils::ObjectAggregatedDataMapping, + resources::FromWriteResource, token_models::token_utils::TokenWriteSet, token_v2_models::{ v2_token_datas::CurrentTokenDataV2, @@ -71,7 +72,7 @@ impl TokenDataV2 { txn_timestamp: chrono::NaiveDateTime, object_metadatas: &ObjectAggregatedDataMapping, ) -> anyhow::Result> { - if let Some(inner) = &TokenV2::from_write_resource(write_resource, txn_version)? { + if let Some(inner) = &TokenV2::from_write_resource(write_resource)? { let token_data_id = standardize_address(&write_resource.address.to_string()); let mut token_name = inner.get_name_trunc(); let is_fungible_v2; diff --git a/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_ownerships.rs b/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_ownerships.rs index 267d332c0..9089b1604 100644 --- a/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_ownerships.rs +++ b/rust/processor/src/db/common/models/token_v2_models/parquet_v2_token_ownerships.rs @@ -10,6 +10,7 @@ use crate::{ db::common::models::{ fungible_asset_models::parquet_v2_fungible_asset_balances::DEFAULT_AMOUNT_VALUE, object_models::v2_object_utils::{ObjectAggregatedDataMapping, ObjectWithMetadata}, + resources::FromWriteResource, token_models::{token_utils::TokenWriteSet, tokens::TableHandleToOwner}, token_v2_models::{ parquet_v2_token_datas::TokenDataV2, @@ -373,9 +374,7 @@ impl TokenOwnershipV2 { .get(&standardize_address(&token_data_id)) .is_some() { - if let Some(object) = - &ObjectWithMetadata::from_write_resource(write_resource, txn_version)? - { + if let Some(object) = &ObjectWithMetadata::from_write_resource(write_resource)? { let object_core = &object.object_core; let owner_address = object_core.get_owner_address(); let storage_id = token_data_id.clone(); diff --git a/rust/processor/src/db/common/models/token_v2_models/v2_collections.rs b/rust/processor/src/db/common/models/token_v2_models/v2_collections.rs index 75cce2cd3..d73eba3e8 100644 --- a/rust/processor/src/db/common/models/token_v2_models/v2_collections.rs +++ b/rust/processor/src/db/common/models/token_v2_models/v2_collections.rs @@ -5,11 +5,11 @@ #![allow(clippy::extra_unused_lifetimes)] #![allow(clippy::unused_unit)] -use super::v2_token_utils::{TokenStandard, V2TokenResource}; +use super::v2_token_utils::{Collection, TokenStandard}; use crate::{ db::common::models::{ - default_models::move_resources::MoveResource, object_models::v2_object_utils::ObjectAggregatedDataMapping, + resources::FromWriteResource, token_models::{ collection_datas::CollectionData, token_utils::{CollectionDataIdType, TokenWriteSet}, @@ -87,27 +87,13 @@ impl CollectionV2 { txn_timestamp: chrono::NaiveDateTime, object_metadatas: &ObjectAggregatedDataMapping, ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::Collection(inner) = &V2TokenResource::from_resource( - &type_str, - resource.data.as_ref().unwrap(), - txn_version, - )? { + if let Some(inner) = Collection::from_write_resource(write_resource)? { let (mut current_supply, mut max_supply, mut total_minted_v2) = (BigDecimal::zero(), None, None); let (mut mutable_description, mut mutable_uri) = (None, None); let mut collection_properties = serde_json::Value::Null; - if let Some(object_data) = object_metadatas.get(&resource.address) { + let address = standardize_address(&write_resource.address); + if let Some(object_data) = object_metadatas.get(&address) { // Getting supply data (prefer fixed supply over unlimited supply although they should never appear at the same time anyway) let fixed_supply = object_data.fixed_supply.as_ref(); let unlimited_supply = object_data.unlimited_supply.as_ref(); @@ -157,7 +143,7 @@ impl CollectionV2 { return Ok(None); } - let collection_id = resource.address.clone(); + let collection_id = address; let creator_address = inner.get_creator_address(); let collection_name = inner.get_name_trunc(); let description = inner.description.clone(); diff --git a/rust/processor/src/db/common/models/token_v2_models/v2_token_datas.rs b/rust/processor/src/db/common/models/token_v2_models/v2_token_datas.rs index 3be211eb0..790ff5cd4 100644 --- a/rust/processor/src/db/common/models/token_v2_models/v2_token_datas.rs +++ b/rust/processor/src/db/common/models/token_v2_models/v2_token_datas.rs @@ -8,7 +8,7 @@ use super::v2_token_utils::{TokenStandard, TokenV2, TokenV2Burned}; use crate::{ db::common::models::{ - object_models::v2_object_utils::ObjectAggregatedDataMapping, + object_models::v2_object_utils::ObjectAggregatedDataMapping, resources::FromWriteResource, token_models::token_utils::TokenWriteSet, }, schema::{current_token_datas_v2, token_datas_v2}, @@ -79,7 +79,7 @@ impl TokenDataV2 { txn_timestamp: chrono::NaiveDateTime, object_metadatas: &ObjectAggregatedDataMapping, ) -> anyhow::Result> { - if let Some(inner) = &TokenV2::from_write_resource(write_resource, txn_version)? { + if let Some(inner) = &TokenV2::from_write_resource(write_resource)? { let token_data_id = standardize_address(&write_resource.address.to_string()); let mut token_name = inner.get_name_trunc(); let is_fungible_v2; diff --git a/rust/processor/src/db/common/models/token_v2_models/v2_token_metadata.rs b/rust/processor/src/db/common/models/token_v2_models/v2_token_metadata.rs index 0ed1b7cb7..a05766140 100644 --- a/rust/processor/src/db/common/models/token_v2_models/v2_token_metadata.rs +++ b/rust/processor/src/db/common/models/token_v2_models/v2_token_metadata.rs @@ -5,13 +5,12 @@ #![allow(clippy::extra_unused_lifetimes)] #![allow(clippy::unused_unit)] -use super::v2_token_utils::TOKEN_V2_ADDR; use crate::{ db::common::models::{ - coin_models::coin_utils::COIN_ADDR, default_models::move_resources::MoveResource, object_models::v2_object_utils::ObjectAggregatedDataMapping, - token_models::token_utils::{NAME_LENGTH, TOKEN_ADDR}, + resources::{COIN_ADDR, TOKEN_ADDR, TOKEN_V2_ADDR}, + token_models::token_utils::NAME_LENGTH, }, schema::current_token_v2_metadata, utils::util::{standardize_address, truncate_str}, diff --git a/rust/processor/src/db/common/models/token_v2_models/v2_token_ownerships.rs b/rust/processor/src/db/common/models/token_v2_models/v2_token_ownerships.rs index ecc26f539..d71bfff22 100644 --- a/rust/processor/src/db/common/models/token_v2_models/v2_token_ownerships.rs +++ b/rust/processor/src/db/common/models/token_v2_models/v2_token_ownerships.rs @@ -12,6 +12,7 @@ use super::{ use crate::{ db::common::models::{ object_models::v2_object_utils::{ObjectAggregatedDataMapping, ObjectWithMetadata}, + resources::FromWriteResource, token_models::{token_utils::TokenWriteSet, tokens::TableHandleToOwner}, token_v2_models::v2_token_utils::DEFAULT_OWNER_ADDRESS, }, @@ -264,9 +265,7 @@ impl TokenOwnershipV2 { .get(&standardize_address(&token_data_id)) .is_some() { - if let Some(object) = - &ObjectWithMetadata::from_write_resource(write_resource, txn_version)? - { + if let Some(object) = &ObjectWithMetadata::from_write_resource(write_resource)? { let object_core = &object.object_core; let owner_address = object_core.get_owner_address(); let storage_id = token_data_id.clone(); diff --git a/rust/processor/src/db/common/models/token_v2_models/v2_token_utils.rs b/rust/processor/src/db/common/models/token_v2_models/v2_token_utils.rs index 714d852f2..365725228 100644 --- a/rust/processor/src/db/common/models/token_v2_models/v2_token_utils.rs +++ b/rust/processor/src/db/common/models/token_v2_models/v2_token_utils.rs @@ -6,9 +6,7 @@ use crate::{ db::common::models::{ - coin_models::coin_utils::COIN_ADDR, - default_models::move_resources::MoveResource, - object_models::v2_object_utils::{CurrentObjectPK, ObjectCore, Untransferable}, + object_models::v2_object_utils::CurrentObjectPK, token_models::token_utils::{NAME_LENGTH, URI_LENGTH}, }, utils::util::{ @@ -24,9 +22,6 @@ use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use std::fmt::{self, Formatter}; -pub const TOKEN_V2_ADDR: &str = - "0x0000000000000000000000000000000000000000000000000000000000000004"; - pub const DEFAULT_OWNER_ADDRESS: &str = "unknown"; lazy_static! { @@ -79,35 +74,25 @@ impl Collection { } } +impl TryFrom<&WriteResource> for Collection { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) + } +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct AptosCollection { pub mutable_description: bool, pub mutable_uri: bool, } -impl AptosCollection { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::AptosCollection(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for AptosCollection { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -120,6 +105,14 @@ pub struct TokenV2 { uri: String, } +impl TryFrom<&WriteResource> for TokenV2 { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) + } +} + impl TokenV2 { pub fn get_collection_address(&self) -> String { self.collection.get_reference_address() @@ -132,39 +125,6 @@ impl TokenV2 { pub fn get_name_trunc(&self) -> String { truncate_str(&self.name, NAME_LENGTH) } - - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::TokenV2(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - if let Some(token_identifiers) = - TokenIdentifiers::from_write_resource(write_resource, txn_version).unwrap() - { - Ok(Some(TokenV2 { - name: token_identifiers.name.value, - ..inner - })) - } else { - Ok(Some(inner)) - } - } else { - Ok(None) - } - } } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -189,29 +149,11 @@ pub struct FixedSupply { pub total_minted: BigDecimal, } -impl FixedSupply { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::FixedSupply(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for FixedSupply { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -223,29 +165,11 @@ pub struct UnlimitedSupply { pub total_minted: BigDecimal, } -impl UnlimitedSupply { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::UnlimitedSupply(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for UnlimitedSupply { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -255,29 +179,11 @@ pub struct ConcurrentSupply { pub total_minted: Aggregator, } -impl ConcurrentSupply { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::ConcurrentSupply(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for ConcurrentSupply { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -429,29 +335,11 @@ pub struct PropertyMapModel { pub inner: serde_json::Value, } -impl PropertyMapModel { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::PropertyMapModel(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - Ok(Some(inner)) - } else { - Ok(None) - } +impl TryFrom<&WriteResource> for PropertyMapModel { + type Error = anyhow::Error; + + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } @@ -460,116 +348,17 @@ pub struct TokenIdentifiers { name: DerivedStringSnapshot, } -impl TokenIdentifiers { - pub fn from_write_resource( - write_resource: &WriteResource, - txn_version: i64, - ) -> anyhow::Result> { - let type_str = MoveResource::get_outer_type_from_write_resource(write_resource); - if !V2TokenResource::is_resource_supported(type_str.as_str()) { - return Ok(None); - } - let resource = MoveResource::from_write_resource( - write_resource, - 0, // Placeholder, this isn't used anyway - txn_version, - 0, // Placeholder, this isn't used anyway - ); - - if let V2TokenResource::TokenIdentifiers(inner) = - V2TokenResource::from_resource(&type_str, resource.data.as_ref().unwrap(), txn_version)? - { - Ok(Some(inner)) - } else { - Ok(None) - } - } +impl TryFrom<&WriteResource> for TokenIdentifiers { + type Error = anyhow::Error; - pub fn get_name_trunc(&self) -> String { - truncate_str(&self.name.value, NAME_LENGTH) + fn try_from(write_resource: &WriteResource) -> anyhow::Result { + serde_json::from_str(write_resource.data.as_str()).map_err(anyhow::Error::msg) } } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum V2TokenResource { - AptosCollection(AptosCollection), - Collection(Collection), - ConcurrentSupply(ConcurrentSupply), - FixedSupply(FixedSupply), - ObjectCore(ObjectCore), - UnlimitedSupply(UnlimitedSupply), - Untransferable(Untransferable), - TokenV2(TokenV2), - PropertyMapModel(PropertyMapModel), - TokenIdentifiers(TokenIdentifiers), -} - -impl V2TokenResource { - pub fn is_resource_supported(data_type: &str) -> bool { - [ - format!("{}::object::ObjectCore", COIN_ADDR), - format!("{}::object::Untransferable", COIN_ADDR), - format!("{}::collection::Collection", TOKEN_V2_ADDR), - format!("{}::collection::ConcurrentSupply", TOKEN_V2_ADDR), - format!("{}::collection::FixedSupply", TOKEN_V2_ADDR), - format!("{}::collection::UnlimitedSupply", TOKEN_V2_ADDR), - format!("{}::aptos_token::AptosCollection", TOKEN_V2_ADDR), - format!("{}::token::Token", TOKEN_V2_ADDR), - format!("{}::property_map::PropertyMap", TOKEN_V2_ADDR), - format!("{}::token::TokenIdentifiers", TOKEN_V2_ADDR), - ] - .contains(&data_type.to_string()) - } - - pub fn from_resource( - data_type: &str, - data: &serde_json::Value, - txn_version: i64, - ) -> Result { - match data_type { - x if x == format!("{}::object::ObjectCore", COIN_ADDR) => { - serde_json::from_value(data.clone()).map(|inner| Some(Self::ObjectCore(inner))) - }, - x if x == format!("{}::object::Untransferable", COIN_ADDR) => { - serde_json::from_value(data.clone()).map(|inner| Some(Self::Untransferable(inner))) - }, - x if x == format!("{}::collection::Collection", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()).map(|inner| Some(Self::Collection(inner))) - }, - x if x == format!("{}::collection::ConcurrentSupply", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::ConcurrentSupply(inner))) - }, - x if x == format!("{}::collection::FixedSupply", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()).map(|inner| Some(Self::FixedSupply(inner))) - }, - x if x == format!("{}::collection::UnlimitedSupply", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()).map(|inner| Some(Self::UnlimitedSupply(inner))) - }, - x if x == format!("{}::aptos_token::AptosCollection", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()).map(|inner| Some(Self::AptosCollection(inner))) - }, - x if x == format!("{}::token::Token", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()).map(|inner| Some(Self::TokenV2(inner))) - }, - x if x == format!("{}::token::TokenIdentifiers", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::TokenIdentifiers(inner))) - }, - x if x == format!("{}::property_map::PropertyMap", TOKEN_V2_ADDR) => { - serde_json::from_value(data.clone()) - .map(|inner| Some(Self::PropertyMapModel(inner))) - }, - _ => Ok(None), - } - .context(format!( - "version {} failed! failed to parse type {}, data {:?}", - txn_version, data_type, data - ))? - .context(format!( - "Resource unsupported! Call is_resource_supported first. version {} type {}", - txn_version, data_type - )) +impl TokenIdentifiers { + pub fn get_name_trunc(&self) -> String { + truncate_str(&self.name.value, NAME_LENGTH) } } diff --git a/rust/processor/src/processors/fungible_asset_processor.rs b/rust/processor/src/processors/fungible_asset_processor.rs index 704ed4bfe..82c6fb8ba 100644 --- a/rust/processor/src/processors/fungible_asset_processor.rs +++ b/rust/processor/src/processors/fungible_asset_processor.rs @@ -11,15 +11,13 @@ use crate::{ CurrentFungibleAssetBalance, CurrentFungibleAssetMapping, CurrentUnifiedFungibleAssetBalance, FungibleAssetBalance, }, - v2_fungible_asset_utils::{ - ConcurrentFungibleAssetBalance, ConcurrentFungibleAssetSupply, FeeStatement, - FungibleAssetMetadata, FungibleAssetStore, FungibleAssetSupply, - }, + v2_fungible_asset_utils::FeeStatement, v2_fungible_metadata::{FungibleAssetMetadataMapping, FungibleAssetMetadataModel}, }, object_models::v2_object_utils::{ ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, Untransferable, }, + resources::{FromWriteResource, V2FungibleAssetResource}, }, gap_detectors::ProcessingResult, schema, @@ -524,9 +522,7 @@ async fn parse_v2_coin( // Need to do a first pass to get all the objects for wsc in transaction_info.changes.iter() { if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { - if let Some(object) = - ObjectWithMetadata::from_write_resource(wr, txn_version).unwrap() - { + if let Some(object) = ObjectWithMetadata::from_write_resource(wr).unwrap() { fungible_asset_object_helper.insert( standardize_address(&wr.address.to_string()), ObjectAggregatedData { @@ -558,47 +554,44 @@ async fn parse_v2_coin( // Fill the v2 object metadata let address = standardize_address(&write_resource.address.to_string()); if let Some(aggregated_data) = fungible_asset_object_helper.get_mut(&address) { - if let Some(fungible_asset_metadata) = - FungibleAssetMetadata::from_write_resource(write_resource, txn_version) - .unwrap() - { - aggregated_data.fungible_asset_metadata = Some(fungible_asset_metadata); - } - if let Some(fungible_asset_store) = - FungibleAssetStore::from_write_resource(write_resource, txn_version) - .unwrap() - { - aggregated_data.fungible_asset_store = Some(fungible_asset_store); - } - if let Some(fungible_asset_supply) = - FungibleAssetSupply::from_write_resource(write_resource, txn_version) - .unwrap() - { - aggregated_data.fungible_asset_supply = Some(fungible_asset_supply); - } - if let Some(concurrent_fungible_asset_supply) = - ConcurrentFungibleAssetSupply::from_write_resource( - write_resource, - txn_version, - ) - .unwrap() - { - aggregated_data.concurrent_fungible_asset_supply = - Some(concurrent_fungible_asset_supply); - } - if let Some(concurrent_fungible_asset_balance) = - ConcurrentFungibleAssetBalance::from_write_resource( - write_resource, - txn_version, - ) - .unwrap() + if let Some(v2_fungible_asset_resource) = + V2FungibleAssetResource::from_write_resource(write_resource).unwrap() { - aggregated_data.concurrent_fungible_asset_balance = - Some(concurrent_fungible_asset_balance); + match v2_fungible_asset_resource { + V2FungibleAssetResource::FungibleAssetMetadata( + fungible_asset_metadata, + ) => { + aggregated_data.fungible_asset_metadata = + Some(fungible_asset_metadata); + }, + V2FungibleAssetResource::FungibleAssetStore( + fungible_asset_store, + ) => { + aggregated_data.fungible_asset_store = + Some(fungible_asset_store); + }, + V2FungibleAssetResource::FungibleAssetSupply( + fungible_asset_supply, + ) => { + aggregated_data.fungible_asset_supply = + Some(fungible_asset_supply); + }, + V2FungibleAssetResource::ConcurrentFungibleAssetSupply( + concurrent_fungible_asset_supply, + ) => { + aggregated_data.concurrent_fungible_asset_supply = + Some(concurrent_fungible_asset_supply); + }, + V2FungibleAssetResource::ConcurrentFungibleAssetBalance( + concurrent_fungible_asset_balance, + ) => { + aggregated_data.concurrent_fungible_asset_balance = + Some(concurrent_fungible_asset_balance); + }, + } } if let Some(untransferable) = - Untransferable::from_write_resource(write_resource, txn_version) - .unwrap() + Untransferable::from_write_resource(write_resource).unwrap() { aggregated_data.untransferable = Some(untransferable); } diff --git a/rust/processor/src/processors/nft_metadata_processor.rs b/rust/processor/src/processors/nft_metadata_processor.rs index 4fcb9a922..04e1438e9 100644 --- a/rust/processor/src/processors/nft_metadata_processor.rs +++ b/rust/processor/src/processors/nft_metadata_processor.rs @@ -7,6 +7,7 @@ use crate::{ object_models::v2_object_utils::{ ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, }, + resources::FromWriteResource, token_models::tokens::{TableHandleToOwner, TableMetadataForToken}, token_v2_models::{ v2_collections::{CollectionV2, CurrentCollectionV2, CurrentCollectionV2PK}, @@ -237,9 +238,7 @@ async fn parse_v2_token( let mut token_v2_metadata_helper: ObjectAggregatedDataMapping = AHashMap::new(); for wsc in transaction_info.changes.iter() { if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { - if let Some(object) = - ObjectWithMetadata::from_write_resource(wr, txn_version).unwrap() - { + if let Some(object) = ObjectWithMetadata::from_write_resource(wr).unwrap() { token_v2_metadata_helper.insert( standardize_address(&wr.address.to_string()), ObjectAggregatedData { diff --git a/rust/processor/src/processors/objects_processor.rs b/rust/processor/src/processors/objects_processor.rs index 4e8e6bea5..e3aad3123 100644 --- a/rust/processor/src/processors/objects_processor.rs +++ b/rust/processor/src/processors/objects_processor.rs @@ -3,9 +3,14 @@ use super::{DefaultProcessingResult, ProcessorName, ProcessorTrait}; use crate::{ - db::common::models::object_models::{ - v2_object_utils::{ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata}, - v2_objects::{CurrentObject, Object}, + db::common::models::{ + object_models::{ + v2_object_utils::{ + ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, + }, + v2_objects::{CurrentObject, Object}, + }, + resources::FromWriteResource, }, gap_detectors::ProcessingResult, schema, @@ -195,7 +200,7 @@ impl ProcessorTrait for ObjectsProcessor { if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { let address = standardize_address(&wr.address.to_string()); if let Some(object_with_metadata) = - ObjectWithMetadata::from_write_resource(wr, txn_version).unwrap() + ObjectWithMetadata::from_write_resource(wr).unwrap() { // Object core is the first struct that we need to get object_metadata_helper.insert(address.clone(), ObjectAggregatedData { diff --git a/rust/processor/src/processors/parquet_processors/parquet_fungible_asset_processor.rs b/rust/processor/src/processors/parquet_processors/parquet_fungible_asset_processor.rs index 0f699aea8..94420d70e 100644 --- a/rust/processor/src/processors/parquet_processors/parquet_fungible_asset_processor.rs +++ b/rust/processor/src/processors/parquet_processors/parquet_fungible_asset_processor.rs @@ -15,6 +15,7 @@ use crate::{ object_models::v2_object_utils::{ ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, }, + resources::FromWriteResource, }, gap_detectors::ProcessingResult, processors::{ProcessorName, ProcessorTrait}, @@ -177,9 +178,7 @@ async fn parse_v2_coin( // Need to do a first pass to get all the objects for wsc in transaction_info.changes.iter() { if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { - if let Some(object) = - ObjectWithMetadata::from_write_resource(wr, txn_version).unwrap() - { + if let Some(object) = ObjectWithMetadata::from_write_resource(wr).unwrap() { fungible_asset_object_helper.insert( standardize_address(&wr.address.to_string()), ObjectAggregatedData { diff --git a/rust/processor/src/processors/parquet_processors/parquet_token_v2_processor.rs b/rust/processor/src/processors/parquet_processors/parquet_token_v2_processor.rs index dd9e12d9c..bb55bfccf 100644 --- a/rust/processor/src/processors/parquet_processors/parquet_token_v2_processor.rs +++ b/rust/processor/src/processors/parquet_processors/parquet_token_v2_processor.rs @@ -9,17 +9,16 @@ use crate::{ db::common::models::{ fungible_asset_models::v2_fungible_asset_utils::FungibleAssetMetadata, object_models::v2_object_utils::{ - ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, Untransferable, + ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, }, + resources::{FromWriteResource, V2TokenResource}, token_models::tokens::{TableHandleToOwner, TableMetadataForToken}, token_v2_models::{ parquet_v2_token_datas::TokenDataV2, parquet_v2_token_ownerships::TokenOwnershipV2, v2_token_ownerships::NFTOwnershipV2, v2_token_utils::{ - AptosCollection, Burn, BurnEvent, ConcurrentSupply, FixedSupply, MintEvent, - PropertyMapModel, TokenIdentifiers, TokenV2, TokenV2Burned, TokenV2Minted, - TransferEvent, UnlimitedSupply, + Burn, BurnEvent, MintEvent, TokenV2Burned, TokenV2Minted, TransferEvent, }, }, }, @@ -213,9 +212,7 @@ async fn parse_v2_token( // Need to do a first pass to get all the objects for wsc in transaction_info.changes.iter() { if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { - if let Some(object) = - ObjectWithMetadata::from_write_resource(wr, txn_version).unwrap() - { + if let Some(object) = ObjectWithMetadata::from_write_resource(wr).unwrap() { token_v2_metadata_helper.insert( standardize_address(&wr.address.to_string()), ObjectAggregatedData { @@ -232,50 +229,42 @@ async fn parse_v2_token( if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { let address = standardize_address(&wr.address.to_string()); if let Some(aggregated_data) = token_v2_metadata_helper.get_mut(&address) { - if let Some(fixed_supply) = - FixedSupply::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.fixed_supply = Some(fixed_supply); - } - if let Some(unlimited_supply) = - UnlimitedSupply::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.unlimited_supply = Some(unlimited_supply); - } - if let Some(aptos_collection) = - AptosCollection::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.aptos_collection = Some(aptos_collection); - } - if let Some(property_map) = - PropertyMapModel::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.property_map = Some(property_map); - } - if let Some(concurrent_supply) = - ConcurrentSupply::from_write_resource(wr, txn_version).unwrap() + if let Some(token_v2_resource) = + V2TokenResource::from_write_resource(wr).unwrap() { - aggregated_data.concurrent_supply = Some(concurrent_supply); - } - if let Some(token) = TokenV2::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.token = Some(token); + match token_v2_resource { + V2TokenResource::FixedSupply(fixed_supply) => { + aggregated_data.fixed_supply = Some(fixed_supply); + }, + V2TokenResource::UnlimitedSupply(unlimited_supply) => { + aggregated_data.unlimited_supply = Some(unlimited_supply); + }, + V2TokenResource::AptosCollection(aptos_collection) => { + aggregated_data.aptos_collection = Some(aptos_collection); + }, + V2TokenResource::PropertyMapModel(property_map) => { + aggregated_data.property_map = Some(property_map); + }, + V2TokenResource::ConcurrentSupply(concurrent_supply) => { + aggregated_data.concurrent_supply = Some(concurrent_supply); + }, + V2TokenResource::TokenV2(token) => { + aggregated_data.token = Some(token); + }, + V2TokenResource::TokenIdentifiers(token_identifier) => { + aggregated_data.token_identifier = Some(token_identifier); + }, + V2TokenResource::Untransferable(untransferable) => { + aggregated_data.untransferable = Some(untransferable); + }, + _ => {}, + } } if let Some(fungible_asset_metadata) = - FungibleAssetMetadata::from_write_resource(wr, txn_version).unwrap() + FungibleAssetMetadata::from_write_resource(wr).unwrap() { aggregated_data.fungible_asset_metadata = Some(fungible_asset_metadata); } - if let Some(token_identifier) = - TokenIdentifiers::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.token_identifier = Some(token_identifier); - } - if let Some(untransferable) = - Untransferable::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.untransferable = Some(untransferable); - } } } } diff --git a/rust/processor/src/processors/token_v2_processor.rs b/rust/processor/src/processors/token_v2_processor.rs index 95645dd8d..afbf0025b 100644 --- a/rust/processor/src/processors/token_v2_processor.rs +++ b/rust/processor/src/processors/token_v2_processor.rs @@ -6,8 +6,9 @@ use crate::{ db::common::models::{ fungible_asset_models::v2_fungible_asset_utils::FungibleAssetMetadata, object_models::v2_object_utils::{ - ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, Untransferable, + ObjectAggregatedData, ObjectAggregatedDataMapping, ObjectWithMetadata, }, + resources::{FromWriteResource, V2TokenResource}, token_models::{ token_claims::CurrentTokenPendingClaim, tokens::{CurrentTokenPendingClaimPK, TableHandleToOwner, TableMetadataForToken}, @@ -23,9 +24,7 @@ use crate::{ TokenOwnershipV2, }, v2_token_utils::{ - AptosCollection, Burn, BurnEvent, ConcurrentSupply, FixedSupply, MintEvent, - PropertyMapModel, TokenIdentifiers, TokenV2, TokenV2Burned, TokenV2Minted, - TransferEvent, UnlimitedSupply, + Burn, BurnEvent, MintEvent, TokenV2Burned, TokenV2Minted, TransferEvent, }, }, }, @@ -787,9 +786,7 @@ async fn parse_v2_token( // Need to do a first pass to get all the objects for wsc in transaction_info.changes.iter() { if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { - if let Some(object) = - ObjectWithMetadata::from_write_resource(wr, txn_version).unwrap() - { + if let Some(object) = ObjectWithMetadata::from_write_resource(wr).unwrap() { token_v2_metadata_helper.insert( standardize_address(&wr.address.to_string()), ObjectAggregatedData { @@ -806,50 +803,42 @@ async fn parse_v2_token( if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { let address = standardize_address(&wr.address.to_string()); if let Some(aggregated_data) = token_v2_metadata_helper.get_mut(&address) { - if let Some(fixed_supply) = - FixedSupply::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.fixed_supply = Some(fixed_supply); - } - if let Some(unlimited_supply) = - UnlimitedSupply::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.unlimited_supply = Some(unlimited_supply); - } - if let Some(aptos_collection) = - AptosCollection::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.aptos_collection = Some(aptos_collection); - } - if let Some(property_map) = - PropertyMapModel::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.property_map = Some(property_map); - } - if let Some(concurrent_supply) = - ConcurrentSupply::from_write_resource(wr, txn_version).unwrap() + if let Some(v2_token_resource) = + V2TokenResource::from_write_resource(wr).unwrap() { - aggregated_data.concurrent_supply = Some(concurrent_supply); - } - if let Some(token) = TokenV2::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.token = Some(token); + match v2_token_resource { + V2TokenResource::FixedSupply(fixed_supply) => { + aggregated_data.fixed_supply = Some(fixed_supply); + }, + V2TokenResource::UnlimitedSupply(unlimited_supply) => { + aggregated_data.unlimited_supply = Some(unlimited_supply); + }, + V2TokenResource::AptosCollection(aptos_collection) => { + aggregated_data.aptos_collection = Some(aptos_collection); + }, + V2TokenResource::PropertyMapModel(property_map) => { + aggregated_data.property_map = Some(property_map); + }, + V2TokenResource::ConcurrentSupply(concurrent_supply) => { + aggregated_data.concurrent_supply = Some(concurrent_supply); + }, + V2TokenResource::TokenV2(token) => { + aggregated_data.token = Some(token); + }, + V2TokenResource::TokenIdentifiers(token_identifier) => { + aggregated_data.token_identifier = Some(token_identifier); + }, + V2TokenResource::Untransferable(untransferable) => { + aggregated_data.untransferable = Some(untransferable); + }, + _ => {}, + } } if let Some(fungible_asset_metadata) = - FungibleAssetMetadata::from_write_resource(wr, txn_version).unwrap() + FungibleAssetMetadata::from_write_resource(wr).unwrap() { aggregated_data.fungible_asset_metadata = Some(fungible_asset_metadata); } - if let Some(token_identifier) = - TokenIdentifiers::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.token_identifier = Some(token_identifier); - } - if let Some(untransferable) = - Untransferable::from_write_resource(wr, txn_version).unwrap() - { - aggregated_data.untransferable = Some(untransferable); - } } } }