diff --git a/CHANGELOG.md b/CHANGELOG.md index daba9ad..71b79d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased changes +## [1.4.0] - 2025-10-30 + +- Bumping Rust SDK version. Unknown events introduced in future protocol + versions will be skipped, but generate warning log messages: + "The node/protocol version may not be fully supported by this version of concordium-rosetta". +- Fix an issue where the `token_update` operation type was not reported by + `/network/options`. + ## [1.3.1] - 2025-09-24 - Bumping up Rust SDK version to newer one which support protocol version 9. diff --git a/Cargo.lock b/Cargo.lock index 5c78bf3..f10bb3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -737,7 +737,7 @@ dependencies = [ [[package]] name = "concordium-rosetta" -version = "1.3.1" +version = "1.4.0" dependencies = [ "anyhow", "clap 3.1.18", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "concordium-rust-sdk" -version = "7.0.0-alpha.4" +version = "8.0.0" dependencies = [ "aes-gcm", "anyhow", @@ -834,7 +834,7 @@ dependencies = [ [[package]] name = "concordium_base" -version = "8.0.0" +version = "9.0.0" dependencies = [ "aes", "anyhow", @@ -885,7 +885,7 @@ dependencies = [ [[package]] name = "concordium_base_derive" -version = "1.1.0" +version = "1.1.0-alpha.3" dependencies = [ "convert_case 0.8.0", "darling", diff --git a/Cargo.toml b/Cargo.toml index 57e11db..e6e1614 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ [package] name = "concordium-rosetta" -version = "1.3.1" +version = "1.4.0" edition = "2024" diff --git a/concordium-rust-sdk b/concordium-rust-sdk index fb0c3cf..a43baee 160000 --- a/concordium-rust-sdk +++ b/concordium-rust-sdk @@ -1 +1 @@ -Subproject commit fb0c3cfddc2e508f6d4267b6c2f6464ec72abc77 +Subproject commit a43baeeae7a434ca39b03bd7cf56cd7f9fe4ff7d diff --git a/src/api/block.rs b/src/api/block.rs index 7b7db21..7dceb4a 100644 --- a/src/api/block.rs +++ b/src/api/block.rs @@ -10,9 +10,10 @@ use crate::{ use concordium_rust_sdk::{ common::SerdeSerialize, types::{BakerId, SpecialTransactionOutcome}, - v2::IntoBlockIdentifier, + v2::{IntoBlockIdentifier, Upward}, }; use futures::{TryStreamExt, stream::StreamExt}; +use log::warn; use rosetta::models::*; use std::cmp::max; @@ -132,6 +133,14 @@ impl BlockApi { .await?; while let Some(e) = special_events.next().await.transpose()? { + let Upward::Known(e) = e else { + warn!( + "Encountered unknown special transaction outcome; skipping. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + continue; + }; match e { SpecialTransactionOutcome::Mint { mint_baking_reward, diff --git a/src/api/network.rs b/src/api/network.rs index bfa67e4..c0cab00 100644 --- a/src/api/network.rs +++ b/src/api/network.rs @@ -87,6 +87,7 @@ impl NetworkApi { OPERATION_TYPE_CONFIGURE_DELEGATION.to_string(), OPERATION_TYPE_VALIDATOR_PRIMED_FOR_SUSPENSION.to_string(), OPERATION_TYPE_VALIDATOR_SUSPENDED.to_string(), + OPERATION_TYPE_TOKEN_UPDATE.to_string(), ], errors: vec![ handler_error::invalid_input_unsupported_field_error(None), diff --git a/src/api/query.rs b/src/api/query.rs index 168f096..1923ca5 100644 --- a/src/api/query.rs +++ b/src/api/query.rs @@ -3,7 +3,7 @@ use crate::api::{ transaction::*, }; use concordium_rust_sdk::{ - common::types::Amount, + common::{types::Amount, upward::Upward}, endpoints::{BlocksAtHeightInput, QueryError}, id::types::AccountAddress, types::{ @@ -170,7 +170,7 @@ impl QueryHelper { pub async fn query_block_special_events( &self, block_id: impl IntoBlockIdentifier, - ) -> ApiResult>> { + ) -> ApiResult>>> { let mapped_stream = map_query_result( self.client .clone() diff --git a/src/api/transaction.rs b/src/api/transaction.rs index f0a4d87..8e6023f 100644 --- a/src/api/transaction.rs +++ b/src/api/transaction.rs @@ -6,11 +6,13 @@ use concordium_rust_sdk::{ common::{ SerdeSerialize, types::{Amount, Timestamp, TransactionTime}, + upward::Upward::*, }, constants::EncryptedAmountsCurve, encrypted_transfers::types::*, id::types::AccountAddress, types::*, + v2::Upward, }; use rosetta::models::{ AccountIdentifier, Operation, OperationIdentifier, Transaction, TransactionIdentifier, @@ -262,6 +264,8 @@ pub const OPERATION_TYPE_CONFIGURE_DELEGATION: &str = "configure_delegation"; pub const OPERATION_TYPE_VALIDATOR_PRIMED_FOR_SUSPENSION: &str = "validator_primed_for_suspension"; pub const OPERATION_TYPE_VALIDATOR_SUSPENDED: &str = "validator_suspended"; pub const OPERATION_TYPE_TOKEN_UPDATE: &str = "token_update"; +// Note: All operations should be returned by the `network_options` endpoint. +// If you add a new operation type, make sure to add it there as well. pub const TRANSACTION_HASH_TOKENOMICS: &str = "tokenomics"; @@ -274,7 +278,7 @@ pub fn contract_address_string(contract_addr: &ContractAddress) -> String { pub fn map_transaction(info: BlockItemSummary) -> Transaction { let (operations, extra_metadata) = match &info.details { - BlockItemSummaryDetails::AccountTransaction(details) => { + Known(BlockItemSummaryDetails::AccountTransaction(details)) => { let (ops, metadata) = operations_and_metadata_from_account_transaction_details(details); let mut ops_with_fee = ops.clone(); if details.cost.micro_ccd() != 0 { @@ -293,18 +297,26 @@ pub fn map_transaction(info: BlockItemSummary) -> Transaction { } (ops_with_fee, metadata) } - BlockItemSummaryDetails::AccountCreation(details) => ( + Known(BlockItemSummaryDetails::AccountCreation(details)) => ( operations_and_metadata_from_account_creation_details(details), None, ), - BlockItemSummaryDetails::Update(details) => ( + Known(BlockItemSummaryDetails::Update(details)) => ( operations_and_metadata_from_chain_update_details(details), None, ), - BlockItemSummaryDetails::TokenCreationDetails(_details) => { + Known(BlockItemSummaryDetails::TokenCreationDetails(_details)) => { log::warn!("Token creation not yet supported"); (vec![], None) } + Unknown(_) => { + log::warn!( + "Encountered unknown block item details; skipping. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + (vec![], None) + } }; Transaction { transaction_identifier: Box::new(TransactionIdentifier { @@ -320,10 +332,10 @@ fn operations_and_metadata_from_account_transaction_details( details: &AccountTransactionDetails, ) -> (Vec, Option>) { match &details.effects { - AccountTransactionEffects::None { + Known(AccountTransactionEffects::None { transaction_type, reject_reason, - } => ( + }) => ( vec![Operation { operation_identifier: Box::new(OperationIdentifier::new(0)), related_operations: None, @@ -332,16 +344,26 @@ fn operations_and_metadata_from_account_transaction_details( account: Some(Box::new(AccountIdentifier::new(details.sender.to_string()))), amount: None, coin_change: None, - metadata: Some( - serde_json::to_value(&TransactionRejectedMetadata { - reject_reason: reject_reason.clone(), + metadata: reject_reason + .as_known() + .map(|reject_reason| { + serde_json::to_value(&TransactionRejectedMetadata { + reject_reason: reject_reason.clone(), + }) + .unwrap() }) - .unwrap(), - ), + .or_else(|| { + log::warn!( + "Unknown reject reason in transaction effects. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + None + }), }], None, ), - AccountTransactionEffects::ModuleDeployed { module_ref } => ( + Known(AccountTransactionEffects::ModuleDeployed { module_ref }) => ( vec![normal_account_transaction_operation( 0, details, @@ -352,7 +374,7 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::ContractInitialized { data } => { + Known(AccountTransactionEffects::ContractInitialized { data }) => { // TODO Adapt and use 'simple_transfer_operations'? let mut ops = vec![normal_account_transaction_operation( 0, @@ -376,19 +398,19 @@ fn operations_and_metadata_from_account_transaction_details( } (ops, None) } - AccountTransactionEffects::ContractUpdateIssued { effects } => { + Known(AccountTransactionEffects::ContractUpdateIssued { effects }) => { (contract_update_operations(details, effects), None) } - AccountTransactionEffects::AccountTransfer { amount, to } => { + Known(AccountTransactionEffects::AccountTransfer { amount, to }) => { (simple_transfer_operations(details, amount, to), None) } - AccountTransactionEffects::AccountTransferWithMemo { amount, to, memo } => ( + Known(AccountTransactionEffects::AccountTransferWithMemo { amount, to, memo }) => ( simple_transfer_operations(details, amount, to), Some(serde_json::to_value(MemoMetadata { memo: Some(memo.clone()), })), ), - AccountTransactionEffects::BakerAdded { data } => ( + Known(AccountTransactionEffects::BakerAdded { data }) => ( vec![normal_account_transaction_operation( 0, details, @@ -405,7 +427,7 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::BakerRemoved { baker_id } => ( + Known(AccountTransactionEffects::BakerRemoved { baker_id }) => ( vec![normal_account_transaction_operation( 0, details, @@ -416,7 +438,7 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::BakerStakeUpdated { data } => ( + Known(AccountTransactionEffects::BakerStakeUpdated { data }) => ( vec![normal_account_transaction_operation( 0, details, @@ -430,10 +452,10 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::BakerRestakeEarningsUpdated { + Known(AccountTransactionEffects::BakerRestakeEarningsUpdated { baker_id, restake_earnings, - } => ( + }) => ( vec![normal_account_transaction_operation( 0, details, @@ -445,7 +467,7 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::BakerKeysUpdated { data } => ( + Known(AccountTransactionEffects::BakerKeysUpdated { data }) => ( vec![normal_account_transaction_operation( 0, details, @@ -460,20 +482,20 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::EncryptedAmountTransferred { removed, added } => { + Known(AccountTransactionEffects::EncryptedAmountTransferred { removed, added }) => { (encrypted_transfer_operations(details, removed, added), None) } - AccountTransactionEffects::EncryptedAmountTransferredWithMemo { + Known(AccountTransactionEffects::EncryptedAmountTransferredWithMemo { removed, added, memo, - } => ( + }) => ( encrypted_transfer_operations(details, removed, added), Some(serde_json::to_value(MemoMetadata { memo: Some(memo.clone()), })), ), - AccountTransactionEffects::TransferredToEncrypted { data } => ( + Known(AccountTransactionEffects::TransferredToEncrypted { data }) => ( vec![normal_account_transaction_operation( 0, details, @@ -484,7 +506,7 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::TransferredToPublic { removed, amount } => ( + Known(AccountTransactionEffects::TransferredToPublic { removed, amount }) => ( vec![normal_account_transaction_operation( 0, details, @@ -498,7 +520,7 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::TransferredWithSchedule { to, amount } => ( + Known(AccountTransactionEffects::TransferredWithSchedule { to, amount }) => ( simple_transfer_operations( details, &Amount::from_micro_ccd(amount.iter().map(|(_, a)| a.micro_ccd()).sum()), @@ -515,7 +537,7 @@ fn operations_and_metadata_from_account_transaction_details( memo: None, })), ), - AccountTransactionEffects::TransferredWithScheduleAndMemo { to, amount, memo } => ( + Known(AccountTransactionEffects::TransferredWithScheduleAndMemo { to, amount, memo }) => ( simple_transfer_operations( details, &Amount::from_micro_ccd(amount.iter().map(|(_, a)| a.micro_ccd()).sum()), @@ -532,7 +554,7 @@ fn operations_and_metadata_from_account_transaction_details( memo: Some(memo.clone()), })), ), - AccountTransactionEffects::CredentialKeysUpdated { cred_id } => ( + Known(AccountTransactionEffects::CredentialKeysUpdated { cred_id }) => ( vec![normal_account_transaction_operation( 0, details, @@ -543,11 +565,11 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::CredentialsUpdated { + Known(AccountTransactionEffects::CredentialsUpdated { new_cred_ids, removed_cred_ids, new_threshold, - } => ( + }) => ( vec![normal_account_transaction_operation( 0, details, @@ -560,7 +582,7 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::DataRegistered { data } => ( + Known(AccountTransactionEffects::DataRegistered { data }) => ( vec![normal_account_transaction_operation( 0, details, @@ -569,280 +591,313 @@ fn operations_and_metadata_from_account_transaction_details( )], None, ), - AccountTransactionEffects::BakerConfigured { data: events } => ( + Known(AccountTransactionEffects::BakerConfigured { data: events }) => ( events .iter() .enumerate() - .map(|(i, event)| match event { - BakerEvent::DelegationRemoved { delegator_id } => { - normal_account_transaction_operation( + .filter_map(|(i, event)| { + event.as_known().or_else(|| { + log::warn!( + "Encountered unknown baker configure event; skipping. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + None + }).map(|event| match event { + BakerEvent::DelegationRemoved { delegator_id } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&DelegationRemovedMetadata { + delegator_id: *delegator_id, + }), + ) + } + BakerEvent::BakerAdded { data } => normal_account_transaction_operation( i as i64, details, None, - Some(&DelegationRemovedMetadata { - delegator_id: *delegator_id, + Some(&BakerAddedMetadata { + baker_id: data.keys_event.baker_id, + account: data.keys_event.account, + sign_key: data.keys_event.sign_key.clone(), + election_key: data.keys_event.election_key.clone(), + aggregation_key: data.keys_event.aggregation_key.clone(), + stake_uccd: data.stake, + restake_earnings: data.restake_earnings, + }), + ), + BakerEvent::BakerRemoved { baker_id } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerRemovedMetadata { + baker_id: *baker_id, + }), + ) + } + BakerEvent::BakerStakeIncreased { + baker_id, + new_stake, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerStakeUpdatedMetadata { + baker_id: *baker_id, + new_stake_uccd: *new_stake, + increased: true, + }), + ), + BakerEvent::BakerStakeDecreased { + baker_id, + new_stake, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerStakeUpdatedMetadata { + baker_id: *baker_id, + new_stake_uccd: *new_stake, + increased: false, + }), + ), + BakerEvent::BakerRestakeEarningsUpdated { + baker_id, + restake_earnings, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerRestakeEarningsUpdatedMetadata { + baker_id: *baker_id, + restake_earnings: *restake_earnings, + }), + ), + BakerEvent::BakerKeysUpdated { data } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerKeysUpdatedMetadata { + baker_id: data.baker_id, + account: data.account, + sign_key: data.sign_key.clone(), + election_key: data.election_key.clone(), + aggregation_key: data.aggregation_key.clone(), + }), + ) + } + BakerEvent::BakerSetOpenStatus { + baker_id, + open_status, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerSetOpenStatusMetadata { + baker_id: *baker_id, + open_status: match open_status { + Known(OpenStatus::OpenForAll) => "open_for_all".to_string(), + Known(OpenStatus::ClosedForNew) => "closed_for_new".to_string(), + Known(OpenStatus::ClosedForAll) => "closed_for_all".to_string(), + Unknown(_) => "unknown".to_string(), + }, + }), + ), + BakerEvent::BakerSetMetadataURL { + baker_id, + metadata_url, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerSetMetadataUrlMetadata { + baker_id: *baker_id, + metadata_url: metadata_url.to_string(), }), - ) - } - BakerEvent::BakerAdded { data } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerAddedMetadata { - baker_id: data.keys_event.baker_id, - account: data.keys_event.account, - sign_key: data.keys_event.sign_key.clone(), - election_key: data.keys_event.election_key.clone(), - aggregation_key: data.keys_event.aggregation_key.clone(), - stake_uccd: data.stake, - restake_earnings: data.restake_earnings, - }), - ), - BakerEvent::BakerRemoved { baker_id } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerRemovedMetadata { - baker_id: *baker_id, - }), - ), - BakerEvent::BakerStakeIncreased { - baker_id, - new_stake, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerStakeUpdatedMetadata { - baker_id: *baker_id, - new_stake_uccd: *new_stake, - increased: true, - }), - ), - BakerEvent::BakerStakeDecreased { - baker_id, - new_stake, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerStakeUpdatedMetadata { - baker_id: *baker_id, - new_stake_uccd: *new_stake, - increased: false, - }), - ), - BakerEvent::BakerRestakeEarningsUpdated { - baker_id, - restake_earnings, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerRestakeEarningsUpdatedMetadata { - baker_id: *baker_id, - restake_earnings: *restake_earnings, - }), - ), - BakerEvent::BakerKeysUpdated { data } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerKeysUpdatedMetadata { - baker_id: data.baker_id, - account: data.account, - sign_key: data.sign_key.clone(), - election_key: data.election_key.clone(), - aggregation_key: data.aggregation_key.clone(), - }), - ), - BakerEvent::BakerSetOpenStatus { - baker_id, - open_status, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerSetOpenStatusMetadata { - baker_id: *baker_id, - open_status: match open_status { - OpenStatus::OpenForAll => "open_for_all".to_string(), - OpenStatus::ClosedForNew => "closed_for_new".to_string(), - OpenStatus::ClosedForAll => "closed_for_all".to_string(), - }, - }), - ), - BakerEvent::BakerSetMetadataURL { - baker_id, - metadata_url, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerSetMetadataUrlMetadata { - baker_id: *baker_id, - metadata_url: metadata_url.to_string(), - }), - ), - BakerEvent::BakerSetTransactionFeeCommission { - baker_id, - transaction_fee_commission, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerSetTransactionFeeCommissionMetadata { - baker_id: *baker_id, - transaction_fee_commission: transaction_fee_commission.to_string(), - }), - ), - BakerEvent::BakerSetBakingRewardCommission { - baker_id, - baking_reward_commission, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerSetBakingRewardCommissionMetadata { - baker_id: *baker_id, - baking_reward_commission: baking_reward_commission.to_string(), - }), - ), - BakerEvent::BakerSetFinalizationRewardCommission { - baker_id, - finalization_reward_commission, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerSetFinalizationRewardCommissionMetadata { - baker_id: *baker_id, - finalization_reward_commission: finalization_reward_commission - .to_string(), - }), - ), - BakerEvent::BakerSuspended { baker_id } => { - normal_account_transaction_operation( + ), + BakerEvent::BakerSetTransactionFeeCommission { + baker_id, + transaction_fee_commission, + } => normal_account_transaction_operation( i as i64, details, None, - Some(&BakerSuspensionMetadata { + Some(&BakerSetTransactionFeeCommissionMetadata { baker_id: *baker_id, - suspended: true, + transaction_fee_commission: transaction_fee_commission.to_string(), }), - ) - } - BakerEvent::BakerResumed { baker_id } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&BakerSuspensionMetadata { - baker_id: *baker_id, - suspended: false, - }), - ), + ), + BakerEvent::BakerSetBakingRewardCommission { + baker_id, + baking_reward_commission, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerSetBakingRewardCommissionMetadata { + baker_id: *baker_id, + baking_reward_commission: baking_reward_commission.to_string(), + }), + ), + BakerEvent::BakerSetFinalizationRewardCommission { + baker_id, + finalization_reward_commission, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerSetFinalizationRewardCommissionMetadata { + baker_id: *baker_id, + finalization_reward_commission: finalization_reward_commission + .to_string(), + }), + ), + BakerEvent::BakerSuspended { baker_id } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerSuspensionMetadata { + baker_id: *baker_id, + suspended: true, + }), + ) + } + BakerEvent::BakerResumed { baker_id } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerSuspensionMetadata { + baker_id: *baker_id, + suspended: false, + }), + ) + } + }) }) .collect(), None, ), - AccountTransactionEffects::DelegationConfigured { data: events } => ( + Known(AccountTransactionEffects::DelegationConfigured { data: events }) => ( events .iter() .enumerate() - .map(|(i, event)| match event { - DelegationEvent::BakerRemoved { baker_id } => { - normal_account_transaction_operation( + .filter_map(|(i, event)| { + event.as_known().or_else(|| { + log::warn!( + "Encountered unknown delegation configure event; skipping. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + None + }).map(|event| match event { + DelegationEvent::BakerRemoved { baker_id } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&BakerRemovedMetadata { + baker_id: *baker_id, + }), + ) + } + DelegationEvent::DelegationAdded { delegator_id } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&DelegationAddedMetadata { + delegator_id: *delegator_id, + }), + ) + } + DelegationEvent::DelegationRemoved { delegator_id } => { + normal_account_transaction_operation( + i as i64, + details, + None, + Some(&DelegationRemovedMetadata { + delegator_id: *delegator_id, + }), + ) + } + DelegationEvent::DelegationStakeIncreased { + delegator_id, + new_stake, + } => normal_account_transaction_operation( i as i64, details, None, - Some(&BakerRemovedMetadata { - baker_id: *baker_id, + Some(&DelegationStakeUpdatedMetadata { + delegator_id: *delegator_id, + new_stake_uccd: *new_stake, + increased: true, }), - ) - } - DelegationEvent::DelegationAdded { delegator_id } => { - normal_account_transaction_operation( + ), + DelegationEvent::DelegationStakeDecreased { + delegator_id, + new_stake, + } => normal_account_transaction_operation( i as i64, details, None, - Some(&DelegationAddedMetadata { + Some(&DelegationStakeUpdatedMetadata { delegator_id: *delegator_id, + new_stake_uccd: *new_stake, + increased: false, }), - ) - } - DelegationEvent::DelegationRemoved { delegator_id } => { - normal_account_transaction_operation( + ), + DelegationEvent::DelegationSetRestakeEarnings { + delegator_id, + restake_earnings, + } => normal_account_transaction_operation( i as i64, details, None, - Some(&DelegationRemovedMetadata { + Some(&DelegationSetRestakeEarningsMetadata { delegator_id: *delegator_id, + restake_earnings: *restake_earnings, }), - ) - } - DelegationEvent::DelegationStakeIncreased { - delegator_id, - new_stake, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&DelegationStakeUpdatedMetadata { - delegator_id: *delegator_id, - new_stake_uccd: *new_stake, - increased: true, - }), - ), - DelegationEvent::DelegationStakeDecreased { - delegator_id, - new_stake, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&DelegationStakeUpdatedMetadata { - delegator_id: *delegator_id, - new_stake_uccd: *new_stake, - increased: false, - }), - ), - DelegationEvent::DelegationSetRestakeEarnings { - delegator_id, - restake_earnings, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&DelegationSetRestakeEarningsMetadata { - delegator_id: *delegator_id, - restake_earnings: *restake_earnings, - }), - ), - DelegationEvent::DelegationSetDelegationTarget { - delegator_id, - delegation_target, - } => normal_account_transaction_operation( - i as i64, - details, - None, - Some(&DelegationSetDelegationTargetMetadata { - delegator_id: *delegator_id, - delegation_target: match delegation_target { - DelegationTarget::Passive => "passive".to_string(), - DelegationTarget::Baker { baker_id } => { - format!("baker:{}", baker_id.id) - } - }, - }), - ), + ), + DelegationEvent::DelegationSetDelegationTarget { + delegator_id, + delegation_target, + } => normal_account_transaction_operation( + i as i64, + details, + None, + Some(&DelegationSetDelegationTargetMetadata { + delegator_id: *delegator_id, + delegation_target: match delegation_target { + DelegationTarget::Passive => "passive".to_string(), + DelegationTarget::Baker { baker_id } => { + format!("baker:{}", baker_id.id) + } + }, + }), + ), + }) }) .collect(), None, ), - AccountTransactionEffects::TokenUpdate { .. } => { + Known(AccountTransactionEffects::TokenUpdate { .. }) => { log::warn!("Token update not yet supported"); (vec![], None) } + Unknown(_) => { + log::warn!( + "Unknown account transaction effects. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + (vec![], None) + } } } @@ -890,25 +945,36 @@ fn operations_and_metadata_from_chain_update_details(details: &UpdateDetails) -> account: None, amount: None, coin_change: None, - metadata: Some( - serde_json::to_value(&ChainUpdateMetadata { - effective_time: details.effective_time, - payload: details.payload.clone(), + metadata: details + .payload + .as_known() + .or_else(|| { + log::warn!( + "Encountered unknown chain update event. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + None }) - .unwrap(), - ), + .map(|payload| { + serde_json::to_value(&ChainUpdateMetadata { + effective_time: details.effective_time, + payload: payload.clone(), + }) + .unwrap() + }), }] } fn contract_update_operations( details: &AccountTransactionDetails, - effects: &[ContractTraceElement], + effects: &[Upward], ) -> Vec { let mut ops = vec![]; let mut next_index = 0; for e in effects.iter() { match e { - ContractTraceElement::Updated { data } => { + Known(ContractTraceElement::Updated { data }) => { // TODO Adapt and use 'simple_transfer_operations'. ops.push(account_transaction_operation::( next_index, @@ -929,7 +995,7 @@ fn contract_update_operations( )); next_index += 2; } - ContractTraceElement::Transferred { from, amount, to } => { + Known(ContractTraceElement::Transferred { from, amount, to }) => { // TODO Adapt and use 'simple_transfer_operations'. ops.push(account_transaction_operation::( next_index, @@ -947,9 +1013,16 @@ fn contract_update_operations( )); next_index += 2; } - ContractTraceElement::Interrupted { .. } => {} - ContractTraceElement::Resumed { .. } => {} - ContractTraceElement::Upgraded { .. } => {} + Known(ContractTraceElement::Interrupted { .. }) => {} + Known(ContractTraceElement::Resumed { .. }) => {} + Known(ContractTraceElement::Upgraded { .. }) => {} + Unknown(_) => { + log::warn!( + "Unknown contract trace element in contract update effects; skipping. \ + The node/protocol version may not be fully supported by this version of {}.", + env!("CARGO_PKG_NAME") + ); + } } } ops @@ -1030,7 +1103,9 @@ fn account_transaction_operation( Operation { operation_identifier: Box::new(OperationIdentifier::new(index)), related_operations: None, - _type: transaction_type_to_operation_type(details.transaction_type()), + _type: transaction_type_to_operation_type( + details.transaction_type().and_then(Upward::known), + ), status: Some(OPERATION_STATUS_OK.to_string()), account: Some(Box::new(AccountIdentifier::new(account_address))), amount: amount.map(Box::new),