starknet_accounts/factory/
argent.rs

1use crate::{AccountFactory, PreparedAccountDeploymentV3, RawAccountDeploymentV3};
2
3use async_trait::async_trait;
4use starknet_core::{
5    codec::Encode,
6    types::{BlockId, BlockTag, Felt},
7};
8use starknet_providers::Provider;
9use starknet_signers::{Signer, SignerInteractivityContext};
10
11/// [`AccountFactory`] implementation for deploying `Argent X` account contracts (v0.4.0).
12#[derive(Debug)]
13pub struct ArgentAccountFactory<S, P> {
14    class_hash: Felt,
15    chain_id: Felt,
16    owner_public_key: Felt,
17    guardian_public_key: Option<Felt>,
18    signer: S,
19    provider: P,
20    block_id: BlockId,
21}
22
23/// Constructor parameters for Argent account v0.4.0.
24#[derive(Encode)]
25#[starknet(core = "starknet_core")]
26struct ArgentAccountConstructorParams {
27    owner: ArgentSigner,
28    guardian: Option<ArgentSigner>,
29}
30
31/// A simplified version of `argent::signer::signer_signature::Signer` that only supports the simple
32/// Starknet signer.
33#[derive(Encode)]
34#[starknet(core = "starknet_core")]
35enum ArgentSigner {
36    Starknet(Felt),
37}
38
39impl<S, P> ArgentAccountFactory<S, P>
40where
41    S: Signer,
42{
43    /// Constructs a new [`ArgentAccountFactory`].
44    pub async fn new(
45        class_hash: Felt,
46        chain_id: Felt,
47        guardian_public_key: Option<Felt>,
48        signer: S,
49        provider: P,
50    ) -> Result<Self, S::GetPublicKeyError> {
51        let signer_public_key = signer.get_public_key().await?;
52        Ok(Self {
53            class_hash,
54            chain_id,
55            owner_public_key: signer_public_key.scalar(),
56            guardian_public_key,
57            signer,
58            provider,
59            block_id: BlockId::Tag(BlockTag::Latest),
60        })
61    }
62
63    /// Sets a new block ID to run queries against.
64    pub fn set_block_id(&mut self, block_id: BlockId) -> &Self {
65        self.block_id = block_id;
66        self
67    }
68}
69
70#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
71#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
72impl<S, P> AccountFactory for ArgentAccountFactory<S, P>
73where
74    S: Signer + Sync + Send,
75    P: Provider + Sync + Send,
76{
77    type Provider = P;
78    type SignError = S::SignError;
79
80    fn class_hash(&self) -> Felt {
81        self.class_hash
82    }
83
84    fn calldata(&self) -> Vec<Felt> {
85        let mut calldata = vec![];
86
87        // Encoding this sturct never fails
88        ArgentAccountConstructorParams {
89            owner: ArgentSigner::Starknet(self.owner_public_key),
90            guardian: self.guardian_public_key.map(ArgentSigner::Starknet),
91        }
92        .encode(&mut calldata)
93        .unwrap();
94
95        calldata
96    }
97
98    fn chain_id(&self) -> Felt {
99        self.chain_id
100    }
101
102    fn provider(&self) -> &Self::Provider {
103        &self.provider
104    }
105
106    fn is_signer_interactive(&self) -> bool {
107        self.signer
108            .is_interactive(SignerInteractivityContext::Other)
109    }
110
111    fn block_id(&self) -> BlockId {
112        self.block_id
113    }
114
115    async fn sign_deployment_v3(
116        &self,
117        deployment: &RawAccountDeploymentV3,
118        query_only: bool,
119    ) -> Result<Vec<Felt>, Self::SignError> {
120        let tx_hash = PreparedAccountDeploymentV3::from_raw(deployment.clone(), self)
121            .transaction_hash(query_only);
122        let signature = self.signer.sign_hash(&tx_hash).await?;
123
124        Ok(vec![signature.r, signature.s])
125    }
126}