use std::fmt;
use p256::ecdsa::Signature;
use primitive_types::H256;
use serde::{Deserialize, Serialize};
use signature::hazmat::{PrehashSigner, PrehashVerifier};
use crate::{
neo_builder::{Transaction, TransactionError},
neo_clients::JsonRpcProvider,
neo_crypto::HashableForVec,
neo_types::Address,
neo_wallets::WalletError,
};
#[derive(Clone, Serialize, Deserialize)]
pub struct WalletSigner<D: PrehashSigner<Signature>> {
pub(crate) signer: D,
pub(crate) address: Address,
pub(crate) network: Option<u64>,
}
impl<D: PrehashSigner<Signature>> WalletSigner<D> {
pub fn new_with_signer(signer: D, address: Address) -> Self {
WalletSigner { signer, address, network: None }
}
}
impl<D: Sync + Send + PrehashSigner<Signature>> WalletSigner<D> {
#[allow(dead_code)]
pub(crate) async fn sign_transaction<'a, P: JsonRpcProvider + 'static>(
&self,
tx: &Transaction<'a, P>,
) -> Result<Signature, WalletError> {
let tx_with_network = tx;
if tx_with_network.network().is_none() {
}
let hash_data = tx_with_network.get_hash_data().await.map_err(|e| {
WalletError::TransactionError(TransactionError::TransactionConfiguration(format!(
"Failed to get transaction hash data: {}",
e
)))
})?;
self.signer.sign_prehash(&hash_data).map_err(|_| WalletError::SignHashError)
}
pub fn sign_hash(&self, hash: H256) -> Result<Signature, WalletError> {
self.signer.sign_prehash(hash.as_ref()).map_err(|_| WalletError::SignHashError)
}
pub async fn sign_message(&self, message: &[u8]) -> Result<Signature, WalletError> {
let hash = message.hash256();
self.sign_hash(H256::from_slice(hash.as_slice()))
}
pub fn signer(&self) -> &D {
&self.signer
}
#[allow(dead_code)]
pub(crate) fn address(&self) -> Address {
self.address.clone()
}
#[allow(dead_code)]
fn network(&self) -> Option<u64> {
self.network
}
#[allow(dead_code)]
fn with_network<T: Into<u64>>(mut self, network: T) -> Self {
self.network = Some(network.into());
self
}
}
impl<D: PrehashSigner<Signature> + PrehashVerifier<Signature>> fmt::Debug for WalletSigner<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("WalletSigner")
.field("address", &self.address)
.field("chain_Id", &self.network)
.finish()
}
}