diff --git a/crates/rpc/src/method/add_declare_transaction.rs b/crates/rpc/src/method/add_declare_transaction.rs index 134c891f14..69591610aa 100644 --- a/crates/rpc/src/method/add_declare_transaction.rs +++ b/crates/rpc/src/method/add_declare_transaction.rs @@ -154,6 +154,122 @@ pub struct Input { token: Option, } +impl Input { + pub fn is_v3_transaction(&self) -> bool { + matches!( + self.declare_transaction, + Transaction::Declare(BroadcastedDeclareTransaction::V3(_)) + ) + } +} + +#[cfg(test)] +impl Input { + pub(crate) fn for_test_with_v0_transaction() -> Self { + Self { + declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V0( + crate::types::request::BroadcastedDeclareTransactionV0 { + max_fee: Default::default(), + version: pathfinder_common::TransactionVersion::ZERO, + signature: Default::default(), + contract_class: crate::types::CairoContractClass { + program: Default::default(), + entry_points_by_type: crate::types::ContractEntryPoints { + constructor: Default::default(), + external: Default::default(), + l1_handler: Default::default(), + }, + abi: Default::default(), + }, + sender_address: Default::default(), + }, + )), + token: None, + } + } + + pub(crate) fn for_test_with_v1_transaction() -> Self { + Self { + declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V1( + crate::types::request::BroadcastedDeclareTransactionV1 { + max_fee: Default::default(), + version: pathfinder_common::TransactionVersion::ONE, + signature: Default::default(), + nonce: Default::default(), + contract_class: crate::types::CairoContractClass { + program: Default::default(), + entry_points_by_type: crate::types::ContractEntryPoints { + constructor: Default::default(), + external: Default::default(), + l1_handler: Default::default(), + }, + abi: Default::default(), + }, + sender_address: Default::default(), + }, + )), + token: None, + } + } + + pub(crate) fn for_test_with_v2_transaction() -> Self { + Self { + declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V2( + crate::types::request::BroadcastedDeclareTransactionV2 { + max_fee: Default::default(), + version: pathfinder_common::TransactionVersion::TWO, + signature: Default::default(), + nonce: Default::default(), + compiled_class_hash: Default::default(), + contract_class: crate::types::SierraContractClass { + sierra_program: Default::default(), + contract_class_version: Default::default(), + entry_points_by_type: crate::types::SierraEntryPoints { + constructor: Default::default(), + external: Default::default(), + l1_handler: Default::default(), + }, + abi: Default::default(), + }, + sender_address: Default::default(), + }, + )), + token: None, + } + } + + pub(crate) fn for_test_with_v3_transaction() -> Self { + Self { + declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V3( + crate::types::request::BroadcastedDeclareTransactionV3 { + version: pathfinder_common::TransactionVersion::THREE, + signature: Default::default(), + nonce: Default::default(), + resource_bounds: Default::default(), + tip: Default::default(), + paymaster_data: Default::default(), + account_deployment_data: Default::default(), + nonce_data_availability_mode: Default::default(), + fee_data_availability_mode: Default::default(), + compiled_class_hash: Default::default(), + contract_class: crate::types::SierraContractClass { + sierra_program: Default::default(), + contract_class_version: Default::default(), + entry_points_by_type: crate::types::SierraEntryPoints { + constructor: Default::default(), + external: Default::default(), + l1_handler: Default::default(), + }, + abi: Default::default(), + }, + sender_address: Default::default(), + }, + )), + token: None, + } + } +} + impl crate::dto::DeserializeForVersion for Input { fn deserialize(value: crate::dto::Value) -> Result { value.deserialize_map(|value| { diff --git a/crates/rpc/src/method/add_deploy_account_transaction.rs b/crates/rpc/src/method/add_deploy_account_transaction.rs index e27951eba0..b6aefc1d6c 100644 --- a/crates/rpc/src/method/add_deploy_account_transaction.rs +++ b/crates/rpc/src/method/add_deploy_account_transaction.rs @@ -31,6 +31,55 @@ pub struct Input { deploy_account_transaction: Transaction, } +impl Input { + pub fn is_v3_transaction(&self) -> bool { + matches!( + self.deploy_account_transaction, + Transaction::DeployAccount(BroadcastedDeployAccountTransaction::V3(_)) + ) + } +} +#[cfg(test)] +impl Input { + pub(crate) fn for_test_with_v1_transaction() -> Self { + Self { + deploy_account_transaction: Transaction::DeployAccount( + BroadcastedDeployAccountTransaction::V1(BroadcastedDeployAccountTransactionV1 { + version: pathfinder_common::TransactionVersion::ONE, + max_fee: Default::default(), + signature: Default::default(), + nonce: Default::default(), + class_hash: Default::default(), + contract_address_salt: Default::default(), + constructor_calldata: Default::default(), + }), + ), + } + } + + pub(crate) fn for_test_with_v3_transaction() -> Self { + Self { + deploy_account_transaction: Transaction::DeployAccount( + BroadcastedDeployAccountTransaction::V3( + crate::types::request::BroadcastedDeployAccountTransactionV3 { + version: pathfinder_common::TransactionVersion::THREE, + signature: Default::default(), + nonce: Default::default(), + resource_bounds: Default::default(), + tip: Default::default(), + paymaster_data: Default::default(), + nonce_data_availability_mode: Default::default(), + fee_data_availability_mode: Default::default(), + contract_address_salt: Default::default(), + constructor_calldata: Default::default(), + class_hash: Default::default(), + }, + ), + ), + } + } +} + impl crate::dto::DeserializeForVersion for Input { fn deserialize(value: crate::dto::Value) -> Result { value.deserialize_map(|value| { diff --git a/crates/rpc/src/method/add_invoke_transaction.rs b/crates/rpc/src/method/add_invoke_transaction.rs index 5c18cbe2f2..c1d1c1c23b 100644 --- a/crates/rpc/src/method/add_invoke_transaction.rs +++ b/crates/rpc/src/method/add_invoke_transaction.rs @@ -28,6 +28,68 @@ pub struct Input { invoke_transaction: Transaction, } +impl Input { + pub fn is_v3_transaction(&self) -> bool { + matches!( + self.invoke_transaction, + Transaction::Invoke(BroadcastedInvokeTransaction::V3(_)) + ) + } +} + +#[cfg(test)] +impl Input { + pub(crate) fn for_test_with_v0_transaction() -> Self { + Self { + invoke_transaction: Transaction::Invoke(BroadcastedInvokeTransaction::V0( + crate::types::request::BroadcastedInvokeTransactionV0 { + version: pathfinder_common::TransactionVersion::ZERO, + max_fee: Default::default(), + signature: Default::default(), + contract_address: Default::default(), + entry_point_selector: Default::default(), + calldata: Default::default(), + }, + )), + } + } + + pub(crate) fn for_test_with_v1_transaction() -> Self { + Self { + invoke_transaction: Transaction::Invoke(BroadcastedInvokeTransaction::V1( + crate::types::request::BroadcastedInvokeTransactionV1 { + version: pathfinder_common::TransactionVersion::ONE, + max_fee: Default::default(), + signature: Default::default(), + nonce: Default::default(), + sender_address: Default::default(), + calldata: Default::default(), + }, + )), + } + } + + pub(crate) fn for_test_with_v3_transaction() -> Self { + Self { + invoke_transaction: Transaction::Invoke(BroadcastedInvokeTransaction::V3( + crate::types::request::BroadcastedInvokeTransactionV3 { + version: pathfinder_common::TransactionVersion::THREE, + signature: Default::default(), + nonce: Default::default(), + resource_bounds: Default::default(), + tip: Default::default(), + paymaster_data: Default::default(), + account_deployment_data: Default::default(), + nonce_data_availability_mode: Default::default(), + fee_data_availability_mode: Default::default(), + sender_address: Default::default(), + calldata: Default::default(), + }, + )), + } + } +} + impl crate::dto::DeserializeForVersion for Input { fn deserialize(value: crate::dto::Value) -> Result { value.deserialize_map(|value| { diff --git a/crates/rpc/src/v08.rs b/crates/rpc/src/v08.rs index 9106c9134d..b9889bc985 100644 --- a/crates/rpc/src/v08.rs +++ b/crates/rpc/src/v08.rs @@ -1,3 +1,7 @@ +mod method; + +use method as v08_method; + use crate::jsonrpc::{RpcRouter, RpcRouterBuilder}; use crate::method::subscribe_events::SubscribeEvents; use crate::method::subscribe_new_heads::SubscribeNewHeads; @@ -7,9 +11,9 @@ use crate::method::subscribe_transaction_status::SubscribeTransactionStatus; #[rustfmt::skip] pub fn register_routes() -> RpcRouterBuilder { RpcRouter::builder(crate::RpcVersion::V08) - .register("starknet_addDeclareTransaction", crate::method::add_declare_transaction) - .register("starknet_addDeployAccountTransaction", crate::method::add_deploy_account_transaction) - .register("starknet_addInvokeTransaction", crate::method::add_invoke_transaction) + .register("starknet_addDeclareTransaction", v08_method::add_declare_transaction) + .register("starknet_addDeployAccountTransaction", v08_method::add_deploy_account_transaction) + .register("starknet_addInvokeTransaction", v08_method::add_invoke_transaction) .register("starknet_blockHashAndNumber", crate::method::block_hash_and_number) .register("starknet_blockNumber", crate::method::block_number) .register("starknet_call", crate::method::call) diff --git a/crates/rpc/src/v08/method.rs b/crates/rpc/src/v08/method.rs new file mode 100644 index 0000000000..1cd4de8c3a --- /dev/null +++ b/crates/rpc/src/v08/method.rs @@ -0,0 +1,7 @@ +mod add_declare_transaction; +mod add_deploy_account_transaction; +mod add_invoke_transaction; + +pub use add_declare_transaction::add_declare_transaction; +pub use add_deploy_account_transaction::add_deploy_account_transaction; +pub use add_invoke_transaction::add_invoke_transaction; diff --git a/crates/rpc/src/v08/method/add_declare_transaction.rs b/crates/rpc/src/v08/method/add_declare_transaction.rs new file mode 100644 index 0000000000..1a4ec7e06f --- /dev/null +++ b/crates/rpc/src/v08/method/add_declare_transaction.rs @@ -0,0 +1,37 @@ +use crate::context::RpcContext; +use crate::method::add_declare_transaction::{AddDeclareTransactionError, Input, Output}; + +pub async fn add_declare_transaction( + context: RpcContext, + input: Input, +) -> Result { + if !input.is_v3_transaction() { + return Err(AddDeclareTransactionError::UnsupportedTransactionVersion); + } + + crate::method::add_declare_transaction::add_declare_transaction(context, input).await +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::context::RpcContext; + + #[rstest::rstest] + #[case::v0_is_unsupported(Input::for_test_with_v0_transaction(), false)] + #[case::v1_is_unsupported(Input::for_test_with_v1_transaction(), false)] + #[case::v2_is_unsupported(Input::for_test_with_v2_transaction(), false)] + #[case::v3_is_supported(Input::for_test_with_v3_transaction(), true)] + #[tokio::test] + async fn only_v3_transactions_are_accepted(#[case] input: Input, #[case] is_supported: bool) { + let context = RpcContext::for_tests(); + let result = add_declare_transaction(context, input).await; + assert_eq!( + !is_supported, + matches!( + result, + Err(AddDeclareTransactionError::UnsupportedTransactionVersion) + ) + ); + } +} diff --git a/crates/rpc/src/v08/method/add_deploy_account_transaction.rs b/crates/rpc/src/v08/method/add_deploy_account_transaction.rs new file mode 100644 index 0000000000..d80b8ea357 --- /dev/null +++ b/crates/rpc/src/v08/method/add_deploy_account_transaction.rs @@ -0,0 +1,40 @@ +use crate::context::RpcContext; +use crate::method::add_deploy_account_transaction::{ + AddDeployAccountTransactionError, + Input, + Output, +}; + +pub async fn add_deploy_account_transaction( + context: RpcContext, + input: Input, +) -> Result { + if !input.is_v3_transaction() { + return Err(AddDeployAccountTransactionError::UnsupportedTransactionVersion); + } + + crate::method::add_deploy_account_transaction::add_deploy_account_transaction(context, input) + .await +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::context::RpcContext; + + #[rstest::rstest] + #[case::v1_is_unsupported(Input::for_test_with_v1_transaction(), false)] + #[case::v3_is_supported(Input::for_test_with_v3_transaction(), true)] + #[tokio::test] + async fn only_v3_transactions_are_accepted(#[case] input: Input, #[case] is_supported: bool) { + let context = RpcContext::for_tests(); + let result = add_deploy_account_transaction(context, input).await; + assert_eq!( + !is_supported, + matches!( + result, + Err(AddDeployAccountTransactionError::UnsupportedTransactionVersion) + ) + ); + } +} diff --git a/crates/rpc/src/v08/method/add_invoke_transaction.rs b/crates/rpc/src/v08/method/add_invoke_transaction.rs new file mode 100644 index 0000000000..ad610c0d38 --- /dev/null +++ b/crates/rpc/src/v08/method/add_invoke_transaction.rs @@ -0,0 +1,36 @@ +use crate::context::RpcContext; +use crate::method::add_invoke_transaction::{AddInvokeTransactionError, Input, Output}; + +pub async fn add_invoke_transaction( + context: RpcContext, + input: Input, +) -> Result { + if !input.is_v3_transaction() { + return Err(AddInvokeTransactionError::UnsupportedTransactionVersion); + } + + crate::method::add_invoke_transaction::add_invoke_transaction(context, input).await +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::context::RpcContext; + + #[rstest::rstest] + #[case::v0_is_unsupported(Input::for_test_with_v0_transaction(), false)] + #[case::v1_is_unsupported(Input::for_test_with_v1_transaction(), false)] + #[case::v3_is_supported(Input::for_test_with_v3_transaction(), true)] + #[tokio::test] + async fn only_v3_transactions_are_accepted(#[case] input: Input, #[case] is_supported: bool) { + let context = RpcContext::for_tests(); + let result = add_invoke_transaction(context, input).await; + assert_eq!( + !is_supported, + matches!( + result, + Err(AddInvokeTransactionError::UnsupportedTransactionVersion) + ) + ); + } +}