Interface Abi

Application Binary Interface (ABI)

ABIs are composed of 3 elements: methods, events, and types.

  • The methods define the names of the entries of the smart contract, the corresponding endpoints and the name of the types used.
  • The events define possible events triggered by the smart contract and the name of the types used.
  • The types contain the description to serialize and deserialize data using proto buffers. It is used to encode/decode the methods and events. These types can be provided in binary format or json format (koilib_types)

To generate the types is necessary to use the dependency protobufjs. The following example shows how to generate the protobuf descriptor from a .proto file.

const fs = require("fs");
const pbjs = require("protobufjs/cli/pbjs");

pbjs.main(
["--target", "json", "./token.proto"],
(err, output) => {
if (err) throw err;
fs.writeFileSync("./token-proto.json", output);
}
);

Then this descriptor can be loaded to define the ABI:

const tokenJson = require("./token-proto.json");
const abiToken = {
methods: {
balanceOf: {
entry_point: 0x15619248,
argument: "balance_of_arguments",
return: "balance_of_result",
read_only: true,
default_output: { value: "0" },
},
transfer: {
entry_point: 0x62efa292,
argument: "transfer_arguments",
return: "transfer_result",
},
mint: {
entry_point: 0xc2f82bdc,
argument: "mint_arguments",
return: "mint_result",
},
},
events: {
'koinos.contracts.token.mint_event': {
type: "mint_arguments"
},
},
koilib_types: tokenJson,
};

Note that this example uses "default_output" for the method "balanceOf". This is used when the smart contract returns an empty response (for instance when there are no balance records for a specific address) and you require a default output in such cases.

Definition of events

There are 2 ways to define events in koinos:

  • Event names as protobuffer names
  • Custom event names
  1. Event names as protobuffer names: The name of the event links with the protobuffer definition. In this case there is no need to define the event in the ABI.

Example:

Proto definition

package koinos.contracts.token;

message transfer_arguments {
bytes from = 1 [(btype) = ADDRESS];
bytes to = 2 [(btype) = ADDRESS];
uint64 value = 3 [jstype = JS_STRING];
}

message transfer_event {
bytes from = 1 [(btype) = ADDRESS];
bytes to = 2 [(btype) = ADDRESS];
uint64 value = 3 [jstype = JS_STRING];
}

Contract

// token-contract.ts
transfer(args: token.transfer_arguments): token.transfer_result {
...
System.event("koinos.contracts.token.transfer_event", Protobuf.encode(event, token.transfer_event.encode), impacted);
}
  1. Custom event names: The previous definition has a limitation. It's necessary to define a proto message for each event and argument, and they can not be reused. In this second solution, the event names are defined in the ABI and they are linked with the corresponding protobuffer definitions. In this sense, they can be reused.

Example

Proto definition

package koinos.contracts.token;

// only 1 message
message transfer {
bytes from = 1 [(btype) = ADDRESS];
bytes to = 2 [(btype) = ADDRESS];
uint64 value = 3 [jstype = JS_STRING];
}

Contract

// token-contract.ts

// Transfer of tokens
// @event transfer_event token.transfer
transfer(args: token.transfer): void {
...
System.event("transfer_event", Protobuf.encode(event, token.transfer.encode), impacted);
}

ABI

const abiToken = {
methods: {
transfer: {
entry_point: 0x62efa292,
argument: "transfer",
return: "",
},
},
events: {
'transfer_event': {
type: "transfer"
},
},
koilib_types: tokenJson,
};

Hierarchy

  • Abi

Properties

events?: { [x: string]: { argument?: string; description?: string; type?: string } }

Definition of events

Type declaration

  • [x: string]: { argument?: string; description?: string; type?: string }
    • Optional argument?: string

      Deprecated, use type instead

    • Optional description?: string

      Description of the event

    • Optional type?: string

      Protobuffer type for event

koilib_types?: INamespace

Protobuffers descriptor in JSON format. See https://www.npmjs.com/package/protobufjs#using-json-descriptors

methods: { [x: string]: { argument?: string; default_output?: unknown; description?: string; entry_point: number; preformat_argument?: ((arg: unknown) => Record<string, unknown>); preformat_return?: ((output: Record<string, unknown>) => unknown); read_only?: boolean; return?: string } }

Type declaration

  • [x: string]: { argument?: string; default_output?: unknown; description?: string; entry_point: number; preformat_argument?: ((arg: unknown) => Record<string, unknown>); preformat_return?: ((output: Record<string, unknown>) => unknown); read_only?: boolean; return?: string }
    • Optional argument?: string

      Protobuffer type for argument

    • Optional default_output?: unknown

      Default value when the output is undefined

    • Optional description?: string

      Description of the method

    • entry_point: number

      Entry point ID

    • Optional preformat_argument?: ((arg: unknown) => Record<string, unknown>)
        • (arg: unknown): Record<string, unknown>
        • Optional function to preformat the argument

          Parameters

          • arg: unknown

          Returns Record<string, unknown>

    • Optional preformat_return?: ((output: Record<string, unknown>) => unknown)
        • (output: Record<string, unknown>): unknown
        • Optional function to preformat the returned value

          Parameters

          • output: Record<string, unknown>

          Returns unknown

    • Optional read_only?: boolean

      Boolean to differentiate write methods (using transactions) from read methods (query the contract)

    • Optional return?: string

      Protobuffer type for returned value

types?: string

Protobuffers descriptor in binary format encoded in base64url.

Generated using TypeDoc