starknet_accounts/account/
mod.rs1use async_trait::async_trait;
2use auto_impl::auto_impl;
3use starknet_core::types::{
4 contract::ComputeClassHashError, BlockId, BlockTag, Call, Felt, FlattenedSierraClass,
5};
6use starknet_providers::{Provider, ProviderError};
7use starknet_signers::SignerInteractivityContext;
8use std::{error::Error, sync::Arc};
9
10mod declaration;
11mod execution;
12
13#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
18#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
19pub trait Account: ExecutionEncoder + Sized {
20 type SignError: Error + Send + Sync;
22
23 fn address(&self) -> Felt;
25
26 fn chain_id(&self) -> Felt;
28
29 async fn sign_execution_v3(
35 &self,
36 execution: &RawExecutionV3,
37 query_only: bool,
38 ) -> Result<Vec<Felt>, Self::SignError>;
39
40 async fn sign_declaration_v3(
46 &self,
47 declaration: &RawDeclarationV3,
48 query_only: bool,
49 ) -> Result<Vec<Felt>, Self::SignError>;
50
51 fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool;
58
59 fn execute_v3(&self, calls: Vec<Call>) -> ExecutionV3<'_, Self> {
62 ExecutionV3::new(calls, self)
63 }
64
65 #[deprecated = "transaction version used might change unexpectedly; use `execute_v3` instead"]
68 fn execute(&self, calls: Vec<Call>) -> ExecutionV3<'_, Self> {
69 self.execute_v3(calls)
70 }
71
72 fn declare_v3(
88 &self,
89 contract_class: Arc<FlattenedSierraClass>,
90 compiled_class_hash: Felt,
91 ) -> DeclarationV3<'_, Self> {
92 DeclarationV3::new(contract_class, compiled_class_hash, self)
93 }
94
95 #[deprecated = "transaction version used might change unexpectedly; use `declare_v3` instead"]
111 fn declare(
112 &self,
113 contract_class: Arc<FlattenedSierraClass>,
114 compiled_class_hash: Felt,
115 ) -> DeclarationV3<'_, Self> {
116 self.declare_v3(contract_class, compiled_class_hash)
117 }
118}
119
120#[auto_impl(&, Box, Arc)]
125pub trait ExecutionEncoder {
126 fn encode_calls(&self, calls: &[Call]) -> Vec<Felt>;
129}
130
131#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
135#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
136pub trait ConnectedAccount: Account {
137 type Provider: Provider + Sync;
139
140 fn provider(&self) -> &Self::Provider;
142
143 fn block_id(&self) -> BlockId {
145 BlockId::Tag(BlockTag::Latest)
146 }
147
148 async fn get_nonce(&self) -> Result<Felt, ProviderError> {
150 self.provider()
151 .get_nonce(self.block_id(), self.address())
152 .await
153 }
154}
155
156#[must_use]
162#[derive(Debug)]
163pub struct ExecutionV3<'a, A> {
164 account: &'a A,
165 calls: Vec<Call>,
166 nonce: Option<Felt>,
167 l1_gas: Option<u64>,
168 l1_gas_price: Option<u128>,
169 l2_gas: Option<u64>,
170 l2_gas_price: Option<u128>,
171 l1_data_gas: Option<u64>,
172 l1_data_gas_price: Option<u128>,
173 gas_estimate_multiplier: f64,
174 gas_price_estimate_multiplier: f64,
175 tip: Option<u64>,
176}
177
178#[must_use]
184#[derive(Debug)]
185pub struct DeclarationV3<'a, A> {
186 account: &'a A,
187 contract_class: Arc<FlattenedSierraClass>,
188 compiled_class_hash: Felt,
189 nonce: Option<Felt>,
190 l1_gas: Option<u64>,
191 l1_gas_price: Option<u128>,
192 l2_gas: Option<u64>,
193 l2_gas_price: Option<u128>,
194 l1_data_gas: Option<u64>,
195 l1_data_gas_price: Option<u128>,
196 gas_estimate_multiplier: f64,
197 gas_price_estimate_multiplier: f64,
198 tip: Option<u64>,
199}
200
201#[derive(Debug)]
203pub struct RawExecutionV3 {
204 calls: Vec<Call>,
205 nonce: Felt,
206 l1_gas: u64,
207 l1_gas_price: u128,
208 l2_gas: u64,
209 l2_gas_price: u128,
210 l1_data_gas: u64,
211 l1_data_gas_price: u128,
212 tip: u64,
213}
214
215#[derive(Debug)]
217pub struct RawDeclarationV3 {
218 contract_class: Arc<FlattenedSierraClass>,
219 compiled_class_hash: Felt,
220 nonce: Felt,
221 l1_gas: u64,
222 l1_gas_price: u128,
223 l2_gas: u64,
224 l2_gas_price: u128,
225 l1_data_gas: u64,
226 l1_data_gas_price: u128,
227 tip: u64,
228}
229
230#[derive(Debug)]
232pub struct PreparedExecutionV3<'a, A> {
233 account: &'a A,
234 inner: RawExecutionV3,
235}
236
237#[derive(Debug)]
239pub struct PreparedDeclarationV3<'a, A> {
240 account: &'a A,
241 inner: RawDeclarationV3,
242}
243
244#[derive(Debug, thiserror::Error)]
246pub enum AccountError<S> {
247 #[error(transparent)]
249 Signing(S),
250 #[error(transparent)]
252 Provider(ProviderError),
253 #[error(transparent)]
255 ClassHashCalculation(ComputeClassHashError),
256 #[error("fee calculation overflow")]
258 FeeOutOfRange,
259}
260
261#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
262#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
263impl<A> Account for &A
264where
265 A: Account + Sync,
266{
267 type SignError = A::SignError;
268
269 fn address(&self) -> Felt {
270 (*self).address()
271 }
272
273 fn chain_id(&self) -> Felt {
274 (*self).chain_id()
275 }
276
277 async fn sign_execution_v3(
278 &self,
279 execution: &RawExecutionV3,
280 query_only: bool,
281 ) -> Result<Vec<Felt>, Self::SignError> {
282 (*self).sign_execution_v3(execution, query_only).await
283 }
284
285 async fn sign_declaration_v3(
286 &self,
287 declaration: &RawDeclarationV3,
288 query_only: bool,
289 ) -> Result<Vec<Felt>, Self::SignError> {
290 (*self).sign_declaration_v3(declaration, query_only).await
291 }
292
293 fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool {
294 (*self).is_signer_interactive(context)
295 }
296}
297
298#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
299#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
300impl<A> Account for Box<A>
301where
302 A: Account + Sync + Send,
303{
304 type SignError = A::SignError;
305
306 fn address(&self) -> Felt {
307 self.as_ref().address()
308 }
309
310 fn chain_id(&self) -> Felt {
311 self.as_ref().chain_id()
312 }
313
314 async fn sign_execution_v3(
315 &self,
316 execution: &RawExecutionV3,
317 query_only: bool,
318 ) -> Result<Vec<Felt>, Self::SignError> {
319 self.as_ref().sign_execution_v3(execution, query_only).await
320 }
321
322 async fn sign_declaration_v3(
323 &self,
324 declaration: &RawDeclarationV3,
325 query_only: bool,
326 ) -> Result<Vec<Felt>, Self::SignError> {
327 self.as_ref()
328 .sign_declaration_v3(declaration, query_only)
329 .await
330 }
331
332 fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool {
333 self.as_ref().is_signer_interactive(context)
334 }
335}
336
337#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
338#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
339impl<A> Account for Arc<A>
340where
341 A: Account + Sync + Send,
342{
343 type SignError = A::SignError;
344
345 fn address(&self) -> Felt {
346 self.as_ref().address()
347 }
348
349 fn chain_id(&self) -> Felt {
350 self.as_ref().chain_id()
351 }
352
353 async fn sign_execution_v3(
354 &self,
355 execution: &RawExecutionV3,
356 query_only: bool,
357 ) -> Result<Vec<Felt>, Self::SignError> {
358 self.as_ref().sign_execution_v3(execution, query_only).await
359 }
360
361 async fn sign_declaration_v3(
362 &self,
363 declaration: &RawDeclarationV3,
364 query_only: bool,
365 ) -> Result<Vec<Felt>, Self::SignError> {
366 self.as_ref()
367 .sign_declaration_v3(declaration, query_only)
368 .await
369 }
370
371 fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool {
372 self.as_ref().is_signer_interactive(context)
373 }
374}
375
376#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
377#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
378impl<A> ConnectedAccount for &A
379where
380 A: ConnectedAccount + Sync,
381{
382 type Provider = A::Provider;
383
384 fn provider(&self) -> &Self::Provider {
385 (*self).provider()
386 }
387
388 fn block_id(&self) -> BlockId {
389 (*self).block_id()
390 }
391
392 async fn get_nonce(&self) -> Result<Felt, ProviderError> {
393 (*self).get_nonce().await
394 }
395}
396
397#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
398#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
399impl<A> ConnectedAccount for Box<A>
400where
401 A: ConnectedAccount + Sync + Send,
402{
403 type Provider = A::Provider;
404
405 fn provider(&self) -> &Self::Provider {
406 self.as_ref().provider()
407 }
408
409 fn block_id(&self) -> BlockId {
410 self.as_ref().block_id()
411 }
412
413 async fn get_nonce(&self) -> Result<Felt, ProviderError> {
414 self.as_ref().get_nonce().await
415 }
416}
417
418#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
419#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
420impl<A> ConnectedAccount for Arc<A>
421where
422 A: ConnectedAccount + Sync + Send,
423{
424 type Provider = A::Provider;
425
426 fn provider(&self) -> &Self::Provider {
427 self.as_ref().provider()
428 }
429
430 fn block_id(&self) -> BlockId {
431 self.as_ref().block_id()
432 }
433
434 async fn get_nonce(&self) -> Result<Felt, ProviderError> {
435 self.as_ref().get_nonce().await
436 }
437}