2

I am trying to write a decoder for data which generates by contracts pallet. For this purpose i have to convert metadata types to types which are supported by scale decoder which i use. Where i can found information about types available in contract's metadata?

Now i have this code but i am not sure that it will cover all possible types in contract's metadata:

import {Type, TypeKind} from "@subsquid/scale-codec"
import {TypeDef} from "./interfaces"
import assert from "assert"


export function normalizeTypes(types: TypeDef[]): Type[] {
    return types.map(type => {
        let keys = Object.keys(type.type.def)
        assert(keys.length == 1)
        switch(keys[0]) {
            case 'primitive':
                return {
                    kind: TypeKind.Primitive,
                    primitive: type.type.def.primitive.toUpperCase(),
                }
            case 'composite':
                return {
                    kind: TypeKind.Composite,
                    fields: type.type.def.composite.fields,
                }
            case 'array':
                return {
                    kind: TypeKind.Array,
                    len: type.type.def.array.len,
                    type: type.type.def.array.type,
                }
            case 'tuple':
                return {
                    kind: TypeKind.Tuple,
                    tuple: type.type.def.tuple,
                }
            case 'variant':
                return {
                    kind: TypeKind.Variant,
                    variants: type.type.def.variant.variants.map((variant: any) => {
                        return {
                            ...variant,
                            fields: variant.fields || [],
                        }
                    }),
                }
            default:
                throw new Error(`Unexpected type '${keys[0]}'`)
        }
    })
}

1 Answer 1

2

The available types come from the scale-info crate. The types get broken down into one of eight categories, as you can see here.

pub enum TypeDef {
    /// A composite type (e.g. a struct or a tuple)
    Composite,
    /// A variant type (e.g. an enum)
    Variant,
    /// A sequence type with runtime known length.
    Sequence,
    /// An array type with compile-time known length.
    Array,
    /// A tuple type.
    Tuple,
    /// A Rust primitive type.
    Primitive,
    /// A type using the [`Compact`] encoding
    Compact,
    /// A type representing a sequence of bits.
    BitSequence,
}

However, we realize that it sucks to have to hardcode this validation in your code. We've recently started working on a JSON Schema for the ink! metadata so that things like types can be programatically verified. Here's a preview of the schema for ink!'s metadata.

If you dig in there you can see that types are described by PortableType and TypeDef_for_PortableForm. You should be able to use those to decode the given types.

"TypeDef_for_PortableForm": {
  "description": "The possible types a SCALE encodable Rust value could have....",
  "oneOf": [
    {
      "description": "A composite type (e.g. a struct or a tuple)",
      "type": "object",
      "required": [
        "composite"
      ],
      "properties": {
        "composite": {
          "$ref": "#/definitions/TypeDefComposite_for_PortableForm"
        }
      },
      "additionalProperties": false
    },
    {
      "description": "A variant type (e.g. an enum)",
      "type": "object",
      "required": [
        "variant"
      ],
      "properties": {
        "variant": {
          "$ref": "#/definitions/TypeDefVariant_for_PortableForm"
        }
      },
      "additionalProperties": false
    },
    {
      "description": "A sequence type with runtime known length.",
      "type": "object",
      "required": [
        "sequence"
      ],
      "properties": {
        "sequence": {
          "$ref": "#/definitions/TypeDefSequence_for_PortableForm"
        }
      },
      "additionalProperties": false
    },
    {
      "description": "An array type with compile-time known length.",
      "type": "object",
      "required": [
        "array"
      ],
      "properties": {
        "array": {
          "$ref": "#/definitions/TypeDefArray_for_PortableForm"
        }
      },
      "additionalProperties": false
    },
    {
      "description": "A tuple type.",
      "type": "object",
      "required": [
        "tuple"
      ],
      "properties": {
        "tuple": {
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint32",
            "minimum": 0.0
          }
        }
      },
      "additionalProperties": false
    },
    {
      "description": "A Rust primitive type.",
      "type": "object",
      "required": [
        "primitive"
      ],
      "properties": {
        "primitive": {
          "$ref": "#/definitions/TypeDefPrimitive"
        }
      },
      "additionalProperties": false
    },
    {
      "description": "A type using the [`Compact`] encoding",
      "type": "object",
      "required": [
        "compact"
      ],
      "properties": {
        "compact": {
          "$ref": "#/definitions/TypeDefCompact_for_PortableForm"
        }
      },
      "additionalProperties": false
    },
    {
      "description": "A type representing a sequence of bits.",
      "type": "object",
      "required": [
        "bitsequence"
      ],
      "properties": {
        "bitsequence": {
          "$ref": "#/definitions/TypeDefBitSequence_for_PortableForm"
        }
      },
      "additionalProperties": false
    }
  ]
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.