1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::{AccountFactory, PreparedAccountDeployment, RawAccountDeployment};

use async_trait::async_trait;
use starknet_core::types::FieldElement;
use starknet_providers::Provider;
use starknet_signers::Signer;

/// Selector for "initialize"
const SELECTOR_INITIALIZE: FieldElement = FieldElement::from_mont([
    14382173896205878522,
    7380089477680411368,
    4404362358337226556,
    132905214994424316,
]);

pub struct ArgentAccountFactory<S, P> {
    proxy_class_hash: FieldElement,
    impl_class_hash: FieldElement,
    chain_id: FieldElement,
    signer_public_key: FieldElement,
    guardian_public_key: FieldElement,
    signer: S,
    provider: P,
}

impl<S, P> ArgentAccountFactory<S, P>
where
    S: Signer,
{
    pub async fn new(
        proxy_class_hash: FieldElement,
        impl_class_hash: FieldElement,
        chain_id: FieldElement,
        guardian_public_key: FieldElement,
        signer: S,
        provider: P,
    ) -> Result<Self, S::GetPublicKeyError> {
        let signer_public_key = signer.get_public_key().await?;
        Ok(Self {
            proxy_class_hash,
            impl_class_hash,
            chain_id,
            signer_public_key: signer_public_key.scalar(),
            guardian_public_key,
            signer,
            provider,
        })
    }
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl<S, P> AccountFactory for ArgentAccountFactory<S, P>
where
    S: Signer + Sync + Send,
    P: Provider + Sync + Send,
{
    type Provider = P;
    type SignError = S::SignError;

    fn class_hash(&self) -> FieldElement {
        self.proxy_class_hash
    }

    fn calldata(&self) -> Vec<FieldElement> {
        vec![
            self.impl_class_hash,
            SELECTOR_INITIALIZE,
            FieldElement::TWO,
            self.signer_public_key,
            self.guardian_public_key,
        ]
    }

    fn chain_id(&self) -> FieldElement {
        self.chain_id
    }

    fn provider(&self) -> &Self::Provider {
        &self.provider
    }

    async fn sign_deployment(
        &self,
        deployment: &RawAccountDeployment,
    ) -> Result<Vec<FieldElement>, Self::SignError> {
        let tx_hash =
            PreparedAccountDeployment::from_raw(deployment.clone(), self).transaction_hash();
        let signature = self.signer.sign_hash(&tx_hash).await?;

        Ok(vec![signature.r, signature.s])
    }
}