From 0da8dc25be516d8cf14d05df65bf637403d0b553 Mon Sep 17 00:00:00 2001 From: rtso <8248583+rtso@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:42:56 -0500 Subject: [PATCH] fix claims --- .../models/token_models/token_claims.rs | 35 +++++++++++-- .../token_v2_models/v2_token_activities.rs | 49 +++++++++++++------ .../src/processors/token_v2_processor.rs | 8 ++- 3 files changed, 72 insertions(+), 20 deletions(-) diff --git a/rust/processor/src/db/postgres/models/token_models/token_claims.rs b/rust/processor/src/db/postgres/models/token_models/token_claims.rs index f418aede5..7c76a2073 100644 --- a/rust/processor/src/db/postgres/models/token_models/token_claims.rs +++ b/rust/processor/src/db/postgres/models/token_models/token_claims.rs @@ -6,12 +6,20 @@ #![allow(clippy::unused_unit)] use super::{token_utils::TokenWriteSet, tokens::TableHandleToOwner}; -use crate::{schema::current_token_pending_claims, utils::util::standardize_address}; +use crate::{ + db::common::models::token_v2_models::v2_token_activities::TokenActivityHelperV1, + schema::current_token_pending_claims, utils::util::standardize_address, +}; +use ahash::AHashMap; use aptos_protos::transaction::v1::{DeleteTableItem, WriteTableItem}; use bigdecimal::{BigDecimal, Zero}; use field_count::FieldCount; use serde::{Deserialize, Serialize}; +// Map to keep track of the metadata of token offers that were claimed. The key is the token data id of the offer. +// Potentially it'd also be useful to keep track of offers that were canceled. +pub type TokenV1Claimed = AHashMap; + #[derive( Clone, Debug, Deserialize, Eq, FieldCount, Identifiable, Insertable, PartialEq, Serialize, )] @@ -136,6 +144,7 @@ impl CurrentTokenPendingClaim { txn_version: i64, txn_timestamp: chrono::NaiveDateTime, table_handle_to_owner: &TableHandleToOwner, + tokens_claimed: &TokenV1Claimed, ) -> anyhow::Result> { let table_item_data = table_item.data.as_ref().unwrap(); @@ -149,12 +158,28 @@ impl CurrentTokenPendingClaim { }; if let Some(offer) = &maybe_offer { let table_handle = standardize_address(&table_item.handle.to_string()); + let token_data_id = offer.token_id.token_data_id.to_id(); + + // Try to find owner from write resources + let mut maybe_owner_address = match table_handle_to_owner.get(&table_handle) { + Some(table_metadata) => Some(table_metadata.get_owner_address()), + _ => None, + }; + + // If table handle isn't in TableHandleToOwner, try to find owner from token v1 claim events + if maybe_owner_address.is_none() { + if let Some(token_claimed) = tokens_claimed.get(&token_data_id) { + maybe_owner_address = token_claimed.from_address.clone(); + } + } - let table_metadata = table_handle_to_owner.get(&table_handle).unwrap_or_else(|| { + let owner_address = maybe_owner_address.unwrap_or_else(|| { panic!( "Missing table handle metadata for claim. \ - Version: {}, table handle for PendingClaims: {}, all metadata: {:?}", - txn_version, table_handle, table_handle_to_owner + Version: {}, table handle for PendingClaims: {}, all metadata: {:?} \ + Missing token data id in token claim event. \ + token_data_id: {}, all token claim events: {:?}", + txn_version, table_handle, table_handle_to_owner, token_data_id, tokens_claimed ) }); @@ -171,7 +196,7 @@ impl CurrentTokenPendingClaim { return Ok(Some(Self { token_data_id_hash, property_version: token_id.property_version, - from_address: table_metadata.get_owner_address(), + from_address: owner_address, to_address: offer.get_to_address(), collection_data_id_hash, creator_address: token_data_id_struct.get_creator_address(), diff --git a/rust/processor/src/db/postgres/models/token_v2_models/v2_token_activities.rs b/rust/processor/src/db/postgres/models/token_v2_models/v2_token_activities.rs index 6121baf07..2df0d62cc 100644 --- a/rust/processor/src/db/postgres/models/token_v2_models/v2_token_activities.rs +++ b/rust/processor/src/db/postgres/models/token_v2_models/v2_token_activities.rs @@ -9,7 +9,10 @@ use super::v2_token_utils::{TokenStandard, V2TokenEvent}; use crate::{ db::postgres::models::{ object_models::v2_object_utils::ObjectAggregatedDataMapping, - token_models::token_utils::{TokenDataIdType, TokenEvent}, + token_models::{ + token_claims::TokenV1Claimed, + token_utils::{TokenDataIdType, TokenEvent}, + }, }, schema::token_activities_v2, utils::util::standardize_address, @@ -41,7 +44,8 @@ pub struct TokenActivityV2 { } /// A simplified TokenActivity (excluded common fields) to reduce code duplication -struct TokenActivityHelperV1 { +#[derive(Clone, Debug)] +pub struct TokenActivityHelperV1 { pub token_data_id_struct: TokenDataIdType, pub property_version: BigDecimal, pub from_address: Option, @@ -200,9 +204,16 @@ impl TokenActivityV2 { txn_timestamp: chrono::NaiveDateTime, event_index: i64, entry_function_id_str: &Option, + tokens_claimed: &mut TokenV1Claimed, ) -> anyhow::Result> { let event_type = event.type_str.clone(); + tracing::info!("event_type: {}, event: {:?}", event_type, event); if let Some(token_event) = &TokenEvent::from_event(&event_type, &event.data, txn_version)? { + tracing::info!( + "TokenActivityV2::get_v1_from_parsed_event: event_type: {}, event: {:?}", + event_type, + token_event + ); let event_account_address = standardize_address(&event.key.as_ref().unwrap().account_address); let token_activity_helper = match token_event { @@ -290,12 +301,17 @@ impl TokenActivityV2 { to_address: Some(inner.get_to_address()), token_amount: inner.amount.clone(), }, - TokenEvent::ClaimTokenEvent(inner) => TokenActivityHelperV1 { - token_data_id_struct: inner.token_id.token_data_id.clone(), - property_version: inner.token_id.property_version.clone(), - from_address: Some(event_account_address.clone()), - to_address: Some(inner.get_to_address()), - token_amount: inner.amount.clone(), + TokenEvent::ClaimTokenEvent(inner) => { + let token_data_id_struct = inner.token_id.token_data_id.clone(); + let helper = TokenActivityHelperV1 { + token_data_id_struct: token_data_id_struct.clone(), + property_version: inner.token_id.property_version.clone(), + from_address: Some(event_account_address.clone()), + to_address: Some(inner.get_to_address()), + token_amount: inner.amount.clone(), + }; + tokens_claimed.insert(token_data_id_struct.to_id(), helper.clone()); + helper }, TokenEvent::Offer(inner) => TokenActivityHelperV1 { token_data_id_struct: inner.token_id.token_data_id.clone(), @@ -311,12 +327,17 @@ impl TokenActivityV2 { to_address: Some(inner.get_to_address()), token_amount: inner.amount.clone(), }, - TokenEvent::Claim(inner) => TokenActivityHelperV1 { - token_data_id_struct: inner.token_id.token_data_id.clone(), - property_version: inner.token_id.property_version.clone(), - from_address: Some(inner.get_from_address()), - to_address: Some(inner.get_to_address()), - token_amount: inner.amount.clone(), + TokenEvent::Claim(inner) => { + let token_data_id_struct = inner.token_id.token_data_id.clone(); + let helper = TokenActivityHelperV1 { + token_data_id_struct, + property_version: inner.token_id.property_version.clone(), + from_address: Some(inner.get_from_address()), + to_address: Some(inner.get_to_address()), + token_amount: inner.amount.clone(), + }; + tokens_claimed.insert(token_data_id_struct.to_id(), helper.clone()); + helper }, }; let token_data_id_struct = token_activity_helper.token_data_id_struct; diff --git a/rust/processor/src/processors/token_v2_processor.rs b/rust/processor/src/processors/token_v2_processor.rs index 591ed2bae..c7247c780 100644 --- a/rust/processor/src/processors/token_v2_processor.rs +++ b/rust/processor/src/processors/token_v2_processor.rs @@ -10,7 +10,7 @@ use crate::{ }, resources::{FromWriteResource, V2TokenResource}, token_models::{ - token_claims::CurrentTokenPendingClaim, + token_claims::{CurrentTokenPendingClaim, TokenV1Claimed}, tokens::{CurrentTokenPendingClaimPK, TableHandleToOwner, TableMetadataForToken}, }, token_v2_models::{ @@ -783,6 +783,9 @@ pub async fn parse_v2_token( // Get mint events for token v2 by object let mut tokens_minted: TokenV2Minted = AHashSet::new(); + // Get claim events for token v1 by table handle + let mut tokens_claimed: TokenV1Claimed = AHashMap::new(); + // Loop 1: Need to do a first pass to get all the object addresses and insert them into the helper for wsc in transaction_info.changes.iter() { if let Change::WriteResource(wr) = wsc.change.as_ref().unwrap() { @@ -847,6 +850,7 @@ pub async fn parse_v2_token( // Loop 3: Pass through events to get the burn events and token activities v2 // This needs to be here because we need the metadata parsed in loop 2 for token activities // and burn / transfer events need to come before the next loop + // Also parses token v1 claim events, which will be used in Loop 4 to build the claims table for (index, event) in user_txn.events.iter().enumerate() { if let Some(burn_event) = Burn::from_event(event, txn_version).unwrap() { tokens_burned.insert(burn_event.get_token_address(), burn_event.clone()); @@ -890,6 +894,7 @@ pub async fn parse_v2_token( txn_timestamp, index as i64, &entry_function_id_str, + &mut tokens_claimed, ) .unwrap() { @@ -1053,6 +1058,7 @@ pub async fn parse_v2_token( txn_version, txn_timestamp, table_handle_to_owner, + &tokens_claimed, ) .unwrap() {