1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use crate::{
UserError,
subxt_signer::{SecretUri, sr25519::Keypair},
};
use avail_rust_core::{
AccountId, H256,
ext::subxt_core::utils::AccountId32,
utils::{account_id_from_slice, account_id_from_str},
};
/// Extension helpers for working with `H256` values.
pub trait H256Ext {
/// Parses a string (with or without `0x`) into an `H256`.
///
/// # Arguments
/// * `s` - Hexadecimal string representation of the hash, optionally prefixed with `0x`.
///
/// # Returns
/// Returns the decoded `H256` value.
///
/// # Errors
/// Returns an error if the string is not 64 characters (after removing prefix) or contains invalid hex.
fn from_str(s: &str) -> Result<H256, String>;
}
impl H256Ext for H256 {
fn from_str(s: &str) -> Result<H256, String> {
let mut s = s;
if s.starts_with("0x") {
s = &s[2..];
}
if s.len() != 64 {
let msg = std::format!(
"Failed to convert string to H256. Expected 64 bytes got {}. Input string: {}",
s.len(),
s
);
return Err(msg);
}
let block_hash = const_hex::decode(s).map_err(|e| e.to_string())?;
let block_hash = TryInto::<[u8; 32]>::try_into(block_hash);
match block_hash {
Ok(v) => Ok(H256(v)),
Err(e) => {
let msg = std::format!("Failed to covert decoded string to H256. Input {:?}", e);
Err(msg)
},
}
}
}
/// Extension helpers for constructing `AccountId` values.
pub trait AccountIdExt {
/// Parses an address string into an `AccountId`.
///
/// # Arguments
/// * `value` - SS58-encoded address string.
///
/// # Returns
/// Returns the decoded `AccountId`.
///
/// # Errors
/// Returns an error if the address string is malformed or uses an invalid SS58 format.
fn from_str(value: &str) -> Result<AccountId, String>;
/// Decodes an `AccountId` from raw bytes.
///
/// # Arguments
/// * `value` - Raw 32-byte account identifier.
///
/// # Returns
/// Returns the decoded `AccountId`.
///
/// # Errors
/// Returns an error if the byte slice is not exactly 32 bytes.
fn from_slice(value: &[u8]) -> Result<AccountId, String>;
/// Returns the zero `AccountId`.
///
/// # Returns
/// Returns an `AccountId` with all bytes set to zero.
fn default() -> AccountId;
}
impl AccountIdExt for AccountId {
fn from_str(value: &str) -> Result<AccountId, String> {
account_id_from_str(value)
}
fn from_slice(value: &[u8]) -> Result<AccountId, String> {
account_id_from_slice(value)
}
fn default() -> AccountId {
AccountId32([0u8; 32])
}
}
/// Extension helpers for parsing signer URIs.
pub trait SecretUriExt {
/// Parses a secret URI string into a signer `SecretUri`.
///
/// # Arguments
/// * `value` - Secret URI string (e.g., seed phrase, mnemonic, or raw secret).
///
/// # Returns
/// Returns the parsed `SecretUri`.
///
/// # Errors
/// Returns a `UserError` if the URI format is invalid or cannot be parsed.
fn from_str(value: &str) -> Result<SecretUri, UserError>;
}
impl SecretUriExt for SecretUri {
fn from_str(value: &str) -> Result<SecretUri, UserError> {
value.parse().map_err(|e| UserError::Other(std::format!("{:?}", e)))
}
}
/// Extension helpers for building and inspecting sr25519 keypairs.
pub trait KeypairExt {
/// Parses a secret URI string into a sr25519 keypair.
///
/// # Arguments
/// * `value` - Secret URI string (e.g., seed phrase or mnemonic).
///
/// # Returns
/// Returns the derived sr25519 keypair.
///
/// # Errors
/// Returns a `UserError` if the URI cannot be parsed or keypair derivation fails.
fn from_str(value: &str) -> Result<Keypair, UserError>;
/// Derives the associated `AccountId` from the public key.
///
/// # Returns
/// Returns the `AccountId` corresponding to this keypair's public key.
fn account_id(&self) -> AccountId;
}
impl KeypairExt for Keypair {
fn from_str(value: &str) -> Result<Keypair, UserError> {
let secret_uri = SecretUri::from_str(value).map_err(|e| UserError::Other(e.to_string()))?;
let keypair = Keypair::from_uri(&secret_uri).map_err(|e| UserError::Other(e.to_string()))?;
Ok(keypair)
}
fn account_id(&self) -> AccountId {
self.public_key().to_account_id()
}
}