apex_sdk_substrate/
signer.rs

1//! Custom signer implementation for Substrate transactions
2//!
3//! This module provides a custom signer that replaces the deprecated PairSigner
4//! from substrate-compat. It implements the subxt::tx::Signer trait for SR25519
5//! and ED25519 key pairs.
6
7use sp_core::{ed25519, sr25519, Pair as _};
8use subxt::tx::Signer;
9
10// Import AccountId32 and MultiSignature from subxt instead of sp_runtime
11type AccountId32 = subxt::utils::AccountId32;
12type MultiSignature = subxt::utils::MultiSignature;
13
14/// Custom signer for SR25519 key pairs
15#[derive(Clone)]
16pub struct Sr25519Signer {
17    pair: sr25519::Pair,
18    account_id: AccountId32,
19}
20
21impl Sr25519Signer {
22    /// Create a new SR25519 signer from a key pair
23    pub fn new(pair: sr25519::Pair) -> Self {
24        let public_key = pair.public();
25        // Convert sp_core public key to subxt AccountId32
26        let account_id = AccountId32::from(public_key.0);
27        Self { pair, account_id }
28    }
29
30    /// Get the account ID
31    pub fn account_id(&self) -> &AccountId32 {
32        &self.account_id
33    }
34
35    /// Get the public key
36    pub fn public_key(&self) -> sr25519::Public {
37        self.pair.public()
38    }
39}
40
41impl Signer<subxt::PolkadotConfig> for Sr25519Signer {
42    fn account_id(&self) -> AccountId32 {
43        self.account_id.clone()
44    }
45
46    fn sign(&self, payload: &[u8]) -> <subxt::PolkadotConfig as subxt::Config>::Signature {
47        let signature = self.pair.sign(payload);
48        // Convert sp_core signature to subxt MultiSignature
49        MultiSignature::Sr25519(signature.0)
50    }
51}
52
53/// Custom signer for ED25519 key pairs
54#[derive(Clone)]
55pub struct Ed25519Signer {
56    pair: ed25519::Pair,
57    account_id: AccountId32,
58}
59
60impl Ed25519Signer {
61    /// Create a new ED25519 signer from a key pair
62    pub fn new(pair: ed25519::Pair) -> Self {
63        let public_key = pair.public();
64        // Convert sp_core public key to subxt AccountId32
65        let account_id = AccountId32::from(public_key.0);
66        Self { pair, account_id }
67    }
68
69    /// Get the account ID
70    pub fn account_id(&self) -> &AccountId32 {
71        &self.account_id
72    }
73
74    /// Get the public key
75    pub fn public_key(&self) -> ed25519::Public {
76        self.pair.public()
77    }
78}
79
80impl Signer<subxt::PolkadotConfig> for Ed25519Signer {
81    fn account_id(&self) -> AccountId32 {
82        self.account_id.clone()
83    }
84
85    fn sign(&self, payload: &[u8]) -> <subxt::PolkadotConfig as subxt::Config>::Signature {
86        let signature = self.pair.sign(payload);
87        // Convert sp_core signature to subxt MultiSignature
88        MultiSignature::Ed25519(signature.0)
89    }
90}
91
92/// Enum to hold either SR25519 or ED25519 signer
93#[derive(Clone)]
94pub enum ApexSigner {
95    Sr25519(Box<Sr25519Signer>),
96    Ed25519(Box<Ed25519Signer>),
97}
98
99impl ApexSigner {
100    /// Create from SR25519 pair
101    pub fn from_sr25519(pair: sr25519::Pair) -> Self {
102        Self::Sr25519(Box::new(Sr25519Signer::new(pair)))
103    }
104
105    /// Create from ED25519 pair
106    pub fn from_ed25519(pair: ed25519::Pair) -> Self {
107        Self::Ed25519(Box::new(Ed25519Signer::new(pair)))
108    }
109}
110
111impl Signer<subxt::PolkadotConfig> for ApexSigner {
112    fn account_id(&self) -> AccountId32 {
113        match self {
114            Self::Sr25519(signer) => signer.account_id().clone(),
115            Self::Ed25519(signer) => signer.account_id().clone(),
116        }
117    }
118
119    fn sign(&self, payload: &[u8]) -> <subxt::PolkadotConfig as subxt::Config>::Signature {
120        match self {
121            Self::Sr25519(signer) => signer.sign(payload),
122            Self::Ed25519(signer) => signer.sign(payload),
123        }
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130    use sp_core::Pair;
131
132    #[test]
133    fn test_sr25519_signer() {
134        let (pair, _) = sr25519::Pair::generate();
135        let signer = Sr25519Signer::new(pair);
136
137        let account_id = signer.account_id();
138        assert_eq!(account_id.0.len(), 32);
139    }
140
141    #[test]
142    fn test_ed25519_signer() {
143        let (pair, _) = ed25519::Pair::generate();
144        let signer = Ed25519Signer::new(pair);
145
146        let account_id = signer.account_id();
147        assert_eq!(account_id.0.len(), 32);
148    }
149
150    #[test]
151    fn test_apex_signer_sr25519() {
152        let (pair, _) = sr25519::Pair::generate();
153        let signer = ApexSigner::from_sr25519(pair.clone());
154
155        let message = b"test message";
156        let _signature = signer.sign(message);
157
158        // Verify account ID is correct
159        assert_eq!(signer.account_id().0.len(), 32);
160    }
161
162    #[test]
163    fn test_apex_signer_ed25519() {
164        let (pair, _) = ed25519::Pair::generate();
165        let signer = ApexSigner::from_ed25519(pair);
166
167        let message = b"test message";
168        let _signature = signer.sign(message);
169
170        // Verify account ID is correct
171        assert_eq!(signer.account_id().0.len(), 32);
172    }
173}