mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 19:21:13 +00:00
Merge branch 'master' into staking
* master: decode option event arg (#158) Release v0.12.0 (#157) Only return an error if the extrinsic failed. (#156) Update to rc6. (#155) Different assert. (#153) Add a method to fetch an unhashed key, close #100 (#152) Fix port number. (#151)
This commit is contained in:
+29
-15
@@ -62,13 +62,7 @@ pub enum Error {
|
||||
TypeSizeUnavailable(String),
|
||||
/// Runtime error.
|
||||
#[error("Runtime error: {0}")]
|
||||
Runtime(RuntimeError),
|
||||
/// Bad origin.
|
||||
#[error("Bad origin: throw by ensure_signed, ensure_root or ensure_none.")]
|
||||
BadOrigin,
|
||||
/// Cannot lookup.
|
||||
#[error("Cannot lookup some information required to validate the transaction.")]
|
||||
CannotLookup,
|
||||
Runtime(#[from] RuntimeError),
|
||||
/// Other error.
|
||||
#[error("Other error: {0}")]
|
||||
Other(String),
|
||||
@@ -98,9 +92,29 @@ impl From<String> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Runtime error.
|
||||
#[derive(Clone, Debug, Eq, Error, PartialEq)]
|
||||
pub enum RuntimeError {
|
||||
/// Module error.
|
||||
#[error("Runtime module error: {0}")]
|
||||
Module(ModuleError),
|
||||
/// Bad origin.
|
||||
#[error("Bad origin: throw by ensure_signed, ensure_root or ensure_none.")]
|
||||
BadOrigin,
|
||||
/// Cannot lookup.
|
||||
#[error("Cannot lookup some information required to validate the transaction.")]
|
||||
CannotLookup,
|
||||
/// Other error.
|
||||
#[error("Other error: {0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl RuntimeError {
|
||||
/// Converts a `DispatchError` into a subxt error.
|
||||
pub fn from_dispatch(metadata: &Metadata, error: DispatchError) -> Result<(), Self> {
|
||||
pub fn from_dispatch(
|
||||
metadata: &Metadata,
|
||||
error: DispatchError,
|
||||
) -> Result<Self, Error> {
|
||||
match error {
|
||||
DispatchError::Module {
|
||||
index,
|
||||
@@ -109,22 +123,22 @@ impl Error {
|
||||
} => {
|
||||
let module = metadata.module_with_errors(index)?;
|
||||
let error = module.error(error)?;
|
||||
Err(Error::Runtime(RuntimeError {
|
||||
Ok(Self::Module(ModuleError {
|
||||
module: module.name().to_string(),
|
||||
error: error.to_string(),
|
||||
}))
|
||||
}
|
||||
DispatchError::BadOrigin => Err(Error::BadOrigin),
|
||||
DispatchError::CannotLookup => Err(Error::CannotLookup),
|
||||
DispatchError::Other(msg) => Err(Error::Other(msg.into())),
|
||||
DispatchError::BadOrigin => Ok(Self::BadOrigin),
|
||||
DispatchError::CannotLookup => Ok(Self::CannotLookup),
|
||||
DispatchError::Other(msg) => Ok(Self::Other(msg.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Runtime errors.
|
||||
/// Module error.
|
||||
#[derive(Clone, Debug, Eq, Error, PartialEq)]
|
||||
#[error("{error} from {module}")]
|
||||
pub struct RuntimeError {
|
||||
pub struct ModuleError {
|
||||
pub module: String,
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
+44
-15
@@ -39,7 +39,10 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
error::{
|
||||
Error,
|
||||
RuntimeError,
|
||||
},
|
||||
metadata::{
|
||||
EventArg,
|
||||
Metadata,
|
||||
@@ -151,6 +154,17 @@ impl<T: System> EventsDecoder<T> {
|
||||
self.decode_raw_bytes(&[*arg.clone()], input, output)?
|
||||
}
|
||||
}
|
||||
EventArg::Option(arg) => {
|
||||
match input.read_byte()? {
|
||||
0 => (),
|
||||
1 => self.decode_raw_bytes(&[*arg.clone()], input, output)?,
|
||||
_ => {
|
||||
return Err(Error::Other(
|
||||
"unexpected first byte decoding Option".into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
EventArg::Tuple(args) => self.decode_raw_bytes(args, input, output)?,
|
||||
EventArg::Primitive(name) => {
|
||||
let result = match name.as_str() {
|
||||
@@ -168,7 +182,9 @@ impl<T: System> EventsDecoder<T> {
|
||||
}
|
||||
};
|
||||
if let Err(error) = result {
|
||||
Error::from_dispatch(&self.metadata, error)?;
|
||||
return Err(
|
||||
RuntimeError::from_dispatch(&self.metadata, error)?.into()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,10 +193,7 @@ impl<T: System> EventsDecoder<T> {
|
||||
}
|
||||
|
||||
/// Decode events.
|
||||
pub fn decode_events(
|
||||
&self,
|
||||
input: &mut &[u8],
|
||||
) -> Result<Vec<(Phase, RawEvent)>, Error> {
|
||||
pub fn decode_events(&self, input: &mut &[u8]) -> Result<Vec<(Phase, Raw)>, Error> {
|
||||
let compact_len = <Compact<u32>>::decode(input)?;
|
||||
let len = compact_len.0 as usize;
|
||||
|
||||
@@ -201,20 +214,36 @@ impl<T: System> EventsDecoder<T> {
|
||||
);
|
||||
|
||||
let mut event_data = Vec::<u8>::new();
|
||||
self.decode_raw_bytes(&event_metadata.arguments(), input, &mut event_data)?;
|
||||
let result = self.decode_raw_bytes(
|
||||
&event_metadata.arguments(),
|
||||
input,
|
||||
&mut event_data,
|
||||
);
|
||||
let raw = match result {
|
||||
Ok(()) => {
|
||||
log::debug!("raw bytes: {}", hex::encode(&event_data),);
|
||||
|
||||
log::debug!("raw bytes: {}", hex::encode(&event_data),);
|
||||
let event = RawEvent {
|
||||
module: module.name().to_string(),
|
||||
variant: event_metadata.name.clone(),
|
||||
data: event_data,
|
||||
};
|
||||
|
||||
let event = RawEvent {
|
||||
module: module.name().to_string(),
|
||||
variant: event_metadata.name.clone(),
|
||||
data: event_data,
|
||||
// topics come after the event data in EventRecord
|
||||
let _topics = Vec::<T::Hash>::decode(input)?;
|
||||
Raw::Event(event)
|
||||
}
|
||||
Err(Error::Runtime(err)) => Raw::Error(err),
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
// topics come after the event data in EventRecord
|
||||
let _topics = Vec::<T::Hash>::decode(input)?;
|
||||
r.push((phase, event));
|
||||
r.push((phase, raw));
|
||||
}
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Raw {
|
||||
Event(RawEvent),
|
||||
Error(RuntimeError),
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ mod tests {
|
||||
use crate::{
|
||||
error::{
|
||||
Error,
|
||||
ModuleError,
|
||||
RuntimeError,
|
||||
},
|
||||
events::EventsDecoder,
|
||||
@@ -193,8 +194,8 @@ mod tests {
|
||||
let res = client
|
||||
.transfer_and_watch(&hans, alice.account_id(), 100_000_000_000)
|
||||
.await;
|
||||
if let Err(Error::Runtime(error)) = res {
|
||||
let error2 = RuntimeError {
|
||||
if let Err(Error::Runtime(RuntimeError::Module(error))) = res {
|
||||
let error2 = ModuleError {
|
||||
module: "Balances".into(),
|
||||
error: "InsufficientBalance".into(),
|
||||
};
|
||||
|
||||
+5
-2
@@ -43,7 +43,10 @@ pub struct SudoCall<'a, T: Sudo> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
error::Error,
|
||||
error::{
|
||||
Error,
|
||||
RuntimeError,
|
||||
},
|
||||
extrinsic::PairSigner,
|
||||
frame::balances::TransferCall,
|
||||
tests::{
|
||||
@@ -68,7 +71,7 @@ mod tests {
|
||||
|
||||
let res = client.sudo_and_watch(&alice, &call).await;
|
||||
assert!(
|
||||
if let Err(Error::BadOrigin) = res {
|
||||
if let Err(Error::Runtime(RuntimeError::BadOrigin)) = res {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
||||
+17
-8
@@ -247,7 +247,7 @@ impl<T: Runtime, F: Store<T>> KeyIter<T, F> {
|
||||
}
|
||||
}
|
||||
}
|
||||
debug_assert_eq!(self.buffer.len(), self.count as usize);
|
||||
debug_assert_eq!(self.buffer.len(), keys.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,6 +269,19 @@ impl<T: Runtime> Client<T> {
|
||||
&self.properties
|
||||
}
|
||||
|
||||
/// Fetch the value under an unhashed storage key
|
||||
pub async fn fetch_unhashed<V: Decode>(
|
||||
&self,
|
||||
key: StorageKey,
|
||||
hash: Option<T::Hash>,
|
||||
) -> Result<Option<V>, Error> {
|
||||
if let Some(data) = self.rpc.storage(&key, hash).await? {
|
||||
Ok(Some(Decode::decode(&mut &data.0[..])?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch a StorageKey with an optional block hash.
|
||||
pub async fn fetch<F: Store<T>>(
|
||||
&self,
|
||||
@@ -276,11 +289,7 @@ impl<T: Runtime> Client<T> {
|
||||
hash: Option<T::Hash>,
|
||||
) -> Result<Option<F::Returns>, Error> {
|
||||
let key = store.key(&self.metadata)?;
|
||||
if let Some(data) = self.rpc.storage(&key, hash).await? {
|
||||
Ok(Some(Decode::decode(&mut &data.0[..])?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
self.fetch_unhashed::<F::Returns>(key, hash).await
|
||||
}
|
||||
|
||||
/// Fetch a StorageKey that has a default value with an optional block hash.
|
||||
@@ -599,14 +608,14 @@ mod tests {
|
||||
},
|
||||
chain_spec: test_node::chain_spec::development_config().unwrap(),
|
||||
role: Role::Authority(key),
|
||||
enable_telemetry: false,
|
||||
telemetry: None,
|
||||
};
|
||||
let client = ClientBuilder::new()
|
||||
.set_client(
|
||||
SubxtClient::from_config(config, test_node::service::new_full)
|
||||
.expect("Error creating subxt client"),
|
||||
)
|
||||
.set_page_size(2)
|
||||
.set_page_size(3)
|
||||
.build()
|
||||
.await
|
||||
.expect("Error creating client");
|
||||
|
||||
@@ -398,6 +398,7 @@ pub enum EventArg {
|
||||
Primitive(String),
|
||||
Vec(Box<EventArg>),
|
||||
Tuple(Vec<EventArg>),
|
||||
Option(Box<EventArg>),
|
||||
}
|
||||
|
||||
impl FromStr for EventArg {
|
||||
@@ -413,6 +414,15 @@ impl FromStr for EventArg {
|
||||
"Expected closing `>` for `Vec`",
|
||||
))
|
||||
}
|
||||
} else if s.starts_with("Option<") {
|
||||
if s.ends_with('>') {
|
||||
Ok(EventArg::Option(Box::new(s[7..s.len() - 1].parse()?)))
|
||||
} else {
|
||||
Err(ConversionError::InvalidEventArg(
|
||||
s.to_string(),
|
||||
"Expected closing `>` for `Option`",
|
||||
))
|
||||
}
|
||||
} else if s.starts_with('(') {
|
||||
if s.ends_with(')') {
|
||||
let mut args = Vec::new();
|
||||
@@ -439,6 +449,7 @@ impl EventArg {
|
||||
match self {
|
||||
EventArg::Primitive(p) => vec![p.clone()],
|
||||
EventArg::Vec(arg) => arg.primitives(),
|
||||
EventArg::Option(arg) => arg.primitives(),
|
||||
EventArg::Tuple(args) => {
|
||||
let mut primitives = Vec::new();
|
||||
for arg in args {
|
||||
|
||||
+6
-1
@@ -22,6 +22,7 @@ use crate::{
|
||||
error::Error,
|
||||
events::{
|
||||
EventsDecoder,
|
||||
Raw,
|
||||
RawEvent,
|
||||
},
|
||||
frame::{
|
||||
@@ -99,13 +100,17 @@ impl<T: Runtime> EventSubscription<T> {
|
||||
Ok(events) => events,
|
||||
Err(error) => return Some(Err(error)),
|
||||
};
|
||||
for (phase, event) in raw_events {
|
||||
for (phase, raw) in raw_events {
|
||||
if let Phase::ApplyExtrinsic(i) = phase {
|
||||
if let Some(ext_index) = self.extrinsic {
|
||||
if i as usize != ext_index {
|
||||
continue
|
||||
}
|
||||
}
|
||||
let event = match raw {
|
||||
Raw::Event(event) => event,
|
||||
Raw::Error(err) => return Some(Err(err.into())),
|
||||
};
|
||||
if let Some((module, variant)) = self.event {
|
||||
if event.module != module || event.variant != variant {
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user