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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::{Network, TransactionBuilder};
use alloy_consensus::SignableTransaction;
use alloy_primitives::Address;
use async_trait::async_trait;
use auto_impl::auto_impl;
use futures_utils_wasm::impl_future;

/// A wallet capable of signing any transaction for the given network.
///
/// Network crate authors should implement this trait on a type capable of
/// signing any transaction (regardless of signature type) on a given network.
/// Signer crate authors should instead implement [`TxSigner`] to signify
/// signing capability for specific signature types.
///
/// Network wallets are expected to contain one or more signing credentials,
/// keyed by signing address. The default signer address should be used when
/// no specific signer address is specified.
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[auto_impl(&, &mut, Box, Rc, Arc)]
pub trait NetworkWallet<N: Network>: std::fmt::Debug + Send + Sync {
    /// Get the default signer address. This address should be used
    /// in [`NetworkWallet::sign_transaction_from`] when no specific signer is
    /// specified.
    fn default_signer_address(&self) -> Address;

    /// Return true if the signer contains a credential for the given address.
    fn has_signer_for(&self, address: &Address) -> bool;

    /// Return an iterator of all signer addresses.
    fn signer_addresses(&self) -> impl Iterator<Item = Address>;

    /// Asynchronously sign an unsigned transaction, with a specified
    /// credential.
    #[doc(alias = "sign_tx_from")]
    async fn sign_transaction_from(
        &self,
        sender: Address,
        tx: N::UnsignedTx,
    ) -> alloy_signer::Result<N::TxEnvelope>;

    /// Asynchronously sign an unsigned transaction.
    #[doc(alias = "sign_tx")]
    fn sign_transaction(
        &self,
        tx: N::UnsignedTx,
    ) -> impl_future!(<Output = alloy_signer::Result<N::TxEnvelope>>) {
        self.sign_transaction_from(self.default_signer_address(), tx)
    }

    /// Asynchronously sign a transaction request, using the sender specified
    /// in the `from` field.
    async fn sign_request(
        &self,
        request: N::TransactionRequest,
    ) -> alloy_signer::Result<N::TxEnvelope> {
        let sender = request.from().unwrap_or_else(|| self.default_signer_address());
        let tx = request.build_unsigned().map_err(alloy_signer::Error::other)?;
        self.sign_transaction_from(sender, tx).await
    }
}

/// Asynchronous transaction signer, capable of signing any [`SignableTransaction`] for the given
/// `Signature` type.
///
/// A signer should hold an optional [`ChainId`] value, which is used for [EIP-155] replay
/// protection.
///
/// If `chain_id` is Some, [EIP-155] should be applied to the input transaction in
/// [`sign_transaction`](Self::sign_transaction), and to the resulting signature in all the methods.
/// If `chain_id` is None, [EIP-155] should not be applied.
///
/// Synchronous signers should implement both this trait and [`TxSignerSync`].
///
/// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
/// [`ChainId`]: alloy_primitives::ChainId
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[auto_impl(&, &mut, Box, Rc, Arc)]
#[doc(alias = "TransactionSigner")]
pub trait TxSigner<Signature> {
    /// Get the address of the signer.
    fn address(&self) -> Address;

    /// Asynchronously sign an unsigned transaction.
    #[doc(alias = "sign_tx")]
    async fn sign_transaction(
        &self,
        tx: &mut dyn SignableTransaction<Signature>,
    ) -> alloy_signer::Result<Signature>;
}

/// Synchronous transaction signer,  capable of signing any [`SignableTransaction`] for the given
/// `Signature` type.
///
/// A signer should hold an optional [`ChainId`] value, which is used for [EIP-155] replay
/// protection.
///
/// If `chain_id` is Some, [EIP-155] should be applied to the input transaction in
/// [`sign_transaction_sync`](Self::sign_transaction_sync), and to the resulting signature in all
/// the methods. If `chain_id` is None, [EIP-155] should not be applied.
///
/// Synchronous signers should also implement [`TxSigner`], as they are always able to by delegating
/// the asynchronous methods to the synchronous ones.
///
/// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
/// [`ChainId`]: alloy_primitives::ChainId
#[auto_impl(&, &mut, Box, Rc, Arc)]
#[doc(alias = "TransactionSignerSync")]
pub trait TxSignerSync<Signature> {
    /// Get the address of the signer.
    fn address(&self) -> Address;

    /// Synchronously sign an unsigned transaction.
    #[doc(alias = "sign_tx_sync")]
    fn sign_transaction_sync(
        &self,
        tx: &mut dyn SignableTransaction<Signature>,
    ) -> alloy_signer::Result<Signature>;
}