Schema Format

Psibase has a schema format which describes the fracpack-format data and JSON-format data it uses for action arguments, event content, and database content.

Type Definitions

Types are represented by a variant with the following alternatives.

Int

A fixed size integer.

FieldTypeDescription
bitsIntegerThe width of the integer in bits.
isSignedBooleanWhether the integer is signed

Implementations MUST support 1, 8, 16, 32, and 64 bit integers and MAY support additional widths.

Float

A floating point number.

FieldTypeDescription
expIntegerThe number of bits in the exponent
mantissaIntegerThe number of bits in the mantissa (including the leading 1)

Implementations MUST support single {"exp":8,"mantissa":24} and double {"exp":11,"mantissa":53} precision and MAY support additional combinations.

Struct

A non-extensible user defined type. The order of the struct fields is significant.

{
  "Struct" : {
    "i": <field type>,
    "j": <field type>,
    ...
  }
}

Object

An extensible user defined type. The order of the object fields is significant.

{
  "Object" : {
    "i": <field type>,
    "j": <field type>,
    ...
  }
}

Tuple

A tuple type.

{
  "Tuple" : [
    <type>, <type>, ...
  ]
}

Array

A fixed length array type.

FieldTypeDescription
typeTypeThe element type of the array
lenIntegerThe number of elements in the array

List

A variable size list.

{
  "List": <element type>
}

Option

An optional value.

{
  "Option": <element type>
}

Variant

A variant type. The order of alternatives is significant.

{
  "Variant" : {
    "u": <alternative type>,
    "v": <alternative type>,
    ...
  }
}

Alternatives whose names begin with @ are untagged. The result of parsing JSON that matches more than one alternative is unspecified.

Note: Since JSON parsing is quite permissive, types might match unexpectedly. It's most reliable to have no more than one untagged alternative in a variant.

FracPack

{
  "FracPack": <nested type>
}

This is encoded as a byte vector {"List": {"Int": {"bits": 8,"isSigned": false}}}.

Custom

A type with a custom JSON representation.

FieldTypeDescription
typeTypeThe underlying type
idStringIdentifies the custom representation. If the implementation does not know the id, it SHOULD fall back to the underlying type.

Implementations should support at least the following custom types

IdUnderlying TypeJSON format
boolu1true or false
hexAny fixed size type, List of fixed size types, or nested FracPackHex string
stringList of 8-bit integersString
mapList of Object, Struct, or Tuple with exactly two membersJSON Object

These custom types are used by psibase

IdUnderlying TypeJSON format
AccountNumberu64String
TimePointSecAny integer type representing seconds since the UNIX epochISO 8601 Extended
TimePointUSecAny integer type representing microseconds since the UNIX epochISO 8601 Extended

Named Type

A String used where a type is expected will be treated as a named type. The actual type will be looked up the the type map.

Type Map

A schema includes a map of named types. This is required to allow recursive type definitions. Type names that begin with "@" are internal to the schema and MAY be renamed any time the schema is processed.

TODO

  • tables

Schema Schema

The schema schema defines both the JSON format and the binary (fracpack) format of schemas.

{
  "ServiceSchema": {
    "Object": {
      "service": "@AccountNumber",
      "types": "@typemap",
      "actions": "@actions",
      "ui": "@events",
      "history": "@events",
      "merkle": "@events"
    }
  },
  "@typemap": {
    "Custom": {
      "id": "map",
      "type": {"List":{"Object": {"name": "@string", "type": "@type"}}}
    }
  },
  "@actions": {
    "Custom": {
      "id": "map",
      "type": {"List": {"Object": {"name":"@string", "type": "@fn"}}}
    }
  },
  "@events": {
    "Custom": {
      "id": "map",
      "type": {"List": {"Object": {"name":"@string", "type": "@type"}}}
    }
  },
  "@fn": {
    "params": "@type",
    "result": {"Option": "@type"}
  },
  "@type": {
    "Variant": {
      "Struct": "@typemap",
      "Object": "@typemap",
      "Array": {"Object": {"type": "@type", "len": "@u64"}},
      "List": "@type",
      "Option": "@type",
      "Variant": "@typemap",
      "Tuple": {"List": "@type"},
      "Int": {"Object": {"bits": "@u32", "isSigned": "@bool"}},
      "Float": {"Object": {"exp": "@u32", "mantissa": "@u32"}},
      "FracPack": "@type",
      "Custom": {"Object": {"type": "@type", "id": "@string"}},
      "@Type": "@string",
    }
  },
  "@u8": {"Int": {"bits": 8, "isSigned": false}},
  "@u32": {"Int": {"bits": 32, "isSigned": false}},
  "@u64": {"Int": {"bits": 64, "isSigned": false}},
  "@bool": {"Custom": {"id": "bool", "type": {"Int": {"bits": 1, "isSigned": false}}}},
  "@string": {"Custom": {"id": "string", "type": {"List": "@u8"}}},
  "@AccountNumber": {"Custom": {"id": "AccountNumber", "type": "@u64"}}
}