alloy_network/ethereum/
wallet.rsuse crate::{Network, NetworkWallet, TxSigner};
use alloy_consensus::{SignableTransaction, TxEnvelope, TypedTransaction};
use alloy_primitives::{map::AddressHashMap, Address};
use alloy_signer::Signature;
use std::sync::Arc;
#[derive(Clone, Default)]
pub struct EthereumWallet {
default: Address,
signers: AddressHashMap<Arc<dyn TxSigner<Signature> + Send + Sync>>,
}
impl std::fmt::Debug for EthereumWallet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EthereumWallet")
.field("default_signer", &self.default)
.field("credentials", &self.signers.len())
.finish()
}
}
impl<S> From<S> for EthereumWallet
where
S: TxSigner<Signature> + Send + Sync + 'static,
{
fn from(signer: S) -> Self {
Self::new(signer)
}
}
impl EthereumWallet {
pub fn new<S>(signer: S) -> Self
where
S: TxSigner<Signature> + Send + Sync + 'static,
{
let mut this = Self::default();
this.register_default_signer(signer);
this
}
pub fn register_signer<S>(&mut self, signer: S)
where
S: TxSigner<Signature> + Send + Sync + 'static,
{
self.signers.insert(signer.address(), Arc::new(signer));
}
pub fn register_default_signer<S>(&mut self, signer: S)
where
S: TxSigner<Signature> + Send + Sync + 'static,
{
self.default = signer.address();
self.register_signer(signer);
}
pub fn default_signer(&self) -> Arc<dyn TxSigner<Signature> + Send + Sync + 'static> {
self.signers.get(&self.default).cloned().expect("invalid signer")
}
pub fn signer_by_address(
&self,
address: Address,
) -> Option<Arc<dyn TxSigner<Signature> + Send + Sync + 'static>> {
self.signers.get(&address).cloned()
}
#[doc(alias = "sign_tx_inner")]
async fn sign_transaction_inner(
&self,
sender: Address,
tx: &mut dyn SignableTransaction<Signature>,
) -> alloy_signer::Result<Signature> {
self.signer_by_address(sender)
.ok_or_else(|| {
alloy_signer::Error::other(format!("Missing signing credential for {}", sender))
})?
.sign_transaction(tx)
.await
}
}
impl<N> NetworkWallet<N> for EthereumWallet
where
N: Network<UnsignedTx = TypedTransaction, TxEnvelope = TxEnvelope>,
{
fn default_signer_address(&self) -> Address {
self.default
}
fn has_signer_for(&self, address: &Address) -> bool {
self.signers.contains_key(address)
}
fn signer_addresses(&self) -> impl Iterator<Item = Address> {
self.signers.keys().copied()
}
#[doc(alias = "sign_tx_from")]
async fn sign_transaction_from(
&self,
sender: Address,
tx: TypedTransaction,
) -> alloy_signer::Result<TxEnvelope> {
match tx {
TypedTransaction::Legacy(mut t) => {
let sig = self.sign_transaction_inner(sender, &mut t).await?;
Ok(t.into_signed(sig).into())
}
TypedTransaction::Eip2930(mut t) => {
let sig = self.sign_transaction_inner(sender, &mut t).await?;
Ok(t.into_signed(sig).into())
}
TypedTransaction::Eip1559(mut t) => {
let sig = self.sign_transaction_inner(sender, &mut t).await?;
Ok(t.into_signed(sig).into())
}
TypedTransaction::Eip4844(mut t) => {
let sig = self.sign_transaction_inner(sender, &mut t).await?;
Ok(t.into_signed(sig).into())
}
TypedTransaction::Eip7702(mut t) => {
let sig = self.sign_transaction_inner(sender, &mut t).await?;
Ok(t.into_signed(sig).into())
}
}
}
}