We've touched upon types in most previous sections, i.e. that these are driven by metadata and that they are created and converted to/from automatically by the API. Since they appear in all results, we will divert a bit from the regularly scheduled program in explaining the API interfaces to giving some info on the base types.
#Everything is a type
Just to re-iterate from the above. Everything returned by the API is a type and has a consistent interface:
Codec. This means that a
Vec<u32> (an array of
u32 values) as well as a
Struct (an pre-defined object) or an
Enum has the same consistent base interface. Specific types types will have values, based on the type - decorated and available.
As a minimum, anything returned by the API, be it a
Struct or any normal type will always have the following methods - as defined on the
.eq(<other value>)- checks for equality against the other value. In all cases, it will accept "like" values, i.e. in the case of a number you can pass a primitive (such as
1), a hex value (such as
0x01) or even an
toHex()- returns a hex-base representation of the value, always prefixed by
toHuman()- returns Human-parsable JSON structure with values formatted as per the settings
toJSON()- returns a JSON-like representation of the value, this is generally used when calling
JSON.stringify(...)on the value
toString()- returns a string representation, in some cases this performs additional encoding, i.e. for
AccountIndexit will encode to the ss58 address
.toU8a()- returns a
Uint8Arrayrepresentation of the encoded value (generally exactly as passed to the node, where values are SCALE encoded)
Additionally, the following getters and utilities are available -
trueif the value is an all-empty value, i.e.
0in for numbers, all-zero for Arrays (or anything
Hash(once again with all the methods above) that is a
blake2-256representation of the contained value
To reiterate the above API, the
#Working with numbers
All numbers wrap and extend an instance of bn.js. This means that in addition to the interfaces defined above, they have some additional methods -
.toNumber()- a JS number (limited to 2^53 - 1). This does mean that for large values, e.g.
u128extension), this can cause overflows
.toBigInt()- a JS
BigIntobject (on supported platforms)
.sub(...), ... - all the base methods available on the
In cases where a
Compact is returned, i.e.
Compact<Balance>, the value is wrapped. This object should be
.unwrap()-ed first to gain access to the underlying
#Working with structures
All structures, a wrapping of an object containing a number of member variables, is an implementation of a standard JS
Map object, so all the functions available on a
Map such as
.entries() are available. Additionally it is decorated with actual getters for the fields.
As an example, a
Header will have getters for the
.digest fields. The same applies for all structures, as they are returned, each member will have an associated getter.
Be aware that in the JS version naming defaults to
camelCase where names of fields in Substrate defaults to
snake_case. (Each version aligning with conventions in the respective languages)
#Working with enums
Each enum has additional getters which are injected based on the fields wrapped. These take the form of
.as<Name> to allow you to check is the enum is a certain value or to retrieve the underlying value as a specific type.
As a real-world example, when an extrinsic is applied, the
Phase enum has one of two states,
Finalization. In this case
.isApplyExtrinsic would be
true when an extrinsic is being applied, and
.asApplyExtrinsic would return the value as a
u32 (which is the index of the extrinsic in the block, as it is being applied). When
asApplyExtrinsic is called, the getter will throw.
#Working with Option<Type>
Option<Type> attempts to mimic the Rust approach of having
Some available. This means the following getters & methods are available on an
trueif no underlying values is wrapped, effectively the same as
.isSome- this is
trueis a value is wrapped, i.e. if a
Option<u32>has an actual underlying
isSome, this will return the wrapped value, i.e. for
Option<u32>, this would return the
u32. When the value is
isNone, this call will throw an exception.
.unwrapOr(<default value>)- this extends
unwrap(), returning the wrapped value when
isSomeand in the case of
isNoneit will return the
.unwrapOrDefault()- returns either the wrapped value when
isSome, or the default for the type when
#Working with Tuples
A tuple is defined in the form of
(u32, AccountId). To access the individual values, you can access it via its index, i.e.
When making a call that expect a
Tuple input, pass it as an array, so to pass the example above into a call, it would be
bool values are returned as nomal JS
Booolean objects, i.e. they extend the JS Boolean to allow it to be used as a
In addition to the default
getValue() on the JS Boolean and the default interfaces explained above, two additional getters have been added for ease-of-use. These are
isFalse that will just return a normal JS primitive
boolean for a quick check without using
For customized chains, the need exists to register types so the API is aware of how to decode values for those types. The next section will provide a walk-through for the definition of custom types allowing the definition or re-definition of any type the API is aware of.