0 votes
1 view
in Blockchain by (5.2k points)

Using the Substrate blockchain framework, how can I convert between Substrate specific types and Rust primitive types and vice versa?

For example:

Convert a time (T::Moment) to a u64
Convert a u64 to a T::Balance
etc...

1 Answer

0 votes
by (11k points)

The substrate has removed as in favor of From/Into. An assumption is made that all types are u32 at least.

Using the trait SimpleArithmatic, the following can be implemented:

From: u8, u16, u32

TryFrom: u64, u128, usize

TryInto: u8, u16, u32, u64, u128, usize

Another trait is also provided to provide ergonomic infallible conversion when you don't care if the value saturates.

UniqueSaturatedInto: u8, u16, u32, u64, u128

UniqueSaturatedFrom: u64, u128

This makes the conversion from u32 to Substrate specific types relatively easy:

pub fn u32_to_balance(input: u32) -> T::Balance {

    input.into()

}

For larger types, you need to handle cases where the Balance type for a run-time is smaller than what is available:

pub fn u64_to_balance_option(input: u64) -> Option<T::Balance> {

    input.try_into().ok()

}

// Note the warning about saturated conversions

pub fn u64_to_balance_saturated(input: u64) -> T::Balance {

    input.saturated_into()

}

While converting from T:Balance to rust primitive, users should also handle conversion between incompatible types:

pub fn balance_to_u64(input: T::Balance) -> Option<u64> {

    TryInto::<u64>::try_into(input).ok()

}

For Substrate v1.0

The substrate provides pub trait as <T> in the sr-primitives crate:

/// Simple trait similar to `Into`, except that it can be used to convert numerics between each

/// other.

pub trait As<T> {

    /// Convert forward (ala `Into::into`).

    fn as_(self) -> T;

    /// Convert backward (ala `From::from`).

    fn sa(_: T) -> Self;

}

Here are some working examples:

impl<T: Trait> Module<T> {

    // `as_` will turn T::Balance into a u64

    pub fn balance_to_u64(input: T::Balance) -> u64 {

        input.as_()

    }

    // Being explicit, you can convert a `u64` to a T::Balance

    // using the `As` trait, with `T: u64`, and then calling `sa`

    pub fn u64_to_balance(input: u64) -> T::Balance {

        <T::Balance as As<u64>>::sa(input)

    }

    // You can also let Rust figure out what `T` is

    pub fn u64_to_balance_implied(input: u64) -> T::Balance {

        <T::Balance as As<_>>::sa(input)

    }

    // You can also let Rust figure out where `sa` is implemented

    pub fn u64_to_balance_implied_more(input: u64) -> T::Balance {

        T::Balance::sa(input)

    }

}

...