From f10df77f937138241b3161f0d18a2f65c77f9015 Mon Sep 17 00:00:00 2001 From: t00ts Date: Mon, 3 Feb 2025 18:52:07 +0400 Subject: [PATCH] feat(rpc/v06): restore `starknet_estimateFee`, `starknet_getTransactionStatus`, `starknet_getTransactionReceipt` --- crates/rpc/src/dto/fee.rs | 43 ++++++++++++++++++- crates/rpc/src/dto/receipt.rs | 10 +++-- crates/rpc/src/lib.rs | 4 -- .../rpc/src/method/get_transaction_status.rs | 40 ++++++++++++++++- crates/rpc/src/v06.rs | 12 +++--- 5 files changed, 90 insertions(+), 19 deletions(-) diff --git a/crates/rpc/src/dto/fee.rs b/crates/rpc/src/dto/fee.rs index 085e426806..c67b9df403 100644 --- a/crates/rpc/src/dto/fee.rs +++ b/crates/rpc/src/dto/fee.rs @@ -17,15 +17,19 @@ impl crate::dto::SerializeForVersion for pathfinder_executor::types::FeeEstimate serializer.serialize_field("l2_gas_price", &U256Hex(self.l2_gas_price))?; serializer.serialize_field("overall_fee", &U256Hex(self.overall_fee))?; serializer.serialize_field("unit", &self.unit)?; - } else { + } else if serializer.version >= crate::dto::RpcVersion::V07 { serializer.serialize_field("gas_price", &U256Hex(self.l1_gas_price))?; serializer.serialize_field("gas_consumed", &U256Hex(self.l1_gas_consumed))?; serializer.serialize_field("data_gas_consumed", &U256Hex(self.l1_data_gas_consumed))?; serializer.serialize_field("data_gas_price", &U256Hex(self.l1_data_gas_price))?; serializer.serialize_field("overall_fee", &U256Hex(self.overall_fee))?; serializer.serialize_field("unit", &self.unit)?; + } else { + serializer.serialize_field("gas_price", &U256Hex(self.l1_gas_price))?; + serializer.serialize_field("gas_consumed", &U256Hex(self.l1_gas_consumed))?; + serializer.serialize_field("overall_fee", &U256Hex(self.overall_fee))?; + serializer.serialize_field("unit", &self.unit)?; } - serializer.end() } } @@ -41,3 +45,38 @@ impl crate::dto::SerializeForVersion for pathfinder_executor::types::PriceUnit { }) } } + +#[cfg(test)] +mod tests { + use pathfinder_executor::types::{FeeEstimate, PriceUnit}; + use primitive_types::U256; + + use super::*; + use crate::dto::SerializeForVersion; + + #[test] + fn fee_estimate_v06_serialization() { + let fee = FeeEstimate { + l1_gas_consumed: U256::from(100), + l1_gas_price: U256::from(50), + l1_data_gas_consumed: U256::from(200), + l1_data_gas_price: U256::from(25), + l2_gas_consumed: U256::from(300), + l2_gas_price: U256::from(10), + overall_fee: U256::from(1000), + unit: PriceUnit::Wei, + }; + + let serializer = crate::dto::Serializer::new(crate::dto::RpcVersion::V06); + let result = serde_json::to_value(fee.serialize(serializer).unwrap()).unwrap(); + + let expected = serde_json::json!({ + "gas_consumed": "0x64", // 100 + "gas_price": "0x32", // 50 + "overall_fee": "0x3e8", // 1000 + "unit": "WEI" + }); + + assert_eq!(result, expected); + } +} diff --git a/crates/rpc/src/dto/receipt.rs b/crates/rpc/src/dto/receipt.rs index 236342a1e8..4e070b9c7f 100644 --- a/crates/rpc/src/dto/receipt.rs +++ b/crates/rpc/src/dto/receipt.rs @@ -377,10 +377,12 @@ impl SerializeForVersion for ExecutionResources<'_> { if serializer.version < RpcVersion::V08 { serializer.flatten(&ComputationResources(self.0))?; - serializer.serialize_field( - "data_availability", - &DataAvailability(&self.0.data_availability), - )?; + if serializer.version > RpcVersion::V06 { + serializer.serialize_field( + "data_availability", + &DataAvailability(&self.0.data_availability), + )?; + } } else { serializer.serialize_field("l1_gas", &self.0.total_gas_consumed.l1_gas)?; serializer.serialize_field("l1_data_gas", &self.0.total_gas_consumed.l1_data_gas)?; diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index e60bd72f15..c739e89d4f 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -967,12 +967,8 @@ mod tests { "v06/starknet_api_openrpc.json", &[ "starknet_getStateUpdate", - "starknet_getTransactionReceipt", - "starknet_getTransactionStatus", - "starknet_estimateFee", "starknet_estimateMessageFee", "starknet_getEvents", - "starknet_call", ], Api::HttpOnly)] // #[case::v0_6_api_websocket("/ws/rpc/v0_6", "v06/starknet_api_openrpc.json", &[], Api::WebsocketOnly)] diff --git a/crates/rpc/src/method/get_transaction_status.rs b/crates/rpc/src/method/get_transaction_status.rs index 81578b7ec7..674cd9535e 100644 --- a/crates/rpc/src/method/get_transaction_status.rs +++ b/crates/rpc/src/method/get_transaction_status.rs @@ -168,8 +168,7 @@ impl crate::dto::SerializeForVersion for Output { let mut serializer = serializer.serialize_struct()?; serializer.serialize_field("finality_status", &self.finality_status())?; serializer.serialize_optional("execution_status", self.execution_status())?; - // Delete check once rustc gives you a friendly reminder - if serializer.version != RpcVersion::V07 { + if serializer.version > RpcVersion::V07 { serializer.serialize_optional("failure_reason", self.failure_reason())?; } serializer.end() @@ -315,4 +314,41 @@ mod tests { assert_matches!(err, Error::TxnHashNotFound); } + + #[test] + fn test_v06_serialization() { + use crate::dto::SerializeForVersion; + + let cases = [ + (Output::Received, json!({"finality_status": "RECEIVED"})), + ( + Output::Rejected { + error_message: Some("error".to_string()), + }, + json!({"finality_status": "REJECTED"}), + ), + ( + Output::AcceptedOnL1(TxnExecutionStatus::Succeeded), + json!({ + "finality_status": "ACCEPTED_ON_L1", + "execution_status": "SUCCEEDED" + }), + ), + ( + Output::AcceptedOnL2(TxnExecutionStatus::Reverted { + reason: Some("error".to_string()), + }), + json!({ + "finality_status": "ACCEPTED_ON_L2", + "execution_status": "REVERTED" + }), + ), + ]; + + for (output, expected) in cases { + let serializer = crate::dto::Serializer::new(crate::RpcVersion::V06); + let encoded = output.serialize(serializer).unwrap(); + assert_eq!(encoded, expected); + } + } } diff --git a/crates/rpc/src/v06.rs b/crates/rpc/src/v06.rs index 69b4fee983..10e3c678e2 100644 --- a/crates/rpc/src/v06.rs +++ b/crates/rpc/src/v06.rs @@ -15,17 +15,15 @@ pub fn register_routes() -> RpcRouterBuilder { .register("starknet_getBlockWithTxHashes", crate::method::get_block_with_tx_hashes) .register("starknet_getBlockWithTxs", crate::method::get_block_with_txs) .register("starknet_getClassHashAt", crate::method::get_class_hash_at) + .register("starknet_estimateFee", crate::method::estimate_fee) .register("starknet_getNonce", crate::method::get_nonce) .register("starknet_getStorageAt", crate::method::get_storage_at) .register("starknet_getTransactionByHash", crate::method::get_transaction_by_hash) + .register("starknet_getTransactionStatus", crate::method::get_transaction_status) + .register("starknet_getTransactionReceipt", crate::method::get_transaction_receipt) .register("starknet_getTransactionByBlockIdAndIndex", crate::method::get_transaction_by_block_id_and_index) - .register("starknet_specVersion", || "0.6.0") .register("starknet_syncing", crate::method::syncing) .register("pathfinder_getProof", crate::pathfinder::methods::get_proof) - .register("starknet_blockNumber", crate::method::block_number) - .register("starknet_chainId", crate::method::chain_id) - .register("starknet_getBlockTransactionCount", crate::method::get_block_transaction_count) - .register("starknet_getNonce", crate::method::get_nonce) - .register("starknet_getStorageAt", crate::method::get_storage_at) .register("starknet_call", crate::method::call) -} + .register("starknet_specVersion", || "0.6.0") + }