avail_rust_client/
extensions.rs

1use crate::subxt_signer::{SecretUri, sr25519::Keypair};
2use avail_rust_core::{AccountId, H256};
3
4#[cfg(feature = "generated_metadata")]
5use crate::subxt_core::tx::payload::DefaultPayload;
6#[cfg(feature = "generated_metadata")]
7use crate::{Client, SubmittableTransaction};
8#[cfg(feature = "generated_metadata")]
9use avail_rust_core::TransactionCall;
10
11pub trait H256Ext {
12	fn from_str(s: &str) -> Result<H256, String>;
13}
14
15impl H256Ext for H256 {
16	fn from_str(s: &str) -> Result<H256, String> {
17		let mut s = s;
18		if s.starts_with("0x") {
19			s = &s[2..];
20		}
21
22		if s.len() != 64 {
23			let msg = std::format!(
24				"Failed to convert string to H256. Expected 64 bytes got {}. Input string: {}",
25				s.len(),
26				s
27			);
28			return Err(msg);
29		}
30
31		let block_hash = hex::decode(s).map_err(|e| e.to_string())?;
32		let block_hash = TryInto::<[u8; 32]>::try_into(block_hash);
33		match block_hash {
34			Ok(v) => Ok(H256(v)),
35			Err(e) => {
36				let msg = std::format!("Failed to covert decoded string to H256. Input {:?}", e);
37				Err(msg)
38			},
39		}
40	}
41}
42
43pub trait AccountIdExt {
44	fn from_str(value: &str) -> Result<AccountId, String>;
45	fn from_slice(value: &[u8]) -> Result<AccountId, String>;
46}
47
48impl AccountIdExt for AccountId {
49	fn from_str(value: &str) -> Result<AccountId, String> {
50		value.parse().map_err(|e| std::format!("{:?}", e))
51	}
52
53	fn from_slice(value: &[u8]) -> Result<AccountId, String> {
54		let account_id: [u8; 32] = match value.try_into() {
55			Ok(x) => x,
56			Err(err) => return Err(err.to_string()),
57		};
58
59		Ok(AccountId { 0: account_id })
60	}
61}
62
63pub trait SecretUriExt {
64	fn from_str(value: &str) -> Result<SecretUri, String>;
65}
66
67impl SecretUriExt for SecretUri {
68	fn from_str(value: &str) -> Result<SecretUri, String> {
69		value.parse().map_err(|e| std::format!("{:?}", e))
70	}
71}
72
73pub trait KeypairExt {
74	fn from_str(value: &str) -> Result<Keypair, String>;
75	fn account_id(&self) -> AccountId;
76}
77
78impl KeypairExt for Keypair {
79	fn from_str(value: &str) -> Result<Keypair, String> {
80		let secret_uri = SecretUri::from_str(value).map_err(|e| e.to_string())?;
81		let keypair = Keypair::from_uri(&secret_uri).map_err(|e| e.to_string())?;
82		Ok(keypair)
83	}
84
85	fn account_id(&self) -> AccountId {
86		self.public_key().to_account_id()
87	}
88}
89
90#[cfg(feature = "generated_metadata")]
91pub trait DefaultPayloadExt {
92	fn to_transaction_call(&self, client: &Client) -> Result<TransactionCall, String>;
93	fn to_submittable_transaction(&self, client: Client) -> Result<SubmittableTransaction, String>;
94}
95
96#[cfg(feature = "generated_metadata")]
97impl<CallData: crate::codec::Encode> DefaultPayloadExt for DefaultPayload<CallData> {
98	fn to_transaction_call(&self, client: &Client) -> Result<TransactionCall, String> {
99		let pallet_name = self.pallet_name();
100		let call_name = self.call_name();
101
102		let metadata = client.online_client().metadata();
103		let Some(pallet) = metadata.pallet_by_name(pallet_name) else {
104			return Err("Failed to find pallet index".into());
105		};
106		let Some(call_variant) = pallet.call_variant_by_name(call_name) else {
107			return Err("Failed to find call index".into());
108		};
109
110		let pallet_index = pallet.index();
111		let call_index = call_variant.index;
112		let call_data = self.call_data().encode();
113
114		let value = TransactionCall::new(pallet_index, call_index, call_data);
115
116		Ok(value)
117	}
118
119	fn to_submittable_transaction(&self, client: Client) -> Result<SubmittableTransaction, String> {
120		let call = self.to_transaction_call(&client)?;
121		let value = SubmittableTransaction::new(client, call);
122
123		Ok(value)
124	}
125}