diff --git a/README.md b/README.md
index 3d278023c3c6d034add252f09a1c7a43b60e3c46..267fb59d6c7c7963dac0da1221bf83adb383c9df 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Duniter-Squid
 
 A [Squid](https://subsquid.io)-based indexer.
-It takes [ĞDev](https://kusama.network) data and serves it via GraphQL API.
+It takes [ĞDev](https://forum.duniter.org/c/currencies/gdev/63) data and serves it via GraphQL API.
 
 ## Dev requirements
 
@@ -107,9 +107,7 @@ See https://duniter.org/wiki/duniter-v2/indexers/duniter-squid/
 
 ## TODO
 
-- [ ] Refac way to process data from events (new, fetch needed...)
-- [ ] Use cache abilities
-- [ ] Look if it is possible to add relation without fetching endpoints
+- [x] Refac way to process data from events (new, fetch needed...)
 - [ ] Add events:
   - [ ] identity.IdtyCreated
   - [ ] identity.IdtyConfirmed
diff --git a/src/genesis.ts b/src/genesis.ts
index a0e51900dcbbcb634f53d1818da8a66ca1f75f7e..3222780ef5e45486e5328fc744836ad33599071e 100644
--- a/src/genesis.ts
+++ b/src/genesis.ts
@@ -111,7 +111,7 @@ export async function saveGenesis(ctx: ProcessorContext<StoreWithCache>) {
     identities.set(
       idty.index,
       new Identity({
-        id: String(idty.name),
+        id: String(idty.index),
         index: idty.index,
         account: accounts.get(idty.value.owner_key),
         name: idty.name,
@@ -177,6 +177,7 @@ export async function saveGenesis(ctx: ProcessorContext<StoreWithCache>) {
   await ctx.store.insert(smithCerts);
   await ctx.store.insert(memberships);
   await ctx.store.insert(smithMemberships);
+  // await ctx.store.flush(); // do not flush otherwise we lose cache
 
   ctx.log.info("Genesis saved");
 
@@ -208,14 +209,13 @@ export async function saveGenesis(ctx: ProcessorContext<StoreWithCache>) {
   // const unknown_wallets = wallets.difference(genesis_wallets)
   let unknown_wallets = new Set([...all_wallets].filter((x) => !accounts.has(x)));
   ctx.log.info(`There are ${accounts.size} genesis wallets, ${all_wallets.size} total wallets, ${unknown_wallets.size} unknown wallets`);
-  if (unknown_wallets.size != 0) {
-    for (const address of unknown_wallets) {
-      let account = new Account({
-        id: address,
-      });
-      accounts.set(address, account);
-      other_accounts.set(address, account);
-    }
+  // create accounts for unknown wallets
+  for (const address of unknown_wallets) {
+    let account = new Account({
+      id: address,
+    });
+    accounts.set(address, account);
+    other_accounts.set(address, account);
   }
 
   // add txs
@@ -246,6 +246,7 @@ export async function saveGenesis(ctx: ProcessorContext<StoreWithCache>) {
   ctx.log.info("Saving transaction history");
   await ctx.store.insert([...other_accounts.values()]);
   await ctx.store.insert(genesis_transfers);
+  await ctx.store.flush();
   ctx.log.info("Saved transaction history");
   ctx.log.info("======================");
   ctx.log.info("Starting blockchain indexing");
diff --git a/src/main.ts b/src/main.ts
index a2eb3803f5996098bec1396dc63703560864f1ee..b2c4ef01427bb850e6101fb2eb296a6a5f657c03 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,13 +1,11 @@
 // import { TypeormDatabase, Store } from "@subsquid/typeorm-store";
 import { StoreWithCache, TypeormDatabaseWithCache } from "@belopash/typeorm-store";
-import { In } from "typeorm";
 import * as ss58 from "@subsquid/ss58";
 import assert from "assert";
 
 import { processor, ProcessorContext } from "./processor";
 import { Account, Cert, Identity, Transfer } from "./model";
 import { events as events_t, calls as calls_t } from "./types";
-import { string } from "./model/generated/marshal";
 
 import { saveBlock, saveExtrinsic, saveCall, saveEvent } from "./giant-squid";
 import { saveGenesis } from "./genesis";
@@ -38,26 +36,26 @@ processor.run(new TypeormDatabaseWithCache(), async (ctx) => {
     }
   }
 
+  // collect new data from events
   let ndata: NewData = {
     accounts: [],
-    identitiesCreated: [],
+    identities: [],
     idtyChangedOwnerKey: [],
     transfers: [],
     certs: [],
   };
   getNewData(ctx, ndata);
 
+  // transform new data to objects
   let prepared: PreparedData = {
     accounts: new Map(),
-    newAccounts: [],
     identities: new Map(),
-    newIdentities: [],
-    changedIdentities: [],
     transfers: [],
     certs: [],
   };
   await prepareData(ctx, ndata, prepared);
 
+  // store data
   await storeData(ctx, prepared);
 });
 
@@ -67,9 +65,10 @@ export type IdtyIndex = number;
 type BlockNumber = number;
 
 // a way to group data returned from events
+// this contains partial data to be turned into types
 interface NewData {
   accounts: Address[];
-  identitiesCreated: IdtyCreatedEvent[];
+  identities: IdtyCreatedEvent[];
   idtyChangedOwnerKey: IdtyChangedOwnerKeyEvent[];
   transfers: TransferEvent[];
   certs: CertEvent[];
@@ -101,31 +100,38 @@ interface IdtyChangedOwnerKeyEvent {
 
 // a way to group data prepared for database insertion
 interface PreparedData {
-  // all accounts that other entities point to
   accounts: Map<Address, Account>;
-  // non existing accounts to add in the database before transactions and identites
-  newAccounts: Account[];
-  // all identities that other entities point to or which might have changed
   identities: Map<IdtyIndex, Identity>;
-  // non existing identities to add in the database before certifications and memberships
-  newIdentities: Identity[];
-  // existing identities that have changed
-  changedIdentities: Identity[];
-  // transfers
   transfers: Transfer[];
-  // certifications
   certs: Cert[];
 }
 
 /// fill data with data collected from events
 function getNewData(ctx: ProcessorContext<StoreWithCache>, ndata: NewData) {
+  const silence_events = [
+    events_t.system.extrinsicSuccess.name,
+    events_t.system.killedAccount.name,
+    events_t.cert.removedCert.name,
+    events_t.session.newSession.name,
+    events_t.imOnline.allGood.name,
+    events_t.membership.membershipExpired.name,
+    events_t.universalDividend.udsAutoPaidAtRemoval.name,
+    events_t.universalDividend.newUdCreated.name,
+    events_t.balances.withdraw.name,
+    events_t.balances.deposit.name,
+    events_t.transactionPayment.transactionFeePaid.name,
+    events_t.identity.idtyRemoved.name,
+    events_t.quota.refunded.name,
+  ];
   // ===== Blocks =====
 
   for (let block of ctx.blocks) {
     // ===== Events =====
 
     for (let event of block.events) {
-      ctx.log.debug(event.name);
+      if (!silence_events.includes(event.name)) {
+        ctx.log.info("" + block.header.height + " " + event.name);
+      }
       switch (event.name) {
         // ===== System.NewAccount
         case events_t.system.newAccount.name:
@@ -165,7 +171,7 @@ function getNewData(ctx: ProcessorContext<StoreWithCache>, ndata: NewData) {
           } else {
             throw new Error("Unsupported spec");
           }
-          ndata.identitiesCreated.push({
+          ndata.identities.push({
             id: event.id,
             index: newI.idtyIndex,
             account: ss58.codec(42).encode(newI.ownerKey),
@@ -231,19 +237,18 @@ async function prepareData(ctx: ProcessorContext<StoreWithCache>, newData: NewDa
   await createAccounts(ctx, newData, data);
   await createIdentities(ctx, newData, data);
   await changeIdtyOwnerKey(ctx, newData, data);
-  createTransfers(newData, data);
-  createCerts(newData, data);
+  await createTransfers(ctx, newData, data);
+  await createCerts(ctx, newData, data);
 }
 
 /// store prepared data into database
 async function storeData(ctx: ProcessorContext<StoreWithCache>, data: PreparedData) {
   // UPSERT = update or insert if not existing
   // account can have already existed, been killed, and recreated
-  await ctx.store.upsert(data.newAccounts);
-  // identities which have changed
-  await ctx.store.upsert([...data.changedIdentities.values()]);
+  await ctx.store.upsert([...data.accounts.values()]);
+  // identities can have been changed (change owner key)
+  await ctx.store.upsert([...data.identities.values()]);
   // INSERT
-  await ctx.store.insert([...data.newIdentities.values()]);
   await ctx.store.insert(data.transfers);
   await ctx.store.insert(data.certs);
 }
@@ -251,89 +256,40 @@ async function storeData(ctx: ProcessorContext<StoreWithCache>, data: PreparedDa
 // ===== create new instances if not existing in database =====
 
 async function createAccounts(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
-  // collect all accounts from transfers that we need to fetch
-  // accounts can only be created from a transfer
-  const accountIds = new Set<Address>();
-  for (let t of newData.transfers) {
-    accountIds.add(t.from);
-    accountIds.add(t.to);
-  }
   // system will tell when accounts are created (but this should be added above)
-  for (let a of newData.accounts) {
-    accountIds.add(a);
-  }
-  // fill the map of accounts with those that are already stored
-  await ctx.store.findBy(Account, { id: In([...accountIds]) }).then((accounts) => {
-    accounts.map((a) => data.accounts.set(a.id, a));
-  });
-  // for each account, add an account if not already existing (not found above)
-  for (let a of accountIds) {
-    updateAccounts(a);
-  }
-  // function to add inexisting accounts to the map
-  function updateAccounts(id: Address): void {
-    const acc = data.accounts.get(id);
-    if (acc == null) {
-      let newA = new Account({ id });
-      data.accounts.set(id, newA);
-      data.newAccounts.push(newA);
-    }
+  for (let id of newData.accounts) {
+    let newA = new Account({ id });
+    data.accounts.set(id, newA);
+    ctx.log.info(`added account ${id}`);
   }
 }
 
 async function createIdentities(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
-  const idtyIds = new Set<IdtyIndex>();
-  for (let c of newData.certs) {
-    idtyIds.add(c.issuer);
-    idtyIds.add(c.receiver);
-  }
-  await ctx.store.findBy(Identity, { index: In([...idtyIds]) }).then((idties) => {
-    idties.map((i) => data.identities.set(i.index, i));
-  });
-  for (let i of newData.identitiesCreated) {
-    let account = data.accounts.get(i.account);
+  for (let i of newData.identities) {
+    let account = await ctx.store.getOrFail(Account, i.account);
     let newI = new Identity({
       id: String(i.index),
       index: i.index,
       account,
-      name: "<created>",
     });
     data.identities.set(i.index, newI);
-    data.newIdentities.push(newI);
   }
 }
 
 async function changeIdtyOwnerKey(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
-  const idtyIds = new Set<IdtyIndex>();
-  const accountIds = new Set<Address>();
-  for (let i of newData.idtyChangedOwnerKey) {
-    idtyIds.add(i.index);
-    accountIds.add(i.account);
-  }
-  // TODO avoid fetching multiple times
-  await ctx.store.findBy(Identity, { index: In([...idtyIds]) }).then((idties) => {
-    idties.map((i) => data.identities.set(i.index, i));
-  });
-  await ctx.store.findBy(Account, { id: In([...accountIds]) }).then((accounts) => {
-    accounts.map((a) => data.accounts.set(a.id, a));
-  });
-  for (let i of newData.idtyChangedOwnerKey) {
-    let idty = data.identities.get(i.index);
-    let account = data.accounts.get(i.account);
-    if (idty && account) {
-      idty.account = account;
-      data.changedIdentities.push(idty);
-    } else {
-      ctx.log.error(`changed owner key to non existing account ${account} or identity ${idty}`);
-    }
+  for (let icok of newData.idtyChangedOwnerKey) {
+    let idty = await ctx.store.getOrFail(Identity, String(icok.index));
+    let account = await ctx.store.getOrFail(Account, icok.account);
+    idty.account = account;
+    data.identities.set(idty.index, idty);
   }
 }
 
-function createTransfers(newData: NewData, data: PreparedData) {
+async function createTransfers(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
   for (let t of newData.transfers) {
     let { id, blockNumber, timestamp, amount } = t;
-    let from = data.accounts.get(t.from);
-    let to = data.accounts.get(t.to);
+    let from = data.accounts.get(t.from) ?? (await ctx.store.getOrFail(Account, t.from));
+    let to = data.accounts.get(t.to) ?? (await ctx.store.getOrFail(Account, t.to));
     data.transfers.push(
       new Transfer({
         id,
@@ -347,11 +303,11 @@ function createTransfers(newData: NewData, data: PreparedData) {
   }
 }
 
-function createCerts(newData: NewData, data: PreparedData) {
+async function createCerts(ctx: ProcessorContext<StoreWithCache>, newData: NewData, data: PreparedData) {
   for (let c of newData.certs) {
     let { id, blockNumber, issuer, receiver } = c;
-    let issuerIdty = data.identities.get(issuer);
-    let receiverIdty = data.identities.get(receiver);
+    let issuerIdty = data.identities.get(issuer) ?? await ctx.store.getOrFail(Identity, String(issuer));
+    let receiverIdty = data.identities.get(receiver) ?? await ctx.store.getOrFail(Identity, String(receiver));
     data.certs.push(
       new Cert({
         id,
diff --git a/src/types/calls.ts b/src/types/calls.ts
index e2191a5ca5e60d1ba225271e26669be55797789b..dfd6803f971a99130057f729d6d80826771c9aeb 100644
--- a/src/types/calls.ts
+++ b/src/types/calls.ts
@@ -2,6 +2,9 @@ export * as system from './system/calls'
 export * as timestamp from './timestamp/calls'
 export * as balances from './balances/calls'
 export * as authorityMembers from './authority-members/calls'
+export * as session from './session/calls'
+export * as imOnline from './im-online/calls'
+export * as universalDividend from './universal-dividend/calls'
 export * as identity from './identity/calls'
 export * as membership from './membership/calls'
 export * as cert from './cert/calls'
diff --git a/src/types/constants.ts b/src/types/constants.ts
index 4ca57551fd93baff0568e64f4396693d961f06ea..96c32d36067876d2cebc1150bbb30090dd61d4da 100644
--- a/src/types/constants.ts
+++ b/src/types/constants.ts
@@ -1,7 +1,11 @@
 export * as system from './system/constants'
 export * as timestamp from './timestamp/constants'
 export * as balances from './balances/constants'
+export * as transactionPayment from './transaction-payment/constants'
+export * as quota from './quota/constants'
 export * as authorityMembers from './authority-members/constants'
+export * as imOnline from './im-online/constants'
+export * as universalDividend from './universal-dividend/constants'
 export * as identity from './identity/constants'
 export * as membership from './membership/constants'
 export * as cert from './cert/constants'
diff --git a/src/types/events.ts b/src/types/events.ts
index 33fdac0df99c82e0114645b3ff883754ab47371a..79d8b78a7dc610c45d73bd093e0dc0d43b094d22 100644
--- a/src/types/events.ts
+++ b/src/types/events.ts
@@ -1,6 +1,11 @@
 export * as system from './system/events'
 export * as balances from './balances/events'
+export * as transactionPayment from './transaction-payment/events'
+export * as quota from './quota/events'
 export * as authorityMembers from './authority-members/events'
+export * as session from './session/events'
+export * as imOnline from './im-online/events'
+export * as universalDividend from './universal-dividend/events'
 export * as identity from './identity/events'
 export * as membership from './membership/events'
 export * as cert from './cert/events'
diff --git a/src/types/im-online/calls.ts b/src/types/im-online/calls.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fe5d10ad18bb9db40cf713c92c3b4f8a824dadc8
--- /dev/null
+++ b/src/types/im-online/calls.ts
@@ -0,0 +1,20 @@
+import {sts, Block, Bytes, Option, Result, CallType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const heartbeat =  {
+    name: 'ImOnline.heartbeat',
+    /**
+     * ## Complexity:
+     * - `O(K + E)` where K is length of `Keys` (heartbeat.validators_len) and E is length of
+     *   `heartbeat.network_state.external_address`
+     *   - `O(K)`: decoding of length `K`
+     *   - `O(E)`: decoding/encoding of length `E`
+     */
+    v700: new CallType(
+        'ImOnline.heartbeat',
+        sts.struct({
+            heartbeat: v700.Heartbeat,
+            signature: sts.bytes(),
+        })
+    ),
+}
diff --git a/src/types/im-online/constants.ts b/src/types/im-online/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b366a47b1f3a6815eab906bce0ab5e0e489aedd
--- /dev/null
+++ b/src/types/im-online/constants.ts
@@ -0,0 +1,14 @@
+import {sts, Block, Bytes, Option, Result, ConstantType, RuntimeCtx} from '../support'
+
+export const unsignedPriority =  {
+    /**
+     *  A configuration for base priority of unsigned transactions.
+     * 
+     *  This is exposed so that it can be tuned for particular runtime, when
+     *  multiple pallets send unsigned transactions.
+     */
+    v700: new ConstantType(
+        'ImOnline.UnsignedPriority',
+        sts.bigint()
+    ),
+}
diff --git a/src/types/im-online/events.ts b/src/types/im-online/events.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1bb050352af4016aafad3f9a95e3dc9850edb4d8
--- /dev/null
+++ b/src/types/im-online/events.ts
@@ -0,0 +1,39 @@
+import {sts, Block, Bytes, Option, Result, EventType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const heartbeatReceived =  {
+    name: 'ImOnline.HeartbeatReceived',
+    /**
+     * A new heartbeat was received from `AuthorityId`.
+     */
+    v700: new EventType(
+        'ImOnline.HeartbeatReceived',
+        sts.struct({
+            authorityId: sts.bytes(),
+        })
+    ),
+}
+
+export const allGood =  {
+    name: 'ImOnline.AllGood',
+    /**
+     * At the end of the session, no offence was committed.
+     */
+    v700: new EventType(
+        'ImOnline.AllGood',
+        sts.unit()
+    ),
+}
+
+export const someOffline =  {
+    name: 'ImOnline.SomeOffline',
+    /**
+     * At the end of the session, at least one validator was found to be offline.
+     */
+    v700: new EventType(
+        'ImOnline.SomeOffline',
+        sts.struct({
+            offline: sts.array(() => sts.tuple(() => [v700.AccountId32, v700.ValidatorFullIdentification])),
+        })
+    ),
+}
diff --git a/src/types/im-online/storage.ts b/src/types/im-online/storage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7d3b6d86c840313f2339870d919588c91b148e64
--- /dev/null
+++ b/src/types/im-online/storage.ts
@@ -0,0 +1,115 @@
+import {sts, Block, Bytes, Option, Result, StorageType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const heartbeatAfter =  {
+    /**
+     *  The block number after which it's ok to send heartbeats in the current
+     *  session.
+     * 
+     *  At the beginning of each session we set this to a value that should fall
+     *  roughly in the middle of the session duration. The idea is to first wait for
+     *  the validators to produce a block in the current session, so that the
+     *  heartbeat later on will not be necessary.
+     * 
+     *  This value will only be used as a fallback if we fail to get a proper session
+     *  progress estimate from `NextSessionRotation`, as those estimates should be
+     *  more accurate then the value we calculate for `HeartbeatAfter`.
+     */
+    v700: new StorageType('ImOnline.HeartbeatAfter', 'Default', [], sts.number()) as HeartbeatAfterV700,
+}
+
+/**
+ *  The block number after which it's ok to send heartbeats in the current
+ *  session.
+ * 
+ *  At the beginning of each session we set this to a value that should fall
+ *  roughly in the middle of the session duration. The idea is to first wait for
+ *  the validators to produce a block in the current session, so that the
+ *  heartbeat later on will not be necessary.
+ * 
+ *  This value will only be used as a fallback if we fail to get a proper session
+ *  progress estimate from `NextSessionRotation`, as those estimates should be
+ *  more accurate then the value we calculate for `HeartbeatAfter`.
+ */
+export interface HeartbeatAfterV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): number
+    get(block: Block): Promise<(number | undefined)>
+}
+
+export const keys =  {
+    /**
+     *  The current set of keys that may issue a heartbeat.
+     */
+    v700: new StorageType('ImOnline.Keys', 'Default', [], sts.array(() => sts.bytes())) as KeysV700,
+}
+
+/**
+ *  The current set of keys that may issue a heartbeat.
+ */
+export interface KeysV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): Bytes[]
+    get(block: Block): Promise<(Bytes[] | undefined)>
+}
+
+export const receivedHeartbeats =  {
+    /**
+     *  For each session index, we keep a mapping of `SessionIndex` and `AuthIndex` to
+     *  `WrapperOpaque<BoundedOpaqueNetworkState>`.
+     */
+    v700: new StorageType('ImOnline.ReceivedHeartbeats', 'Optional', [sts.number(), sts.number()], v700.WrapperOpaque) as ReceivedHeartbeatsV700,
+}
+
+/**
+ *  For each session index, we keep a mapping of `SessionIndex` and `AuthIndex` to
+ *  `WrapperOpaque<BoundedOpaqueNetworkState>`.
+ */
+export interface ReceivedHeartbeatsV700  {
+    is(block: RuntimeCtx): boolean
+    get(block: Block, key1: number, key2: number): Promise<(v700.WrapperOpaque | undefined)>
+    getMany(block: Block, keys: [number, number][]): Promise<(v700.WrapperOpaque | undefined)[]>
+    getKeys(block: Block): Promise<[number, number][]>
+    getKeys(block: Block, key1: number): Promise<[number, number][]>
+    getKeys(block: Block, key1: number, key2: number): Promise<[number, number][]>
+    getKeysPaged(pageSize: number, block: Block): AsyncIterable<[number, number][]>
+    getKeysPaged(pageSize: number, block: Block, key1: number): AsyncIterable<[number, number][]>
+    getKeysPaged(pageSize: number, block: Block, key1: number, key2: number): AsyncIterable<[number, number][]>
+    getPairs(block: Block): Promise<[k: [number, number], v: (v700.WrapperOpaque | undefined)][]>
+    getPairs(block: Block, key1: number): Promise<[k: [number, number], v: (v700.WrapperOpaque | undefined)][]>
+    getPairs(block: Block, key1: number, key2: number): Promise<[k: [number, number], v: (v700.WrapperOpaque | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block): AsyncIterable<[k: [number, number], v: (v700.WrapperOpaque | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block, key1: number): AsyncIterable<[k: [number, number], v: (v700.WrapperOpaque | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block, key1: number, key2: number): AsyncIterable<[k: [number, number], v: (v700.WrapperOpaque | undefined)][]>
+}
+
+export const authoredBlocks =  {
+    /**
+     *  For each session index, we keep a mapping of `ValidatorId<T>` to the
+     *  number of blocks authored by the given authority.
+     */
+    v700: new StorageType('ImOnline.AuthoredBlocks', 'Default', [sts.number(), v700.AccountId32], sts.number()) as AuthoredBlocksV700,
+}
+
+/**
+ *  For each session index, we keep a mapping of `ValidatorId<T>` to the
+ *  number of blocks authored by the given authority.
+ */
+export interface AuthoredBlocksV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): number
+    get(block: Block, key1: number, key2: v700.AccountId32): Promise<(number | undefined)>
+    getMany(block: Block, keys: [number, v700.AccountId32][]): Promise<(number | undefined)[]>
+    getKeys(block: Block): Promise<[number, v700.AccountId32][]>
+    getKeys(block: Block, key1: number): Promise<[number, v700.AccountId32][]>
+    getKeys(block: Block, key1: number, key2: v700.AccountId32): Promise<[number, v700.AccountId32][]>
+    getKeysPaged(pageSize: number, block: Block): AsyncIterable<[number, v700.AccountId32][]>
+    getKeysPaged(pageSize: number, block: Block, key1: number): AsyncIterable<[number, v700.AccountId32][]>
+    getKeysPaged(pageSize: number, block: Block, key1: number, key2: v700.AccountId32): AsyncIterable<[number, v700.AccountId32][]>
+    getPairs(block: Block): Promise<[k: [number, v700.AccountId32], v: (number | undefined)][]>
+    getPairs(block: Block, key1: number): Promise<[k: [number, v700.AccountId32], v: (number | undefined)][]>
+    getPairs(block: Block, key1: number, key2: v700.AccountId32): Promise<[k: [number, v700.AccountId32], v: (number | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block): AsyncIterable<[k: [number, v700.AccountId32], v: (number | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block, key1: number): AsyncIterable<[k: [number, v700.AccountId32], v: (number | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block, key1: number, key2: v700.AccountId32): AsyncIterable<[k: [number, v700.AccountId32], v: (number | undefined)][]>
+}
diff --git a/src/types/quota/constants.ts b/src/types/quota/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..04878998b2e59615f58b2445ef61dc599cc694c4
--- /dev/null
+++ b/src/types/quota/constants.ts
@@ -0,0 +1,12 @@
+import {sts, Block, Bytes, Option, Result, ConstantType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const refundAccount =  {
+    /**
+     *  Account used to refund fee
+     */
+    v700: new ConstantType(
+        'Quota.RefundAccount',
+        v700.AccountId32
+    ),
+}
diff --git a/src/types/quota/events.ts b/src/types/quota/events.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e6a6609cd35bd9c1380f248840666b33cc1c43a2
--- /dev/null
+++ b/src/types/quota/events.ts
@@ -0,0 +1,61 @@
+import {sts, Block, Bytes, Option, Result, EventType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const refunded =  {
+    name: 'Quota.Refunded',
+    /**
+     * Refunded fees to an account
+     */
+    v700: new EventType(
+        'Quota.Refunded',
+        sts.struct({
+            who: v700.AccountId32,
+            identity: sts.number(),
+            amount: sts.bigint(),
+        })
+    ),
+}
+
+export const noQuotaForIdty =  {
+    name: 'Quota.NoQuotaForIdty',
+    /**
+     * No quota for identity
+     */
+    v700: new EventType(
+        'Quota.NoQuotaForIdty',
+        sts.number()
+    ),
+}
+
+export const noMoreCurrencyForRefund =  {
+    name: 'Quota.NoMoreCurrencyForRefund',
+    /**
+     * No more currency available for refund
+     */
+    v700: new EventType(
+        'Quota.NoMoreCurrencyForRefund',
+        sts.unit()
+    ),
+}
+
+export const refundFailed =  {
+    name: 'Quota.RefundFailed',
+    /**
+     * Refund failed
+     */
+    v700: new EventType(
+        'Quota.RefundFailed',
+        v700.AccountId32
+    ),
+}
+
+export const refundQueueFull =  {
+    name: 'Quota.RefundQueueFull',
+    /**
+     * Refund queue full
+     */
+    v700: new EventType(
+        'Quota.RefundQueueFull',
+        sts.unit()
+    ),
+}
diff --git a/src/types/quota/storage.ts b/src/types/quota/storage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..573fa4ab6d4a8a5ce4f1c49f7f7d759ce7df9d92
--- /dev/null
+++ b/src/types/quota/storage.ts
@@ -0,0 +1,42 @@
+import {sts, Block, Bytes, Option, Result, StorageType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const idtyQuota =  {
+    /**
+     *  maps identity index to quota
+     */
+    v700: new StorageType('Quota.IdtyQuota', 'Optional', [sts.number()], v700.Quota) as IdtyQuotaV700,
+}
+
+/**
+ *  maps identity index to quota
+ */
+export interface IdtyQuotaV700  {
+    is(block: RuntimeCtx): boolean
+    get(block: Block, key: number): Promise<(v700.Quota | undefined)>
+    getMany(block: Block, keys: number[]): Promise<(v700.Quota | undefined)[]>
+    getKeys(block: Block): Promise<number[]>
+    getKeys(block: Block, key: number): Promise<number[]>
+    getKeysPaged(pageSize: number, block: Block): AsyncIterable<number[]>
+    getKeysPaged(pageSize: number, block: Block, key: number): AsyncIterable<number[]>
+    getPairs(block: Block): Promise<[k: number, v: (v700.Quota | undefined)][]>
+    getPairs(block: Block, key: number): Promise<[k: number, v: (v700.Quota | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block): AsyncIterable<[k: number, v: (v700.Quota | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block, key: number): AsyncIterable<[k: number, v: (v700.Quota | undefined)][]>
+}
+
+export const refundQueue =  {
+    /**
+     *  fees waiting for refund
+     */
+    v700: new StorageType('Quota.RefundQueue', 'Default', [], sts.array(() => v700.Refund)) as RefundQueueV700,
+}
+
+/**
+ *  fees waiting for refund
+ */
+export interface RefundQueueV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): v700.Refund[]
+    get(block: Block): Promise<(v700.Refund[] | undefined)>
+}
diff --git a/src/types/session/calls.ts b/src/types/session/calls.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1141936f6796f0c1834c880384b282300a398b34
--- /dev/null
+++ b/src/types/session/calls.ts
@@ -0,0 +1,46 @@
+import {sts, Block, Bytes, Option, Result, CallType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const setKeys =  {
+    name: 'Session.set_keys',
+    /**
+     * Sets the session key(s) of the function caller to `keys`.
+     * Allows an account to set its session key prior to becoming a validator.
+     * This doesn't take effect until the next session.
+     * 
+     * The dispatch origin of this function must be signed.
+     * 
+     * ## Complexity
+     * - `O(1)`. Actual cost depends on the number of length of `T::Keys::key_ids()` which is
+     *   fixed.
+     */
+    v700: new CallType(
+        'Session.set_keys',
+        sts.struct({
+            keys: v700.SessionKeys,
+            proof: sts.bytes(),
+        })
+    ),
+}
+
+export const purgeKeys =  {
+    name: 'Session.purge_keys',
+    /**
+     * Removes any session key(s) of the function caller.
+     * 
+     * This doesn't take effect until the next session.
+     * 
+     * The dispatch origin of this function must be Signed and the account must be either be
+     * convertible to a validator ID using the chain's typical addressing system (this usually
+     * means being a controller account) or directly convertible into a validator ID (which
+     * usually means being a stash account).
+     * 
+     * ## Complexity
+     * - `O(1)` in number of key types. Actual cost depends on the number of length of
+     *   `T::Keys::key_ids()` which is fixed.
+     */
+    v700: new CallType(
+        'Session.purge_keys',
+        sts.unit()
+    ),
+}
diff --git a/src/types/session/events.ts b/src/types/session/events.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d8858ba1c8f521ff934982486d90f22b66138ec1
--- /dev/null
+++ b/src/types/session/events.ts
@@ -0,0 +1,15 @@
+import {sts, Block, Bytes, Option, Result, EventType, RuntimeCtx} from '../support'
+
+export const newSession =  {
+    name: 'Session.NewSession',
+    /**
+     * New session has happened. Note that the argument is the session index, not the
+     * block number as the type might suggest.
+     */
+    v700: new EventType(
+        'Session.NewSession',
+        sts.struct({
+            sessionIndex: sts.number(),
+        })
+    ),
+}
diff --git a/src/types/session/storage.ts b/src/types/session/storage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a5f8c2225ad1ee89b8f2b4f184e4eba6b7ddff49
--- /dev/null
+++ b/src/types/session/storage.ts
@@ -0,0 +1,142 @@
+import {sts, Block, Bytes, Option, Result, StorageType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const validators =  {
+    /**
+     *  The current set of validators.
+     */
+    v700: new StorageType('Session.Validators', 'Default', [], sts.array(() => v700.AccountId32)) as ValidatorsV700,
+}
+
+/**
+ *  The current set of validators.
+ */
+export interface ValidatorsV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): v700.AccountId32[]
+    get(block: Block): Promise<(v700.AccountId32[] | undefined)>
+}
+
+export const currentIndex =  {
+    /**
+     *  Current index of the session.
+     */
+    v700: new StorageType('Session.CurrentIndex', 'Default', [], sts.number()) as CurrentIndexV700,
+}
+
+/**
+ *  Current index of the session.
+ */
+export interface CurrentIndexV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): number
+    get(block: Block): Promise<(number | undefined)>
+}
+
+export const queuedChanged =  {
+    /**
+     *  True if the underlying economic identities or weighting behind the validators
+     *  has changed in the queued validator set.
+     */
+    v700: new StorageType('Session.QueuedChanged', 'Default', [], sts.boolean()) as QueuedChangedV700,
+}
+
+/**
+ *  True if the underlying economic identities or weighting behind the validators
+ *  has changed in the queued validator set.
+ */
+export interface QueuedChangedV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): boolean
+    get(block: Block): Promise<(boolean | undefined)>
+}
+
+export const queuedKeys =  {
+    /**
+     *  The queued keys for the next session. When the next session begins, these keys
+     *  will be used to determine the validator's session keys.
+     */
+    v700: new StorageType('Session.QueuedKeys', 'Default', [], sts.array(() => sts.tuple(() => [v700.AccountId32, v700.SessionKeys]))) as QueuedKeysV700,
+}
+
+/**
+ *  The queued keys for the next session. When the next session begins, these keys
+ *  will be used to determine the validator's session keys.
+ */
+export interface QueuedKeysV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): [v700.AccountId32, v700.SessionKeys][]
+    get(block: Block): Promise<([v700.AccountId32, v700.SessionKeys][] | undefined)>
+}
+
+export const disabledValidators =  {
+    /**
+     *  Indices of disabled validators.
+     * 
+     *  The vec is always kept sorted so that we can find whether a given validator is
+     *  disabled using binary search. It gets cleared when `on_session_ending` returns
+     *  a new set of identities.
+     */
+    v700: new StorageType('Session.DisabledValidators', 'Default', [], sts.array(() => sts.number())) as DisabledValidatorsV700,
+}
+
+/**
+ *  Indices of disabled validators.
+ * 
+ *  The vec is always kept sorted so that we can find whether a given validator is
+ *  disabled using binary search. It gets cleared when `on_session_ending` returns
+ *  a new set of identities.
+ */
+export interface DisabledValidatorsV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): number[]
+    get(block: Block): Promise<(number[] | undefined)>
+}
+
+export const nextKeys =  {
+    /**
+     *  The next session keys for a validator.
+     */
+    v700: new StorageType('Session.NextKeys', 'Optional', [v700.AccountId32], v700.SessionKeys) as NextKeysV700,
+}
+
+/**
+ *  The next session keys for a validator.
+ */
+export interface NextKeysV700  {
+    is(block: RuntimeCtx): boolean
+    get(block: Block, key: v700.AccountId32): Promise<(v700.SessionKeys | undefined)>
+    getMany(block: Block, keys: v700.AccountId32[]): Promise<(v700.SessionKeys | undefined)[]>
+    getKeys(block: Block): Promise<v700.AccountId32[]>
+    getKeys(block: Block, key: v700.AccountId32): Promise<v700.AccountId32[]>
+    getKeysPaged(pageSize: number, block: Block): AsyncIterable<v700.AccountId32[]>
+    getKeysPaged(pageSize: number, block: Block, key: v700.AccountId32): AsyncIterable<v700.AccountId32[]>
+    getPairs(block: Block): Promise<[k: v700.AccountId32, v: (v700.SessionKeys | undefined)][]>
+    getPairs(block: Block, key: v700.AccountId32): Promise<[k: v700.AccountId32, v: (v700.SessionKeys | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block): AsyncIterable<[k: v700.AccountId32, v: (v700.SessionKeys | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block, key: v700.AccountId32): AsyncIterable<[k: v700.AccountId32, v: (v700.SessionKeys | undefined)][]>
+}
+
+export const keyOwner =  {
+    /**
+     *  The owner of a key. The key is the `KeyTypeId` + the encoded key.
+     */
+    v700: new StorageType('Session.KeyOwner', 'Optional', [sts.tuple(() => [v700.KeyTypeId, sts.bytes()])], v700.AccountId32) as KeyOwnerV700,
+}
+
+/**
+ *  The owner of a key. The key is the `KeyTypeId` + the encoded key.
+ */
+export interface KeyOwnerV700  {
+    is(block: RuntimeCtx): boolean
+    get(block: Block, key: [v700.KeyTypeId, Bytes]): Promise<(v700.AccountId32 | undefined)>
+    getMany(block: Block, keys: [v700.KeyTypeId, Bytes][]): Promise<(v700.AccountId32 | undefined)[]>
+    getKeys(block: Block): Promise<[v700.KeyTypeId, Bytes][]>
+    getKeys(block: Block, key: [v700.KeyTypeId, Bytes]): Promise<[v700.KeyTypeId, Bytes][]>
+    getKeysPaged(pageSize: number, block: Block): AsyncIterable<[v700.KeyTypeId, Bytes][]>
+    getKeysPaged(pageSize: number, block: Block, key: [v700.KeyTypeId, Bytes]): AsyncIterable<[v700.KeyTypeId, Bytes][]>
+    getPairs(block: Block): Promise<[k: [v700.KeyTypeId, Bytes], v: (v700.AccountId32 | undefined)][]>
+    getPairs(block: Block, key: [v700.KeyTypeId, Bytes]): Promise<[k: [v700.KeyTypeId, Bytes], v: (v700.AccountId32 | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block): AsyncIterable<[k: [v700.KeyTypeId, Bytes], v: (v700.AccountId32 | undefined)][]>
+    getPairsPaged(pageSize: number, block: Block, key: [v700.KeyTypeId, Bytes]): AsyncIterable<[k: [v700.KeyTypeId, Bytes], v: (v700.AccountId32 | undefined)][]>
+}
diff --git a/src/types/storage.ts b/src/types/storage.ts
index 7b9446495957925aabce51e00d8560b20a182224..37e5a29a596a55e5bcf0bbbed3bd17766febf720 100644
--- a/src/types/storage.ts
+++ b/src/types/storage.ts
@@ -1,7 +1,12 @@
 export * as system from './system/storage'
 export * as timestamp from './timestamp/storage'
 export * as balances from './balances/storage'
+export * as transactionPayment from './transaction-payment/storage'
+export * as quota from './quota/storage'
 export * as authorityMembers from './authority-members/storage'
+export * as session from './session/storage'
+export * as imOnline from './im-online/storage'
+export * as universalDividend from './universal-dividend/storage'
 export * as identity from './identity/storage'
 export * as membership from './membership/storage'
 export * as cert from './cert/storage'
diff --git a/src/types/transaction-payment/constants.ts b/src/types/transaction-payment/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..313d00b5756536ad159f17465f22512a6084fe68
--- /dev/null
+++ b/src/types/transaction-payment/constants.ts
@@ -0,0 +1,31 @@
+import {sts, Block, Bytes, Option, Result, ConstantType, RuntimeCtx} from '../support'
+
+export const operationalFeeMultiplier =  {
+    /**
+     *  A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their
+     *  `priority`
+     * 
+     *  This value is multipled by the `final_fee` to obtain a "virtual tip" that is later
+     *  added to a tip component in regular `priority` calculations.
+     *  It means that a `Normal` transaction can front-run a similarly-sized `Operational`
+     *  extrinsic (with no tip), by including a tip value greater than the virtual tip.
+     * 
+     *  ```rust,ignore
+     *  // For `Normal`
+     *  let priority = priority_calc(tip);
+     * 
+     *  // For `Operational`
+     *  let virtual_tip = (inclusion_fee + tip) * OperationalFeeMultiplier;
+     *  let priority = priority_calc(tip + virtual_tip);
+     *  ```
+     * 
+     *  Note that since we use `final_fee` the multiplier applies also to the regular `tip`
+     *  sent with the transaction. So, not only does the transaction get a priority bump based
+     *  on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational`
+     *  transactions.
+     */
+    v700: new ConstantType(
+        'TransactionPayment.OperationalFeeMultiplier',
+        sts.number()
+    ),
+}
diff --git a/src/types/transaction-payment/events.ts b/src/types/transaction-payment/events.ts
new file mode 100644
index 0000000000000000000000000000000000000000..43baf1f260c1f3ae331ba9f1f81134285942f31b
--- /dev/null
+++ b/src/types/transaction-payment/events.ts
@@ -0,0 +1,18 @@
+import {sts, Block, Bytes, Option, Result, EventType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const transactionFeePaid =  {
+    name: 'TransactionPayment.TransactionFeePaid',
+    /**
+     * A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee,
+     * has been paid by `who`.
+     */
+    v700: new EventType(
+        'TransactionPayment.TransactionFeePaid',
+        sts.struct({
+            who: v700.AccountId32,
+            actualFee: sts.bigint(),
+            tip: sts.bigint(),
+        })
+    ),
+}
diff --git a/src/types/transaction-payment/storage.ts b/src/types/transaction-payment/storage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..41a021d40f065c6ef091710c0f874fff1a9f593a
--- /dev/null
+++ b/src/types/transaction-payment/storage.ts
@@ -0,0 +1,22 @@
+import {sts, Block, Bytes, Option, Result, StorageType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const nextFeeMultiplier =  {
+    v700: new StorageType('TransactionPayment.NextFeeMultiplier', 'Default', [], v700.FixedU128) as NextFeeMultiplierV700,
+}
+
+export interface NextFeeMultiplierV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): v700.FixedU128
+    get(block: Block): Promise<(v700.FixedU128 | undefined)>
+}
+
+export const storageVersion =  {
+    v700: new StorageType('TransactionPayment.StorageVersion', 'Default', [], v700.Releases) as StorageVersionV700,
+}
+
+export interface StorageVersionV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): v700.Releases
+    get(block: Block): Promise<(v700.Releases | undefined)>
+}
diff --git a/src/types/universal-dividend/calls.ts b/src/types/universal-dividend/calls.ts
new file mode 100644
index 0000000000000000000000000000000000000000..728cfb5571a23f1944d8b51b7654ec31d6dfc280
--- /dev/null
+++ b/src/types/universal-dividend/calls.ts
@@ -0,0 +1,41 @@
+import {sts, Block, Bytes, Option, Result, CallType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const claimUds =  {
+    name: 'UniversalDividend.claim_uds',
+    /**
+     * Claim Universal Dividends
+     */
+    v700: new CallType(
+        'UniversalDividend.claim_uds',
+        sts.unit()
+    ),
+}
+
+export const transferUd =  {
+    name: 'UniversalDividend.transfer_ud',
+    /**
+     * Transfer some liquid free balance to another account, in milliUD.
+     */
+    v700: new CallType(
+        'UniversalDividend.transfer_ud',
+        sts.struct({
+            dest: v700.MultiAddress,
+            value: sts.bigint(),
+        })
+    ),
+}
+
+export const transferUdKeepAlive =  {
+    name: 'UniversalDividend.transfer_ud_keep_alive',
+    /**
+     * Transfer some liquid free balance to another account, in milliUD.
+     */
+    v700: new CallType(
+        'UniversalDividend.transfer_ud_keep_alive',
+        sts.struct({
+            dest: v700.MultiAddress,
+            value: sts.bigint(),
+        })
+    ),
+}
diff --git a/src/types/universal-dividend/constants.ts b/src/types/universal-dividend/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..da94213f046262bc9486245eae634e253ee191b3
--- /dev/null
+++ b/src/types/universal-dividend/constants.ts
@@ -0,0 +1,54 @@
+import {sts, Block, Bytes, Option, Result, ConstantType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const maxPastReeval =  {
+    /**
+     *  Maximum number of past UD revaluations to keep in storage.
+     */
+    v700: new ConstantType(
+        'UniversalDividend.MaxPastReeval',
+        sts.number()
+    ),
+}
+
+export const squareMoneyGrowthRate =  {
+    /**
+     *  Square of the money growth rate per ud reevaluation period
+     */
+    v700: new ConstantType(
+        'UniversalDividend.SquareMoneyGrowthRate',
+        v700.Perbill
+    ),
+}
+
+export const udCreationPeriod =  {
+    /**
+     *  Universal dividend creation period (ms)
+     */
+    v700: new ConstantType(
+        'UniversalDividend.UdCreationPeriod',
+        sts.bigint()
+    ),
+}
+
+export const udReevalPeriod =  {
+    /**
+     *  Universal dividend reevaluation period (ms)
+     */
+    v700: new ConstantType(
+        'UniversalDividend.UdReevalPeriod',
+        sts.bigint()
+    ),
+}
+
+export const unitsPerUd =  {
+    /**
+     *  The number of units to divide the amounts expressed in number of UDs
+     *  Example: If you wish to express the UD amounts with a maximum precision of the order
+     *  of the milliUD, choose 1000
+     */
+    v700: new ConstantType(
+        'UniversalDividend.UnitsPerUd',
+        sts.bigint()
+    ),
+}
diff --git a/src/types/universal-dividend/events.ts b/src/types/universal-dividend/events.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fe3eec34300c4cb759f1446d7cd7af87b720bf87
--- /dev/null
+++ b/src/types/universal-dividend/events.ts
@@ -0,0 +1,63 @@
+import {sts, Block, Bytes, Option, Result, EventType, RuntimeCtx} from '../support'
+import * as v700 from '../v700'
+
+export const newUdCreated =  {
+    name: 'UniversalDividend.NewUdCreated',
+    /**
+     * A new universal dividend is created.
+     */
+    v700: new EventType(
+        'UniversalDividend.NewUdCreated',
+        sts.struct({
+            amount: sts.bigint(),
+            index: sts.number(),
+            monetaryMass: sts.bigint(),
+            membersCount: sts.bigint(),
+        })
+    ),
+}
+
+export const udReevalued =  {
+    name: 'UniversalDividend.UdReevalued',
+    /**
+     * The universal dividend has been re-evaluated.
+     */
+    v700: new EventType(
+        'UniversalDividend.UdReevalued',
+        sts.struct({
+            newUdAmount: sts.bigint(),
+            monetaryMass: sts.bigint(),
+            membersCount: sts.bigint(),
+        })
+    ),
+}
+
+export const udsAutoPaidAtRemoval =  {
+    name: 'UniversalDividend.UdsAutoPaidAtRemoval',
+    /**
+     * DUs were automatically transferred as part of a member removal.
+     */
+    v700: new EventType(
+        'UniversalDividend.UdsAutoPaidAtRemoval',
+        sts.struct({
+            count: sts.number(),
+            total: sts.bigint(),
+            who: v700.AccountId32,
+        })
+    ),
+}
+
+export const udsClaimed =  {
+    name: 'UniversalDividend.UdsClaimed',
+    /**
+     * A member claimed his UDs.
+     */
+    v700: new EventType(
+        'UniversalDividend.UdsClaimed',
+        sts.struct({
+            count: sts.number(),
+            total: sts.bigint(),
+            who: v700.AccountId32,
+        })
+    ),
+}
diff --git a/src/types/universal-dividend/storage.ts b/src/types/universal-dividend/storage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..16f175ea0309d5ca2c49ba04d9222916500d0d4a
--- /dev/null
+++ b/src/types/universal-dividend/storage.ts
@@ -0,0 +1,95 @@
+import {sts, Block, Bytes, Option, Result, StorageType, RuntimeCtx} from '../support'
+
+export const currentUd =  {
+    /**
+     *  Current UD amount
+     */
+    v700: new StorageType('UniversalDividend.CurrentUd', 'Default', [], sts.bigint()) as CurrentUdV700,
+}
+
+/**
+ *  Current UD amount
+ */
+export interface CurrentUdV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): bigint
+    get(block: Block): Promise<(bigint | undefined)>
+}
+
+export const currentUdIndex =  {
+    /**
+     *  Current UD index
+     */
+    v700: new StorageType('UniversalDividend.CurrentUdIndex', 'Default', [], sts.number()) as CurrentUdIndexV700,
+}
+
+/**
+ *  Current UD index
+ */
+export interface CurrentUdIndexV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): number
+    get(block: Block): Promise<(number | undefined)>
+}
+
+export const monetaryMass =  {
+    /**
+     *  Total quantity of money created by universal dividend (does not take into account the possible destruction of money)
+     */
+    v700: new StorageType('UniversalDividend.MonetaryMass', 'Default', [], sts.bigint()) as MonetaryMassV700,
+}
+
+/**
+ *  Total quantity of money created by universal dividend (does not take into account the possible destruction of money)
+ */
+export interface MonetaryMassV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): bigint
+    get(block: Block): Promise<(bigint | undefined)>
+}
+
+export const nextReeval =  {
+    /**
+     *  Next UD reevaluation
+     */
+    v700: new StorageType('UniversalDividend.NextReeval', 'Optional', [], sts.bigint()) as NextReevalV700,
+}
+
+/**
+ *  Next UD reevaluation
+ */
+export interface NextReevalV700  {
+    is(block: RuntimeCtx): boolean
+    get(block: Block): Promise<(bigint | undefined)>
+}
+
+export const nextUd =  {
+    /**
+     *  Next UD creation
+     */
+    v700: new StorageType('UniversalDividend.NextUd', 'Optional', [], sts.bigint()) as NextUdV700,
+}
+
+/**
+ *  Next UD creation
+ */
+export interface NextUdV700  {
+    is(block: RuntimeCtx): boolean
+    get(block: Block): Promise<(bigint | undefined)>
+}
+
+export const pastReevals =  {
+    /**
+     *  Past UD reevaluations
+     */
+    v700: new StorageType('UniversalDividend.PastReevals', 'Default', [], sts.array(() => sts.tuple(() => [sts.number(), sts.bigint()]))) as PastReevalsV700,
+}
+
+/**
+ *  Past UD reevaluations
+ */
+export interface PastReevalsV700  {
+    is(block: RuntimeCtx): boolean
+    getDefault(block: Block): [number, bigint][]
+    get(block: Block): Promise<([number, bigint][] | undefined)>
+}
diff --git a/src/types/v700.ts b/src/types/v700.ts
index 5ef0a4e571572acbd0b3dc1b47ef4c98f474515b..fd4588d47d87463d02a3f6ba955a9adf1921db80 100644
--- a/src/types/v700.ts
+++ b/src/types/v700.ts
@@ -1,5 +1,7 @@
 import {sts, Result, Option, Bytes, BitSequence} from './support'
 
+export const Perbill = sts.number()
+
 export const RuntimeVersion: sts.Type<RuntimeVersion> = sts.struct(() => {
     return  {
         specName: sts.string(),
@@ -192,6 +194,39 @@ export const IdtyData: sts.Type<IdtyData> = sts.struct(() => {
     }
 })
 
+export type WrapperOpaque = [number, BoundedOpaqueNetworkState]
+
+export interface BoundedOpaqueNetworkState {
+    peerId: WeakBoundedVec
+    externalAddresses: WeakBoundedVec[]
+}
+
+export type WeakBoundedVec = Bytes
+
+export const WrapperOpaque = sts.tuple(() => [sts.number(), BoundedOpaqueNetworkState])
+
+export const BoundedOpaqueNetworkState: sts.Type<BoundedOpaqueNetworkState> = sts.struct(() => {
+    return  {
+        peerId: WeakBoundedVec,
+        externalAddresses: sts.array(() => WeakBoundedVec),
+    }
+})
+
+export const WeakBoundedVec = sts.bytes()
+
+export type KeyTypeId = Bytes
+
+export const KeyTypeId = sts.bytes()
+
+export interface SessionKeys {
+    grandpa: Public
+    babe: Bytes
+    imOnline: Bytes
+    authorityDiscovery: Bytes
+}
+
+export type Public = Bytes
+
 export interface MemberData {
     ownerKey: AccountId32
 }
@@ -202,6 +237,53 @@ export const MemberData: sts.Type<MemberData> = sts.struct(() => {
     }
 })
 
+export interface Refund {
+    account: AccountId32
+    identity: number
+    amount: bigint
+}
+
+export const Refund: sts.Type<Refund> = sts.struct(() => {
+    return  {
+        account: AccountId32,
+        identity: sts.number(),
+        amount: sts.bigint(),
+    }
+})
+
+export interface Quota {
+    lastUse: number
+    amount: bigint
+}
+
+export const Quota: sts.Type<Quota> = sts.struct(() => {
+    return  {
+        lastUse: sts.number(),
+        amount: sts.bigint(),
+    }
+})
+
+export type Releases = Releases_V1Ancient | Releases_V2
+
+export interface Releases_V1Ancient {
+    __kind: 'V1Ancient'
+}
+
+export interface Releases_V2 {
+    __kind: 'V2'
+}
+
+export const Releases: sts.Type<Releases> = sts.closedEnum(() => {
+    return  {
+        V1Ancient: sts.unit(),
+        V2: sts.unit(),
+    }
+})
+
+export type FixedU128 = bigint
+
+export const FixedU128 = sts.bigint()
+
 export interface IdAmount {
     amount: bigint
 }
@@ -1696,8 +1778,6 @@ export interface GrandpaEvent_Resumed {
     __kind: 'Resumed'
 }
 
-export type Public = Bytes
-
 /**
  * 
 			The [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted
@@ -2683,8 +2763,6 @@ export const ImOnlineEvent: sts.Type<ImOnlineEvent> = sts.closedEnum(() => {
     }
 })
 
-export const ValidatorFullIdentification = sts.unit()
-
 /**
  * 
 			The [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted
@@ -3059,6 +3137,44 @@ export interface MultiSignature_Sr25519 {
     value: Bytes
 }
 
+export const Heartbeat: sts.Type<Heartbeat> = sts.struct(() => {
+    return  {
+        blockNumber: sts.number(),
+        networkState: OpaqueNetworkState,
+        sessionIndex: sts.number(),
+        authorityIndex: sts.number(),
+        validatorsLen: sts.number(),
+    }
+})
+
+export const OpaqueNetworkState: sts.Type<OpaqueNetworkState> = sts.struct(() => {
+    return  {
+        peerId: OpaquePeerId,
+        externalAddresses: sts.array(() => OpaqueMultiaddr),
+    }
+})
+
+export const OpaqueMultiaddr = sts.bytes()
+
+export const OpaquePeerId = sts.bytes()
+
+export interface OpaqueNetworkState {
+    peerId: OpaquePeerId
+    externalAddresses: OpaqueMultiaddr[]
+}
+
+export type OpaqueMultiaddr = Bytes
+
+export type OpaquePeerId = Bytes
+
+export interface Heartbeat {
+    blockNumber: number
+    networkState: OpaqueNetworkState
+    sessionIndex: number
+    authorityIndex: number
+    validatorsLen: number
+}
+
 export const SessionKeys: sts.Type<SessionKeys> = sts.struct(() => {
     return  {
         grandpa: Public,
@@ -3068,13 +3184,6 @@ export const SessionKeys: sts.Type<SessionKeys> = sts.struct(() => {
     }
 })
 
-export interface SessionKeys {
-    grandpa: Public
-    babe: Bytes
-    imOnline: Bytes
-    authorityDiscovery: Bytes
-}
-
 export const MultiAddress: sts.Type<MultiAddress> = sts.closedEnum(() => {
     return  {
         Address20: sts.bytes(),
@@ -3127,6 +3236,8 @@ export const IdtyRemovalWotReason: sts.Type<IdtyRemovalWotReason> = sts.closedEn
     }
 })
 
+export const ValidatorFullIdentification = sts.unit()
+
 export const BalanceStatus: sts.Type<BalanceStatus> = sts.closedEnum(() => {
     return  {
         Free: sts.unit(),
diff --git a/typegen.json b/typegen.json
index 6e77f3cafd4d6e79d486fa893d09aee1942bd262..091110bfeb92ef34ce5f52b624b88ec32671b425 100644
--- a/typegen.json
+++ b/typegen.json
@@ -8,6 +8,24 @@
       "storage": true,
       "constants": true
     },
+    "Session": {
+      "events": true,
+      "calls": true,
+      "storage": true,
+      "constants": true
+    },
+    "ImOnline": {
+      "events": true,
+      "calls": true,
+      "storage": true,
+      "constants": true
+    },
+    "TransactionPayment": {
+      "events": true,
+      "calls": true,
+      "storage": true,
+      "constants": true
+    },
     "Timestamp": {
       "events": true,
       "calls": true,
@@ -20,6 +38,18 @@
       "storage": true,
       "constants": true
     },
+    "Quota": {
+      "events": true,
+      "calls": true,
+      "storage": true,
+      "constants": true
+    },
+    "UniversalDividend": {
+      "events": true,
+      "calls": true,
+      "storage": true,
+      "constants": true
+    },
     "Identity": {
       "events": true,
       "calls": true,