diff --git a/docs/api/runtime-calls.md b/docs/api/runtime-calls.md
index f6a2ddb8aa0aad99e8e3e4100924948699223373..39d58a35a791b50697c4845f3c0c9b9385214ea0 100644
--- a/docs/api/runtime-calls.md
+++ b/docs/api/runtime-calls.md
@@ -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>
 
diff --git a/docs/api/runtime-events.md b/docs/api/runtime-events.md
new file mode 100644
index 0000000000000000000000000000000000000000..e8f92c641daf786eb76b5a967399b072b6cde7da
--- /dev/null
+++ b/docs/api/runtime-events.md
@@ -0,0 +1,1880 @@
+# Runtime events
+
+There are **130** events from **37** pallets.
+
+<ul>
+<li>System - 0
+<ul>
+<li>
+<details>
+<summary>
+<code>ExtrinsicSuccess(dispatch_info)</code> - 0</summary>
+An extrinsic completed successfully.
+
+```rust
+dispatch_info: DispatchInfo
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ExtrinsicFailed(dispatch_error, dispatch_info)</code> - 1</summary>
+An extrinsic failed.
+
+```rust
+dispatch_error: DispatchError
+dispatch_info: DispatchInfo
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CodeUpdated()</code> - 2</summary>
+`:code` was updated.
+
+```rust
+no args
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NewAccount(account)</code> - 3</summary>
+A new account was created.
+
+```rust
+account: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>KilledAccount(account)</code> - 4</summary>
+An account was reaped.
+
+```rust
+account: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Remarked(sender, hash)</code> - 5</summary>
+On on-chain remark happened.
+
+```rust
+sender: T::AccountId
+hash: T::Hash
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Account - 1
+<ul>
+<li>
+<details>
+<summary>
+<code>ForceDestroy(who, balance)</code> - 0</summary>
+Force the destruction of an account because its free balance is insufficient to pay
+the account creation price.
+[who, balance]
+
+```rust
+who: T::AccountId
+balance: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RandomIdAssigned(who, random_id)</code> - 1</summary>
+Random id assigned
+[account_id, random_id]
+
+```rust
+who: T::AccountId
+random_id: H256
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>AccountLinked(who, identity)</code> - 2</summary>
+account linked to identity
+
+```rust
+who: T::AccountId
+identity: IdtyIdOf<T>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>AccountUnlinked()</code> - 3</summary>
+account unlinked from identity
+
+```rust
+: T::AccountId
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Scheduler - 2
+<ul>
+<li>
+<details>
+<summary>
+<code>Scheduled(when, index)</code> - 0</summary>
+Scheduled some task.
+
+```rust
+when: T::BlockNumber
+index: u32
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Canceled(when, index)</code> - 1</summary>
+Canceled some task.
+
+```rust
+when: T::BlockNumber
+index: u32
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Dispatched(task, id, result)</code> - 2</summary>
+Dispatched some task.
+
+```rust
+task: TaskAddress<T::BlockNumber>
+id: Option<TaskName>
+result: DispatchResult
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>CallUnavailable(task, id)</code> - 3</summary>
+The call for the provided hash was not found so the task has been aborted.
+
+```rust
+task: TaskAddress<T::BlockNumber>
+id: Option<TaskName>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PeriodicFailed(task, id)</code> - 4</summary>
+The given task was unable to be renewed since the agenda is full at that block.
+
+```rust
+task: TaskAddress<T::BlockNumber>
+id: Option<TaskName>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PermanentlyOverweight(task, id)</code> - 5</summary>
+The given task can never be executed since it is overweight.
+
+```rust
+task: TaskAddress<T::BlockNumber>
+id: Option<TaskName>
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Babe - 3
+<ul>
+</ul>
+</li>
+<li>Timestamp - 4
+<ul>
+</ul>
+</li>
+<li>Parameters - 5
+<ul>
+</ul>
+</li>
+<li>Balances - 6
+<ul>
+<li>
+<details>
+<summary>
+<code>Endowed(account, free_balance)</code> - 0</summary>
+An account was created with some free balance.
+
+```rust
+account: T::AccountId
+free_balance: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>DustLost(account, amount)</code> - 1</summary>
+An account was removed whose balance was non-zero but below ExistentialDeposit,
+resulting in an outright loss.
+
+```rust
+account: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Transfer(from, to, amount)</code> - 2</summary>
+Transfer succeeded.
+
+```rust
+from: T::AccountId
+to: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>BalanceSet(who, free)</code> - 3</summary>
+A balance was set by root.
+
+```rust
+who: T::AccountId
+free: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Reserved(who, amount)</code> - 4</summary>
+Some balance was reserved (moved from free to reserved).
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Unreserved(who, amount)</code> - 5</summary>
+Some balance was unreserved (moved from reserved to free).
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ReserveRepatriated(from, to, amount, destination_status)</code> - 6</summary>
+Some balance was moved from the reserve of the first account to the second account.
+Final argument indicates the destination balance type.
+
+```rust
+from: T::AccountId
+to: T::AccountId
+amount: T::Balance
+destination_status: Status
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Deposit(who, amount)</code> - 7</summary>
+Some amount was deposited (e.g. for transaction fees).
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Withdraw(who, amount)</code> - 8</summary>
+Some amount was withdrawn from the account (e.g. for transaction fees).
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Slashed(who, amount)</code> - 9</summary>
+Some amount was removed from the account (e.g. for misbehavior).
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Minted(who, amount)</code> - 10</summary>
+Some amount was minted into an account.
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Burned(who, amount)</code> - 11</summary>
+Some amount was burned from an account.
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Suspended(who, amount)</code> - 12</summary>
+Some amount was suspended from an account (it can be restored later).
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Restored(who, amount)</code> - 13</summary>
+Some amount was restored into an account.
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Upgraded(who)</code> - 14</summary>
+An account was upgraded.
+
+```rust
+who: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Issued(amount)</code> - 15</summary>
+Total issuance was increased by `amount`, creating a credit to be balanced.
+
+```rust
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Rescinded(amount)</code> - 16</summary>
+Total issuance was decreased by `amount`, creating a debt to be balanced.
+
+```rust
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Locked(who, amount)</code> - 17</summary>
+Some balance was locked.
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Unlocked(who, amount)</code> - 18</summary>
+Some balance was unlocked.
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Frozen(who, amount)</code> - 19</summary>
+Some balance was frozen.
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Thawed(who, amount)</code> - 20</summary>
+Some balance was thawed.
+
+```rust
+who: T::AccountId
+amount: T::Balance
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>TransactionPayment - 32
+<ul>
+<li>
+<details>
+<summary>
+<code>TransactionFeePaid(who, actual_fee, tip)</code> - 0</summary>
+A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee,
+has been paid by `who`.
+
+```rust
+who: T::AccountId
+actual_fee: BalanceOf<T>
+tip: BalanceOf<T>
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>OneshotAccount - 7
+<ul>
+<li>
+<details>
+<summary>
+<code>OneshotAccountCreated(account, balance, creator)</code> - 0</summary>
+
+
+```rust
+account: T::AccountId
+balance: <T::Currency as Currency<T::AccountId>>::Balance
+creator: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>OneshotAccountConsumed(account, dest1, dest2)</code> - 1</summary>
+
+
+```rust
+account: T::AccountId
+dest1: (T::AccountId,<T::Currency as Currency<T::AccountId>>::Balance,)
+dest2: Option<
+(T::AccountId,<T::Currency as Currency<T::AccountId>>::Balance,)
+>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Withdraw(account, balance)</code> - 2</summary>
+
+
+```rust
+account: T::AccountId
+balance: <T::Currency as Currency<T::AccountId>>::Balance
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Quota - 66
+<ul>
+<li>
+<details>
+<summary>
+<code>Refunded(who, identity, amount)</code> - 0</summary>
+Refunded fees to an account
+
+```rust
+who: T::AccountId
+identity: IdtyId<T>
+amount: BalanceOf<T>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NoQuotaForIdty()</code> - 1</summary>
+No quota for identity
+
+```rust
+: IdtyId<T>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>NoMoreCurrencyForRefund()</code> - 2</summary>
+No more currency available for refund
+
+```rust
+no args
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RefundFailed()</code> - 3</summary>
+Refund failed
+
+```rust
+: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RefundQueueFull()</code> - 4</summary>
+Refund queue full
+
+```rust
+no args
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>AuthorityMembers - 10
+<ul>
+<li>
+<details>
+<summary>
+<code>IncomingAuthorities()</code> - 0</summary>
+List of members who will enter the set of authorities at the next session.
+[Vec<member_id>]
+
+```rust
+: Vec<T::MemberId>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>OutgoingAuthorities()</code> - 1</summary>
+List of members who will leave the set of authorities at the next session.
+[Vec<member_id>]
+
+```rust
+: Vec<T::MemberId>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MemberGoOffline()</code> - 2</summary>
+A member will leave the set of authorities in 2 sessions.
+[member_id]
+
+```rust
+: T::MemberId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MemberGoOnline()</code> - 3</summary>
+A member will enter the set of authorities in 2 sessions.
+[member_id]
+
+```rust
+: T::MemberId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MemberRemoved()</code> - 4</summary>
+A member has lost the right to be part of the authorities,
+this member will be removed from the authority set in 2 sessions.
+[member_id]
+
+```rust
+: T::MemberId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MemberRemovedFromBlackList()</code> - 5</summary>
+A member has been removed from the blacklist.
+[member_id]
+
+```rust
+: T::MemberId
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Authorship - 11
+<ul>
+</ul>
+</li>
+<li>Offences - 12
+<ul>
+<li>
+<details>
+<summary>
+<code>Offence(kind, timeslot)</code> - 0</summary>
+There is an offence reported of the given `kind` happened at the `session_index` and
+(kind-specific) time slot. This event is not deposited for duplicate slashes.
+\[kind, timeslot\].
+
+```rust
+kind: Kind
+timeslot: OpaqueTimeSlot
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Historical - 13
+<ul>
+</ul>
+</li>
+<li>Session - 14
+<ul>
+<li>
+<details>
+<summary>
+<code>NewSession(session_index)</code> - 0</summary>
+New session has happened. Note that the argument is the session index, not the
+block number as the type might suggest.
+
+```rust
+session_index: SessionIndex
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Grandpa - 15
+<ul>
+<li>
+<details>
+<summary>
+<code>NewAuthorities(authority_set)</code> - 0</summary>
+New authority set has been applied.
+
+```rust
+authority_set: AuthorityList
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Paused()</code> - 1</summary>
+Current authority set has been paused.
+
+```rust
+no args
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Resumed()</code> - 2</summary>
+Current authority set has been resumed.
+
+```rust
+no args
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>ImOnline - 16
+<ul>
+<li>
+<details>
+<summary>
+<code>HeartbeatReceived(authority_id)</code> - 0</summary>
+A new heartbeat was received from `AuthorityId`.
+
+```rust
+authority_id: T::AuthorityId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>AllGood()</code> - 1</summary>
+At the end of the session, no offence was committed.
+
+```rust
+no args
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SomeOffline(offline)</code> - 2</summary>
+At the end of the session, at least one validator was found to be offline.
+
+```rust
+offline: Vec<IdentificationTuple<T>>
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>AuthorityDiscovery - 17
+<ul>
+</ul>
+</li>
+<li>Sudo - 20
+<ul>
+<li>
+<details>
+<summary>
+<code>Sudid(sudo_result)</code> - 0</summary>
+A sudo just took place. \[result\]
+
+```rust
+sudo_result: DispatchResult
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>KeyChanged(old_sudoer)</code> - 1</summary>
+The \[sudoer\] just switched identity; the old key is supplied if one existed.
+
+```rust
+old_sudoer: Option<T::AccountId>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SudoAsDone(sudo_result)</code> - 2</summary>
+A sudo just took place. \[result\]
+
+```rust
+sudo_result: DispatchResult
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>UpgradeOrigin - 21
+<ul>
+<li>
+<details>
+<summary>
+<code>DispatchedAsRoot(result)</code> - 0</summary>
+A call was dispatched as root from an upgradable origin
+
+```rust
+result: DispatchResult
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Preimage - 22
+<ul>
+<li>
+<details>
+<summary>
+<code>Noted(hash)</code> - 0</summary>
+A preimage has been noted.
+
+```rust
+hash: T::Hash
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Requested(hash)</code> - 1</summary>
+A preimage has been requested.
+
+```rust
+hash: T::Hash
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Cleared(hash)</code> - 2</summary>
+A preimage has ben cleared.
+
+```rust
+hash: T::Hash
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>TechnicalCommittee - 23
+<ul>
+<li>
+<details>
+<summary>
+<code>Proposed(account, proposal_index, proposal_hash, threshold)</code> - 0</summary>
+A motion (given hash) has been proposed (by given account) with a threshold (given
+`MemberCount`).
+
+```rust
+account: T::AccountId
+proposal_index: ProposalIndex
+proposal_hash: T::Hash
+threshold: MemberCount
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Voted(account, proposal_hash, voted, yes, no)</code> - 1</summary>
+A motion (given hash) has been voted on by given account, leaving
+a tally (yes votes and no votes given respectively as `MemberCount`).
+
+```rust
+account: T::AccountId
+proposal_hash: T::Hash
+voted: bool
+yes: MemberCount
+no: MemberCount
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Approved(proposal_hash)</code> - 2</summary>
+A motion was approved by the required threshold.
+
+```rust
+proposal_hash: T::Hash
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Disapproved(proposal_hash)</code> - 3</summary>
+A motion was not approved by the required threshold.
+
+```rust
+proposal_hash: T::Hash
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Executed(proposal_hash, result)</code> - 4</summary>
+A motion was executed; result will be `Ok` if it returned without error.
+
+```rust
+proposal_hash: T::Hash
+result: DispatchResult
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MemberExecuted(proposal_hash, result)</code> - 5</summary>
+A single member did some action; result will be `Ok` if it returned without error.
+
+```rust
+proposal_hash: T::Hash
+result: DispatchResult
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Closed(proposal_hash, yes, no)</code> - 6</summary>
+A proposal was closed because its threshold was reached or after its duration was up.
+
+```rust
+proposal_hash: T::Hash
+yes: MemberCount
+no: MemberCount
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>UniversalDividend - 30
+<ul>
+<li>
+<details>
+<summary>
+<code>NewUdCreated(amount, index, monetary_mass, members_count)</code> - 0</summary>
+A new universal dividend is created.
+
+```rust
+amount: BalanceOf<T>
+index: UdIndex
+monetary_mass: BalanceOf<T>
+members_count: BalanceOf<T>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>UdReevalued(new_ud_amount, monetary_mass, members_count)</code> - 1</summary>
+The universal dividend has been re-evaluated.
+
+```rust
+new_ud_amount: BalanceOf<T>
+monetary_mass: BalanceOf<T>
+members_count: BalanceOf<T>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>UdsAutoPaidAtRemoval(count, total, who)</code> - 2</summary>
+DUs were automatically transferred as part of a member removal.
+
+```rust
+count: UdIndex
+total: BalanceOf<T>
+who: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>UdsClaimed(count, total, who)</code> - 3</summary>
+A member claimed his UDs.
+
+```rust
+count: UdIndex
+total: BalanceOf<T>
+who: T::AccountId
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Wot - 40
+<ul>
+</ul>
+</li>
+<li>Identity - 41
+<ul>
+<li>
+<details>
+<summary>
+<code>IdtyCreated(idty_index, owner_key)</code> - 0</summary>
+A new identity has been created
+[idty_index, owner_key]
+
+```rust
+idty_index: T::IdtyIndex
+owner_key: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdtyConfirmed(idty_index, owner_key, name)</code> - 1</summary>
+An identity has been confirmed by its owner
+[idty_index, owner_key, name]
+
+```rust
+idty_index: T::IdtyIndex
+owner_key: T::AccountId
+name: IdtyName
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdtyValidated(idty_index)</code> - 2</summary>
+An identity has been validated
+[idty_index]
+
+```rust
+idty_index: T::IdtyIndex
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdtyChangedOwnerKey(idty_index, new_owner_key)</code> - 3</summary>
+
+
+```rust
+idty_index: T::IdtyIndex
+new_owner_key: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>IdtyRemoved(idty_index, reason)</code> - 4</summary>
+An identity has been removed
+[idty_index]
+
+```rust
+idty_index: T::IdtyIndex
+reason: IdtyRemovalReason<T::IdtyRemovalOtherReason>
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Membership - 42
+<ul>
+<li>
+<details>
+<summary>
+<code>MembershipAcquired()</code> - 0</summary>
+A membership was acquired
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipExpired()</code> - 1</summary>
+A membership expired
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipRenewed()</code> - 2</summary>
+A membership was renewed
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipRequested()</code> - 3</summary>
+An membership was requested
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipRevoked()</code> - 4</summary>
+A membership was revoked
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingMembershipExpired()</code> - 5</summary>
+A pending membership request has expired
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Cert - 43
+<ul>
+<li>
+<details>
+<summary>
+<code>NewCert(issuer, issuer_issued_count, receiver, receiver_received_count)</code> - 0</summary>
+New certification
+[issuer, issuer_issued_count, receiver, receiver_received_count]
+
+```rust
+issuer: T::IdtyIndex
+issuer_issued_count: u32
+receiver: T::IdtyIndex
+receiver_received_count: u32
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RemovedCert(issuer, issuer_issued_count, receiver, receiver_received_count, expiration)</code> - 1</summary>
+Removed certification
+[issuer, issuer_issued_count, receiver, receiver_received_count, expiration]
+
+```rust
+issuer: T::IdtyIndex
+issuer_issued_count: u32
+receiver: T::IdtyIndex
+receiver_received_count: u32
+expiration: bool
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RenewedCert(issuer, receiver)</code> - 2</summary>
+Renewed certification
+[issuer, receiver]
+
+```rust
+issuer: T::IdtyIndex
+receiver: T::IdtyIndex
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Distance - 44
+<ul>
+</ul>
+</li>
+<li>SmithSubWot - 50
+<ul>
+</ul>
+</li>
+<li>SmithMembership - 52
+<ul>
+<li>
+<details>
+<summary>
+<code>MembershipAcquired()</code> - 0</summary>
+A membership was acquired
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipExpired()</code> - 1</summary>
+A membership expired
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipRenewed()</code> - 2</summary>
+A membership was renewed
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipRequested()</code> - 3</summary>
+An membership was requested
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MembershipRevoked()</code> - 4</summary>
+A membership was revoked
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PendingMembershipExpired()</code> - 5</summary>
+A pending membership request has expired
+[idty_id]
+
+```rust
+: T::IdtyId
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>SmithCert - 53
+<ul>
+<li>
+<details>
+<summary>
+<code>NewCert(issuer, issuer_issued_count, receiver, receiver_received_count)</code> - 0</summary>
+New certification
+[issuer, issuer_issued_count, receiver, receiver_received_count]
+
+```rust
+issuer: T::IdtyIndex
+issuer_issued_count: u32
+receiver: T::IdtyIndex
+receiver_received_count: u32
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RemovedCert(issuer, issuer_issued_count, receiver, receiver_received_count, expiration)</code> - 1</summary>
+Removed certification
+[issuer, issuer_issued_count, receiver, receiver_received_count, expiration]
+
+```rust
+issuer: T::IdtyIndex
+issuer_issued_count: u32
+receiver: T::IdtyIndex
+receiver_received_count: u32
+expiration: bool
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RenewedCert(issuer, receiver)</code> - 2</summary>
+Renewed certification
+[issuer, receiver]
+
+```rust
+issuer: T::IdtyIndex
+receiver: T::IdtyIndex
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>AtomicSwap - 60
+<ul>
+<li>
+<details>
+<summary>
+<code>NewSwap(account, proof, swap)</code> - 0</summary>
+Swap created.
+
+```rust
+account: T::AccountId
+proof: HashedProof
+swap: PendingSwap<T>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SwapClaimed(account, proof, success)</code> - 1</summary>
+Swap claimed. The last parameter indicates whether the execution succeeds.
+
+```rust
+account: T::AccountId
+proof: HashedProof
+success: bool
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SwapCancelled(account, proof)</code> - 2</summary>
+Swap cancelled.
+
+```rust
+account: T::AccountId
+proof: HashedProof
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Multisig - 61
+<ul>
+<li>
+<details>
+<summary>
+<code>NewMultisig(approving, multisig, call_hash)</code> - 0</summary>
+A new multisig operation has begun.
+
+```rust
+approving: T::AccountId
+multisig: T::AccountId
+call_hash: CallHash
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MultisigApproval(approving, timepoint, multisig, call_hash)</code> - 1</summary>
+A multisig operation has been approved by someone.
+
+```rust
+approving: T::AccountId
+timepoint: Timepoint<T::BlockNumber>
+multisig: T::AccountId
+call_hash: CallHash
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MultisigExecuted(approving, timepoint, multisig, call_hash, result)</code> - 2</summary>
+A multisig operation has been executed.
+
+```rust
+approving: T::AccountId
+timepoint: Timepoint<T::BlockNumber>
+multisig: T::AccountId
+call_hash: CallHash
+result: DispatchResult
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>MultisigCancelled(cancelling, timepoint, multisig, call_hash)</code> - 3</summary>
+A multisig operation has been cancelled.
+
+```rust
+cancelling: T::AccountId
+timepoint: Timepoint<T::BlockNumber>
+multisig: T::AccountId
+call_hash: CallHash
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>ProvideRandomness - 62
+<ul>
+<li>
+<details>
+<summary>
+<code>FilledRandomness(request_id, randomness)</code> - 0</summary>
+Filled randomness
+
+```rust
+request_id: RequestId
+randomness: H256
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>RequestedRandomness(request_id, salt, r#type)</code> - 1</summary>
+Requested randomness
+
+```rust
+request_id: RequestId
+salt: H256
+r#type: RandomnessType
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Proxy - 63
+<ul>
+<li>
+<details>
+<summary>
+<code>ProxyExecuted(result)</code> - 0</summary>
+A proxy was executed correctly, with the given.
+
+```rust
+result: DispatchResult
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>PureCreated(pure, who, proxy_type, disambiguation_index)</code> - 1</summary>
+A pure account has been created by new proxy with given
+disambiguation index and proxy type.
+
+```rust
+pure: T::AccountId
+who: T::AccountId
+proxy_type: T::ProxyType
+disambiguation_index: u16
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Announced(real, proxy, call_hash)</code> - 2</summary>
+An announcement was placed to make a call in the future.
+
+```rust
+real: T::AccountId
+proxy: T::AccountId
+call_hash: CallHashOf<T>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ProxyAdded(delegator, delegatee, proxy_type, delay)</code> - 3</summary>
+A proxy was added.
+
+```rust
+delegator: T::AccountId
+delegatee: T::AccountId
+proxy_type: T::ProxyType
+delay: T::BlockNumber
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ProxyRemoved(delegator, delegatee, proxy_type, delay)</code> - 4</summary>
+A proxy was removed.
+
+```rust
+delegator: T::AccountId
+delegatee: T::AccountId
+proxy_type: T::ProxyType
+delay: T::BlockNumber
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Utility - 64
+<ul>
+<li>
+<details>
+<summary>
+<code>BatchInterrupted(index, error)</code> - 0</summary>
+Batch of dispatches did not complete fully. Index of first failing dispatch given, as
+well as the error.
+
+```rust
+index: u32
+error: DispatchError
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>BatchCompleted()</code> - 1</summary>
+Batch of dispatches completed fully with no error.
+
+```rust
+no args
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>BatchCompletedWithErrors()</code> - 2</summary>
+Batch of dispatches completed but has errors.
+
+```rust
+no args
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ItemCompleted()</code> - 3</summary>
+A single item within a Batch of dispatches has completed with no error.
+
+```rust
+no args
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>ItemFailed(error)</code> - 4</summary>
+A single item within a Batch of dispatches has completed with error.
+
+```rust
+error: DispatchError
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>DispatchedAs(result)</code> - 5</summary>
+A call was dispatched.
+
+```rust
+result: DispatchResult
+```
+
+</details>
+</li>
+</ul>
+</li>
+<li>Treasury - 65
+<ul>
+<li>
+<details>
+<summary>
+<code>Proposed(proposal_index)</code> - 0</summary>
+New proposal.
+
+```rust
+proposal_index: ProposalIndex
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Spending(budget_remaining)</code> - 1</summary>
+We have ended a spend period and will now allocate funds.
+
+```rust
+budget_remaining: BalanceOf<T, I>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Awarded(proposal_index, award, account)</code> - 2</summary>
+Some funds have been allocated.
+
+```rust
+proposal_index: ProposalIndex
+award: BalanceOf<T, I>
+account: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Rejected(proposal_index, slashed)</code> - 3</summary>
+A proposal was rejected; funds were slashed.
+
+```rust
+proposal_index: ProposalIndex
+slashed: BalanceOf<T, I>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Burnt(burnt_funds)</code> - 4</summary>
+Some of our funds have been burnt.
+
+```rust
+burnt_funds: BalanceOf<T, I>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Rollover(rollover_balance)</code> - 5</summary>
+Spending has finished; this is the amount that rolls over until next spend.
+
+```rust
+rollover_balance: BalanceOf<T, I>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>Deposit(value)</code> - 6</summary>
+Some funds have been deposited.
+
+```rust
+value: BalanceOf<T, I>
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>SpendApproved(proposal_index, amount, beneficiary)</code> - 7</summary>
+A new spend proposal has been approved.
+
+```rust
+proposal_index: ProposalIndex
+amount: BalanceOf<T, I>
+beneficiary: T::AccountId
+```
+
+</details>
+</li>
+<li>
+<details>
+<summary>
+<code>UpdatedInactive(reactivated, deactivated)</code> - 8</summary>
+The inactive funds of the pallet have been updated.
+
+```rust
+reactivated: BalanceOf<T, I>
+deactivated: BalanceOf<T, I>
+```
+
+</details>
+</li>
+</ul>
+</li>
+</ul>
\ No newline at end of file
diff --git a/xtask/res/templates/runtime-events.md b/xtask/res/templates/runtime-events.md
new file mode 100644
index 0000000000000000000000000000000000000000..6c612bc8a784865ad6b7974a420b3e4a05e6690d
--- /dev/null
+++ b/xtask/res/templates/runtime-events.md
@@ -0,0 +1,33 @@
+# 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
diff --git a/xtask/src/gen_calls_doc.rs b/xtask/src/gen_doc.rs
similarity index 64%
rename from xtask/src/gen_calls_doc.rs
rename to xtask/src/gen_doc.rs
index c1c03b3c9c44cc3fd3f8f712c558ff4f4151d027..5fb1f56a36a683663812f6f6cdb4c91dad90ce75 100644
--- a/xtask/src/gen_calls_doc.rs
+++ b/xtask/src/gen_doc.rs
@@ -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)
 }
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index e29fbe9ae66604c62731d4ea12ce05e8c097e1c7..331bab7a9edb1333687885206eb2fd0d5ce34371 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -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)
         }