ac_primitives/extrinsics/
signer.rs1use crate::config::Config;
21use codec::{Decode, Encode};
22use core::marker::PhantomData;
23use sp_core::{crypto::AccountId32, Pair};
24use sp_runtime::MultiAddress;
25
26pub trait SignExtrinsic<AccountId: Clone + Encode> {
27 type Signature: Encode;
28 type ExtrinsicAddress: Clone + Encode;
29
30 fn sign(&self, payload: &[u8]) -> Self::Signature;
32
33 fn public_account_id(&self) -> &AccountId;
35
36 fn extrinsic_address(&self) -> Self::ExtrinsicAddress;
40}
41
42#[derive(Encode, Decode, Clone, PartialEq)]
43pub struct ExtrinsicSigner<T: Config> {
44 signer: T::CryptoKey,
45 account_id: T::AccountId,
46 extrinsic_address: T::Address,
47 _phantom: PhantomData<T::Signature>,
48}
49
50impl<T: Config> ExtrinsicSigner<T> {
51 pub fn new(signer: T::CryptoKey) -> Self {
52 let account_id: T::AccountId = signer.public().into();
53 let extrinsic_address: T::Address = account_id.clone().into();
54 Self { signer, account_id, extrinsic_address, _phantom: Default::default() }
55 }
56
57 pub fn signer(&self) -> &T::CryptoKey {
58 &self.signer
59 }
60}
61
62impl<T: Config> SignExtrinsic<T::AccountId> for ExtrinsicSigner<T> {
63 type Signature = T::Signature;
64 type ExtrinsicAddress = T::Address;
65
66 fn sign(&self, payload: &[u8]) -> Self::Signature {
67 self.signer.sign(payload).into()
68 }
69
70 fn public_account_id(&self) -> &T::AccountId {
71 &self.account_id
72 }
73
74 fn extrinsic_address(&self) -> Self::ExtrinsicAddress {
75 self.extrinsic_address.clone()
76 }
77}
78
79impl<T, Signer> From<Signer> for ExtrinsicSigner<T>
80where
81 T: Config,
82 Signer: Pair + Into<T::CryptoKey>,
83{
84 fn from(value: Signer) -> Self {
85 ExtrinsicSigner::<T>::new(value.into())
86 }
87}
88
89#[derive(Encode, Decode, Clone, PartialEq)]
93pub struct StaticExtrinsicSigner<Signer, Signature> {
94 signer: Signer,
95 account_id: AccountId32,
96 extrinsic_address: MultiAddress<AccountId32, ()>,
97 _phantom: PhantomData<Signature>,
98}
99
100impl<Signer, Signature> StaticExtrinsicSigner<Signer, Signature>
101where
102 Signer: Pair,
103 Signer::Public: Into<AccountId32>,
104 Signature: From<Signer::Signature> + Encode + Clone,
105{
106 pub fn new(signer: Signer) -> Self {
107 let account_id = signer.public().into();
108 let extrinsic_address = MultiAddress::from(account_id.clone());
109 Self { signer, account_id, extrinsic_address, _phantom: Default::default() }
110 }
111
112 pub fn signer(&self) -> &Signer {
113 &self.signer
114 }
115}
116
117impl<Signer, Signature> SignExtrinsic<AccountId32> for StaticExtrinsicSigner<Signer, Signature>
118where
119 Signer: Pair,
120 Signature: From<Signer::Signature> + Encode + Clone,
121{
122 type Signature = Signature;
123 type ExtrinsicAddress = MultiAddress<AccountId32, ()>;
124
125 fn sign(&self, payload: &[u8]) -> Self::Signature {
126 self.signer.sign(payload).into()
127 }
128
129 fn public_account_id(&self) -> &AccountId32 {
130 &self.account_id
131 }
132
133 fn extrinsic_address(&self) -> Self::ExtrinsicAddress {
134 self.extrinsic_address.clone()
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use crate::AssetRuntimeConfig;
142 use sp_core::sr25519;
143 use sp_keyring::Sr25519Keyring;
144 use sp_runtime::MultiSignature;
145
146 #[test]
147 fn test_extrinsic_signer_clone() {
148 let pair = Sr25519Keyring::Alice.pair();
149 let signer = ExtrinsicSigner::<AssetRuntimeConfig>::new(pair);
150
151 let _signer2 = signer.clone();
152 }
153
154 #[test]
155 fn test_static_extrinsic_signer_clone() {
156 let pair = Sr25519Keyring::Alice.pair();
157 let signer = StaticExtrinsicSigner::<_, MultiSignature>::new(pair);
158
159 let _signer2 = signer.clone();
160 }
161
162 #[test]
163 fn test_extrinsic_signer_from_sr25519_pair() {
164 let alice: sr25519::Pair = Pair::from_string(
165 "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a",
166 None,
167 )
168 .unwrap();
169
170 let es_converted: ExtrinsicSigner<AssetRuntimeConfig> = alice.clone().into();
171 let es_new = ExtrinsicSigner::<AssetRuntimeConfig>::new(alice.clone());
172
173 assert_eq!(es_converted.signer.public(), es_new.signer.public());
174 }
175}