Gno comes with a set of standard libraries which are included to ease development and provide extended functionality to the language. These include:
- standard libraries as we know them in classic Go, i.e.
strings
,testing
, etc. - a special
std
package, which contains types, interfaces, and APIs created to handle blockchain-related functionality, such as fetching the last caller, fetching coins sent along with a transaction, getting the block timestamp and height, and more.
Standard libraries differ from on-chain packages in terms of their import path structure. Unlike on-chain packages, standard libraries do not incorporate a domain-like format at the beginning of their import path. For example:
import "strings"
refers to a standard libraryimport "gno.land/p/demo/avl"
refers to an on-chain package.
To see concrete implementation details & API references of the std
pacakge,
see the reference section.
Apart from the official documentation you are currently reading, you can also access documentation for the standard libraries in several other different ways. You can obtain a list of all the available standard libraries with the following commands:
$ cd gnovm/stdlibs # go to correct directory
$ find -type d
./testing
./math
./crypto
./crypto/chacha20
./crypto/chacha20/chacha
./crypto/chacha20/rand
./crypto/sha256
./crypto/cipher
...
All the packages have automatically generated documentation through the use of the
gno doc
command, which has similar functionality and features to go doc
:
$ gno doc encoding/binary
package binary // import "encoding/binary"
Package binary implements simple translation between numbers and byte sequences
and encoding and decoding of varints.
[...]
var BigEndian bigEndian
var LittleEndian littleEndian
type AppendByteOrder interface{ ... }
type ByteOrder interface{ ... }
$ gno doc -u -src encoding/binary littleEndian.AppendUint16
package binary // import "encoding/binary"
func (littleEndian) AppendUint16(b []byte, v uint16) []byte {
return append(b,
byte(v),
byte(v>>8),
)
}
gno doc
will work automatically when used within the Gno repository or any
repository which has a go.mod
dependency on github.com/gnolang/gno
.
Another alternative is setting your environment variable GNOROOT
to point to
where you cloned the Gno repository.
export GNOROOT=$HOME/gno
A Coin is a native Gno type that has a denomination and an amount. Coins can be issued by the native Gno Banker.
A coin is defined by the following:
type Coin struct {
Denom string `json:"denom"`
Amount int64 `json:"amount"`
}
Denom
is the denomination of the coin, i.e. ugnot
, and Amount
is a
non-negative amount of the coin.
Multiple coins can be bundled together into a Coins
slice:
type Coins []Coin
This slice behaves like a mathematical set - it cannot contain duplicate Coin
instances.
The Coins
slice can be included in a transaction made by a user addresses or a realm.
Coins in this set are then available for access by specific types of Bankers,
which can manipulate them depending on access rights.
Read more about coins in the Effective Gno section.
The Coin(s) API can be found in the std
package.
The Banker's main purpose is to handle balance changes of native coins within Gno chains. This includes issuance, transfers, and burning of coins.
The Banker module can be cast into 4 subtypes of bankers that expose different functionalities and safety features within your packages and realms.
BankerTypeReadonly
- read-only access to coin balancesBankerTypeOriginSend
- full access to coins sent with the transaction that called the bankerBankerTypeRealmSend
- full access to coins that the realm itself owns, including the ones sent with the transactionBankerTypeRealmIssue
- able to issue new coins
Events in Gno are a fundamental aspect of interacting with and monitoring on-chain applications. They serve as a bridge between the on-chain environment and off-chain services, making it simpler for developers, analytics tools, and monitoring services to track and respond to activities happening in gno.land.
Gno events are pieces of data that log specific activities or changes occurring within the state of an on-chain app. These activities are user-defined; they might be token transfers, changes in ownership, updates in user profiles, and more. Each event is recorded in the ABCI results of each block, ensuring that action that happened is verifiable and accessible to off-chain services.
To emit an event, you can use the Emit()
function from the std
package
provided in the Gno standard library. The Emit()
function takes in a string
representing the type of event, and an even number of arguments after representing
key:value
pairs.
Read more about events & Emit()
in
Effective Gno.
An event contained in an ABCI response of a block will include the following data:
{
"@type": "/tm.gnoEvent", // TM2 type
"type": "OwnershipChange", // Type/name of event defined in Gno
"pkg_path": "gno.land/r/demo/example", // Path of the emitter
"func": "ChangeOwner", // Gno function that emitted the event
"attrs": [ // Slice of key:value pairs emitted
{
"key": "oldOwner",
"value": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
},
{
"key": "newOwner",
"value": "g1zzqd6phlfx0a809vhmykg5c6m44ap9756s7cjj"
}
]
}
You can fetch the ABCI response of a specific block by using the /block_results
RPC endpoint.
This is the reference page for the special std
package found in Gno, containing
critical functionality for managing realms, addresses, the Banker module, etc.
Native address type in Gno, conforming to the Bech32 format.
type Address string
func (a Address) IsValid() bool {...}
func (a Address) String() string {...}
Check if Address is of a valid length, and conforms to the bech32 format.
if !address.IsValid() {...}
Get string representation of Address.
stringAddr := addr.String()
type BankerType uint8
const (
BankerTypeReadonly BankerType = iota
BankerTypeOriginSend
BankerTypeRealmSend
BankerTypeRealmIssue
)
type Banker interface {
GetCoins(addr Address) (dst Coins)
SendCoins(from, to Address, coins Coins)
IssueCoin(addr Address, denom string, amount int64)
RemoveCoin(addr Address, denom string, amount int64)
}
Returns Banker
of the specified type.
BankerType
- type of Banker to get:BankerTypeReadonly
- read-only access to coin balancesBankerTypeOrigSend
- full access to coins sent with the transaction that calls the bankerBankerTypeRealmSend
- full access to coins that the realm itself owns, including the ones sent with the transactionBankerTypeRealmIssue
- able to issue new coins
banker := std.NewBanker(std.<BankerType>)
Returns Coins
owned by Address
.
addr
Address to fetch balances for
coins := banker.GetCoins(addr)
Sends coins
from address from
to address to
. coins
needs to be a well-defined
Coins
slice.
from
Address to send fromto
Address to send tocoins
Coins to send
banker.SendCoins(from, to, coins)
Issues amount
of coin with a denomination denom
to address addr
.
addr
Address to issue coins todenom
string denomination of coin to issueamount
int64 amount of coin to issue
banker.IssueCoin(addr, denom, amount)
:::info Coin denominations
Banker
methods expect qualified denomination of the coins. Read more here.
:::
Removes (burns) amount
of coin with a denomination denom
from address addr
.
addr
Address to remove coins fromdenom
string denomination of coin to removeamount
int64 amount of coin to remove
banker.RemoveCoin(addr, denom, amount)
func AssertOriginCall()
Panics if caller of function is not an EOA. Only allows MsgCall
transactions; panics on MsgRun
calls.
std.AssertOriginCall()
func ChainDomain() string
Returns the chain domain. Currently only gno.land
is supported.
domain := std.ChainDomain() // gno.land
func Emit(typ string, attrs ...string)
Emits a Gno event. Takes in a string type (event identifier), and an even number of string arguments acting as key-value pairs to be included in the emitted event.
std.Emit("MyEvent", "myKey1", "myValue1", "myKey2", "myValue2")
func ChainID() string
Returns the chain ID.
chainID := std.ChainID() // dev | test5 | main ...
func ChainHeight() int64
Returns the current block number (height).
height := std.ChainHeight()
func OriginSend() Coins
Returns the Coins
that were sent along with the calling transaction.
coinsSent := std.OriginSend()
func OriginCaller() Address
Returns the original signer of the transaction.
caller := std.OriginCaller()
func OriginPkgAddress() Address
Returns the address of the first (entry point) realm/package in a sequence of realm/package calls.
addr := std.OriginPkgAddress()
func CurrentRealm() Realm
Returns current Realm object.
currentRealm := std.CurrentRealm()
func PreviousRealm() Realm
Returns the previous caller realm (can be code or user realm). If caller is a
user realm, pkgpath
will be empty.
prevRealm := std.PreviousRealm()
func CallerAt(n int) Address
Returns the n-th caller of the function, going back in the call trace. Includes calls to pure packages.
currentRealm := std.CallerAt(1) // returns address of current realm
previousRealm := std.CallerAt(2) // returns address of previous realm/caller
std.CallerAt(0) // error, n must be > 0
func DerivePkgAddr(pkgPath string) Address
Derives the Realm address from its pkgpath
parameter.
realmAddr := std.DerivePkgAddr("gno.land/r/demo/tamagotchi") // g1a3tu874agjlkrpzt9x90xv3uzncapcn959yte4
func CoinDenom(pkgPath, coinName string) string
Composes a qualified denomination string from the realm's pkgPath
and the
provided coin name, e.g. /gno.land/r/demo/blog:blgcoin
. This method should be
used to get fully qualified denominations of coins when interacting with the
Banker
module. It can also be used as a method of the Realm
object.
Read morehere.
pkgPath
string - package path of the realmcoinName
string - The coin name used to build the qualified denomination. Must start with a lowercase letter, followed by 2–15 lowercase letters or digits.
denom := std.CoinDenom("gno.land/r/demo/blog", "blgcoin") // /gno.land/r/demo/blog:blgcoin
type Coin struct {
Denom string `json:"denom"`
Amount int64 `json:"amount"`
}
func NewCoin(denom string, amount int64) Coin {...}
func (c Coin) String() string {...}
func (c Coin) IsGTE(other Coin) bool {...}
func (c Coin) IsLT(other Coin) bool {...}
func (c Coin) IsEqual(other Coin) bool {...}
func (c Coin) Add(other Coin) Coin {...}
func (c Coin) Sub(other Coin) Coin {...}
func (c Coin) IsPositive() bool {...}
func (c Coin) IsNegative() bool {...}
func (c Coin) IsZero() bool {...}
Returns a new Coin with a specific denomination and amount.
coin := std.NewCoin("ugnot", 100)
Returns a string representation of the Coin
it was called upon.
coin := std.NewCoin("ugnot", 100)
coin.String() // 100ugnot
Checks if the amount of other
Coin is greater than or equal than amount of
Coin c
it was called upon. If coins compared are not of the same denomination,
IsGTE
will panic.
other
Coin to compare with
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("ugnot", 100)
coin1.IsGTE(coin2) // true
coin2.IsGTE(coin1) // false
Checks if the amount of other
Coin is less than the amount of Coin c
it was
called upon. If coins compared are not of the same denomination, IsLT
will
panic.
other
Coin to compare with
coin := std.NewCoin("ugnot", 150)
coin := std.NewCoin("ugnot", 100)
coin1.IsLT(coin2) // false
coin2.IsLT(coin1) // true
Checks if the amount of other
Coin is equal to the amount of Coin c
it was
called upon. If coins compared are not of the same denomination, IsEqual
will
panic.
other
Coin to compare with
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("ugnot", 100)
coin3 := std.NewCoin("ugnot", 100)
coin1.IsEqual(coin2) // false
coin2.IsEqual(coin1) // false
coin2.IsEqual(coin3) // true
Adds two coins of the same denomination. If coins are not of the same
denomination, Add
will panic. If final amount is larger than the maximum size
of int64
, Add
will panic with an overflow error. Adding a negative amount
will result in subtraction.
other
Coin to add
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("ugnot", 100)
coin3 := coin1.Add(coin2)
coin3.String() // 250ugnot
Subtracts two coins of the same denomination. If coins are not of the same
denomination, Sub
will panic. If final amount is smaller than the minimum size
of int64
, Sub
will panic with an underflow error. Subtracting a negative amount
will result in addition.
other
Coin to subtract
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("ugnot", 100)
coin3 := coin1.Sub(coin2)
coin3.String() // 50ugnot
Checks if a coin amount is positive.
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("ugnot", -150)
coin1.IsPositive() // true
coin2.IsPositive() // false
Checks if a coin amount is negative.
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("ugnot", -150)
coin1.IsNegative() // false
coin2.IsNegative() // true
Checks if a coin amount is zero.
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("ugnot", 0)
coin1.IsZero() // false
coin2.IsZero() // true
Coins
is a set of Coin
, one per denomination.
type Coins []Coin
func NewCoins(coins ...Coin) Coins {...}
func (c Coins) String() string {...}
func (c Coins) AmountOf(denom string) int64 {...}
func (c Coins) Add(other Coins) Coins {...}
Returns a new set of Coins
given one or more Coin
. Consolidates any denom
duplicates into one, keeping the properties of a mathematical set.
coin1 := std.NewCoin("ugnot", 150)
coin2 := std.NewCoin("example", 100)
coin3 := std.NewCoin("ugnot", 100)
coins := std.NewCoins(coin1, coin2, coin3)
coins.String() // 250ugnot, 100example
Returns a string representation of the Coins
set it was called upon.
coins := std.Coins{std.Coin{"ugnot", 100}, std.Coin{"foo", 150}, std.Coin{"bar", 200}}
coins.String() // 100ugnot,150foo,200bar
Returns int64 amount of specified coin within the Coins
set it was called upon. Returns 0
if the specified coin does not exist in the set.
denom
string denomination of specified coin
coins := std.Coins{std.Coin{"ugnot", 100}, std.Coin{"foo", 150}, std.Coin{"bar", 200}}
coins.AmountOf("foo") // 150
Adds (or updates) the amount of specified coins in the Coins
set. If the specified coin does not exist, Add
adds it to the set.
other
Coins to add toCoins
set
coins := // ...
otherCoins := // ...
coins.Add(otherCoins)
Realm
is the structure representing a realm in Gno. See our realm documentation for more details.
type Realm struct {
addr Address
pkgPath string
}
func (r Realm) Address() Address {...}
func (r Realm) PkgPath() string {...}
func (r Realm) IsUser() bool {...}
func (r Realm) CoinDenom(coinName string) string {...}
Returns the Address field of the realm it was called upon.
realmAddr := r.Address() // eg. g1n2j0gdyv45aem9p0qsfk5d2gqjupv5z536na3d
Returns the string package path of the realm it was called upon.
realmPath := r.PkgPath() // eg. gno.land/r/gnoland/blog
Checks if the realm it was called upon is a user realm. This check passes for both MsgCall
and MsgRun
transactions.
if r.IsUser() {...}
Composes a qualified denomination string from the realm's pkgPath
and the
provided coin name, e.g. /gno.land/r/demo/blog:blgcoin
. This method should be
used to get fully qualified denominations of coins when interacting with the
Banker
module.
coinName
string - The coin name used to build the qualified denomination. Must start with a lowercase letter, followed by 2–15 lowercase letters or digits.
// in "gno.land/r/gnoland/blog"
denom := r.CoinDenom("blgcoin") // /gno.land/r/gnoland/blog:blgcoin
// package `testing`
func SkipHeights(count int64)
func SetOriginCaller(origCaller std.Address)
func SetOriginPkgAddress(addr std.Address)
func SetOriginSend(sent std.Coins)
func IssueCoins(addr std.Address, coins std.Coins)
func SetRealm(realm std.Realm)
// package `std`
func NewUserRealm(address std.Address) std.Realm
func NewCodeRealm(pkgPath string) std.Realm
func SkipHeights(count int64)
Modifies the block height variable by skipping count blocks.
It also increases block timestamp by 5 seconds for every single count
testing.SkipHeights(100)
func SetOriginCaller(origCaller std.Address)
Sets the current caller of the transaction to addr.
testing.SetOriginCaller(std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"))
func SetOriginPkgAddress(addr std.Address)
Sets the call entry realm address to addr.
testing.SetOriginPkgAddress(std.Address("g1ecely4gjy0yl6s9kt409ll330q9hk2lj9ls3ec"))
func SetOriginSend(sent std.Coins)
Sets the sent & spent coins for the current context.
testing.SetOriginSend(sent Coins)
func IssueCoins(addr std.Address, coins std.Coins)
Issues testing context coins to addr.
issue := std.Coins{{"coin1", 100}, {"coin2", 200}}
addr := std.Address("g1ecely4gjy0yl6s9kt409ll330q9hk2lj9ls3ec")
testing.TestIssueCoins(addr, issue)
func SetRealm(rlm Realm)
Sets the realm for the current frame. After calling SetRealm()
, calling
CurrentRealm()
in the same test function will yield the value of rlm
, and
any PreviousRealm()
called from a function used after TestSetRealm will yield rlm
.
Should be used in combination with NewUserRealm
&
NewCodeRealm
.
addr := std.Address("g1ecely4gjy0yl6s9kt409ll330q9hk2lj9ls3ec")
testing.SetRealm(std.NewUserRealm(""))
// or
testing.SetRealm(std.NewCodeRealm("gno.land/r/demo/users"))
func NewUserRealm(address std.Address) Realm
Creates a new user realm for testing purposes.
addr := std.Address("g1ecely4gjy0yl6s9kt409ll330q9hk2lj9ls3ec")
userRealm := std.NewUserRealm(addr)
func NewCodeRealm(pkgPath string) std.Realm
Creates a new code realm for testing purposes.
path := "gno.land/r/demo/boards"
codeRealm := std.NewCodeRealm(path)