Skip to main content

anvil_polkadot/api_server/
signer.rs

1use crate::api_server::{
2    error::{Error, Result},
3    revive_conversions::ReviveAddress,
4};
5use alloy_dyn_abi::TypedData;
6use alloy_primitives::{Address, utils::eip191_hash_message};
7use polkadot_sdk::pallet_revive::evm::{Account, TransactionSigned, TransactionUnsigned};
8use std::collections::HashMap;
9use subxt::utils::H160;
10use subxt_signer::eth::Keypair;
11
12pub struct DevSigner {
13    keypairs: HashMap<H160, Keypair>,
14}
15
16impl DevSigner {
17    pub fn new(private_keys: Vec<Keypair>) -> Result<Self> {
18        let keypairs: HashMap<H160, Keypair> =
19            private_keys.into_iter().map(|kp| (Account::from(kp.clone()).address(), kp)).collect();
20        Ok(Self { keypairs })
21    }
22
23    fn recovery_id_mapper(id: u8) -> u8 {
24        id + 27
25    }
26
27    pub(crate) fn accounts(&self) -> Vec<H160> {
28        self.keypairs.keys().copied().collect()
29    }
30
31    pub(crate) fn sign_transaction(
32        &self,
33        address: Address,
34        transaction: TransactionUnsigned,
35    ) -> Result<TransactionSigned> {
36        let keypair = self
37            .keypairs
38            .get(&ReviveAddress::from(address).inner())
39            .ok_or(Error::NoSignerAvailable)?;
40        let account = Account::from(keypair.clone());
41        Ok(account.sign_transaction(transaction))
42    }
43
44    pub(crate) fn sign(&self, address: Address, message: &[u8]) -> Result<[u8; 65]> {
45        let keypair = self
46            .keypairs
47            .get(&ReviveAddress::from(address).inner())
48            .ok_or(Error::NoSignerAvailable)?;
49        let hash = eip191_hash_message(message);
50        let mut signature = keypair.sign_prehashed(hash.as_ref()).0;
51        signature[64] = Self::recovery_id_mapper(signature[64]);
52        Ok(signature)
53    }
54
55    pub(crate) fn sign_typed_data(
56        &self,
57        address: Address,
58        typed_data: &TypedData,
59    ) -> Result<[u8; 65]> {
60        let keypair = self
61            .keypairs
62            .get(&ReviveAddress::from(address).inner())
63            .ok_or(Error::NoSignerAvailable)?;
64
65        // Compute the EIP-712 signing hash
66        let hash =
67            typed_data.eip712_signing_hash().map_err(|e| Error::InternalError(e.to_string()))?;
68        let mut signature = keypair.sign_prehashed(hash.as_ref()).0;
69        signature[64] = Self::recovery_id_mapper(signature[64]);
70        Ok(signature)
71    }
72}