diff --git a/Cargo.lock b/Cargo.lock
index c808f60f5cff62c148dc3c7fef81e6175427f6f2..55b25b2160f0040f036f0748530228a78dbe3811 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -98,6 +98,12 @@ version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
 
+[[package]]
+name = "ascii"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e"
+
 [[package]]
 name = "async-lock"
 version = "2.5.0"
@@ -342,6 +348,19 @@ dependencies = [
  "os_str_bytes",
 ]
 
+[[package]]
+name = "combine"
+version = "3.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680"
+dependencies = [
+ "ascii",
+ "byteorder",
+ "either",
+ "memchr",
+ "unreachable",
+]
+
 [[package]]
 name = "constant_time_eq"
 version = "0.1.5"
@@ -583,6 +602,15 @@ version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
 
+[[package]]
+name = "encoding_rs"
+version = "0.8.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 name = "env_logger"
 version = "0.9.0"
@@ -614,6 +642,15 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
 
+[[package]]
+name = "fastrand"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+dependencies = [
+ "instant",
+]
+
 [[package]]
 name = "fixed-hash"
 version = "0.7.0"
@@ -632,6 +669,31 @@ version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
+dependencies = [
+ "matches",
+ "percent-encoding",
+]
+
 [[package]]
 name = "frame-metadata"
 version = "15.0.0"
@@ -753,9 +815,12 @@ dependencies = [
  "anyhow",
  "clap",
  "env_logger",
+ "graphql_client",
  "hex",
  "logs",
  "parity-scale-codec",
+ "reqwest",
+ "serde",
  "serde_json",
  "sp-core",
  "subxt",
@@ -811,6 +876,84 @@ version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 
+[[package]]
+name = "graphql-introspection-query"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f2a4732cf5140bd6c082434494f785a19cfb566ab07d1382c3671f5812fed6d"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "graphql-parser"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2ebc8013b4426d5b81a4364c419a95ed0b404af2b82e2457de52d9348f0e474"
+dependencies = [
+ "combine",
+ "thiserror",
+]
+
+[[package]]
+name = "graphql_client"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fc16d75d169fddb720d8f1c7aed6413e329e1584079b9734ff07266a193f5bc"
+dependencies = [
+ "graphql_query_derive",
+ "reqwest",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "graphql_client_codegen"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f290ecfa3bea3e8a157899dc8a1d96ee7dd6405c18c8ddd213fc58939d18a0e9"
+dependencies = [
+ "graphql-introspection-query",
+ "graphql-parser",
+ "heck",
+ "lazy_static",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "syn",
+]
+
+[[package]]
+name = "graphql_query_derive"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a755cc59cda2641ea3037b4f9f7ef40471c329f55c1fa2db6fa0bb7ae6c1f7ce"
+dependencies = [
+ "graphql_client_codegen",
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
 [[package]]
 name = "hash-db"
 version = "0.15.2"
@@ -898,18 +1041,72 @@ dependencies = [
  "itoa 1.0.3",
 ]
 
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
 [[package]]
 name = "httparse"
 version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
 
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
 [[package]]
 name = "humantime"
 version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
+[[package]]
+name = "hyper"
+version = "0.14.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa 1.0.3",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
+dependencies = [
+ "bytes",
+ "hyper",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+]
+
 [[package]]
 name = "iana-time-zone"
 version = "0.1.41"
@@ -929,6 +1126,17 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
+[[package]]
+name = "idna"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
 [[package]]
 name = "impl-codec"
 version = "0.6.0"
@@ -968,6 +1176,15 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 name = "integer-sqrt"
 version = "0.1.5"
@@ -977,6 +1194,12 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "ipnet"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
+
 [[package]]
 name = "itoa"
 version = "0.4.8"
@@ -1168,6 +1391,12 @@ dependencies = [
  "regex-automata",
 ]
 
+[[package]]
+name = "matches"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
+
 [[package]]
 name = "memchr"
 version = "2.5.0"
@@ -1203,6 +1432,12 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "mime"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+
 [[package]]
 name = "miniz_oxide"
 version = "0.5.3"
@@ -1224,6 +1459,24 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "native-tls"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
 [[package]]
 name = "nodrop"
 version = "0.1.14"
@@ -1319,12 +1572,51 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
 
+[[package]]
+name = "openssl"
+version = "0.10.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "openssl-probe"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 
+[[package]]
+name = "openssl-sys"
+version = "0.9.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
+dependencies = [
+ "autocfg",
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
 [[package]]
 name = "os_str_bytes"
 version = "6.2.0"
@@ -1436,6 +1728,12 @@ dependencies = [
  "crypto-mac 0.11.1",
 ]
 
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
 [[package]]
 name = "pin-project"
 version = "1.0.11"
@@ -1468,6 +1766,12 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
+[[package]]
+name = "pkg-config"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.16"
@@ -1682,6 +1986,52 @@ version = "0.6.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
 
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "reqwest"
+version = "0.11.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92"
+dependencies = [
+ "base64",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-tls",
+ "ipnet",
+ "js-sys",
+ "lazy_static",
+ "log",
+ "mime",
+ "native-tls",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "tokio",
+ "tokio-native-tls",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "winreg",
+]
+
 [[package]]
 name = "ring"
 version = "0.16.20"
@@ -1905,6 +2255,18 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa 1.0.3",
+ "ryu",
+ "serde",
+]
+
 [[package]]
 name = "sha-1"
 version = "0.9.8"
@@ -2454,6 +2816,20 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
 
+[[package]]
+name = "tempfile"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "libc",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
 [[package]]
 name = "termcolor"
 version = "1.1.3"
@@ -2550,7 +2926,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
 dependencies = [
  "autocfg",
+ "bytes",
  "libc",
+ "memchr",
  "mio",
  "once_cell",
  "pin-project-lite",
@@ -2570,6 +2948,16 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
 [[package]]
 name = "tokio-rustls"
 version = "0.23.4"
@@ -2593,6 +2981,7 @@ dependencies = [
  "futures-sink",
  "pin-project-lite",
  "tokio",
+ "tracing",
 ]
 
 [[package]]
@@ -2604,6 +2993,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
 [[package]]
 name = "tracing"
 version = "0.1.36"
@@ -2702,6 +3097,12 @@ dependencies = [
  "hash-db",
 ]
 
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
 [[package]]
 name = "twox-hash"
 version = "1.6.3"
@@ -2732,6 +3133,12 @@ dependencies = [
  "static_assertions",
 ]
 
+[[package]]
+name = "unicode-bidi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.3"
@@ -2753,24 +3160,67 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
 
+[[package]]
+name = "unreachable"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+dependencies = [
+ "void",
+]
+
 [[package]]
 name = "untrusted"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
 
+[[package]]
+name = "url"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "matches",
+ "percent-encoding",
+]
+
 [[package]]
 name = "valuable"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
 [[package]]
 name = "version_check"
 version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
 [[package]]
 name = "wasi"
 version = "0.9.0+wasi-snapshot-preview1"
@@ -2814,6 +3264,18 @@ dependencies = [
  "wasm-bindgen-shared",
 ]
 
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
 [[package]]
 name = "wasm-bindgen-macro"
 version = "0.2.82"
@@ -2970,6 +3432,15 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 
+[[package]]
+name = "winreg"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "wyz"
 version = "0.5.0"
diff --git a/Cargo.toml b/Cargo.toml
index 4db670852ac85208845f874b0b9d7af8875c35c5..532712fc22be46f5204885b5c52c973b4076004a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,9 +10,12 @@ version = "0.1.0"
 anyhow = "1.0"
 clap = { version = "3.0", features = ["derive"] }
 env_logger = "0.9.0"
+graphql_client = { version = "0.11.0", features = ["reqwest"] }
 hex = "0.4.3"
 logs = "0.5"
 codec = { package = "parity-scale-codec", version = "3.1.5" }
+reqwest = "0.11.11"
+serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0.64"
 sp-core = { git = "https://github.com/duniter/substrate", branch = "duniter-substrate-v0.9.23" }
 subxt =  { git = 'https://github.com/duniter/subxt.git', branch = 'duniter-substrate-v0.9.23' }
diff --git a/README.md b/README.md
index ad00aeb7193d2626799825f05f729ca4a0852547..8bf013f029d98b68a1fdf99ff36355f8f9db8429 100644
--- a/README.md
+++ b/README.md
@@ -11,3 +11,7 @@ Send 10 ÄžD from Alice to Ferdie:
 If using a different runtime, update the metadata for the client to compile:
 
 	subxt metadata -f bytes > res/metadata.scale
+
+List certifications and session keys that will expire within one month:
+
+	cargo run -- --url wss://gdev.librelois.fr:443/ws --secret //Alice expire --blocks 432000
diff --git a/res/indexer-queries.graphql b/res/indexer-queries.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..0e979ae09a076c346ad6848380f9c702e64ebabe
--- /dev/null
+++ b/res/indexer-queries.graphql
@@ -0,0 +1,5 @@
+query IdentityNameByPubkey($pubkey: String!) {
+	identity_by_pk(id: $pubkey) {
+		name
+	}
+}
diff --git a/res/indexer-schema.graphql b/res/indexer-schema.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..4295c5b1087e564d3b38acf902d6f1eace0e7084
--- /dev/null
+++ b/res/indexer-schema.graphql
@@ -0,0 +1,2026 @@
+schema {
+  query: query_root
+  subscription: subscription_root
+}
+
+"""whether this query should be cached (Hasura Cloud only)"""
+directive @cached(
+  """measured in seconds"""
+  ttl: Int! = 60
+
+  """refresh the cache entry"""
+  refresh: Boolean! = false
+) on QUERY
+
+"""Table of accounts."""
+type account {
+  """An object relationship"""
+  block: block!
+  created_at: timestamptz!
+
+  """Block number where account was created."""
+  created_on: Int!
+
+  """
+  A computed field, executes function "has_identity"
+  """
+  has_identity: Boolean
+
+  """Pubkey of the account."""
+  id: String!
+
+  """An object relationship"""
+  identity: identity
+  killed_at: timestamptz
+
+  """Block number where account was killed."""
+  killed_on: Int
+
+  """An array relationship"""
+  transactions_issued(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): [transaction!]!
+
+  """An aggregate relationship"""
+  transactions_issued_aggregate(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): transaction_aggregate!
+
+  """An array relationship"""
+  transactions_received(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): [transaction!]!
+
+  """An aggregate relationship"""
+  transactions_received_aggregate(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): transaction_aggregate!
+}
+
+"""
+Boolean expression to filter rows from the table "account". All fields are combined with a logical 'AND'.
+"""
+input account_bool_exp {
+  _and: [account_bool_exp!]
+  _not: account_bool_exp
+  _or: [account_bool_exp!]
+  block: block_bool_exp
+  created_at: timestamptz_comparison_exp
+  created_on: Int_comparison_exp
+  has_identity: Boolean_comparison_exp
+  id: String_comparison_exp
+  identity: identity_bool_exp
+  killed_at: timestamptz_comparison_exp
+  killed_on: Int_comparison_exp
+  transactions_issued: transaction_bool_exp
+  transactions_received: transaction_bool_exp
+}
+
+"""Ordering options when selecting data from "account"."""
+input account_order_by {
+  block: block_order_by
+  created_at: order_by
+  created_on: order_by
+  has_identity: order_by
+  id: order_by
+  identity: identity_order_by
+  killed_at: order_by
+  killed_on: order_by
+  transactions_issued_aggregate: transaction_aggregate_order_by
+  transactions_received_aggregate: transaction_aggregate_order_by
+}
+
+"""
+select columns of table "account"
+"""
+enum account_select_column {
+  """column name"""
+  created_at
+
+  """column name"""
+  created_on
+
+  """column name"""
+  id
+
+  """column name"""
+  killed_at
+
+  """column name"""
+  killed_on
+}
+
+"""
+Streaming cursor of the table "account"
+"""
+input account_stream_cursor_input {
+  """Stream column input with initial value"""
+  initial_value: account_stream_cursor_value_input!
+
+  """cursor ordering"""
+  ordering: cursor_ordering
+}
+
+"""Initial value of the column from where the streaming should start"""
+input account_stream_cursor_value_input {
+  created_at: timestamptz
+
+  """Block number where account was created."""
+  created_on: Int
+
+  """Pubkey of the account."""
+  id: String
+  killed_at: timestamptz
+
+  """Block number where account was killed."""
+  killed_on: Int
+}
+
+"""Table of blocks."""
+type block {
+  created_at: timestamp!
+
+  """
+  Data contains `extrinsics` and `events` of the block. Exemple for querying
+  specific data: `data(path: "extrinsics[0].isSigned")`.
+  """
+  data(
+    """JSON select path"""
+    path: String
+  ): jsonb
+  hash: String!
+
+  """Index of the block in substrate."""
+  index: Int!
+}
+
+"""
+Boolean expression to filter rows from the table "block". All fields are combined with a logical 'AND'.
+"""
+input block_bool_exp {
+  _and: [block_bool_exp!]
+  _not: block_bool_exp
+  _or: [block_bool_exp!]
+  created_at: timestamp_comparison_exp
+  data: jsonb_comparison_exp
+  hash: String_comparison_exp
+  index: Int_comparison_exp
+}
+
+"""Ordering options when selecting data from "block"."""
+input block_order_by {
+  created_at: order_by
+  data: order_by
+  hash: order_by
+  index: order_by
+}
+
+"""
+select columns of table "block"
+"""
+enum block_select_column {
+  """column name"""
+  created_at
+
+  """column name"""
+  data
+
+  """column name"""
+  hash
+
+  """column name"""
+  index
+}
+
+"""
+Streaming cursor of the table "block"
+"""
+input block_stream_cursor_input {
+  """Stream column input with initial value"""
+  initial_value: block_stream_cursor_value_input!
+
+  """cursor ordering"""
+  ordering: cursor_ordering
+}
+
+"""Initial value of the column from where the streaming should start"""
+input block_stream_cursor_value_input {
+  created_at: timestamp
+
+  """
+  Data contains `extrinsics` and `events` of the block. Exemple for querying
+  specific data: `data(path: "extrinsics[0].isSigned")`.
+  """
+  data: jsonb
+  hash: String
+
+  """Index of the block in substrate."""
+  index: Int
+}
+
+"""
+Boolean expression to compare columns of type "Boolean". All fields are combined with logical 'AND'.
+"""
+input Boolean_comparison_exp {
+  _eq: Boolean
+  _gt: Boolean
+  _gte: Boolean
+  _in: [Boolean!]
+  _is_null: Boolean
+  _lt: Boolean
+  _lte: Boolean
+  _neq: Boolean
+  _nin: [Boolean!]
+}
+
+"""Table of certifications."""
+type certification {
+  created_at: timestamptz!
+
+  """Block number where certification was created."""
+  created_on: Int!
+
+  """An object relationship"""
+  created_on_block: block!
+
+  """An object relationship"""
+  issuer: identity!
+  issuer_id: String!
+
+  """An object relationship"""
+  receiver: identity!
+  receiver_id: String!
+}
+
+"""
+aggregated selection of "certification"
+"""
+type certification_aggregate {
+  aggregate: certification_aggregate_fields
+  nodes: [certification!]!
+}
+
+"""
+aggregate fields of "certification"
+"""
+type certification_aggregate_fields {
+  avg: certification_avg_fields
+  count(columns: [certification_select_column!], distinct: Boolean): Int!
+  max: certification_max_fields
+  min: certification_min_fields
+  stddev: certification_stddev_fields
+  stddev_pop: certification_stddev_pop_fields
+  stddev_samp: certification_stddev_samp_fields
+  sum: certification_sum_fields
+  var_pop: certification_var_pop_fields
+  var_samp: certification_var_samp_fields
+  variance: certification_variance_fields
+}
+
+"""
+order by aggregate values of table "certification"
+"""
+input certification_aggregate_order_by {
+  avg: certification_avg_order_by
+  count: order_by
+  max: certification_max_order_by
+  min: certification_min_order_by
+  stddev: certification_stddev_order_by
+  stddev_pop: certification_stddev_pop_order_by
+  stddev_samp: certification_stddev_samp_order_by
+  sum: certification_sum_order_by
+  var_pop: certification_var_pop_order_by
+  var_samp: certification_var_samp_order_by
+  variance: certification_variance_order_by
+}
+
+"""aggregate avg on columns"""
+type certification_avg_fields {
+  """Block number where certification was created."""
+  created_on: Float
+}
+
+"""
+order by avg() on columns of table "certification"
+"""
+input certification_avg_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""
+Boolean expression to filter rows from the table "certification". All fields are combined with a logical 'AND'.
+"""
+input certification_bool_exp {
+  _and: [certification_bool_exp!]
+  _not: certification_bool_exp
+  _or: [certification_bool_exp!]
+  created_at: timestamptz_comparison_exp
+  created_on: Int_comparison_exp
+  created_on_block: block_bool_exp
+  issuer: identity_bool_exp
+  issuer_id: String_comparison_exp
+  receiver: identity_bool_exp
+  receiver_id: String_comparison_exp
+}
+
+"""aggregate max on columns"""
+type certification_max_fields {
+  created_at: timestamptz
+
+  """Block number where certification was created."""
+  created_on: Int
+  issuer_id: String
+  receiver_id: String
+}
+
+"""
+order by max() on columns of table "certification"
+"""
+input certification_max_order_by {
+  created_at: order_by
+
+  """Block number where certification was created."""
+  created_on: order_by
+  issuer_id: order_by
+  receiver_id: order_by
+}
+
+"""aggregate min on columns"""
+type certification_min_fields {
+  created_at: timestamptz
+
+  """Block number where certification was created."""
+  created_on: Int
+  issuer_id: String
+  receiver_id: String
+}
+
+"""
+order by min() on columns of table "certification"
+"""
+input certification_min_order_by {
+  created_at: order_by
+
+  """Block number where certification was created."""
+  created_on: order_by
+  issuer_id: order_by
+  receiver_id: order_by
+}
+
+"""Ordering options when selecting data from "certification"."""
+input certification_order_by {
+  created_at: order_by
+  created_on: order_by
+  created_on_block: block_order_by
+  issuer: identity_order_by
+  issuer_id: order_by
+  receiver: identity_order_by
+  receiver_id: order_by
+}
+
+"""
+select columns of table "certification"
+"""
+enum certification_select_column {
+  """column name"""
+  created_at
+
+  """column name"""
+  created_on
+
+  """column name"""
+  issuer_id
+
+  """column name"""
+  receiver_id
+}
+
+"""aggregate stddev on columns"""
+type certification_stddev_fields {
+  """Block number where certification was created."""
+  created_on: Float
+}
+
+"""
+order by stddev() on columns of table "certification"
+"""
+input certification_stddev_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""aggregate stddev_pop on columns"""
+type certification_stddev_pop_fields {
+  """Block number where certification was created."""
+  created_on: Float
+}
+
+"""
+order by stddev_pop() on columns of table "certification"
+"""
+input certification_stddev_pop_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""aggregate stddev_samp on columns"""
+type certification_stddev_samp_fields {
+  """Block number where certification was created."""
+  created_on: Float
+}
+
+"""
+order by stddev_samp() on columns of table "certification"
+"""
+input certification_stddev_samp_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""
+Streaming cursor of the table "certification"
+"""
+input certification_stream_cursor_input {
+  """Stream column input with initial value"""
+  initial_value: certification_stream_cursor_value_input!
+
+  """cursor ordering"""
+  ordering: cursor_ordering
+}
+
+"""Initial value of the column from where the streaming should start"""
+input certification_stream_cursor_value_input {
+  created_at: timestamptz
+
+  """Block number where certification was created."""
+  created_on: Int
+  issuer_id: String
+  receiver_id: String
+}
+
+"""aggregate sum on columns"""
+type certification_sum_fields {
+  """Block number where certification was created."""
+  created_on: Int
+}
+
+"""
+order by sum() on columns of table "certification"
+"""
+input certification_sum_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""aggregate var_pop on columns"""
+type certification_var_pop_fields {
+  """Block number where certification was created."""
+  created_on: Float
+}
+
+"""
+order by var_pop() on columns of table "certification"
+"""
+input certification_var_pop_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""aggregate var_samp on columns"""
+type certification_var_samp_fields {
+  """Block number where certification was created."""
+  created_on: Float
+}
+
+"""
+order by var_samp() on columns of table "certification"
+"""
+input certification_var_samp_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""aggregate variance on columns"""
+type certification_variance_fields {
+  """Block number where certification was created."""
+  created_on: Float
+}
+
+"""
+order by variance() on columns of table "certification"
+"""
+input certification_variance_order_by {
+  """Block number where certification was created."""
+  created_on: order_by
+}
+
+"""ordering argument of a cursor"""
+enum cursor_ordering {
+  """ascending ordering of the cursor"""
+  ASC
+
+  """descending ordering of the cursor"""
+  DESC
+}
+
+"""
+Boolean expression to compare columns of type "Float". All fields are combined with logical 'AND'.
+"""
+input Float_comparison_exp {
+  _eq: Float
+  _gt: Float
+  _gte: Float
+  _in: [Float!]
+  _is_null: Boolean
+  _lt: Float
+  _lte: Float
+  _neq: Float
+  _nin: [Float!]
+}
+
+"""Table of identities."""
+type identity {
+  """An object relationship"""
+  account: account
+
+  """An array relationship"""
+  certifications_issued(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): [certification!]!
+
+  """An aggregate relationship"""
+  certifications_issued_aggregate(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): certification_aggregate!
+
+  """An array relationship"""
+  certifications_received(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): [certification!]!
+
+  """An aggregate relationship"""
+  certifications_received_aggregate(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): certification_aggregate!
+  confirmed_at: timestamptz
+
+  """Block number where identity was confirmed."""
+  confirmed_on: Int
+
+  """An object relationship"""
+  confirmed_on_block: block
+  created_at: timestamptz!
+
+  """Block number where identity was created."""
+  created_on: Int!
+
+  """An object relationship"""
+  created_on_block: block!
+
+  """Pubkey of the account associated to this identity."""
+  id: String!
+
+  """Name of the identity."""
+  name: String
+  revoked_at: timestamptz
+
+  """Block number where identity was revoked."""
+  revoked_on: Int
+
+  """An object relationship"""
+  revoked_on_block: block
+  validated_at: timestamptz
+
+  """Block number where identity was validated."""
+  validated_on: Int
+
+  """An object relationship"""
+  validated_on_block: block
+}
+
+"""
+Boolean expression to filter rows from the table "identity". All fields are combined with a logical 'AND'.
+"""
+input identity_bool_exp {
+  _and: [identity_bool_exp!]
+  _not: identity_bool_exp
+  _or: [identity_bool_exp!]
+  account: account_bool_exp
+  certifications_issued: certification_bool_exp
+  certifications_received: certification_bool_exp
+  confirmed_at: timestamptz_comparison_exp
+  confirmed_on: Int_comparison_exp
+  confirmed_on_block: block_bool_exp
+  created_at: timestamptz_comparison_exp
+  created_on: Int_comparison_exp
+  created_on_block: block_bool_exp
+  id: String_comparison_exp
+  name: String_comparison_exp
+  revoked_at: timestamptz_comparison_exp
+  revoked_on: Int_comparison_exp
+  revoked_on_block: block_bool_exp
+  validated_at: timestamptz_comparison_exp
+  validated_on: Int_comparison_exp
+  validated_on_block: block_bool_exp
+}
+
+"""Ordering options when selecting data from "identity"."""
+input identity_order_by {
+  account: account_order_by
+  certifications_issued_aggregate: certification_aggregate_order_by
+  certifications_received_aggregate: certification_aggregate_order_by
+  confirmed_at: order_by
+  confirmed_on: order_by
+  confirmed_on_block: block_order_by
+  created_at: order_by
+  created_on: order_by
+  created_on_block: block_order_by
+  id: order_by
+  name: order_by
+  revoked_at: order_by
+  revoked_on: order_by
+  revoked_on_block: block_order_by
+  validated_at: order_by
+  validated_on: order_by
+  validated_on_block: block_order_by
+}
+
+"""
+select columns of table "identity"
+"""
+enum identity_select_column {
+  """column name"""
+  confirmed_at
+
+  """column name"""
+  confirmed_on
+
+  """column name"""
+  created_at
+
+  """column name"""
+  created_on
+
+  """column name"""
+  id
+
+  """column name"""
+  name
+
+  """column name"""
+  revoked_at
+
+  """column name"""
+  revoked_on
+
+  """column name"""
+  validated_at
+
+  """column name"""
+  validated_on
+}
+
+"""
+Streaming cursor of the table "identity"
+"""
+input identity_stream_cursor_input {
+  """Stream column input with initial value"""
+  initial_value: identity_stream_cursor_value_input!
+
+  """cursor ordering"""
+  ordering: cursor_ordering
+}
+
+"""Initial value of the column from where the streaming should start"""
+input identity_stream_cursor_value_input {
+  confirmed_at: timestamptz
+
+  """Block number where identity was confirmed."""
+  confirmed_on: Int
+  created_at: timestamptz
+
+  """Block number where identity was created."""
+  created_on: Int
+
+  """Pubkey of the account associated to this identity."""
+  id: String
+
+  """Name of the identity."""
+  name: String
+  revoked_at: timestamptz
+
+  """Block number where identity was revoked."""
+  revoked_on: Int
+  validated_at: timestamptz
+
+  """Block number where identity was validated."""
+  validated_on: Int
+}
+
+"""
+Boolean expression to compare columns of type "Int". All fields are combined with logical 'AND'.
+"""
+input Int_comparison_exp {
+  _eq: Int
+  _gt: Int
+  _gte: Int
+  _in: [Int!]
+  _is_null: Boolean
+  _lt: Int
+  _lte: Int
+  _neq: Int
+  _nin: [Int!]
+}
+
+scalar jsonb
+
+input jsonb_cast_exp {
+  String: String_comparison_exp
+}
+
+"""
+Boolean expression to compare columns of type "jsonb". All fields are combined with logical 'AND'.
+"""
+input jsonb_comparison_exp {
+  _cast: jsonb_cast_exp
+
+  """is the column contained in the given json value"""
+  _contained_in: jsonb
+
+  """does the column contain the given json value at the top level"""
+  _contains: jsonb
+  _eq: jsonb
+  _gt: jsonb
+  _gte: jsonb
+
+  """does the string exist as a top-level key in the column"""
+  _has_key: String
+
+  """do all of these strings exist as top-level keys in the column"""
+  _has_keys_all: [String!]
+
+  """do any of these strings exist as top-level keys in the column"""
+  _has_keys_any: [String!]
+  _in: [jsonb!]
+  _is_null: Boolean
+  _lt: jsonb
+  _lte: jsonb
+  _neq: jsonb
+  _nin: [jsonb!]
+}
+
+"""column ordering options"""
+enum order_by {
+  """in ascending order, nulls last"""
+  asc
+
+  """in ascending order, nulls first"""
+  asc_nulls_first
+
+  """in ascending order, nulls last"""
+  asc_nulls_last
+
+  """in descending order, nulls first"""
+  desc
+
+  """in descending order, nulls first"""
+  desc_nulls_first
+
+  """in descending order, nulls last"""
+  desc_nulls_last
+}
+
+"""Table of key/value parameters."""
+type parameters {
+  key: String!
+  value(
+    """JSON select path"""
+    path: String
+  ): jsonb
+}
+
+"""
+Boolean expression to filter rows from the table "parameters". All fields are combined with a logical 'AND'.
+"""
+input parameters_bool_exp {
+  _and: [parameters_bool_exp!]
+  _not: parameters_bool_exp
+  _or: [parameters_bool_exp!]
+  key: String_comparison_exp
+  value: jsonb_comparison_exp
+}
+
+"""Ordering options when selecting data from "parameters"."""
+input parameters_order_by {
+  key: order_by
+  value: order_by
+}
+
+"""
+select columns of table "parameters"
+"""
+enum parameters_select_column {
+  """column name"""
+  key
+
+  """column name"""
+  value
+}
+
+"""
+Streaming cursor of the table "parameters"
+"""
+input parameters_stream_cursor_input {
+  """Stream column input with initial value"""
+  initial_value: parameters_stream_cursor_value_input!
+
+  """cursor ordering"""
+  ordering: cursor_ordering
+}
+
+"""Initial value of the column from where the streaming should start"""
+input parameters_stream_cursor_value_input {
+  key: String
+  value: jsonb
+}
+
+type query_root {
+  """
+  fetch data from the table: "account"
+  """
+  account(
+    """distinct select on columns"""
+    distinct_on: [account_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [account_order_by!]
+
+    """filter the rows returned"""
+    where: account_bool_exp
+  ): [account!]!
+
+  """fetch data from the table: "account" using primary key columns"""
+  account_by_pk(
+    """Pubkey of the account."""
+    id: String!
+  ): account
+
+  """
+  fetch data from the table: "block"
+  """
+  block(
+    """distinct select on columns"""
+    distinct_on: [block_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [block_order_by!]
+
+    """filter the rows returned"""
+    where: block_bool_exp
+  ): [block!]!
+
+  """fetch data from the table: "block" using primary key columns"""
+  block_by_pk(
+    """Index of the block in substrate."""
+    index: Int!
+  ): block
+
+  """
+  fetch data from the table: "certification"
+  """
+  certification(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): [certification!]!
+
+  """
+  fetch aggregated fields from the table: "certification"
+  """
+  certification_aggregate(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): certification_aggregate!
+
+  """fetch data from the table: "certification" using primary key columns"""
+  certification_by_pk(issuer_id: String!, receiver_id: String!): certification
+
+  """
+  fetch data from the table: "identity"
+  """
+  identity(
+    """distinct select on columns"""
+    distinct_on: [identity_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [identity_order_by!]
+
+    """filter the rows returned"""
+    where: identity_bool_exp
+  ): [identity!]!
+
+  """fetch data from the table: "identity" using primary key columns"""
+  identity_by_pk(
+    """Pubkey of the account associated to this identity."""
+    id: String!
+  ): identity
+
+  """
+  fetch data from the table: "parameters"
+  """
+  parameters(
+    """distinct select on columns"""
+    distinct_on: [parameters_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [parameters_order_by!]
+
+    """filter the rows returned"""
+    where: parameters_bool_exp
+  ): [parameters!]!
+
+  """fetch data from the table: "parameters" using primary key columns"""
+  parameters_by_pk(key: String!): parameters
+
+  """
+  execute function "search_identity" which returns "identity"
+  """
+  search_identity(
+    """
+    input parameters for function "search_identity"
+    """
+    args: search_identity_args!
+
+    """distinct select on columns"""
+    distinct_on: [identity_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [identity_order_by!]
+
+    """filter the rows returned"""
+    where: identity_bool_exp
+  ): [identity!]!
+
+  """
+  fetch data from the table: "transaction"
+  """
+  transaction(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): [transaction!]!
+
+  """
+  fetch aggregated fields from the table: "transaction"
+  """
+  transaction_aggregate(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): transaction_aggregate!
+
+  """fetch data from the table: "transaction" using primary key columns"""
+  transaction_by_pk(
+    """
+    Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+    """
+    id: Int!
+  ): transaction
+}
+
+input search_identity_args {
+  name: String
+}
+
+"""
+Boolean expression to compare columns of type "String". All fields are combined with logical 'AND'.
+"""
+input String_comparison_exp {
+  _eq: String
+  _gt: String
+  _gte: String
+
+  """does the column match the given case-insensitive pattern"""
+  _ilike: String
+  _in: [String!]
+
+  """
+  does the column match the given POSIX regular expression, case insensitive
+  """
+  _iregex: String
+  _is_null: Boolean
+
+  """does the column match the given pattern"""
+  _like: String
+  _lt: String
+  _lte: String
+  _neq: String
+
+  """does the column NOT match the given case-insensitive pattern"""
+  _nilike: String
+  _nin: [String!]
+
+  """
+  does the column NOT match the given POSIX regular expression, case insensitive
+  """
+  _niregex: String
+
+  """does the column NOT match the given pattern"""
+  _nlike: String
+
+  """
+  does the column NOT match the given POSIX regular expression, case sensitive
+  """
+  _nregex: String
+
+  """does the column NOT match the given SQL regular expression"""
+  _nsimilar: String
+
+  """
+  does the column match the given POSIX regular expression, case sensitive
+  """
+  _regex: String
+
+  """does the column match the given SQL regular expression"""
+  _similar: String
+}
+
+type subscription_root {
+  """
+  fetch data from the table: "account"
+  """
+  account(
+    """distinct select on columns"""
+    distinct_on: [account_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [account_order_by!]
+
+    """filter the rows returned"""
+    where: account_bool_exp
+  ): [account!]!
+
+  """fetch data from the table: "account" using primary key columns"""
+  account_by_pk(
+    """Pubkey of the account."""
+    id: String!
+  ): account
+
+  """
+  fetch data from the table in a streaming manner : "account"
+  """
+  account_stream(
+    """maximum number of rows returned in a single batch"""
+    batch_size: Int!
+
+    """cursor to stream the results returned by the query"""
+    cursor: [account_stream_cursor_input]!
+
+    """filter the rows returned"""
+    where: account_bool_exp
+  ): [account!]!
+
+  """
+  fetch data from the table: "block"
+  """
+  block(
+    """distinct select on columns"""
+    distinct_on: [block_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [block_order_by!]
+
+    """filter the rows returned"""
+    where: block_bool_exp
+  ): [block!]!
+
+  """fetch data from the table: "block" using primary key columns"""
+  block_by_pk(
+    """Index of the block in substrate."""
+    index: Int!
+  ): block
+
+  """
+  fetch data from the table in a streaming manner : "block"
+  """
+  block_stream(
+    """maximum number of rows returned in a single batch"""
+    batch_size: Int!
+
+    """cursor to stream the results returned by the query"""
+    cursor: [block_stream_cursor_input]!
+
+    """filter the rows returned"""
+    where: block_bool_exp
+  ): [block!]!
+
+  """
+  fetch data from the table: "certification"
+  """
+  certification(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): [certification!]!
+
+  """
+  fetch aggregated fields from the table: "certification"
+  """
+  certification_aggregate(
+    """distinct select on columns"""
+    distinct_on: [certification_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [certification_order_by!]
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): certification_aggregate!
+
+  """fetch data from the table: "certification" using primary key columns"""
+  certification_by_pk(issuer_id: String!, receiver_id: String!): certification
+
+  """
+  fetch data from the table in a streaming manner : "certification"
+  """
+  certification_stream(
+    """maximum number of rows returned in a single batch"""
+    batch_size: Int!
+
+    """cursor to stream the results returned by the query"""
+    cursor: [certification_stream_cursor_input]!
+
+    """filter the rows returned"""
+    where: certification_bool_exp
+  ): [certification!]!
+
+  """
+  fetch data from the table: "identity"
+  """
+  identity(
+    """distinct select on columns"""
+    distinct_on: [identity_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [identity_order_by!]
+
+    """filter the rows returned"""
+    where: identity_bool_exp
+  ): [identity!]!
+
+  """fetch data from the table: "identity" using primary key columns"""
+  identity_by_pk(
+    """Pubkey of the account associated to this identity."""
+    id: String!
+  ): identity
+
+  """
+  fetch data from the table in a streaming manner : "identity"
+  """
+  identity_stream(
+    """maximum number of rows returned in a single batch"""
+    batch_size: Int!
+
+    """cursor to stream the results returned by the query"""
+    cursor: [identity_stream_cursor_input]!
+
+    """filter the rows returned"""
+    where: identity_bool_exp
+  ): [identity!]!
+
+  """
+  fetch data from the table: "parameters"
+  """
+  parameters(
+    """distinct select on columns"""
+    distinct_on: [parameters_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [parameters_order_by!]
+
+    """filter the rows returned"""
+    where: parameters_bool_exp
+  ): [parameters!]!
+
+  """fetch data from the table: "parameters" using primary key columns"""
+  parameters_by_pk(key: String!): parameters
+
+  """
+  fetch data from the table in a streaming manner : "parameters"
+  """
+  parameters_stream(
+    """maximum number of rows returned in a single batch"""
+    batch_size: Int!
+
+    """cursor to stream the results returned by the query"""
+    cursor: [parameters_stream_cursor_input]!
+
+    """filter the rows returned"""
+    where: parameters_bool_exp
+  ): [parameters!]!
+
+  """
+  execute function "search_identity" which returns "identity"
+  """
+  search_identity(
+    """
+    input parameters for function "search_identity"
+    """
+    args: search_identity_args!
+
+    """distinct select on columns"""
+    distinct_on: [identity_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [identity_order_by!]
+
+    """filter the rows returned"""
+    where: identity_bool_exp
+  ): [identity!]!
+
+  """
+  fetch data from the table: "transaction"
+  """
+  transaction(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): [transaction!]!
+
+  """
+  fetch aggregated fields from the table: "transaction"
+  """
+  transaction_aggregate(
+    """distinct select on columns"""
+    distinct_on: [transaction_select_column!]
+
+    """limit the number of rows returned"""
+    limit: Int
+
+    """skip the first n rows. Use only with order_by"""
+    offset: Int
+
+    """sort the rows by one or more columns"""
+    order_by: [transaction_order_by!]
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): transaction_aggregate!
+
+  """fetch data from the table: "transaction" using primary key columns"""
+  transaction_by_pk(
+    """
+    Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+    """
+    id: Int!
+  ): transaction
+
+  """
+  fetch data from the table in a streaming manner : "transaction"
+  """
+  transaction_stream(
+    """maximum number of rows returned in a single batch"""
+    batch_size: Int!
+
+    """cursor to stream the results returned by the query"""
+    cursor: [transaction_stream_cursor_input]!
+
+    """filter the rows returned"""
+    where: transaction_bool_exp
+  ): [transaction!]!
+}
+
+scalar timestamp
+
+"""
+Boolean expression to compare columns of type "timestamp". All fields are combined with logical 'AND'.
+"""
+input timestamp_comparison_exp {
+  _eq: timestamp
+  _gt: timestamp
+  _gte: timestamp
+  _in: [timestamp!]
+  _is_null: Boolean
+  _lt: timestamp
+  _lte: timestamp
+  _neq: timestamp
+  _nin: [timestamp!]
+}
+
+scalar timestamptz
+
+"""
+Boolean expression to compare columns of type "timestamptz". All fields are combined with logical 'AND'.
+"""
+input timestamptz_comparison_exp {
+  _eq: timestamptz
+  _gt: timestamptz
+  _gte: timestamptz
+  _in: [timestamptz!]
+  _is_null: Boolean
+  _lt: timestamptz
+  _lte: timestamptz
+  _neq: timestamptz
+  _nin: [timestamptz!]
+}
+
+"""Table of transactions."""
+type transaction {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float!
+  created_at: timestamptz!
+
+  """Block number where transaction was created."""
+  created_on: Int!
+
+  """An object relationship"""
+  created_on_block: block!
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Int!
+
+  """An object relationship"""
+  issuer: account!
+  issuer_id: String!
+
+  """An object relationship"""
+  receiver: account!
+  receiver_id: String!
+}
+
+"""
+aggregated selection of "transaction"
+"""
+type transaction_aggregate {
+  aggregate: transaction_aggregate_fields
+  nodes: [transaction!]!
+}
+
+"""
+aggregate fields of "transaction"
+"""
+type transaction_aggregate_fields {
+  avg: transaction_avg_fields
+  count(columns: [transaction_select_column!], distinct: Boolean): Int!
+  max: transaction_max_fields
+  min: transaction_min_fields
+  stddev: transaction_stddev_fields
+  stddev_pop: transaction_stddev_pop_fields
+  stddev_samp: transaction_stddev_samp_fields
+  sum: transaction_sum_fields
+  var_pop: transaction_var_pop_fields
+  var_samp: transaction_var_samp_fields
+  variance: transaction_variance_fields
+}
+
+"""
+order by aggregate values of table "transaction"
+"""
+input transaction_aggregate_order_by {
+  avg: transaction_avg_order_by
+  count: order_by
+  max: transaction_max_order_by
+  min: transaction_min_order_by
+  stddev: transaction_stddev_order_by
+  stddev_pop: transaction_stddev_pop_order_by
+  stddev_samp: transaction_stddev_samp_order_by
+  sum: transaction_sum_order_by
+  var_pop: transaction_var_pop_order_by
+  var_samp: transaction_var_samp_order_by
+  variance: transaction_variance_order_by
+}
+
+"""aggregate avg on columns"""
+type transaction_avg_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Float
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Float
+}
+
+"""
+order by avg() on columns of table "transaction"
+"""
+input transaction_avg_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
+"""
+Boolean expression to filter rows from the table "transaction". All fields are combined with a logical 'AND'.
+"""
+input transaction_bool_exp {
+  _and: [transaction_bool_exp!]
+  _not: transaction_bool_exp
+  _or: [transaction_bool_exp!]
+  amount: Float_comparison_exp
+  created_at: timestamptz_comparison_exp
+  created_on: Int_comparison_exp
+  created_on_block: block_bool_exp
+  id: Int_comparison_exp
+  issuer: account_bool_exp
+  issuer_id: String_comparison_exp
+  receiver: account_bool_exp
+  receiver_id: String_comparison_exp
+}
+
+"""aggregate max on columns"""
+type transaction_max_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+  created_at: timestamptz
+
+  """Block number where transaction was created."""
+  created_on: Int
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Int
+  issuer_id: String
+  receiver_id: String
+}
+
+"""
+order by max() on columns of table "transaction"
+"""
+input transaction_max_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+  created_at: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+  issuer_id: order_by
+  receiver_id: order_by
+}
+
+"""aggregate min on columns"""
+type transaction_min_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+  created_at: timestamptz
+
+  """Block number where transaction was created."""
+  created_on: Int
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Int
+  issuer_id: String
+  receiver_id: String
+}
+
+"""
+order by min() on columns of table "transaction"
+"""
+input transaction_min_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+  created_at: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+  issuer_id: order_by
+  receiver_id: order_by
+}
+
+"""Ordering options when selecting data from "transaction"."""
+input transaction_order_by {
+  amount: order_by
+  created_at: order_by
+  created_on: order_by
+  created_on_block: block_order_by
+  id: order_by
+  issuer: account_order_by
+  issuer_id: order_by
+  receiver: account_order_by
+  receiver_id: order_by
+}
+
+"""
+select columns of table "transaction"
+"""
+enum transaction_select_column {
+  """column name"""
+  amount
+
+  """column name"""
+  created_at
+
+  """column name"""
+  created_on
+
+  """column name"""
+  id
+
+  """column name"""
+  issuer_id
+
+  """column name"""
+  receiver_id
+}
+
+"""aggregate stddev on columns"""
+type transaction_stddev_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Float
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Float
+}
+
+"""
+order by stddev() on columns of table "transaction"
+"""
+input transaction_stddev_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
+"""aggregate stddev_pop on columns"""
+type transaction_stddev_pop_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Float
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Float
+}
+
+"""
+order by stddev_pop() on columns of table "transaction"
+"""
+input transaction_stddev_pop_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
+"""aggregate stddev_samp on columns"""
+type transaction_stddev_samp_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Float
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Float
+}
+
+"""
+order by stddev_samp() on columns of table "transaction"
+"""
+input transaction_stddev_samp_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
+"""
+Streaming cursor of the table "transaction"
+"""
+input transaction_stream_cursor_input {
+  """Stream column input with initial value"""
+  initial_value: transaction_stream_cursor_value_input!
+
+  """cursor ordering"""
+  ordering: cursor_ordering
+}
+
+"""Initial value of the column from where the streaming should start"""
+input transaction_stream_cursor_value_input {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+  created_at: timestamptz
+
+  """Block number where transaction was created."""
+  created_on: Int
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Int
+  issuer_id: String
+  receiver_id: String
+}
+
+"""aggregate sum on columns"""
+type transaction_sum_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Int
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Int
+}
+
+"""
+order by sum() on columns of table "transaction"
+"""
+input transaction_sum_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
+"""aggregate var_pop on columns"""
+type transaction_var_pop_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Float
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Float
+}
+
+"""
+order by var_pop() on columns of table "transaction"
+"""
+input transaction_var_pop_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
+"""aggregate var_samp on columns"""
+type transaction_var_samp_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Float
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Float
+}
+
+"""
+order by var_samp() on columns of table "transaction"
+"""
+input transaction_var_samp_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
+"""aggregate variance on columns"""
+type transaction_variance_fields {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: Float
+
+  """Block number where transaction was created."""
+  created_on: Float
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: Float
+}
+
+"""
+order by variance() on columns of table "transaction"
+"""
+input transaction_variance_order_by {
+  """Amount of the transaction. 100 units = 1 Äž1."""
+  amount: order_by
+
+  """Block number where transaction was created."""
+  created_on: order_by
+
+  """
+  Primary Key `id` is used for postgreSQL and Hasura relationship, not related to any value in substrate.
+  """
+  id: order_by
+}
+
diff --git a/src/cache.rs b/src/cache.rs
new file mode 100644
index 0000000000000000000000000000000000000000..0a7d531ce9604eeeadf98239825de29a305fca29
--- /dev/null
+++ b/src/cache.rs
@@ -0,0 +1,73 @@
+use crate::indexer::*;
+use crate::Api;
+
+use anyhow::{anyhow, Result};
+use std::collections::{hash_map, HashMap};
+
+pub struct IdentityCache<'a> {
+    api: &'a Api,
+    identities: HashMap<u32, String>,
+    indexer: Option<(&'a reqwest::Client, &'a str)>,
+}
+
+impl<'a> IdentityCache<'a> {
+    pub fn new(api: &'a Api, indexer: Option<(&'a reqwest::Client, &'a str)>) -> Self {
+        Self {
+            api,
+            identities: HashMap::new(),
+            indexer,
+        }
+    }
+
+    pub async fn fetch_identity(
+        &mut self,
+        identity_id: u32,
+        parent_hash: sp_core::H256,
+    ) -> Result<String> {
+        Ok(match self.identities.entry(identity_id) {
+            hash_map::Entry::Occupied(entry) => entry.get().clone(),
+            hash_map::Entry::Vacant(entry) => entry
+                .insert({
+                    let pubkey = self
+                        .api
+                        .storage()
+                        .identity()
+                        .identities(&identity_id, Some(parent_hash))
+                        .await?
+                        .ok_or_else(|| anyhow!("Identity {} not found", identity_id))?
+                        .owner_key
+                        .to_string();
+                    if let Some((gql_client, gql_url)) = self.indexer {
+                        if let Ok(resp) = post_graphql::<IdentityNameByPubkey, _>(
+                            gql_client,
+                            gql_url,
+                            identity_name_by_pubkey::Variables {
+                                pubkey: pubkey.clone(),
+                            },
+                        )
+                        .await
+                        {
+                            if let Some(data) = resp.data {
+                                if let Some(identity) = data.identity_by_pk {
+                                    if let Some(name) = identity.name {
+                                        format!("“ {} ”", name)
+                                    } else {
+                                        pubkey
+                                    }
+                                } else {
+                                    pubkey
+                                }
+                            } else {
+                                pubkey
+                            }
+                        } else {
+                            pubkey
+                        }
+                    } else {
+                        pubkey
+                    }
+                })
+                .clone(),
+        })
+    }
+}
diff --git a/src/indexer.rs b/src/indexer.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9183a45d96faf561be4fbdacff809aa36214f446
--- /dev/null
+++ b/src/indexer.rs
@@ -0,0 +1,8 @@
+pub use graphql_client::{reqwest::post_graphql, GraphQLQuery};
+
+#[derive(GraphQLQuery)]
+#[graphql(
+    schema_path = "res/indexer-schema.graphql",
+    query_path = "res/indexer-queries.graphql"
+)]
+pub struct IdentityNameByPubkey;
diff --git a/src/main.rs b/src/main.rs
index f2beb9c7bcfb2958651a86466cccdb2228f7d0a2..f7ca9b0a31125eb3e05e76e0f02f8c31cc360435 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,6 @@
+mod cache;
+mod indexer;
+
 use anyhow::{anyhow, Context, Result};
 use clap::Parser;
 use codec::Encode;
@@ -5,6 +8,7 @@ use sp_core::{
     crypto::{AccountId32, DeriveJunction, Pair as _},
     sr25519::Pair,
 };
+use std::collections::BTreeMap;
 use subxt::sp_runtime::MultiAddress;
 use subxt::{
     extrinsic::{BaseExtrinsicParams, BaseExtrinsicParamsBuilder},
@@ -41,6 +45,12 @@ struct Args {
     #[clap(subcommand)]
     pub subcommand: Subcommand,
 
+    /// Indexer URL
+    #[clap(short, long, default_value = "https://idx.gdev.cgeek.fr/v1/graphql")]
+    indexer: String,
+    /// Do not use indexer
+    #[clap(long)]
+    no_indexer: bool,
     /// Secret key or BIP39 mnemonic
     /// (eventually followed by derivation path)
     #[clap(short, long)]
@@ -70,6 +80,15 @@ pub enum Subcommand {
         #[clap(long = "rem-one")]
         remaining_to_oneshot: bool,
     },
+    /// List upcoming expirations that require an action
+    Expire {
+        /// Show certs that expire within less than this number of blocks
+        #[clap(short, long, default_value_t = 100800)]
+        blocks: u32,
+        /// Show authorities that should rotate keys within less than this number of sessions
+        #[clap(short, long, default_value_t = 100)]
+        sessions: u32,
+    },
     /// Generate a revocation document for the provided account
     GenRevocDoc,
     OneshotBalance {
@@ -109,6 +128,10 @@ async fn main() -> Result<()> {
         .with_context(|| "fail to connect to node")?;
     let api = client.clone().to_runtime_api::<Api>();
 
+    let gql_client = reqwest::Client::builder()
+        .user_agent("gcli/0.1.0")
+        .build()?;
+
     let account_id: sp_core::crypto::AccountId32 = pair.public().into();
     let account = api.storage().system().account(&account_id, None).await?;
     logs::info!("Account free balance: {}", account.data.free);
@@ -184,6 +207,153 @@ async fn main() -> Result<()> {
                 )
                 .await?;
         }
+        Subcommand::Expire { blocks, sessions } => {
+            let parent_hash = api.storage().system().parent_hash(None).await?;
+            let current_block = api.storage().system().number(Some(parent_hash)).await?;
+            let current_session = api
+                .storage()
+                .session()
+                .current_index(Some(parent_hash))
+                .await?;
+            let end_block = current_block + blocks;
+            let end_session = current_session + sessions;
+
+            let mut identity_cache = cache::IdentityCache::new(
+                &api,
+                if args.no_indexer {
+                    None
+                } else {
+                    Some((&gql_client, &args.indexer))
+                },
+            );
+
+            // Rotate keys
+            let mut must_rotate_keys_before_iter = client
+                .storage()
+                .iter::<gdev_300::authority_members::storage::MustRotateKeysBefore>(Some(
+                    parent_hash,
+                ))
+                .await?;
+            let mut must_rotate_keys_before = BTreeMap::new();
+            while let Some((k, v)) = must_rotate_keys_before_iter.next().await? {
+                let session_index = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
+                if session_index < end_session {
+                    must_rotate_keys_before.insert(session_index - current_session, v);
+                }
+            }
+
+            println!("\nAuthority members:");
+            for (sessions_left, identity_ids) in must_rotate_keys_before {
+                println!("Must rotate keys before {} sessions:", sessions_left);
+                for identity_id in identity_ids {
+                    println!(
+                        "  {} ({})",
+                        identity_cache
+                            .fetch_identity(identity_id, parent_hash)
+                            .await
+                            .unwrap_or_else(|_| "?".into()),
+                        identity_id
+                    );
+                }
+            }
+
+            // Certifications
+            let mut basic_certs_iter = client
+                .storage()
+                .iter::<gdev_300::cert::storage::StorageCertsRemovableOn>(Some(parent_hash))
+                .await?;
+            let mut basic_certs = BTreeMap::new();
+            while let Some((k, v)) = basic_certs_iter.next().await? {
+                let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
+                if block_number < end_block {
+                    basic_certs.insert(block_number - current_block, v);
+                }
+            }
+
+            let mut smith_certs_iter = client
+                .storage()
+                .iter::<gdev_300::smiths_cert::storage::StorageCertsRemovableOn>(Some(parent_hash))
+                .await?;
+            let mut smith_certs = BTreeMap::new();
+            while let Some((k, v)) = smith_certs_iter.next().await? {
+                let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
+                if block_number < end_block {
+                    smith_certs.insert(block_number - current_block, v);
+                }
+            }
+
+            for (title, certs) in [
+                ("Certifications", basic_certs),
+                ("Smith certifications", smith_certs),
+            ] {
+                println!("\n{}:", title);
+                for (blocks_left, certs) in certs {
+                    println!("{} blocks before expiration:", blocks_left);
+                    for (issuer_id, receiver_id) in certs {
+                        println!(
+                            "  {} ({}) -> {} ({})",
+                            identity_cache
+                                .fetch_identity(issuer_id, parent_hash)
+                                .await
+                                .unwrap_or_else(|_| "?".into()),
+                            issuer_id,
+                            identity_cache
+                                .fetch_identity(receiver_id, parent_hash)
+                                .await
+                                .unwrap_or_else(|_| "?".into()),
+                            receiver_id,
+                        );
+                    }
+                }
+            }
+
+            // Memberships
+            let mut basic_membership_iter = client
+                .storage()
+                .iter::<gdev_300::membership::storage::MembershipsExpireOn>(Some(parent_hash))
+                .await?;
+            let mut basic_memberships = BTreeMap::new();
+            while let Some((k, v)) = basic_membership_iter.next().await? {
+                let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
+                if block_number < end_block {
+                    basic_memberships.insert(block_number - current_block, v);
+                }
+            }
+
+            let mut smith_membership_iter = client
+                .storage()
+                .iter::<gdev_300::smiths_membership::storage::MembershipsExpireOn>(Some(
+                    parent_hash,
+                ))
+                .await?;
+            let mut smith_memberships = BTreeMap::new();
+            while let Some((k, v)) = smith_membership_iter.next().await? {
+                let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
+                if block_number < end_block {
+                    smith_memberships.insert(block_number - current_block, v);
+                }
+            }
+
+            for (title, memberships) in [
+                ("Memberships", basic_memberships),
+                ("Smith memberships", smith_memberships),
+            ] {
+                println!("\n{}:", title);
+                for (blocks_left, membership) in memberships {
+                    println!("{} blocks before expiration:", blocks_left);
+                    for identity_id in membership {
+                        println!(
+                            "  {} ({})",
+                            identity_cache
+                                .fetch_identity(identity_id, parent_hash)
+                                .await
+                                .unwrap_or_else(|_| "?".into()),
+                            identity_id,
+                        );
+                    }
+                }
+            }
+        }
         Subcommand::GenRevocDoc => gen_revoc_doc(&api, &pair).await?,
         Subcommand::OneshotBalance { account } => {
             logs::info!(