diff --git a/starknet-accounts/src/account/declaration.rs b/starknet-accounts/src/account/declaration.rs index 8efe9b59..17930d72 100644 --- a/starknet-accounts/src/account/declaration.rs +++ b/starknet-accounts/src/account/declaration.rs @@ -68,6 +68,7 @@ impl<'a, A> DeclarationV2<'a, A> { nonce: None, max_fee: None, fee_estimate_multiplier: 1.1, + is_signer_interactive: None, } } @@ -97,6 +98,14 @@ impl<'a, A> DeclarationV2<'a, A> { } } + /// Returns a new [`DeclarationV2`] with the an interactive signer. + pub fn with_interactive_signer(self) -> Self { + Self { + is_signer_interactive: Some(()), + ..self + } + } + /// Calling this function after manually specifying `nonce` and `max_fee` turns [`DeclarationV2`] /// into [`PreparedDeclarationV2`]. Returns `Err` if either field is `None`. pub fn prepared(self) -> Result, NotPreparedError> { @@ -209,7 +218,7 @@ where &self, nonce: Felt, ) -> Result> { - let skip_signature = self.account.is_signer_interactive(); + let skip_signature = self.is_signer_interactive(); let prepared = PreparedDeclarationV2 { account: self.account, @@ -245,7 +254,7 @@ where skip_validate: bool, skip_fee_charge: bool, ) -> Result> { - let skip_signature = if self.account.is_signer_interactive() { + let skip_signature = if self.is_signer_interactive() { // If signer is interactive, we would try to minimize signing requests. However, if the // caller has decided to not skip validation, it's best we still request a real // signature, as otherwise the simulation would most likely fail. @@ -285,6 +294,14 @@ where .await .map_err(AccountError::Provider) } + + fn is_signer_interactive(&self) -> bool { + if self.is_signer_interactive.is_some() { + true + } else { + self.account.is_signer_interactive() + } + } } impl<'a, A> DeclarationV3<'a, A> { @@ -306,6 +323,7 @@ impl<'a, A> DeclarationV3<'a, A> { gas_price: None, gas_estimate_multiplier: 1.5, gas_price_estimate_multiplier: 1.5, + is_signer_interactive: None, } } @@ -353,6 +371,14 @@ impl<'a, A> DeclarationV3<'a, A> { } } + /// Returns a new [`DeclarationV3`] with the an interactive signer. + pub fn with_interactive_signer(self) -> Self { + Self { + is_signer_interactive: Some(()), + ..self + } + } + /// Calling this function after manually specifying `nonce`, `gas` and `gas_price` turns /// [`DeclarationV3`] into [`PreparedDeclarationV3`]. Returns `Err` if any field is `None`. pub fn prepared(self) -> Result, NotPreparedError> { @@ -519,7 +545,7 @@ where &self, nonce: Felt, ) -> Result> { - let skip_signature = self.account.is_signer_interactive(); + let skip_signature = self.is_signer_interactive(); let prepared = PreparedDeclarationV3 { account: self.account, @@ -556,7 +582,7 @@ where skip_validate: bool, skip_fee_charge: bool, ) -> Result> { - let skip_signature = if self.account.is_signer_interactive() { + let skip_signature = if self.is_signer_interactive() { // If signer is interactive, we would try to minimize signing requests. However, if the // caller has decided to not skip validation, it's best we still request a real // signature, as otherwise the simulation would most likely fail. @@ -597,6 +623,14 @@ where .await .map_err(AccountError::Provider) } + + fn is_signer_interactive(&self) -> bool { + if self.is_signer_interactive.is_some() { + true + } else { + self.account.is_signer_interactive() + } + } } impl<'a, A> LegacyDeclaration<'a, A> { @@ -611,6 +645,7 @@ impl<'a, A> LegacyDeclaration<'a, A> { nonce: None, max_fee: None, fee_estimate_multiplier: 1.1, + is_signer_interactive: None, } } @@ -640,6 +675,14 @@ impl<'a, A> LegacyDeclaration<'a, A> { } } + /// Returns a new [`LegacyDeclaration`] with the an interactive signer. + pub fn with_interactive_signer(self) -> Self { + Self { + is_signer_interactive: Some(()), + ..self + } + } + /// Calling this function after manually specifying `nonce` and `max_fee` turns /// [`LegacyDeclaration`] into [`PreparedLegacyDeclaration`]. Returns `Err` if either field is /// `None`. @@ -753,7 +796,7 @@ where &self, nonce: Felt, ) -> Result> { - let skip_signature = self.account.is_signer_interactive(); + let skip_signature = self.is_signer_interactive(); let prepared = PreparedLegacyDeclaration { account: self.account, @@ -788,7 +831,7 @@ where skip_validate: bool, skip_fee_charge: bool, ) -> Result> { - let skip_signature = if self.account.is_signer_interactive() { + let skip_signature = if self.is_signer_interactive() { // If signer is interactive, we would try to minimize signing requests. However, if the // caller has decided to not skip validation, it's best we still request a real // signature, as otherwise the simulation would most likely fail. @@ -827,6 +870,14 @@ where .await .map_err(AccountError::Provider) } + + fn is_signer_interactive(&self) -> bool { + if self.is_signer_interactive.is_some() { + true + } else { + self.account.is_signer_interactive() + } + } } impl RawDeclarationV2 { diff --git a/starknet-accounts/src/account/execution.rs b/starknet-accounts/src/account/execution.rs index b96ee505..b53118e9 100644 --- a/starknet-accounts/src/account/execution.rs +++ b/starknet-accounts/src/account/execution.rs @@ -52,6 +52,7 @@ impl<'a, A> ExecutionV1<'a, A> { nonce: None, max_fee: None, fee_estimate_multiplier: 1.1, + is_signer_interactive: None, } } @@ -81,6 +82,14 @@ impl<'a, A> ExecutionV1<'a, A> { } } + /// Returns a new [`ExecutionV1`] with the an interactive signer. + pub fn with_interactive_signer(self) -> Self { + Self { + is_signer_interactive: Some(()), + ..self + } + } + /// Calling this function after manually specifying `nonce` and `max_fee` turns [`ExecutionV1`] into /// [`PreparedExecutionV1`]. Returns `Err` if either field is `None`. pub fn prepared(self) -> Result, NotPreparedError> { @@ -112,6 +121,7 @@ impl<'a, A> ExecutionV3<'a, A> { gas_price: None, gas_estimate_multiplier: 1.5, gas_price_estimate_multiplier: 1.5, + is_signer_interactive: None, } } @@ -159,6 +169,14 @@ impl<'a, A> ExecutionV3<'a, A> { } } + /// Returns a new [`ExecutionV3`] with the an interactive signer. + pub fn with_interactive_signer(self) -> Self { + Self { + is_signer_interactive: Some(()), + ..self + } + } + /// Calling this function after manually specifying `nonce`, `gas` and `gas_price` turns /// [`ExecutionV3`] into [`PreparedExecutionV3`]. Returns `Err` if any field is `None`. pub fn prepared(self) -> Result, NotPreparedError> { @@ -271,7 +289,7 @@ where &self, nonce: Felt, ) -> Result> { - let skip_signature = self.account.is_signer_interactive(); + let skip_signature = self.is_signer_interactive(); let prepared = PreparedExecutionV1 { account: self.account, @@ -309,7 +327,7 @@ where skip_validate: bool, skip_fee_charge: bool, ) -> Result> { - let skip_signature = if self.account.is_signer_interactive() { + let skip_signature = if self.is_signer_interactive() { // If signer is interactive, we would try to minimize signing requests. However, if the // caller has decided to not skip validation, it's best we still request a real // signature, as otherwise the simulation would most likely fail. @@ -351,6 +369,14 @@ where .await .map_err(AccountError::Provider) } + + fn is_signer_interactive(&self) -> bool { + if self.is_signer_interactive.is_some() { + true + } else { + self.account.is_signer_interactive() + } + } } impl<'a, A> ExecutionV3<'a, A> @@ -498,7 +524,7 @@ where &self, nonce: Felt, ) -> Result> { - let skip_signature = self.account.is_signer_interactive(); + let skip_signature = self.is_signer_interactive(); let prepared = PreparedExecutionV3 { account: self.account, @@ -580,6 +606,14 @@ where .await .map_err(AccountError::Provider) } + + fn is_signer_interactive(&self) -> bool { + if self.is_signer_interactive.is_some() { + true + } else { + self.account.is_signer_interactive() + } + } } impl RawExecutionV1 { diff --git a/starknet-accounts/src/account/mod.rs b/starknet-accounts/src/account/mod.rs index a3e19f54..6a61e165 100644 --- a/starknet-accounts/src/account/mod.rs +++ b/starknet-accounts/src/account/mod.rs @@ -242,6 +242,7 @@ pub struct ExecutionV1<'a, A> { nonce: Option, max_fee: Option, fee_estimate_multiplier: f64, + is_signer_interactive: Option<()>, } /// Abstraction over `INVOKE` transactions from accounts for invoking contracts. This struct uses @@ -260,6 +261,7 @@ pub struct ExecutionV3<'a, A> { gas_price: Option, gas_estimate_multiplier: f64, gas_price_estimate_multiplier: f64, + is_signer_interactive: Option<()>, } /// Abstraction over `DECLARE` transactions from accounts for invoking contracts. This struct uses @@ -276,6 +278,7 @@ pub struct DeclarationV2<'a, A> { nonce: Option, max_fee: Option, fee_estimate_multiplier: f64, + is_signer_interactive: Option<()>, } /// Abstraction over `DECLARE` transactions from accounts for invoking contracts. This struct uses @@ -295,6 +298,7 @@ pub struct DeclarationV3<'a, A> { gas_price: Option, gas_estimate_multiplier: f64, gas_price_estimate_multiplier: f64, + is_signer_interactive: Option<()>, } /// An intermediate type allowing users to optionally specify `nonce` and/or `max_fee`. @@ -306,6 +310,7 @@ pub struct LegacyDeclaration<'a, A> { nonce: Option, max_fee: Option, fee_estimate_multiplier: f64, + is_signer_interactive: Option<()>, } /// [`ExecutionV1`] but with `nonce` and `max_fee` already determined.