ABI

The ABI (Application Binary Interface) in Antelope-based blockchains is a JSON data structure that defines the structure of a Smart Contract and instructs the Serializer on how to encode or decode data.

This document will focus on the retrieval and processing of existing ABIs for use in the Javascript context. For more information about ABIs, as well as how to create them while developing a smart contract, please refer to docs.eosnetwork.com.

Retrieving an ABI Using an APIClient

An ABI can be loaded from the blockchain using an APIClient. To do this we first need to establish the APIClient with the appropriate endpoint configured and then call the get_abi API endpoint.

// Establish APIClient instance with appropriate endpoint
const client = new APIClient({ url: "https://jungle4.greymass.com" })

// Call the `get_abi` API method specifying the account name
const response = await client.v1.chain.get_abi("eosio")

// Ensure the `abi` parameter is defined on the response
if (response.abi) {
  // Convert the `ABIDef` from the API response to an `ABI` instance
  const abi = ABI.from(response.abi)
}

The response value from the API call will return an .abi value typed as an ABIDef, if an ABI has been deployed to that account. If no ABI has been defined on that account, it will return empty.

Manually Providing an ABI

An ABI can also be defined manually by providing an ABIDef.

import { ABI } from "@wharfkit/antelope"

// Pass an object representation
const abi = ABI.from({
  version: "eosio::abi/1.0",
  types: [],
  variants: [],
  structs: [],
  actions: [],
  tables: [],
  ricardian_clauses: [],
})

// Pass a JSON string representation
const abi = ABI.from(
  '{"version":"eosio::abi/1.0","types":[],"variants":[],"structs":[],"actions":[],"tables":[],"ricardian_clauses":[]}'
)

An ABIDef can be either a string, object representation, or actual ABI type from the Antelope library.

export interface ABI.Def {
    version: string
    types: TypeDef[]
    variants: Variant[]
    structs: Struct[]
    actions: Action[]
    tables: Table[]
    ricardian_clauses: Clause[]
}

export type ABIDef = string | Partial<ABI.Def> | ABI

This allows the creation of an ABI using ABI.from() using multiple formats that developers will typically have readily available.

Usage

The ABI data type is typically used as a parameter when creating an Action, using the Serializer, or used internally when working with Struct data types.

Creating an Action

When creating an Action based on untyped action data, the ABI itself must be passed as the 2nd parameter to Action.from() in order to serialize the action data.

const { abi } = await client.v1.chain.get_abi("eosio.token")

const data = {
  authorization: [
    {
      actor: "corecorecore",
      permission: "active",
    },
  ],
  account: "eosio.token",
  name: "transfer",
  data: {
    from: "corecorecore",
    to: "teamgreymass",
    quantity: "0.0042 EOS",
    memo: "antelope is the best <3",
  },
}

const action = Action.from(data, abi)

/**
{
    account: 'eosio.token',
    name: 'transfer',
    authorization: [ { actor: 'corecorecore', permission: 'active' } ],
    data: 'a02e45ea52a42e4580b1915e5d268dca2a0000000000000004454f530000000019656f73696f2d636f7265206973207468652062657374203c33'
}
*/

Decoding an Action

When decoding an Action in order to view its raw data, the decodeData method of the action requires the ABI in order to convert the hex data into a readable data format.

const { abi } = await client.v1.chain.get_abi("eosio.token")

const data = {
  account: "eosio.token",
  name: "transfer",
  authorization: [{ actor: "corecorecore", permission: "active" }],
  data: "a02e45ea52a42e4580b1915e5d268dca2a0000000000000004454f530000000019656f73696f2d636f7265206973207468652062657374203c33",
}

const action = Action.from(data, abi)

const decoded = action.decodeData(abi)

/**
{
    from: Name { value: UInt64 { value: [BN] } },
    to: Name { value: UInt64 { value: [BN] } },
    quantity: Asset {
        units: Int64 { value: [BN] },
        symbol: Symbol { value: [UInt64] }
    },
    memo: 'antelope is the best <3'
}
*/

Using the Serializer

An Action can also be decoded using the Serializer, where you will pass:

  • the abi
  • the type, which is the name of the action as defined in the ABI
  • the data as the raw hex value
const { abi } = await client.v1.chain.get_abi("eosio.token")

const data =
  "a02e45ea52a42e4580b1915e5d268dca2a0000000000000004454f530000000019656f73696f2d636f7265206973207468652062657374203c33"

const decoded = Serializer.decode({ data, abi, type: "transfer" })

/**
{
    from: Name { value: UInt64 { value: [BN] } },
    to: Name { value: UInt64 { value: [BN] } },
    quantity: Asset {
        units: Int64 { value: [BN] },
        symbol: Symbol { value: [UInt64] }
    },
    memo: 'antelope is the best <3'
}
*/