Messages

Messages are the highest level of abstraction in integrations built on top of the Encoding Subsystem, but also the strictest.

Apophis allows integrating new types for de/serialization with standard encodings (currently ProtoBuf and Amino) by following a specific pattern.

Generally, the default encodings expect your messages to be implemented as classes. The ProtoBuf and Amino encoding subsystems define the following types, as well as these methods for registration of new default types:

// @apophis-sdk/core/encoding/protobuf/any.ts
export type ProtobufType<T1 extends string = string, T2 = any> = {
  get protobufTypeUrl(): T1;
  toProtobuf(value: T2): Uint8Array;
  fromProtobuf(value: Uint8Array): T2;
};

export declare function registerDefaultProtobuf(...types: ProtobufType[]): void;

// @apophis-sdk/cosmos/encoding/amino.ts
export type AminoType<T1 extends string = string, T2 = any> = {
  get aminoTypeUrl(): T1;
  new(data: T2): { get data(); T2 }
};

export declare function registerDefaultAmino(...types: AminoType[]): void;

Correspondingly, the Cosmos Bank Send message is implemented as follows:

import { registerDefaultProtobufs } from '@apophis-sdk/core/encoding/protobuf/any.js';
import type { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin';
import { MsgSend } from 'cosmjs-types/cosmos/bank/v1beta1/tx';
import { registerDefaultAminos } from '../encoding/amino';

export namespace Bank {
  export type SendData = {
    fromAddress: string;
    toAddress: string;
    amount: Coin[];
  }

  export class Send {
    static readonly protobufTypeUrl = '/cosmos.bank.v1beta1.MsgSend';
    static readonly aminoTypeUrl = 'cosmos-sdk/MsgSend';

    constructor(public data: SendData) {}

    static toProtobuf(value: Send): Uint8Array {
      return MsgSend.encode(MsgSend.fromPartial(value.data)).finish();
    }

    static fromProtobuf(value: Uint8Array): Send {
      const { fromAddress, toAddress, amount } = MsgSend.decode(value);
      return new Send({ fromAddress, toAddress, amount });
    }
  };

  registerDefaultProtobufs(Send);
  registerDefaultAminos(Send);
}

Amino becomes virtually free. As of the time of writing this document, ProtoBuf is not yet directly supported by Apophis and relies on you to provide the correct de/serialization. The protobuf wire format is very simple, but requires abstractions for maximum ease of use. Most likely, I will implement it using POJO's with decorators.

As the naming suggests, these are merely "default" types. Using the Middleware subsystem, nearly every single aspect can be fine-tuned to the requirements of a specific blockchain, with these default types used as fallbacks.

Last updated