1
+ //! Primitives and inherent data provider for the Native Token Management feature
2
+ //!
3
+ //! # Purpose and context
4
+ //!
5
+ //! This crate defines shared types used by components that implement the Native Token Management
6
+ //! feature of the Partner Chains toolkit, along with an inherent data provider for token transfer
7
+ //! data.
8
+ //!
9
+ //! The Native Token Management feature allows a Partner Chain to keep its token as a native asset
10
+ //! on Cardano and have it be transferable to the Partner Chain. This is achieved by the native
11
+ //! token being locked at an _illiquid supply_ address on Cardano, and the Partner Chain handling
12
+ //! this locking event (a _transfer_) after it has been observed as part of a stable block.
13
+ //!
14
+ //! The inherent data provider defined in this crate is responsible for providing information about
15
+ //! the transfers in form of inherent data, and handling them is the responsibility of the pallet,
16
+ //! which allows the Partner Chain builders to define their own transfer handling logic to suit
17
+ //! their needs.
18
+ //!
19
+ //! # Usage
20
+ //!
21
+ //! ## Prerequisites
22
+ //!
23
+ //! This features depends on the MC Reference Hash feature to provide Cardano block reference for
24
+ //! querying the token transfers. See the documentation of `sidechain_mc_hash` crate for more information.
25
+ //!
26
+ //! ## Implementing runtime APIs
27
+ //!
28
+ //! [NativeTokenManagementInherentDataProvider] requires the runtime to implement the
29
+ //! [NativeTokenManagementApi] runtime API. This only requires passing relevant values from the pallet:
30
+ //! ```rust,ignore
31
+ //! impl sp_native_token_management::NativeTokenManagementApi<Block> for Runtime {
32
+ //! fn get_main_chain_scripts() -> Option<sp_native_token_management::MainChainScripts> {
33
+ //! NativeTokenManagement::get_main_chain_scripts()
34
+ //! }
35
+ //! fn initialized() -> bool {
36
+ //! NativeTokenManagement::initialized()
37
+ //! }
38
+ //! }
39
+ //! ```
40
+ //!
41
+ //! ## Adding the inherent data provider
42
+ //!
43
+ //! The inherent data provider requires a data source implementing [NativeTokenManagementDataSource].
44
+ //! A Db-Sync implementation is provided by the `partner_chains_db_sync_data_sources` crate.
45
+ //!
46
+ //! With the data source present, the IDP is straightfoward to create:
47
+ //!
48
+ //! ```rust
49
+ //! use std::sync::Arc;
50
+ //! use sp_runtime::traits::Block as BlockT;
51
+ //! use sp_native_token_management::*;
52
+ //!
53
+ //! async fn create_idps<Block: BlockT, C>(
54
+ //! parent_hash: Block::Hash,
55
+ //! client: Arc<C>,
56
+ //! native_token_data_source: &(dyn NativeTokenManagementDataSource + Send + Sync)
57
+ //! ) -> Result<(NativeTokenManagementInherentDataProvider /* other IDPs */), Box<dyn std::error::Error + Send + Sync>>
58
+ //! where
59
+ //! C: sp_api::ProvideRuntimeApi<Block> + Send + Sync,
60
+ //! C::Api: NativeTokenManagementApi<Block>
61
+ //! {
62
+ //! let (mc_hash, previous_mc_hash) = todo!("Should come from the MC Reference Hash feature");
63
+ //!
64
+ //! let native_token_idp = NativeTokenManagementInherentDataProvider::new(
65
+ //! client.clone(),
66
+ //! native_token_data_source,
67
+ //! mc_hash,
68
+ //! previous_mc_hash,
69
+ //! parent_hash,
70
+ //! )
71
+ //! .await?;
72
+ //! Ok((native_token_idp /* other IDPs */))
73
+ //! }
74
+ //! ```
75
+ //!
76
+ //! The same constructor can be used for both proposal and validation of blocks.
77
+ //!
78
+ //! [NativeTokenManagementApi]: sp_native_token_management::NativeTokenManagementApi
1
79
#![ cfg_attr( not( feature = "std" ) , no_std) ]
80
+ #![ deny( missing_docs) ]
2
81
3
82
#[ cfg( feature = "std" ) ]
4
83
use { core:: str:: FromStr , sp_runtime:: traits:: Block as BlockT } ;
@@ -14,6 +93,7 @@ use sp_runtime::scale_info::TypeInfo;
14
93
#[ cfg( test) ]
15
94
mod tests;
16
95
96
+ /// Inherent identifier used by the Native Token Management pallet
17
97
pub const INHERENT_IDENTIFIER : InherentIdentifier = * b"nattoken" ;
18
98
19
99
/// Values identifying on-chain entities involved in the native token management system on Cardano.
@@ -31,9 +111,15 @@ pub struct MainChainScripts {
31
111
32
112
#[ cfg( feature = "std" ) ]
33
113
impl MainChainScripts {
114
+ /// Reads the main chain script values from local environment variables
115
+ ///
116
+ /// It expects the following variables to be set:
117
+ /// - `NATIVE_TOKEN_POLICY_ID`
118
+ /// - `NATIVE_TOKEN_ASSET_NAME`
119
+ /// - `ILLIQUID_SUPPLY_VALIDATOR_ADDRESS`
34
120
pub fn read_from_env ( ) -> Result < Self , envy:: Error > {
35
121
#[ derive( serde:: Serialize , serde:: Deserialize ) ]
36
- pub struct MainChainScriptsEnvConfig {
122
+ struct MainChainScriptsEnvConfig {
37
123
pub native_token_policy_id : PolicyId ,
38
124
pub native_token_asset_name : AssetName ,
39
125
pub illiquid_supply_validator_address : String ,
@@ -57,29 +143,37 @@ impl MainChainScripts {
57
143
}
58
144
59
145
sp_api:: decl_runtime_apis! {
146
+ /// Runtime API exposing configuration and initialization status of the Native Token Management pallet
60
147
pub trait NativeTokenManagementApi {
148
+ /// Returns the current main chain scripts configured in the pallet or [None] if they are not set.
61
149
fn get_main_chain_scripts( ) -> Option <MainChainScripts >;
62
150
/// Gets current initializaion status and set it to `true` afterwards. This check is used to
63
151
/// determine whether historical data from the beginning of main chain should be queried.
64
152
fn initialized( ) -> bool ;
65
153
}
66
154
}
67
155
156
+ /// Data about token transfers in some period of time
68
157
#[ derive( Decode , Encode ) ]
69
158
pub struct TokenTransferData {
159
+ /// Aggregate number of tokens transfered
70
160
pub token_amount : NativeTokenAmount ,
71
161
}
72
162
163
+ /// Error type returned by the Native Token Management pallet inherent logic
73
164
#[ derive( Encode , Debug , PartialEq ) ]
74
165
#[ cfg_attr( feature = "std" , derive( Decode , thiserror:: Error ) ) ]
75
166
pub enum InherentError {
167
+ /// Signals that no inherent was submitted despite new token transfers being observed
76
168
#[ cfg_attr( feature = "std" , error( "Inherent missing for token transfer of {0} tokens" ) ) ]
77
169
TokenTransferNotHandled ( NativeTokenAmount ) ,
170
+ /// Signals that the inherent registered an incorrect number of tokens transfered
78
171
#[ cfg_attr(
79
172
feature = "std" ,
80
173
error( "Incorrect token transfer amount: expected {0}, got {1} tokens" )
81
174
) ]
82
175
IncorrectTokenNumberTransfered ( NativeTokenAmount , NativeTokenAmount ) ,
176
+ /// Signals that an inherent was submitted when no token transfers were observed
83
177
#[ cfg_attr( feature = "std" , error( "Unexpected transfer of {0} tokens" ) ) ]
84
178
UnexpectedTokenTransferInherent ( NativeTokenAmount ) ,
85
179
}
@@ -97,6 +191,7 @@ mod inherent_provider {
97
191
use std:: error:: Error ;
98
192
use std:: sync:: Arc ;
99
193
194
+ /// Interface for a data source serving native token transfer data compatible with [NativeTokenManagementInherentDataProvider].
100
195
#[ async_trait:: async_trait]
101
196
pub trait NativeTokenManagementDataSource {
102
197
/// Retrieves total of native token transfers into the illiquid supply in the range (after_block, to_block]
@@ -113,13 +208,17 @@ mod inherent_provider {
113
208
///
114
209
/// This IDP will not provide any inherent data if `token_amount` is [None], but *will* provide data for `Some(0)`.
115
210
pub struct NativeTokenManagementInherentDataProvider {
211
+ /// Aggregate number of tokens transfered
116
212
pub token_amount : Option < NativeTokenAmount > ,
117
213
}
118
214
215
+ /// Error type returned when creation of [NativeTokenManagementInherentDataProvider] fails
119
216
#[ derive( thiserror:: Error , sp_runtime:: RuntimeDebug ) ]
120
217
pub enum IDPCreationError {
218
+ /// Signals that the data source used returned an error
121
219
#[ error( "Failed to read native token data from data source: {0:?}" ) ]
122
220
DataSourceError ( Box < dyn Error + Send + Sync > ) ,
221
+ /// Signals that a runtime API call failed
123
222
#[ error( "Failed to call runtime API: {0:?}" ) ]
124
223
ApiError ( ApiError ) ,
125
224
}
@@ -208,6 +307,7 @@ mod inherent_provider {
208
307
}
209
308
}
210
309
310
+ /// Mock implementation of the data source
211
311
#[ cfg( any( test, feature = "mock" ) ) ]
212
312
pub mod mock {
213
313
use crate :: { MainChainScripts , NativeTokenManagementDataSource } ;
@@ -216,6 +316,7 @@ mod inherent_provider {
216
316
use sidechain_domain:: * ;
217
317
use std:: collections:: HashMap ;
218
318
319
+ /// Mock implementation of [NativeTokenManagementDataSource]
219
320
#[ derive( new, Default ) ]
220
321
pub struct MockNativeTokenDataSource {
221
322
transfers : HashMap < ( Option < McBlockHash > , McBlockHash ) , NativeTokenAmount > ,
0 commit comments