starknet_accounts/factory/
open_zeppelin.rs

1use crate::{AccountFactory, PreparedAccountDeploymentV3, RawAccountDeploymentV3};
2
3use async_trait::async_trait;
4use starknet_core::types::{BlockId, BlockTag, Felt};
5use starknet_providers::Provider;
6use starknet_signers::{Signer, SignerInteractivityContext};
7
8/// [`AccountFactory`] implementation for deploying `OpenZeppelin` account contracts.
9#[derive(Debug)]
10pub struct OpenZeppelinAccountFactory<S, P> {
11    class_hash: Felt,
12    chain_id: Felt,
13    public_key: Felt,
14    signer: S,
15    provider: P,
16    block_id: BlockId,
17}
18
19impl<S, P> OpenZeppelinAccountFactory<S, P>
20where
21    S: Signer,
22{
23    /// Constructs a new [`OpenZeppelinAccountFactory`].
24    pub async fn new(
25        class_hash: Felt,
26        chain_id: Felt,
27        signer: S,
28        provider: P,
29    ) -> Result<Self, S::GetPublicKeyError> {
30        let public_key = signer.get_public_key().await?;
31        Ok(Self {
32            class_hash,
33            chain_id,
34            public_key: public_key.scalar(),
35            signer,
36            provider,
37            block_id: BlockId::Tag(BlockTag::Latest),
38        })
39    }
40
41    /// Sets a new block ID to run queries against.
42    pub fn set_block_id(&mut self, block_id: BlockId) -> &Self {
43        self.block_id = block_id;
44        self
45    }
46}
47
48#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
49#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
50impl<S, P> AccountFactory for OpenZeppelinAccountFactory<S, P>
51where
52    S: Signer + Sync + Send,
53    P: Provider + Sync + Send,
54{
55    type Provider = P;
56    type SignError = S::SignError;
57
58    fn class_hash(&self) -> Felt {
59        self.class_hash
60    }
61
62    fn calldata(&self) -> Vec<Felt> {
63        vec![self.public_key]
64    }
65
66    fn chain_id(&self) -> Felt {
67        self.chain_id
68    }
69
70    fn provider(&self) -> &Self::Provider {
71        &self.provider
72    }
73
74    fn is_signer_interactive(&self) -> bool {
75        self.signer
76            .is_interactive(SignerInteractivityContext::Other)
77    }
78
79    fn block_id(&self) -> BlockId {
80        self.block_id
81    }
82
83    async fn sign_deployment_v3(
84        &self,
85        deployment: &RawAccountDeploymentV3,
86        query_only: bool,
87    ) -> Result<Vec<Felt>, Self::SignError> {
88        let tx_hash = PreparedAccountDeploymentV3::from_raw(deployment.clone(), self)
89            .transaction_hash(query_only);
90        let signature = self.signer.sign_hash(&tx_hash).await?;
91
92        Ok(vec![signature.r, signature.s])
93    }
94}