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
<details><summary><code>set_session_keys(keys)</code></summary>
```rust
keys: T::KeysWrapper
keys: T::Keys
```
</details>
......@@ -750,8 +750,11 @@ Link an account to an identity
</details>
claim pending membership to become actual memberhip
the requested membership must fullfill requirements
claim membership
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
......@@ -844,10 +847,9 @@ Removes the status if `status` is `None`.
#### request_membership - 0
<details><summary><code>request_membership(metadata)</code></summary>
<details><summary><code>request_membership()</code></summary>
```rust
metadata: T::MetaData
```
</details>
......@@ -864,8 +866,11 @@ submit a membership request (must have a declared identity)
</details>
claim pending membership to become actual memberhip
the requested membership must fullfill requirements
claim membership
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
......@@ -2003,10 +2008,9 @@ usually means being a stash account).
#### request_membership - 0
<details><summary><code>request_membership(metadata)</code></summary>
<details><summary><code>request_membership()</code></summary>
```rust
metadata: T::MetaData
```
</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;
// consts
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";
// define structs and implementations
type RuntimeCalls = Vec<Pallet>;
type RuntimePallets = Vec<Pallet>;
#[derive(Clone, Serialize)]
struct Pallet {
index: u8,
name: String,
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 {
fn new(
index: u8,
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> {
if let scale_info::TypeDef::Variant(calls_enum) = scale_type_def {
Ok(Self {
index,
name,
calls: calls_enum.variants.iter().map(Into::into).collect(),
})
let calls = if let Some(call_scale_type_def) = call_scale_type_def {
if let scale_info::TypeDef::Variant(calls_enum) = call_scale_type_def {
calls_enum.variants.iter().map(Into::into).collect()
} else {
bail!("Invalid metadata")
}
} 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 {
fn from(variant: &scale_info::Variant<PortableForm>) -> Self {
Self {
......@@ -83,13 +117,27 @@ impl From<&scale_info::Variant<PortableForm>> for Call {
}
}
#[derive(Clone, Serialize)]
struct CallParam {
name: String,
type_name: String,
impl From<&scale_info::Field<PortableForm>> for CallParam {
fn from(field: &scale_info::Field<PortableForm>) -> Self {
Self {
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 {
Self {
name: field.clone().name.unwrap_or_default(),
......@@ -149,7 +197,7 @@ impl CallCategory {
}
/// generate runtime calls documentation
pub(super) fn gen_calls_doc() -> Result<()> {
pub(super) fn gen_doc() -> Result<()> {
// Read metadata
let mut file = std::fs::File::open("resources/metadata.scale")
.with_context(|| "Failed to open metadata file")?;
......@@ -163,49 +211,80 @@ pub(super) fn gen_calls_doc() -> Result<()> {
println!("Metadata successfully loaded!");
let runtime_calls = if let frame_metadata::RuntimeMetadata::V14(metadata_v14) = metadata.1 {
get_calls_from_metadata_v14(metadata_v14)?
let runtime = if let frame_metadata::RuntimeMetadata::V14(metadata_v14) = metadata.1 {
get_from_metadata_v14(metadata_v14)?
} else {
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)
.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))?;
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(())
}
fn get_calls_from_metadata_v14(
fn get_from_metadata_v14(
metadata_v14: frame_metadata::v14::RuntimeMetadataV14,
) -> Result<RuntimeCalls> {
) -> Result<RuntimePallets> {
println!("Number of pallets: {}", metadata_v14.pallets.len());
let mut pallets = Vec::new();
for pallet in metadata_v14.pallets {
if let Some(calls) = pallet.calls {
if let Some(calls_type) = metadata_v14.types.resolve(calls.ty.id) {
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 {
let calls_type_def = if let Some(calls) = pallet.calls {
let Some(calls_type) = metadata_v14.types.resolve(calls.ty.id) else {
bail!("Invalid metadata")
}
};
Some(calls_type.type_def.clone())
} else {
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)
}
/// 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
let mut user_calls_counter = 0;
let user_calls_pallets: RuntimeCalls = pallets
let user_calls_pallets: RuntimePallets = pallets
.iter()
.cloned()
.filter_map(|mut pallet| {
......@@ -222,7 +301,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
})
.collect();
let mut root_calls_counter = 0;
let root_calls_pallets: RuntimeCalls = pallets
let root_calls_pallets: RuntimePallets = pallets
.iter()
.cloned()
.filter_map(|mut pallet| {
......@@ -239,7 +318,7 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
})
.collect();
let mut disabled_calls_counter = 0;
let disabled_calls_pallets: RuntimeCalls = pallets
let disabled_calls_pallets: RuntimePallets = pallets
.iter()
.cloned()
.filter_map(|mut pallet| {
......@@ -256,6 +335,11 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
})
.collect();
let mut event_counter = 0;
pallets
.iter()
.for_each(|pallet| event_counter += pallet.events.len());
// compile template
let tera = match Tera::new(TEMPLATES_GLOB) {
Ok(t) => t,
......@@ -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();
context.insert("user_calls_counter", &user_calls_counter);
context.insert("user_calls_pallets", &user_calls_pallets);
......@@ -274,6 +358,17 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String {
context.insert("disabled_calls_counter", &disabled_calls_counter);
context.insert("disabled_calls_pallets", &disabled_calls_pallets);
tera.render("runtime-calls.md", &context)
.expect("template error")
let call_doc = tera
.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 @@
// 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/>.
mod gen_calls_doc;
mod gen_doc;
mod release_runtime;
use anyhow::{Context, Result};
......@@ -38,8 +38,8 @@ enum DuniterXTaskCommand {
#[clap(long)]
production: bool,
},
/// Generate calls documentation
GenCallsDoc,
/// Generate documentation (calls and events)
GenDoc,
/// Inject runtime code in raw specs
InjectRuntimeCode {
#[clap(short, long)]
......@@ -82,7 +82,7 @@ async fn main() -> Result<()> {
match args.command {
DuniterXTaskCommand::Build { production } => build(production),
DuniterXTaskCommand::GenCallsDoc => gen_calls_doc::gen_calls_doc(),
DuniterXTaskCommand::GenDoc => gen_doc::gen_doc(),
DuniterXTaskCommand::InjectRuntimeCode { runtime, raw_spec } => {
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