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
154
//! Decode extrinsics and storage values from substrate based networks like Polkadot.
#![warn(missing_docs)]

extern crate alloc;

mod utils;
mod decoding;

// TODO:
// - map_type_id on storage errors, too.
// - Feature flags and test in subxt?

/// This module contains functions for decoding extrinsics.
pub mod extrinsics {
    use scale_info_legacy::{LookupName, TypeRegistrySet};
    use frame_metadata::RuntimeMetadata;
    use super::{AnyError, AnyTypeId};
    use crate::utils::InfoAndResolver;
    
    pub use crate::decoding::extrinsic_type_info::{
        ExtrinsicTypeInfo,
        ExtrinsicInfo,
        ExtrinsicSignatureInfo,
        ExtrinsicInfoArg,
        ExtrinsicInfoError,
    };
    pub use crate::decoding::extrinsic_decoder::{
        Extrinsic,
        ExtrinsicDecodeError,
        decode_extrinsic,
    };

    pub fn decode_extrinsic_any<'resolver, 'info: 'resolver>(
        cursor: &mut &[u8], 
        metadata: &'info frame_metadata::RuntimeMetadata, 
        historic_types: &'resolver TypeRegistrySet
    ) -> Result<Extrinsic<'resolver, AnyTypeId>, AnyError<ExtrinsicDecodeError>> {
        match metadata {
            RuntimeMetadata::V8(m) => decode_extrinsic(cursor, m, historic_types)
                .map(|e| e.map_type_id(AnyTypeId::Legacy))
                .map_err(AnyError::DecodeError),
            RuntimeMetadata::V9(m) => decode_extrinsic(cursor, m, historic_types)
                .map(|e| e.map_type_id(AnyTypeId::Legacy))
                .map_err(AnyError::DecodeError),
            RuntimeMetadata::V10(m) => decode_extrinsic(cursor, m, historic_types)
                .map(|e| e.map_type_id(AnyTypeId::Legacy))
                .map_err(AnyError::DecodeError),
            RuntimeMetadata::V11(m) => decode_extrinsic(cursor, m, historic_types)
                .map(|e| e.map_type_id(AnyTypeId::Legacy))
                .map_err(AnyError::DecodeError),
            RuntimeMetadata::V12(m) => decode_extrinsic(cursor, m, historic_types)
                .map(|e| e.map_type_id(AnyTypeId::Legacy))
                .map_err(AnyError::DecodeError),
            RuntimeMetadata::V13(m) => decode_extrinsic(cursor, m, historic_types)
                .map(|e| e.map_type_id(AnyTypeId::Legacy))
                .map_err(AnyError::DecodeError),
            RuntimeMetadata::V14(m) => decode_extrinsic(cursor, m, &m.types)
                .map(|e| e.map_type_id(AnyTypeId::Current))
                .map_err(AnyError::DecodeError),
            RuntimeMetadata::V15(m) => decode_extrinsic(cursor, m, &m.types)
                .map(|e| e.map_type_id(AnyTypeId::Current))
                .map_err(AnyError::DecodeError),
            _ => Err(AnyError::MetadataNotSupported { metadata_version: metadata.version() })
        }
    }

    pub fn decode_extrinsic_current<'info_and_resolver, T>(
        cursor: &mut &[u8], 
        metadata: &'info_and_resolver T, 
    ) -> Result<Extrinsic<'info_and_resolver, <T::Info as ExtrinsicTypeInfo>::TypeId>, ExtrinsicDecodeError> 
    where
        T: InfoAndResolver,
        T::Info: ExtrinsicTypeInfo,
        <T::Info as ExtrinsicTypeInfo>::TypeId: core::fmt::Debug + Clone,
        T::Resolver: scale_type_resolver::TypeResolver<TypeId = <T::Info as ExtrinsicTypeInfo>::TypeId>,
    {
        decode_extrinsic(cursor, metadata.info(), metadata.resolver())
    }

    pub fn decode_extrinsic_legacy<'info, 'resolver, Info: ExtrinsicTypeInfo<TypeId = LookupName>>(
        cursor: &mut &[u8], 
        metadata: &'info Info, 
        historic_types: &'resolver TypeRegistrySet
    ) -> Result<Extrinsic<'info, LookupName>, ExtrinsicDecodeError> {
        decode_extrinsic(cursor, metadata, historic_types)
    }

}

/// This module contains functions for decoding storage keys and values.
pub mod storage {
    use scale_info_legacy::{LookupName, TypeRegistrySet};
    use frame_metadata::RuntimeMetadata;
    use super::{AnyError,AnyTypeId};

    pub use crate::decoding::storage_decoder::{
        StorageKey,
        StorageKeyPart,
        StorageKeyPartValue,
        StorageKeyDecodeError,
        StorageValue,
        StorageValueDecodeError,
        decode_storage_key,
        decode_storage_value,
    };

    // pub fn decode_storage_key_any<'resolver, 'info: 'resolver>(
    //     pallet_name: &str,
    //     entry_name: &str,
    //     cursor: &mut &[u8], 
    //     metadata: &'info frame_metadata::RuntimeMetadata, 
    //     historic_types: &'resolver TypeRegistrySet
    // ) -> Result<StorageKey<AnyTypeId>, AnyError<StorageKeyDecodeError<AnyTypeId>>> {
    //     match metadata {
    //         RuntimeMetadata::V8(m) => decode_storage_key(pallet_name, entry_name, cursor, m, historic_types)
    //             .map(|e| e.map_type_id(AnyTypeId::Legacy))
    //             .map_err(AnyError::DecodeError),
    //         RuntimeMetadata::V9(m) => decode_storage_key(pallet_name, entry_name, cursor, m, historic_types)
    //             .map(|e| e.map_type_id(AnyTypeId::Legacy))
    //             .map_err(AnyError::DecodeError),
    //         RuntimeMetadata::V10(m) => decode_storage_key(pallet_name, entry_name, cursor, m, historic_types)
    //             .map(|e| e.map_type_id(AnyTypeId::Legacy))
    //             .map_err(AnyError::DecodeError),
    //         RuntimeMetadata::V11(m) => decode_storage_key(pallet_name, entry_name, cursor, m, historic_types)
    //             .map(|e| e.map_type_id(AnyTypeId::Legacy))
    //             .map_err(AnyError::DecodeError),
    //         RuntimeMetadata::V12(m) => decode_storage_key(pallet_name, entry_name, cursor, m, historic_types)
    //             .map(|e| e.map_type_id(AnyTypeId::Legacy))
    //             .map_err(AnyError::DecodeError),
    //         RuntimeMetadata::V13(m) => decode_storage_key(pallet_name, entry_name, cursor, m, historic_types)
    //             .map(|e| e.map_type_id(AnyTypeId::Legacy))
    //             .map_err(AnyError::DecodeError),
    //         RuntimeMetadata::V14(m) => decode_storage_key(pallet_name, entry_name, cursor, m, &m.types)
    //             .map(|e| e.map_type_id(AnyTypeId::Current))
    //             .map_err(AnyError::DecodeError),
    //         RuntimeMetadata::V15(m) => decode_storage_key(pallet_name, entry_name, cursor, m, &m.types)
    //             .map(|e| e.map_type_id(AnyTypeId::Current))
    //             .map_err(AnyError::DecodeError),
    //         _ => Err(AnyError::MetadataNotSupported { metadata_version: metadata.version() })
    //     }
    // }
}

#[derive(Debug, Clone)]
pub enum AnyTypeId {
    Legacy(scale_info_legacy::LookupName),
    Current(u32)
}

#[derive(Debug, Clone)]
pub enum AnyError<Err> {
    MetadataNotSupported { metadata_version: u32 },
    DecodeError(Err)
}