Layout of a contract file
Orbs contacts are written in Golang, you can see some high level explanation on Becoming a Go developer in the Getting Started episode. In this page we will go over the layout of a single contract and explain the different elements of code that the contract is comprised of.
package main
Each contract must be of package main
This requirement originates from the way we later compile and incorporate the code into the blockchain. Orbs do not support multi-package projects at this moment.
In means of good practice around writing contracts, we have seen that usually, when a multi-package contract requirement arises, it means that the design might be calling for two different contracts in regards to storage isolation and code security. More on that later.
Imports
As multi-package environment is not supported, the import
area of your code can only comprise of Golang standard libraries or Orbs Contract SDK imports.
Exporting functions, events, and the constructor
In Golang, functions beginning with the lowercase letters are considered as 'private' or not exported, and those starting with an uppercase are 'public' and exported.
In Orbs, all functions should be written as 'private', meaning beginning with a lowercase letter, and functions that should be exported should be declared explicitly using the sdk.Export()
function, which accepts pointer to a function (i.e. the function name).
The exception to this rule is events, which still need to be exported with a special EVENTS
variable.
PUBLIC
The PUBLIC
export is used to define which functions should be exported and be accessible by the distributed app client. For example:
This example will export two functions named transfer
and getBalance
.
EVENTS
The EVENTS
export is used to declare which events are exported by the contract, for example:
This example will export an event named Approval
SYSTEM
The special system export is reserved, right now, only for the constructor function _init
, it must exist at any contract when the special constructor function exists. This export usually looks like:
It enables the contract compiler to call the constructor function.
Event declaration
Usually, after the initial implementation, the best practice would be to declare which events exist as part of the contract.
Events are declared by writing an empty 'public' function as such:
Note that the empty curly braces {}
must be explicitly written at the end of the line.
Function implementation
Next, and finally, the functions themself should be written as part of the code. These are the functions that may be also exported for client usage.
The functions themselves can either change state or not. A function that does not change the state can later be used under the run query operation, while a function that changes the state (writes to it) must be executed under a transaction.
The example above creates a function called getBalance
which accepts a byte array to a variable named targetAddress
. The logic then validates the address and reads from the state whatever data that was stored there, which should be a unsigned number of up to 64bit in size using state.ReadUint64(targetAddress)
. Since the logic only reads data off the blockchain, it is possible to run this function using run-query
API, but the contract must export the function as described above.
Last updated