Skip to content
Snippets Groups Projects
Commit 727eb6a5 authored by Hugo Trentesaux's avatar Hugo Trentesaux
Browse files

add runtime events doc (!202)

* adds event documentation

* wip more compact

* improve runtime events doc

* add runtime events doc
parent bc11fb2c
No related branches found
No related tags found
1 merge request!202add runtime events doc
...@@ -359,7 +359,7 @@ ask to join the set of validators two sessions after ...@@ -359,7 +359,7 @@ ask to join the set of validators two sessions after
<details><summary><code>set_session_keys(keys)</code></summary> <details><summary><code>set_session_keys(keys)</code></summary>
```rust ```rust
keys: T::KeysWrapper keys: T::Keys
``` ```
</details> </details>
...@@ -750,8 +750,11 @@ Link an account to an identity ...@@ -750,8 +750,11 @@ Link an account to an identity
</details> </details>
claim pending membership to become actual memberhip claim membership
the requested membership must fullfill requirements a pending membership should exist
it must fullfill the requirements (certs, distance)
for main wot claim_membership is called automatically when validating identity
for smith wot, it means joining the authority members
#### renew_membership - 2 #### renew_membership - 2
...@@ -844,10 +847,9 @@ Removes the status if `status` is `None`. ...@@ -844,10 +847,9 @@ Removes the status if `status` is `None`.
#### request_membership - 0 #### request_membership - 0
<details><summary><code>request_membership(metadata)</code></summary> <details><summary><code>request_membership()</code></summary>
```rust ```rust
metadata: T::MetaData
``` ```
</details> </details>
...@@ -864,8 +866,11 @@ submit a membership request (must have a declared identity) ...@@ -864,8 +866,11 @@ submit a membership request (must have a declared identity)
</details> </details>
claim pending membership to become actual memberhip claim membership
the requested membership must fullfill requirements a pending membership should exist
it must fullfill the requirements (certs, distance)
for main wot claim_membership is called automatically when validating identity
for smith wot, it means joining the authority members
#### renew_membership - 2 #### renew_membership - 2
...@@ -2003,10 +2008,9 @@ usually means being a stash account). ...@@ -2003,10 +2008,9 @@ usually means being a stash account).
#### request_membership - 0 #### request_membership - 0
<details><summary><code>request_membership(metadata)</code></summary> <details><summary><code>request_membership()</code></summary>
```rust ```rust
metadata: T::MetaData
``` ```
</details> </details>
......
This diff is collapsed.
# Runtime events
There are **{{event_counter}}** events from **{{ pallets | length }}** pallets.
<ul>
{% for pallet in pallets -%}
<li>{{ pallet.name }} - {{ pallet.index }}
<ul>
{% for event in pallet.events -%}
<li>
<details>
<summary>
<code>{{ event.name }}(
{%- for param in event.params -%}
{{ param.name }}{% if loop.last != true %}, {% endif %}
{%- endfor -%}
)</code> - {{ event.index }}</summary>
{{ event.documentation }}
```rust
{% for param in event.params -%}
{{ param.name }}: {{ param.type_name }}
{%- else -%}no args
{% endfor -%}
```
</details>
</li>
{% endfor -%}
</ul>
</li>
{% endfor -%}
</ul>
\ No newline at end of file
...@@ -27,45 +27,79 @@ use tera::Tera; ...@@ -27,45 +27,79 @@ use tera::Tera;
// consts // consts
const CALLS_DOC_FILEPATH: &str = "docs/api/runtime-calls.md"; const CALLS_DOC_FILEPATH: &str = "docs/api/runtime-calls.md";
const EVENTS_DOC_FILEPATH: &str = "docs/api/runtime-events.md";
const TEMPLATES_GLOB: &str = "xtask/res/templates/*.md"; const TEMPLATES_GLOB: &str = "xtask/res/templates/*.md";
// define structs and implementations // define structs and implementations
type RuntimeCalls = Vec<Pallet>; type RuntimePallets = Vec<Pallet>;
#[derive(Clone, Serialize)] #[derive(Clone, Serialize)]
struct Pallet { struct Pallet {
index: u8, index: u8,
name: String, name: String,
calls: Vec<Call>, calls: Vec<Call>,
events: Vec<Event>,
}
#[derive(Clone, Serialize)]
struct Call {
documentation: String,
index: u8,
name: String,
params: Vec<CallParam>,
}
#[derive(Clone, Serialize)]
struct CallParam {
name: String,
type_name: String,
}
#[derive(Clone, Serialize)]
struct Event {
documentation: String,
index: u8,
name: String,
params: Vec<EventParam>,
}
#[derive(Clone, Serialize)]
struct EventParam {
name: String,
type_name: String,
} }
impl Pallet { impl Pallet {
fn new( fn new(
index: u8, index: u8,
name: String, name: String,
scale_type_def: &scale_info::TypeDef<PortableForm>, call_scale_type_def: &Option<scale_info::TypeDef<PortableForm>>,
event_scale_type_def: &Option<scale_info::TypeDef<PortableForm>>,
) -> Result<Self> { ) -> Result<Self> {
if let scale_info::TypeDef::Variant(calls_enum) = scale_type_def { let calls = if let Some(call_scale_type_def) = call_scale_type_def {
Ok(Self { if let scale_info::TypeDef::Variant(calls_enum) = call_scale_type_def {
index, calls_enum.variants.iter().map(Into::into).collect()
name, } else {
calls: calls_enum.variants.iter().map(Into::into).collect(), bail!("Invalid metadata")
}) }
} else { } else {
bail!("Invalid metadata") vec![]
} };
let events = if let Some(event_scale_type_def) = event_scale_type_def {
if let scale_info::TypeDef::Variant(events_enum) = event_scale_type_def {
events_enum.variants.iter().map(Into::into).collect()
} else {
bail!("Invalid metadata")
}
} else {
vec![]
};
Ok(Self {
index,
name,
calls,
events,
})
} }
} }
#[derive(Clone, Serialize)]
struct Call {
documentation: String,
index: u8,
name: String,
params: Vec<CallParam>,
}
impl From<&scale_info::Variant<PortableForm>> for Call { impl From<&scale_info::Variant<PortableForm>> for Call {
fn from(variant: &scale_info::Variant<PortableForm>) -> Self { fn from(variant: &scale_info::Variant<PortableForm>) -> Self {
Self { Self {
...@@ -83,13 +117,27 @@ impl From<&scale_info::Variant<PortableForm>> for Call { ...@@ -83,13 +117,27 @@ impl From<&scale_info::Variant<PortableForm>> for Call {
} }
} }
#[derive(Clone, Serialize)] impl From<&scale_info::Field<PortableForm>> for CallParam {
struct CallParam { fn from(field: &scale_info::Field<PortableForm>) -> Self {
name: String, Self {
type_name: String, name: field.clone().name.unwrap_or_default(),
type_name: field.clone().type_name.unwrap_or_default(),
}
}
} }
impl From<&scale_info::Field<PortableForm>> for CallParam { impl From<&scale_info::Variant<PortableForm>> for Event {
fn from(variant: &scale_info::Variant<PortableForm>) -> Self {
Self {
documentation: variant.docs.iter().cloned().collect::<Vec<_>>().join("\n"),
index: variant.index,
name: variant.name.to_owned(),
params: variant.fields.iter().map(Into::into).collect(),
}
}
}
impl From<&scale_info::Field<PortableForm>> for EventParam {
fn from(field: &scale_info::Field<PortableForm>) -> Self { fn from(field: &scale_info::Field<PortableForm>) -> Self {
Self { Self {
name: field.clone().name.unwrap_or_default(), name: field.clone().name.unwrap_or_default(),
...@@ -149,7 +197,7 @@ impl CallCategory { ...@@ -149,7 +197,7 @@ impl CallCategory {
} }
/// generate runtime calls documentation /// generate runtime calls documentation
pub(super) fn gen_calls_doc() -> Result<()> { pub(super) fn gen_doc() -> Result<()> {
// Read metadata // Read metadata
let mut file = std::fs::File::open("resources/metadata.scale") let mut file = std::fs::File::open("resources/metadata.scale")
.with_context(|| "Failed to open metadata file")?; .with_context(|| "Failed to open metadata file")?;
...@@ -163,49 +211,80 @@ pub(super) fn gen_calls_doc() -> Result<()> { ...@@ -163,49 +211,80 @@ pub(super) fn gen_calls_doc() -> Result<()> {
println!("Metadata successfully loaded!"); println!("Metadata successfully loaded!");
let runtime_calls = if let frame_metadata::RuntimeMetadata::V14(metadata_v14) = metadata.1 { let runtime = if let frame_metadata::RuntimeMetadata::V14(metadata_v14) = metadata.1 {
get_calls_from_metadata_v14(metadata_v14)? get_from_metadata_v14(metadata_v14)?
} else { } else {
bail!("unsuported metadata version") bail!("unsuported metadata version")
}; };
let output = print_runtime_calls(runtime_calls); let (call_doc, event_doc) = print_runtime(runtime);
let mut file = File::create(CALLS_DOC_FILEPATH) let mut file = File::create(CALLS_DOC_FILEPATH)
.with_context(|| format!("Failed to create file '{}'", CALLS_DOC_FILEPATH))?; .with_context(|| format!("Failed to create file '{}'", CALLS_DOC_FILEPATH))?;
file.write_all(output.as_bytes()) file.write_all(call_doc.as_bytes())
.with_context(|| format!("Failed to write to file '{}'", CALLS_DOC_FILEPATH))?; .with_context(|| format!("Failed to write to file '{}'", CALLS_DOC_FILEPATH))?;
let mut file = File::create(EVENTS_DOC_FILEPATH)
.with_context(|| format!("Failed to create file '{}'", EVENTS_DOC_FILEPATH))?;
file.write_all(event_doc.as_bytes())
.with_context(|| format!("Failed to write to file '{}'", EVENTS_DOC_FILEPATH))?;
Ok(()) Ok(())
} }
fn get_calls_from_metadata_v14( fn get_from_metadata_v14(
metadata_v14: frame_metadata::v14::RuntimeMetadataV14, metadata_v14: frame_metadata::v14::RuntimeMetadataV14,
) -> Result<RuntimeCalls> { ) -> Result<RuntimePallets> {
println!("Number of pallets: {}", metadata_v14.pallets.len()); println!("Number of pallets: {}", metadata_v14.pallets.len());
let mut pallets = Vec::new(); let mut pallets = Vec::new();
for pallet in metadata_v14.pallets { for pallet in metadata_v14.pallets {
if let Some(calls) = pallet.calls { let calls_type_def = if let Some(calls) = pallet.calls {
if let Some(calls_type) = metadata_v14.types.resolve(calls.ty.id) { let Some(calls_type) = metadata_v14.types.resolve(calls.ty.id) else {
let pallet = Pallet::new(pallet.index, pallet.name.clone(), &calls_type.type_def)?;
let calls_len = pallet.calls.len();
println!("{}: {} ({} calls)", pallet.index, pallet.name, calls_len);
pallets.push(pallet);
} else {
bail!("Invalid metadata") bail!("Invalid metadata")
} };
Some(calls_type.type_def.clone())
} else { } else {
println!("{}: {} (0 calls)", pallet.index, pallet.name); println!("{}: {} (0 calls)", pallet.index, pallet.name);
} None
};
let events_type_def = if let Some(events) = pallet.event {
let Some(events_type) = metadata_v14.types.resolve(events.ty.id) else {
bail!("Invalid metadata")
};
Some(events_type.type_def.clone())
} else {
println!("{}: {} (0 events)", pallet.index, pallet.name);
None
};
let pallet = Pallet::new(
pallet.index,
pallet.name.clone(),
&calls_type_def,
&events_type_def,
)?;
println!(
"{}: {} ({} calls)",
pallet.index,
pallet.name,
pallet.calls.len()
);
println!(
"{}: {} ({} events)",
pallet.index,
pallet.name,
pallet.events.len()
);
pallets.push(pallet);
} }
Ok(pallets) Ok(pallets)
} }
/// use template to render markdown file with runtime calls documentation /// use template to render markdown file with runtime calls documentation
fn print_runtime_calls(pallets: RuntimeCalls) -> String { fn print_runtime(pallets: RuntimePallets) -> (String, String) {
// init variables // init variables
let mut user_calls_counter = 0; let mut user_calls_counter = 0;
let user_calls_pallets: RuntimeCalls = pallets let user_calls_pallets: RuntimePallets = pallets
.iter() .iter()
.cloned() .cloned()
.filter_map(|mut pallet| { .filter_map(|mut pallet| {
...@@ -222,7 +301,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String { ...@@ -222,7 +301,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
}) })
.collect(); .collect();
let mut root_calls_counter = 0; let mut root_calls_counter = 0;
let root_calls_pallets: RuntimeCalls = pallets let root_calls_pallets: RuntimePallets = pallets
.iter() .iter()
.cloned() .cloned()
.filter_map(|mut pallet| { .filter_map(|mut pallet| {
...@@ -239,7 +318,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String { ...@@ -239,7 +318,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
}) })
.collect(); .collect();
let mut disabled_calls_counter = 0; let mut disabled_calls_counter = 0;
let disabled_calls_pallets: RuntimeCalls = pallets let disabled_calls_pallets: RuntimePallets = pallets
.iter() .iter()
.cloned() .cloned()
.filter_map(|mut pallet| { .filter_map(|mut pallet| {
...@@ -256,6 +335,11 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String { ...@@ -256,6 +335,11 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
}) })
.collect(); .collect();
let mut event_counter = 0;
pallets
.iter()
.for_each(|pallet| event_counter += pallet.events.len());
// compile template // compile template
let tera = match Tera::new(TEMPLATES_GLOB) { let tera = match Tera::new(TEMPLATES_GLOB) {
Ok(t) => t, Ok(t) => t,
...@@ -265,7 +349,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String { ...@@ -265,7 +349,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
} }
}; };
// fills tera context for rendering // fills tera context for rendering calls
let mut context = tera::Context::new(); let mut context = tera::Context::new();
context.insert("user_calls_counter", &user_calls_counter); context.insert("user_calls_counter", &user_calls_counter);
context.insert("user_calls_pallets", &user_calls_pallets); context.insert("user_calls_pallets", &user_calls_pallets);
...@@ -274,6 +358,17 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String { ...@@ -274,6 +358,17 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
context.insert("disabled_calls_counter", &disabled_calls_counter); context.insert("disabled_calls_counter", &disabled_calls_counter);
context.insert("disabled_calls_pallets", &disabled_calls_pallets); context.insert("disabled_calls_pallets", &disabled_calls_pallets);
tera.render("runtime-calls.md", &context) let call_doc = tera
.expect("template error") .render("runtime-calls.md", &context)
.expect("template error");
// render events
context.insert("pallets", &pallets);
context.insert("event_counter", &event_counter);
let event_doc = tera
.render("runtime-events.md", &context)
.expect("template error");
(call_doc, event_doc)
} }
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
mod gen_calls_doc; mod gen_doc;
mod release_runtime; mod release_runtime;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
...@@ -38,8 +38,8 @@ enum DuniterXTaskCommand { ...@@ -38,8 +38,8 @@ enum DuniterXTaskCommand {
#[clap(long)] #[clap(long)]
production: bool, production: bool,
}, },
/// Generate calls documentation /// Generate documentation (calls and events)
GenCallsDoc, GenDoc,
/// Inject runtime code in raw specs /// Inject runtime code in raw specs
InjectRuntimeCode { InjectRuntimeCode {
#[clap(short, long)] #[clap(short, long)]
...@@ -82,7 +82,7 @@ async fn main() -> Result<()> { ...@@ -82,7 +82,7 @@ async fn main() -> Result<()> {
match args.command { match args.command {
DuniterXTaskCommand::Build { production } => build(production), DuniterXTaskCommand::Build { production } => build(production),
DuniterXTaskCommand::GenCallsDoc => gen_calls_doc::gen_calls_doc(), DuniterXTaskCommand::GenDoc => gen_doc::gen_doc(),
DuniterXTaskCommand::InjectRuntimeCode { runtime, raw_spec } => { DuniterXTaskCommand::InjectRuntimeCode { runtime, raw_spec } => {
inject_runtime_code(&raw_spec, &runtime) inject_runtime_code(&raw_spec, &runtime)
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment