abi

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2025 License: Apache-2.0 Imports: 14 Imported by: 0

README

TON contract interface

Overview

You can define schema of contract get-methods and messages going to and from contract in just one JSON schema.

Contract interface

Anton mainly determines contracts by the presence of get-methods in the contract code. But if it is impossible to identify your contracts by only get-methods (as in Telemint NFT collection contracts), you should define contract addresses in the network or a contract code Bag of Cells.

{
  "interface_name": "",  // name of the contract
  "addresses": [],       // optional contract addresses
  "code_boc": "",        // optional contract code BoC
  "definitions": {},     // map definition name to cell schema
  "in_messages": [],     // possible incoming messages schema
  "out_messages": [],    // possible outgoing messages schema
  "get_methods": []      // get-method names, return values and arguments
}
Message schema

Each message schema has operation name, operation code and field definitions. Each field definition has name, TL-B type and format, which shows how to parse cell. Also, it is possible to define similarly described embedded structures in each field in struct_fields.

{
  "op_name": "nft_start_auction",  // operation name
  "op_code": "0x5fcc3d14",         // TL-B constructor prefix code (operation code)
  "type": "external_out",          // message type: internal, external_in, external_out
  "body": [
    {                              // fields definitions
      "name": "query_id",          // field name
      "tlb_type": "## 64",         // field TL-B type
      "format": "uint64"           // describes how we should parse the field
    }, 
    {
      "name": "auction_config",
      "tlb_type": "^",
      "format": "struct",
      "struct_fields": [           // fields of inner structure
        {
          "name": "beneficiary_address", 
          "tlb_type": "addr", 
          "format": "addr"
        }
      ]
    }
  ]
}

While parsing TL-B cells by fields description, we are trying to parse data according to TL-B type and map it into some Golang type or structure. Each TL-B type used in schemas has value equal to the structure tags in tonutils-go. If it is not possible to parse the field using tlb.LoadFromCell, you can define your custom type with LoadFromCell method in abi package (for example, TelemintText) and register it in tlb_types.go.

Accepted TL-B types in tlb_type:

  1. ## N - integer with N bits; by default maps to uintX or big.Int
  2. ^ - data is stored in the referenced cell; by default maps to cell.Cell or to custom struct, if struct_fields is defined
  3. . - inner struct; by default maps to cell.Cell or to custom struct, if struct_fields is defined
  4. [^]dict [inline] N [-> [^]] - dictionary with key size N, transformation to map is done through ->
  5. bits N - bit slice N len; by default maps to []byte
  6. bool - 1 bit boolean; by default maps to bool
  7. addr - ton address; by default maps to addr.Address
  8. maybe - reads 1 bit, and loads rest if its 1, can be used in combination with others only; by default maps to cell.Cell or to custom struct, if struct_fields is defined
  9. either X Y - reads 1 bit, if its 0 - loads X, if 1 - loads Y; by default maps to cell.Cell or to custom struct, if struct_fields is defined

Accepted types of format:

  1. struct - embed structure, maps into structure described by struct_fields
  2. bytes - byte slice, maps into []byte
  3. bool - boolean (can be used only on tlb_type = bool)
  4. uint8, uint16, uint32, uint64 - unsigned integers
  5. int8, int16, int32, int64 - unsigned integers
  6. bigInt - integer with more than 64 bits, maps into big.Int wrapper
  7. cell - TL-B cell, maps into cell.Cell
  8. dict - TL-B dictionary (hashmap), maps into cell.Dictionary
  9. tag - TL-B constructor prefix
  10. coins - varInt 16, maps into big.Int wrapper
  11. addr - TON address, maps into address.Address wrapper
  12. [TODO] content_cell - token data as in TEP-64; implementation
  13. string - string snake is stored in the cell
  14. telemintText - variable length string with this TL-B constructor
Get-methods

Each get-method consists of name (which is then used to get method_id), arguments and return values.

{
  "interface_name": "jetton_minter",
  "get_methods": [
    {
      "name": "get_wallet_address",         // get-method name
      "arguments": [
        {
          "name": "owner_address",          // argument name
          "stack_type": "slice",
          "format": "addr"
        }
      ],
      "return_values": [
        {
          "name": "jetton_wallet_address",  // return value name
          "stack_type": "slice",            // type we load
          "format": "addr"                  // type we parse into
        }
      ]
    },
    {
      "name": "get_jetton_data",
      "return_values": [
        {
          "name": "total_supply",
          "stack_type": "int",
          "format": "bigInt"
        },
        {
          "name": "mintable",
          "stack_type": "int",
          "format": "bool"
        },
        {
          "name": "admin_address",
          "stack_type": "slice",
          "format": "addr"
        }
      ]
    }
  ]
}

Accepted argument stack types:

  1. int - integer; by default maps from big.Int
  2. cell - map from BoC
  3. slice - cell slice

Accepted return values stack types:

  1. int - integer; by default maps into big.Int
  2. cell - map to BoC
  3. slice - load slice
  4. [TODO] tuple

Accepted types to map from or parse into in format field:

  1. addr - MsgAddress slice type
  2. bool - map int to boolean
  3. uint8, uint16, uint32, uint64 - map int to an unsigned integer
  4. int8, int16, int32, int64 - map int to an signed integer
  5. bigInt - map integer bigger than 64 bits
  6. string - load string snake from cell
  7. bytes - convert big int to bytes
  8. content - load TEP-64 standard token data into nft.ContentAny
  9. struct - define struct_fields to parse cell
Shared TL-B constructors

You can define some cell schema in definitions field of contract interface.

You can use those definitions in message schemas:

{
  "interface_name": "telemint_nft_item",
  "addresses": [
    "EQAOQdwdw8kGftJCSFgOErM1mBjYPe4DBPq8-AhF6vr9si5N",
    "EQCA14o1-VWhS2efqoh_9M1b_A9DtKTuoqfmkn83AbJzwnPi"
  ],
  "definitions": {
    "auction_config": [
      {
        "name": "beneficiary_address",
        "tlb_type": "addr"
      }
    ]
  },
  "in_messages": [
    {
      "op_name": "teleitem_start_auction",
      "op_code": "0x487a8e81",
      "body": [
        {
          "name": "query_id", 
          "tlb_type": "## 64"
        },
        {
          "name": "auction_config",
          "tlb_type": "^",
          "format": "auction_config"
        }
      ]
    }
  ]
}

Or use them in get-method return values' schema:

{
  "interface_name": "amm",
  "definitions": {
    "amm_state": [
      {
        "name": "quote_asset_reserve",
        "tlb_type": ".",
        "format": "coins"
      },
      // ...
    ]
  }, 
  "get_methods": [
    {
      "name": "get_amm_data", 
      "return_values": [
        // ...
        {
          "name": "amm_state",
          "stack_type": "cell",
          "format": "amm_state"
        },
      ]
    }
  ]
}
Union of TLB types

You can make some definitions with tags in the beginning of cell and use them later in unions. See the following example:

{
  "interface": "jetton_vault",
  "definitions": {
    "native_asset": [
      {
        "name": "native_asset",
        "tlb_type": "$0000",
        "format": "tag"
      }
    ],
    "jetton_asset": [
      {
        "name": "jetton_asset",
        "tlb_type": "$0001",
        "format": "tag"
      },
      // ...
    ],
    "pool_params": [
      // ...
      {
        "name": "asset0",
        "tlb_type": "[native_asset,jetton_asset]"
      },
      // ...
    ],
    "deposit_liquidity": [
      {
        "name": "deposit_liquidity",
        "tlb_type": "#40e108d6",
        "format": "tag"
      },
      {
        "name": "pool_params",
        "tlb_type": ".",
        "format": "pool_params"
      },
      // ...
    ],
    "swap": [
      {
        "name": "swap",
        "tlb_type": "#e3a0d482",
        "format": "tag"
      },
      {
        "name": "swap_step",
        "tlb_type": ".",
        "format": "swap_step"
      },
      // ...
    ]
  },
  "in_messages": [
    {
      "op_name": "jetton_transfer_notification",
      "op_code": "0x7362d09c",
      "body": [
        {
          "name": "query_id",
          "tlb_type": "## 64",
          "format": "uint64"
        },
        {
          "name": "amount",
          "tlb_type": ".",
          "format": "coins"
        },
        {
          "name": "sender",
          "tlb_type": "addr",
          "format": "addr"
        },
        {
          "name": "forward_payload", 
          "tlb_type": "either . ^", 
          "format": "struct", 
          "struct_fields": [{
            "name": "value", 
            "tlb_type": "[deposit_liquidity,swap]"
          }]
        }
      ]
    }
  ]
}

Here we define two structs in the interface: deposit_liquidity and swap. Then our contract interface accepts incoming jetton_transfer_notification. Inside forward payload there may be a cell, which corresponds to either deposit_liquidity, either swap. If Anton finds a message with jetton_transfer_notification operation, he will try to determine the structure of forward payload by tag in the beginning of cell.

After parsing deposit_liquidity transfer notification message body will look like this:

{
  "query_id": 3638120226682551939,
  "amount": "1253854400825677",
  "sender": "EQDz0wQL6EEdgbPkFgS7nNmywzr468AvgLyhH7PIMALxPB6G",
  "forward_payload": {
    "value": {
      "deposit_liquidity": {},
      "pool_params": {
        "is_stable": false,
        "asset_0": {
          "native_asset": {}
        },
        "asset_1": {
          "jetton_asset": {},
          "workchain_id": 0,
          "jetton_address": 2422642597
        }
      },
      "min_lp_amount": "49289848313582100",
      "asset_0_target_balance": "135747634478277169790071850",
      "asset_1_target_balance": "30291957672135140790470162860"
    }
  }
}
Dictionary transformation

You can define the format of the dictionary values, so Anton will be able to parse it into the golang map.

In the following example, we use defined limit_order as a dictionary value:

{
  // ...
  "definitions": {
    "limit_order": [
      {
        "name": "order_tag",
        "tlb_type": "$0010",
        "format": "tag"
      },
      {
        "name": "expiration",
        "tlb_type": "## 32"
      },
      // ...
    ]
  },
  // ...
  "in_message": {
    // ...
    "body": [
      {
        "name": "dict_3_bit_key",
        "tlb_type": "dict inline 3 -> ^",
        "format": "limit_order"
      }
    ]
  }
}

Or we can use defined orders union as a dictionary value, but for the union we're setting tlb_type field instead of format.

{
  // ...
  "definitions": {
    "take_order": [
      {
        "name": "take_order_tag",
        "tlb_type": "$0001",
        "format": "tag"
      },
      {
        "name": "expiration",
        "tlb_type": "## 32"
      },
      // ...
    ],
    "limit_order": [
      {
        "name": "order_tag",
        "tlb_type": "$0010",
        "format": "tag"
      },
      {
        "name": "expiration",
        "tlb_type": "## 32"
      },
      // ...
    ]
  },
  // ...
  "in_message": {
    // ...
    "body": [
      {
        "name": "dict_3_bit_key",
        "tlb_type": "dict inline 3 -> ^ [take_order,limit_order]"
      }
    ]
  }
}

Known contracts

  1. TEP-62 NFT Standard: interfaces, description, contract code
  2. TEP-74 Fungible tokens (Jettons) standard: interfaces, description, contract code
  3. TEP-81 DNS contracts: interface, description
  4. TEP-85 NFT SBT tokens: interfaces, description
  5. Telemint contracts: interfaces, contract code
  6. Getgems contracts: interfaces, contract code
  7. Wallets: interfaces, tonweb
  8. STON.fi DEX: architecture, contract code
  9. Megaton.fi DEX: architecture
  10. Tonpay: go-sdk, js-sdk

Converting Golang struct to JSON schema

You can convert Golang struct with described tlb tags to the JSON schema by using abi.NewTLBDesc and abi.NewOperationDesc functions. See an example in tlb_test.go file.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetGoTypeTLB added in v0.4.2

func GetGoTypeTLB(t TLBType) (reflect.Type, bool)

func GetMethodHashes

func GetMethodHashes(code *cell.Cell) ([]int32, error)

func HasGetMethod

func HasGetMethod(code *cell.Cell, getMethodName string) bool

func MethodNameHash

func MethodNameHash(name string) int32

func RegisterDefinitions added in v0.4.1

func RegisterDefinitions(definitions map[TLBType]TLBFieldsDesc, depth ...int) error

Types

type ContractName

type ContractName string

type DedustAsset added in v0.4.1

type DedustAsset struct {
	Asset any `tlb:"[DedustAssetNative,DedustAssetJetton,DedustAssetExtraCurrency]"`
}

func (*DedustAsset) LoadFromCell added in v0.4.1

func (x *DedustAsset) LoadFromCell(loader *cell.Slice) error

func (*DedustAsset) MarshalJSON added in v0.4.1

func (x *DedustAsset) MarshalJSON() ([]byte, error)

type DedustAssetExtraCurrency added in v0.4.1

type DedustAssetExtraCurrency struct {
	CurrencyID int32 `tlb:"## 32"`
	// contains filtered or unexported fields
}

type DedustAssetJetton added in v0.4.1

type DedustAssetJetton struct {
	Workchain int8   `tlb:"## 8"`
	Address   []byte `tlb:"bits 256"`
	// contains filtered or unexported fields
}

type DedustAssetNative added in v0.4.1

type DedustAssetNative struct {
	// contains filtered or unexported fields
}

type GetMethodDesc added in v0.2.1

type GetMethodDesc struct {
	Name         string        `json:"name"`
	Arguments    []VmValueDesc `json:"arguments,omitempty"`
	ReturnValues []VmValueDesc `json:"return_values"`
}

type GetMethodExecution added in v0.3.1

type GetMethodExecution struct {
	Name string `json:"name,omitempty"`

	Address *addr.Address `json:"address,omitempty"`

	Arguments []VmValueDesc `json:"arguments,omitempty"`
	Receives  []any         `json:"receives,omitempty"`

	ReturnValues []VmValueDesc `json:"return_values,omitempty"`
	Returns      []any         `json:"returns,omitempty"`

	Error string `json:"error,omitempty"`
}

type InterfaceDesc added in v0.2.1

type InterfaceDesc struct {
	Name         ContractName              `json:"interface_name"`
	Addresses    []*addr.Address           `json:"addresses,omitempty"`
	CodeBoc      string                    `json:"code_boc,omitempty"`
	Definitions  map[TLBType]TLBFieldsDesc `json:"definitions,omitempty"`
	InMessages   []OperationDesc           `json:"in_messages,omitempty"`
	OutMessages  []OperationDesc           `json:"out_messages,omitempty"`
	GetMethods   []GetMethodDesc           `json:"get_methods,omitempty"`
	ContractData TLBFieldsDesc             `json:"contract_data,omitempty"`
}

type OperationDesc added in v0.2.1

type OperationDesc struct {
	Name string        `json:"op_name"`
	Code string        `json:"op_code"`
	Type string        `json:"type,omitempty"`
	Body TLBFieldsDesc `json:"body"`
}

func NewOperationDesc added in v0.2.1

func NewOperationDesc(x any) (*OperationDesc, error)

func (*OperationDesc) FromCell added in v0.4.1

func (desc *OperationDesc) FromCell(c *cell.Cell) (any, error)

func (*OperationDesc) New added in v0.2.1

func (desc *OperationDesc) New(skipOptional ...bool) (any, error)

type StackType added in v0.2.1

type StackType string
const (
	VmInt   StackType = "int"
	VmCell  StackType = "cell"
	VmSlice StackType = "slice"
)

type StringSnake added in v0.2.1

type StringSnake string

func (*StringSnake) LoadFromCell added in v0.2.1

func (x *StringSnake) LoadFromCell(loader *cell.Slice) error

type TLBFieldDesc added in v0.2.1

type TLBFieldDesc struct {
	Name     string        `json:"name"`
	Type     string        `json:"tlb_type"`
	Format   TLBType       `json:"format,omitempty"`
	Optional bool          `json:"optional,omitempty"`
	Fields   TLBFieldsDesc `json:"struct_fields,omitempty"` // Format = "struct"
}

type TLBFieldsDesc added in v0.2.1

type TLBFieldsDesc []TLBFieldDesc

func GetRegisteredDefinition added in v0.4.2

func GetRegisteredDefinition(t TLBType) (TLBFieldsDesc, bool)

func NewTLBDesc added in v0.2.1

func NewTLBDesc(x any) (TLBFieldsDesc, error)

func (TLBFieldsDesc) FromCell added in v0.4.1

func (desc TLBFieldsDesc) FromCell(c *cell.Cell) (any, error)

func (TLBFieldsDesc) New added in v0.2.1

func (desc TLBFieldsDesc) New(skipOptional ...bool) (any, error)

type TLBType added in v0.4.1

type TLBType string
const (
	TLBAddr        TLBType = "addr"
	TLBBool        TLBType = "bool"
	TLBBigInt      TLBType = "bigInt"
	TLBString      TLBType = "string"
	TLBBytes       TLBType = "bytes"
	TLBCell        TLBType = "cell"
	TLBSlice       TLBType = "slice"
	TLBContentCell TLBType = "content"
	TLBStructCell  TLBType = "struct"
	TLBTag         TLBType = "tag"
)

func GetGoTypeNameTLB added in v0.4.2

func GetGoTypeNameTLB(t reflect.Type) (TLBType, bool)

type TelemintText

type TelemintText struct {
	Len  uint8  // ## 8
	Text string // bits (len * 8)
}

func (*TelemintText) LoadFromCell

func (x *TelemintText) LoadFromCell(loader *cell.Slice) error

type VmStack added in v0.2.1

type VmStack []VmValue

type VmValue added in v0.2.1

type VmValue struct {
	VmValueDesc
	Payload any `json:"payload"`
}

type VmValueDesc added in v0.2.1

type VmValueDesc struct {
	Name      string        `json:"name"`
	StackType StackType     `json:"stack_type"`
	Format    TLBType       `json:"format,omitempty"`
	Fields    TLBFieldsDesc `json:"struct_fields,omitempty"` // Format = "struct"
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL