anvil_polkadot/api_server/
signer.rs1use 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 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}