Lookup Service

Lookup service is the entry point for every of our services to find exact indexes in order to form requests in a proper way.

Here is its interface:

interface SubstrateLookup {
    fun findModule(name: String): Flow<RuntimeModule?>
    fun findConstant(moduleName: String, constantName: String): Flow<RuntimeModuleConstant?>
    fun findStorageItem(moduleName: String, itemName: String): Flow<FindStorageItemResult?>
    fun findRuntimeType(index: BigInteger): Flow<RuntimeType?>
}

Everything is returned as Kotlin's Flow because runtime metadata is considered as endless flow, even though it's supposed to be updated only like once a minute by default. This might be useful if you want to automatically update values on some constants, or storage values to display on your mobile (or not so mobile) application.

To access lookup service simply use this:

val client: SubstrateClient
val lookupService: SubstrateLookup = client.lookup

Modules

As per our library, modules are defined this way:

data class RuntimeModule(
    val name: String,
    val storage: RuntimeModuleStorage?,
    val callIndex: BigInteger?,
    val eventsIndex: BigInteger?,
    val constants: List<RuntimeModuleConstant>,
    val errorsIndex: BigInteger?,
    val indexUInt8: UInt8
) {
    val index: UInt32 get() = indexUInt8.toUInt()
}

Extra index added for more convenience. We still don't know why this can be used, but its accompanying UByte/UInt8 value is not very useful, so feel free to give us a feedback.

This is the core runtime metadata's component, which we rely on for most of our logic.

You're free to use this as much as you want to create your special behavior.

Constants

Constants is the one of the parts of each module/pallet. It's absolutely the same as in Substrate:

data class RuntimeModuleConstant(
    val name: String,
    val type: BigInteger,
    private val valueListOfInt8: List<Int8>,
    val docs: List<String>
) {
    val value get() = valueListOfInt8.toByteArray()
}

Here, our convenience getter of value is very useful finally. In the SCALE codec it's simply array (List in our case) of bytes, so we added this here just once to avoid always converting it to Kotlin's byte array at every single place.

Name is the name which you just provided in search, type is its index in metadata, and value as described above: byte representation in SCALE coding of value in it.

Still, play with this as much as you want. But we strongly encourage using our constants service directly.

Storage

Same, as for constants, it's better to use our storage service in case if you want to get actual values. But if you have specific needs, don't hesitate to use it in whatever way you want. Here is its declaration:

data class RuntimeModuleStorage(
    val prefix: String,
    val items: List<RuntimeModuleStorageItem>
)

You can go deeper to analyze its contents, at least its storage item subtype:

data class RuntimeModuleStorageItem(
    val name: String,
    val modifier: RuntimeModuleStorageItemModifier,
    val type: RuntimeModuleStorageItemType,
    private val fallbackListOfInt8: List<Int8>,
    val docs: List<String>
) {
    val fallback get() = fallbackListOfInt8.toByteArray()
}

At least for getting names of these items. But storage key generation for RPC calls is not the easiest thing, so again, our storage service is your very best friend here.

Runtime types resolving

If you want to get the declaration of exact type by its index you can definitely use findRuntimeType method. It has a long list of subtypes, so if you really want to dive so deep, please look at this at our API reference website.

Last updated