Substrate Runtime Metadata
September 7, 2019
Blockchain
Substrate
Inspecting a Runtime's Metadata can help you out in the following scenarios:
- You want to interact with a Substrate blockchain, but don't have much idea about what features the blockchain provides.
- You want to show the available storage entries and dispatchable functions for users who are using the GUI.
Substrate provides module-based metadata to give an overview of your blockchain runtime. It helps an external client to introspect each module's, storage items, dispatchable functions, and events.
SRML Metadata
In Substrate, the runtime metadata is consolidated and encoded automatically when developing runtime modules. The built-in Metadata module doesn't provide any additional storage entries, dispatchable functions or events. It simply provides the data structure to store the metadata of your blockchain runtime, and related codec to convert between raw data and bytes literal in SCALE (Simple Concatenated Aggregate Little-Endian) format.
Before we dive into more detail, let's have a quick look at what information is included in the metadata. For demo purposes, we'll only show metadata of the Sudo module in JSON format:
{
"modules":[
{
"name":"sudo",
"prefix":"Sudo",
"storage":[
{
"name":"Key",
"modifier":"Default",
"type":{
"PlainType":"AccountId"
},
"fallback":"0x0000000000000000000000000000000000000000000000000000000000000000",
"documentation":[
" The `AccountId` of the sudo key."
]
}
],
"calls":[
{
"name":"sudo",
"args":[
{
"name":"proposal",
"type":"Proposal"
}
],
"documentation":[
" Authenticates the sudo key and dispatches a function call with `Root` origin."
]
},
...
],
"events":[
{
"name":"Sudid",
"args":[
"bool"
],
"documentation":[
" A sudo just took place."
]
},
...
]
}
]
}
Here we are using
V4
of the runtime metadata. Go to its reference document for more versioning information.
The metadata of an entire runtime is an array of its modules’ metadata, including all SRML and custom runtime modules in your blockchain. You can also find the decoded metadata of all build-in modules in Polkadot-js/api.
Now let's walk through each field in module's metadata:
name
: the module's name.prefix
: the name of module's store.storage
: all the available storage entries in the module. Each storage entry is composed of:name
: the storage entry's name.modifier
: whether the entry isOptional
orDefault
.type
: the type of the storage entry, could bePlainType
,MapType
orDoubleMapType
.fallback
: the default value if the entry has not been set.documentation
: notes for the entry.
calls
: an array of dispatchable functions:name
: the function's name.args
: the arguments in function's definition, each includes parameter name and type.documentation
: notes for the function.
event
: all the defined events in a module:name
: the event's name.args
: the arguments in the event definition.documentation
: notes for the event.
Fetch The Metadata
If you are using Javascript, polkadot-js/api already provides friendly APIs to interact with Substrate blockchain, including the getMetadata function. You can try the following code snippets to fetch the metadata in this Substrate UI page:
const { magicNumber, metadata } = await api.rpc.state.getMetadata();
console.log( 'Magic number: ' + magicNumber );
console.log( 'Metadata: ' + metadata.raw );
If you are using other languages to build your client, you can easily send a WebSocket message or HTTP POST request to a Substrate node endpoint by using any existing client. The message or body for getMetadata
is:
{
"id": 1,
"jsonrpc": "2.0",
"method": "state_getMetadata",
"params": []
}
The response looks like following contents, but with much more information in result
field:
{
"jsonrpc": "2.0",
"result": "0x6d65746104241873797374656d1853797374656d012c304163636f756e744e6f6e636501010130543a3a4163636f756e74...",
"id": 1
}
The hexadecimal string in the result
field wraps the runtime metadata in SCALE format. Go to Low-level Data Format page to learn how to decode different types and get more information about the specification and implementations.
Our hex blob starts with a hard coded magic number 6d657461
which represents meta in plain text. The next piece of data shows the version number of the metadata, here we are using 04
to represent version 4. We already mentioned that runtime metadata is composed by available modules. In our case we have 9 modules. After shifting 9 in binary representation two bits to the left, we get 24
in hex to represent the length of the array.
The remaining blob encodes the metadata of each module. Learning more about decoding different types in the struct, please refer to the reference docs and Low-level Data Format page.
After decoding the hex blob successfully, you should be able to see similar metadata in the above example.