Skip to main content

Flare for Go Devs

This guide is for developers who want to interact with Flare using Go. In this guide, using Go, you will learn how to:

  • Query a contract on Flare using the Go API for Geth, a client that implements the full Ethereum JSON-RPC API.
  • Compile a Solidity contract using the CLI interface of solc, the Solidity compiler.
  • Deploy your compiled contract on Flare.
tip

All examples in this guide are available at developer-hub/examples.

Getting started

Install Geth by following the instructions in the Geth documentation. Also install the Solidity compiler by following the instructions in the Solidity documentation. The main commands are provided here:

brew tap ethereum/ethereum
brew install ethereum solidity

Add the ethclient and keystore packages to your Go project:

go get github.com/ethereum/go-ethereum/ethclient
go get github.com/ethereum/go-ethereum/accounts/keystore

The folder structure of your Go project should look like:

developer-hub-go/
├── coston2/
│ └── *.go
├── flare/
│ └── *.go
├── main.go
├── go.mod
└── go.sum

Usage

You need to connect to testnet or mainnet via an RPC, any RPC listed on the Network Configuration page will work. For this guide, you can use the Public RPC.

coston2/chain_id.go
package coston2

import (
"context"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/ethclient"
)

func ChainId() *big.Int {
cl, err := ethclient.Dial("https://coston2-api.flare.network/ext/C/rpc")
if err != nil {
panic(err)
}
chainid, err := cl.ChainID(context.Background())
if err != nil {
panic(err)
}
fmt.Println("Chain ID is", chainid)
// Chain ID is 114
return chainid
}

Querying a contract

To query a contract, two pieces of information are required:

  • Contract address
  • Contract ABI (Application Binary Interface)

For this example, you can use the FlareContractRegistry contract which has the same address 0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019 across both testnet and mainnet.

Fetch ABI

To fetch a contract's ABI, copy the FlareContractRegistry ABI, and paste it into a file named FlareContractRegistry.abi, located in the root of your project, i.e. same level as go.mod.

To generate the ABI bindings, which will be saved to FlareContractRegistry.go:

abigen --abi FlareContractRegistry.abi --pkg coston2 --type FlareContractRegistry --out coston2/FlareContractRegistry.go

Make query

You can now query the FlareContractRegistry contract to get the addresses of other Flare contracts.

For example, querying it for the address of the WNat contract:

coston2/make_query.go
package coston2

import (
"context"
"fmt"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)

func MakeQuery() []common.Address {
client, err := ethclient.Dial("https://coston2-api.flare.network/ext/C/rpc")
if err != nil {
panic(err)
}
registryAddr := common.HexToAddress("0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019")
registry, err := NewFlareContractRegistry(registryAddr, client)
if err != nil {
panic(err)
}
callOpts := &bind.CallOpts{Context: context.Background(), Pending: false}
addr, err := registry.GetContractAddressesByName(callOpts, []string{"WNat"})
if err != nil {
panic(err)
}
fmt.Println("WNat contract address is", addr)
// WNat contract address is [0xC67DCE33D7A8efA5FfEB961899C73fe01bCe9273]
return addr
}

Compiling with solc

For this example, you can use the FtsoV2FeedConsumer contract to query the FTSOv2 feeds. Copy the FtsoV2FeedConsumer sample contract code given below, and save the .sol file in the same folder as your go.mod.

FtsoV2FeedConsumer sample contract

Note that the contract interface dependencies have been inlined to avoid any import issues.

FtsoV2FeedConsumer.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

interface IFlareContractRegistry {
function getContractAddressByName(
string calldata _name
) external view returns (address);
}

/**
* THIS IS A TEST INTERFACE.
* Functions are payable in the production interface.
*/
interface TestFtsoV2Interface {
function getFeedsById(
bytes21[] calldata _feedIds
)
external
view
returns (
uint256[] memory _values,
int8[] memory _decimals,
uint64 _timestamp
);
}

/**
* THIS IS AN EXAMPLE CONTRACT.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
contract FtsoV2FeedConsumer {
IFlareContractRegistry internal contractRegistry;
TestFtsoV2Interface internal ftsoV2;

// Feed IDs, see https://dev.flare.network/ftso/feeds for full list
bytes21[] public feedIds = [
bytes21(0x01464c522f55534400000000000000000000000000), // FLR/USD
bytes21(0x014254432f55534400000000000000000000000000), // BTC/USD
bytes21(0x014554482f55534400000000000000000000000000) // ETH/USD
];

/**
* Constructor initializes the FTSOv2 contract.
* The contract registry is used to fetch the FtsoV2 contract address.
*/
constructor() {
contractRegistry = IFlareContractRegistry(
0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019
);
ftsoV2 = TestFtsoV2Interface(
contractRegistry.getContractAddressByName("FtsoV2")
);
}

/**
* Get the current value of the feeds.
*/
function getFtsoV2CurrentFeedValues()
external
view
returns (
uint256[] memory _feedValues,
int8[] memory _decimals,
uint64 _timestamp
)
{
/* Your custom feed consumption logic. In this example the values are just returned. */
return ftsoV2.getFeedsById(feedIds);
}
}

To compile the contract, use the Solidity compiler:

solc --evm-version london --abi --bin FtsoV2FeedConsumer.sol -o build

The compiled contract will be saved in the build/ folder.

Create account

Before deploying a contract, you need an account. You can create an account using the following code:

create_account.go
package main

import (
"fmt"
"github.com/ethereum/go-ethereum/accounts/keystore"
)

func CreateAccount() {
ks := keystore.NewKeyStore(".", keystore.StandardScryptN, keystore.StandardScryptP)
account, err := ks.NewAccount("Creation password")
if err != nil {
panic(err)
}
fmt.Println("Account: ", account.Address.Hex())
}

This will generate a new account and save the keystore file in the current directory. The account address will be printed to the console.

danger
  • Never share your private keys.
  • Never put your private keys in source code.
  • Never commit private keys to a Git repository.
  • For testnet, you can get free testnet C2FLR on the Coston2 Faucet.
  • For mainnet you will need to fund the account with FLR. You can buy FLR with regular currency in places like centralized exchanges, crypto on-ramps, or swap other tokens for FLR on decentralized exchanges.

Deploying with geth

To deploy the contract, you need to first generate the contract bindings:

abigen --bin=build/FtsoV2FeedConsumer.bin --abi=build/FtsoV2FeedConsumer.abi --pkg coston2 --type FtsoV2FeedConsumer --out coston2/FtsoV2FeedConsumer.go

This will generate the FtsoV2FeedConsumer.go file, with the function DeployFtsoV2FeedConsumer.

Copy the contents of the generated keystore file into the key constant in the following code:

deploy_contract.go
// THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
package coston2

import (
"context"
"fmt"
"strings"
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/ethclient"
)

// Paste the contents of the generated keystore file here
// DO NOT USE THIS CODE IN PRODUCTION.
// NEVER COMMIT PRIVATE KEYS TO A GIT REPOSITORY.
const key = ``

func DeployContract() {
conn, err := ethclient.Dial("https://coston2-api.flare.network/ext/C/rpc")
if err != nil {
panic(err)
}
ctx := context.Background()
chainId, err := conn.ChainID(ctx)
if err != nil {
panic(err)
}
auth, err := bind.NewTransactorWithChainID(strings.NewReader(key), "Creation password", chainId)
if err != nil {
panic(err)
}
address, tx, ftsoV2FeedConsumer, err := DeployFtsoV2FeedConsumer(auth, conn)
if err != nil {
panic(err)
}
fmt.Printf("Contract pending deploy: 0x%x\n", address)
fmt.Printf("Transaction waiting to be mined: 0x%x\n\n", tx.Hash())
time.Sleep(2000 * time.Millisecond)

feeds, err := ftsoV2FeedConsumer.GetFtsoV2CurrentFeedValues(&bind.CallOpts{Context: ctx, Pending: true})
if err != nil {
panic(err)
}
fmt.Println("Feeds values and decimals:", feeds)
}

Congratulations! You have now successfully deployed a contract on Flare using Go.

What's next?

Learn how to interact with Flare's enshrined oracle FTSOv2 using Go.