• Stars
    star
    211
  • Rank 186,867 (Top 4 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Tools for building Go applications on Flow 🌊

Flow Go SDK

GoDoc

The Flow Go SDK provides a set of packages for Go developers to build applications that interact with the Flow network.

Note: This SDK is also fully compatible with the Flow Emulator and can be used for local development.

English | Chinese

What is Flow?

Flow is a new blockchain for open worlds. Read more about it here.

Table of Contents

Getting Started

Installing

To start using the SDK, install Go 1.13 or above and run go get:

go get github.com/onflow/flow-go-sdk

Generating Keys

Flow uses ECDSA to control access to user accounts. Each key pair can be used in combination with the SHA2-256 or SHA3-256 hashing algorithms.

Here's how to generate an ECDSA private key for the P-256 (secp256r1) curve:

import "github.com/onflow/flow-go-sdk/crypto"

// deterministic seed phrase
// note: this is only an example, please use a secure random generator for the key seed
seed := []byte("elephant ears space cowboy octopus rodeo potato cannon pineapple")

privateKey, err := crypto.GeneratePrivateKey(crypto.ECDSA_P256, seed)

The private key can then be encoded as bytes (i.e. for storage):

encPrivateKey := privateKey.Encode()

A private key has an accompanying public key:

publicKey := privateKey.PublicKey()

Supported Curves

The example above uses an ECDSA key pair on the P-256 (secp256r1) elliptic curve. Flow also supports the secp256k1 curve used by Bitcoin and Ethereum.

Here's how to generate an ECDSA private key for the secp256k1 curve:

privateKey, err := crypto.GeneratePrivateKey(crypto.ECDSA_secp256k1, seed)

Here's a full list of the supported signature and hash algorithms: Flow Signature & Hash Algorithms

Creating an Account

Once you have generated a key pair, you can create a new account using its public key.

import (
    "github.com/onflow/flow-go-sdk"
    "github.com/onflow/flow-go-sdk/crypto"
    "github.com/onflow/flow-go-sdk/templates"
)

ctx := context.Background()

// generate a new private key for the account
// note: this is only an example, please use a secure random generator for the key seed
seed := []byte("elephant ears space cowboy octopus rodeo potato cannon pineapple")
privateKey, _ := crypto.GeneratePrivateKey(crypto.ECDSA_P256, seed)

// get the public key
publicKey := privateKey.PublicKey()

// construct an account key from the public key
accountKey := flow.NewAccountKey().
    SetPublicKey(publicKey).
    SetHashAlgo(crypto.SHA3_256).             // pair this key with the SHA3_256 hashing algorithm
    SetWeight(flow.AccountKeyWeightThreshold) // give this key full signing weight

// generate an account creation script
// this creates an account with a single public key and no code
script, _ := templates.CreateAccount([]*flow.AccountKey{accountKey}, nil)

// connect to an emulator running locally
c, err := client.New("localhost:3569")
if err != nil {
    panic("failed to connect to emulator")
}

payer, payerKey, payerSigner := examples.ServiceAccount(c)

tx := flow.NewTransaction().
    SetScript(script).
    SetGasLimit(100).
    SetProposalKey(payer, payerKey.Index, payerKey.SequenceNumber).
    SetPayer(payer)

err = tx.SignEnvelope(payer, payerKey.Index, payerSigner)
if err != nil {
    panic("failed to sign transaction")
}

err = c.SendTransaction(ctx, *tx)
if err != nil {
    panic("failed to send transaction")
}

result, err := c.GetTransactionResult(ctx, tx.ID())
if err != nil {
    panic("failed to get transaction result")
}

var myAddress flow.Address

if result.Status == flow.TransactionStatusSealed {
    for _, event := range result.Events {
        if event.Type == flow.EventAccountCreated {
            accountCreatedEvent := flow.AccountCreatedEvent(event)
            myAddress = accountCreatedEvent.Address()
        }
	}
}

Signing a Transaction

Below is a simple example of how to sign a transaction using a crypto.PrivateKey.

import (
    "github.com/onflow/flow-go-sdk"
    "github.com/onflow/flow-go-sdk/crypto"
)

var (
    myAddress    flow.Address
    myAccountKey flow.AccountKey
    myPrivateKey crypto.PrivateKey
)

tx := flow.NewTransaction().
    SetScript([]byte("transaction { execute { log(\"Hello, World!\") } }")).
    SetGasLimit(100).
    SetProposalKey(myAddress, myAccountKey.Index, myAccountKey.SequenceNumber).
    SetPayer(myAddress)

Transaction signing is done through the crypto.Signer interface. The simplest (and least secure) implementation of crypto.Signer is crypto.InMemorySigner.

Signatures can be generated more securely using keys stored in a hardware device such as an HSM. The crypto.Signer interface is intended to be flexible enough to support a variety of signer implementations and is not limited to in-memory implementations.

// construct a signer from your private key and configured hash algorithm
mySigner, err := crypto.NewInMemorySigner(myPrivateKey, myAccountKey.HashAlgo)
if err != nil {
    panic("failed to create a signer")
}

err = tx.SignEnvelope(myAddress, myAccountKey.Index, mySigner)
if err != nil {
    panic("failed to sign transaction")
}

How Signatures Work in Flow

Flow introduces new concepts that allow for more flexibility when creating and signing transactions. Before trying the examples below, we recommend that you read through the transaction signature documentation.


Single party, single signature

  • Proposer, payer and authorizer are the same account (0x01).
  • Only the envelope must be signed.
  • Proposal key must have full signing weight.
Account Key ID Weight
0x01 1 1000
account1, _ := c.GetAccount(ctx, flow.HexToAddress("01"))

key1 := account1.Keys[0]

// create signer from securely-stored private key
key1Signer := getSignerForKey1()

tx := flow.NewTransaction().
    SetScript([]byte(`
        transaction { 
            prepare(signer: AuthAccount) { log(signer.address) }
        }
    `)).
    SetGasLimit(100).
    SetProposalKey(account1.Address, key1.Index, key1.SequenceNumber).
    SetPayer(account1.Address).
    AddAuthorizer(account1.Address)

// account 1 signs the envelope with key 1
err := tx.SignEnvelope(account1.Address, key1.Index, key1Signer)

Full Runnable Example


Single party, multiple signatures

  • Proposer, payer and authorizer are the same account (0x01).
  • Only the envelope must be signed.
  • Each key has weight 500, so two signatures are required.
Account Key ID Weight
0x01 1 500
0x01 2 500
account1, _ := c.GetAccount(ctx, flow.HexToAddress("01"))

key1 := account1.Keys[0]
key2 := account1.Keys[1]

// create signers from securely-stored private keys
key1Signer := getSignerForKey1()
key2Signer := getSignerForKey2()

tx := flow.NewTransaction().
    SetScript([]byte(`
        transaction { 
            prepare(signer: AuthAccount) { log(signer.address) }
        }
    `)).
    SetGasLimit(100).
    SetProposalKey(account1.Address, key1.Index, key1.SequenceNumber).
    SetPayer(account1.Address).
    AddAuthorizer(account1.Address)

// account 1 signs the envelope with key 1
err := tx.SignEnvelope(account1.Address, key1.Index, key1Signer)

// account 1 signs the envelope with key 2
err = tx.SignEnvelope(account1.Address, key2.Index, key2Signer)

Full Runnable Example


Multiple parties

  • Proposer and authorizer are the same account (0x01).
  • Payer is a separate account (0x02).
  • Account 0x01 signs the payload.
  • Account 0x02 signs the envelope.
    • Account 0x02 must sign last since it is the payer.
Account Key ID Weight
0x01 1 1000
0x02 3 1000
account1, _ := c.GetAccount(ctx, flow.HexToAddress("01"))
account2, _ := c.GetAccount(ctx, flow.HexToAddress("02"))

key1 := account1.Keys[0]
key3 := account2.Keys[0]

// create signers from securely-stored private keys
key1Signer := getSignerForKey1()
key3Signer := getSignerForKey3()

tx := flow.NewTransaction().
    SetScript([]byte(`
        transaction { 
            prepare(signer: AuthAccount) { log(signer.address) }
        }
    `)).
    SetGasLimit(100).
    SetProposalKey(account1.Address, key1.Index, key1.SequenceNumber).
    SetPayer(account2.Address).
    AddAuthorizer(account1.Address)

// account 1 signs the payload with key 1
err := tx.SignPayload(account1.Address, key1.Index, key1Signer)

// account 2 signs the envelope with key 3
// note: payer always signs last
err = tx.SignEnvelope(account2.Address, key3.Index, key3Signer)

Full Runnable Example


Multiple parties, two authorizers

  • Proposer and authorizer are the same account (0x01).
  • Payer is a separate account (0x02).
  • Account 0x01 signs the payload.
  • Account 0x02 signs the envelope.
    • Account 0x02 must sign last since it is the payer.
  • Account 0x02 is also an authorizer to show how to include two AuthAccounts into an transaction
Account Key ID Weight
0x01 1 1000
0x02 3 1000
account1, _ := c.GetAccount(ctx, flow.HexToAddress("01"))
account2, _ := c.GetAccount(ctx, flow.HexToAddress("02"))

key1 := account1.Keys[0]
key3 := account2.Keys[0]

// create signers from securely-stored private keys
key1Signer := getSignerForKey1()
key3Signer := getSignerForKey3()

tx := flow.NewTransaction().
    SetScript([]byte(`
        transaction {
            prepare(signer1: AuthAccount, signer2: AuthAccount) {
              log(signer.address)
              log(signer2.address)
          }
        }
    `)).
    SetGasLimit(100).
    SetProposalKey(account1.Address, key1.Index, key1.SequenceNumber).
    SetPayer(account2.Address).
    AddAuthorizer(account1.Address).
    AddAuthorizer(account2.Address)

// account 1 signs the payload with key 1
err := tx.SignPayload(account1.Address, key1.Index, key1Signer)

// account 2 signs the envelope with key 3
// note: payer always signs last
err = tx.SignEnvelope(account2.Address, key3.Index, key3Signer)

Full Runnable Example


Multiple parties, multiple signatures

  • Proposer and authorizer are the same account (0x01).
  • Payer is a separate account (0x02).
  • Account 0x01 signs the payload.
  • Account 0x02 signs the envelope.
    • Account 0x02 must sign last since it is the payer.
  • Both accounts must sign twice (once with each of their keys).
Account Key ID Weight
0x01 1 500
0x01 2 500
0x02 3 500
0x02 4 500
account1, _ := c.GetAccount(ctx, flow.HexToAddress("01"))
account2, _ := c.GetAccount(ctx, flow.HexToAddress("02"))

key1 := account1.Keys[0]
key2 := account1.Keys[1]
key3 := account2.Keys[0]
key4 := account2.Keys[1]

// create signers from securely-stored private keys
key1Signer := getSignerForKey1()
key2Signer := getSignerForKey1()
key3Signer := getSignerForKey3()
key4Signer := getSignerForKey4()

tx := flow.NewTransaction().
    SetScript([]byte(`
        transaction { 
            prepare(signer: AuthAccount) { log(signer.address) }
        }
    `)).
    SetGasLimit(100).
    SetProposalKey(account1.Address, key1.Index, key1.SequenceNumber).
    SetPayer(account2.Address).
    AddAuthorizer(account1.Address)

// account 1 signs the payload with key 1
err := tx.SignPayload(account1.Address, key1.Index, key1Signer)

// account 1 signs the payload with key 2
err = tx.SignPayload(account1.Address, key2.Index, key2Signer)

// account 2 signs the envelope with key 3
// note: payer always signs last
err = tx.SignEnvelope(account2.Address, key3.Index, key3Signer)

// account 2 signs the envelope with key 4
// note: payer always signs last
err = tx.SignEnvelope(account2.Address, key4.Index, key4Signer)

Full Runnable Example

Sending a Transaction

You can submit a transaction to the network using the Access API client.

import "github.com/onflow/flow-go-sdk/access"

// connect to an emulator running locally
c, err := client.New("localhost:3569")
if err != nil {
    panic("failed to connect to emulator")
}

ctx := context.Background()

err = c.SendTransaction(ctx, tx)
if err != nil {
    panic("failed to send transaction")
}

Querying Transaction Results

After you have submitted a transaction, you can query its status by ID:

result, err := c.GetTransactionResult(ctx, tx.ID())
if err != nil {
    panic("failed to fetch transaction result")
}

The result includes a Status field that will be one of the following values:

  • UNKNOWN - The transaction has not yet been seen by the network.
  • PENDING - The transaction has not yet been included in a block.
  • FINALIZED - The transaction has been included in a block.
  • EXECUTED - The transaction has been executed but the result has not yet been sealed.
  • SEALED - The transaction has been executed and the result is sealed in a block.
if result.Status == flow.TransactionStatusSealed {
  fmt.Println("Transaction is sealed!")
}

The result also contains an Error that holds the error information for a failed transaction.

if result.Error != nil {
    fmt.Printf("Transaction failed with error: %v\n", result.Error)
}

Querying Blocks

You can use the GetLatestBlock method to fetch the latest sealed or unsealed block:

// fetch the latest sealed block
isSealed := true
latestBlock, err := c.GetLatestBlock(ctx, isSealed)
if err != nil {
    panic("failed to fetch latest sealed block")
}

// fetch the latest unsealed block
isSealed := false
latestBlock, err := c.GetLatestBlock(ctx, isSealed)
if err != nil {
    panic("failed to fetch latest unsealed block")
}

A block contains the following fields:

  • ID - The ID (hash) of the block.
  • ParentBlockID - The ID of the previous block in the chain.
  • Height - The height of the block in the chain.
  • CollectionGuarantees - The list of collections included in the block.

Executing a Script

You can use the ExecuteScriptAtLatestBlock method to execute a read-only script against the latest sealed execution state.

This functionality can be used to read state from the blockchain.

Scripts must be in the following form:

  • A single main function with a single return value

This is an example of a valid script:

fun main(): Int { return 1 }
import "github.com/onflow/cadence"

script := []byte("fun main(): Int { return 1 }")

value, err := c.ExecuteScriptAtLatestBlock(ctx, script, nil)
if err != nil {
    panic("failed to execute script")
}

ID := value.(cadence.Int)

// convert to Go int type
myID := ID.Int()

Querying Events

You can query events with the GetEventsForHeightRange function:

import "github.com/onflow/flow-go-sdk/access"

blocks, err := c.GetEventsForHeightRange(ctx, client.EventRangeQuery{
    Type:       "flow.AccountCreated",
    StartHeight: 10,
    EndHeight:   15,
})
if err != nil {
    panic("failed to query events")
}

Event Query Format

An event query includes the following fields:

Type

The event type to filter by. Event types are namespaced by the account and contract in which they are declared.

For example, a Transfer event that was defined in the Token contract deployed at account 0x55555555555555555555 will have a type of A.0x55555555555555555555.Token.Transfer.

Read the language documentation for more information on how to define and emit events in Cadence.

StartHeight, EndHeight

The blocks to filter by. Events will be returned from blocks in the range StartHeight to EndHeight, inclusive.

Event Results

The GetEventsForHeightRange function returns events grouped by block. Each block contains a list of events matching the query in order of execution.

for _, block := range blocks {
    fmt.Printf("Events for block %s:\n", block.BlockID)
    for _, event := range block.Events {
        fmt.Printf(" - %s", event)
    }
}

Querying Accounts

You can query the state of an account with the GetAccount function:

import "github.com/onflow/flow-go-sdk"

address := flow.HexToAddress("01")

account, err := c.GetAccount(ctx, address)
if err != nil {
    panic("failed to fetch account")
}

A flow.Account contains the following fields:

  • Address: flow.Address - The account address.
  • Balance: uint64 - The account balance.
  • Code: []byte - The code deployed at this account.
  • Keys: []flow.AccountKey - A list of the public keys associated with this account.

Examples

The examples directory contains code samples that use the SDK to interact with the Flow Emulator.

More Repositories

1

flow-go

A fast, secure, and developer-friendly blockchain built to support the next generation of games, apps, and the digital assets that power them.
Go
532
star
2

cadence

Cadence, the resource-oriented smart contract programming language πŸƒβ€β™‚οΈ
Go
505
star
3

flow-nft

The non-fungible token standard on the Flow blockchain
Cadence
459
star
4

kitty-items

Kitty Items: CryptoKitties Sample App
JavaScript
408
star
5

flow

Flow is a fast, secure, and developer-friendly blockchain built to support the next generation of games, apps, and the digital assets that power them 🌊
Go
357
star
6

fcl-js

FCL (Flow Client Library) - The best tool for building JavaScript (browser & NodeJS) applications on Flow 🌊
JavaScript
318
star
7

flow-cli

The Flow CLI is a command-line interface that provides useful utilities for building Flow applications
Go
207
star
8

flow-ft

The Fungible Token standard on the Flow Blockchain
Cadence
136
star
9

flow-playground

Flow Playground front-end app πŸ€Ήβ€β™‚οΈ
TypeScript
112
star
10

nft-storefront

A general-purpose Cadence contract for trading NFTs on Flow
Cadence
102
star
11

flow-core-contracts

Cadence smart contracts that define core functionality of the Flow protocol
Go
86
star
12

flow-emulator

The Flow Emulator is a lightweight tool that emulates the behaviour of the real Flow network
Go
84
star
13

freshmint

TypeScript
68
star
14

vscode-cadence

The Visual Studio Code extension for Cadence
TypeScript
52
star
15

fcl-dev-wallet

A Flow wallet for development purposes. To be used with the Flow Emulator.
Go
50
star
16

developer-grants

Grants for developers that contribute to the broader developer ecosystem
50
star
17

flip-fest

A backlog of all the available tasks to complete for Flow's FLIP Fest.
50
star
18

flow-js-testing

Testing framework to enable Cadence testing via a set of JavaScript methods and tools
JavaScript
46
star
19

atree

Atree provides scalable arrays and scalable ordered maps.
Go
39
star
20

nft-catalog

Cadence
37
star
21

flow-101-quest

Cadence
30
star
22

flips

Flow Improvement Proposals
25
star
23

cadence-tools

Developer tools for Cadence
Go
24
star
24

flow-cadut

Node based template generator to simplify interaction with Cadence files.
JavaScript
22
star
25

wallet-api

A REST API to create and manage Flow accounts
HTML
22
star
26

walletless-arcade-example

An example Flow App to demonstrate walletless onboarding and promote composable, secure, and smooth UX for on-chain games without the need for a traditional backend.
Cadence
21
star
27

monster-maker

Create a monster on Flow
TypeScript
18
star
28

hybrid-custody

Cadence suite enabling Hybrid Custody on Flow
Cadence
15
star
29

rosetta

Rosetta implementation for the Flow blockchain
Go
15
star
30

UnityFlowSDK

Flow SDK for Unity - build Unity games on the Flow blockchain
C#
13
star
31

flow-java-client-example

Java
12
star
32

wallet-extension-example

An example and guide showing how to build an FCL-compatible wallet extension on Flow.
JavaScript
12
star
33

fcl-discovery

JavaScript
11
star
34

flow-interaction-template-service

TypeScript
11
star
35

flow-playground-api

Flow Playground back-end app πŸ€Ήβ€β™‚οΈ
Go
11
star
36

linked-accounts

Cadence
11
star
37

ledger-app-flow

JavaScript
10
star
38

sc-eng-gaming

Showcasing how a Rock Paper Scissors game could be made #onFlow
Cadence
10
star
39

flow-batch-scan

Library for running batch scans of the flow network
Go
10
star
40

flow-evm-gateway

FlowEVM Gateway implements an Ethereum-equivalent JSON-RPC API for EVM clients to use
Go
9
star
41

cadence-libraries

Libraries for common programming utilities in the Cadence smart contract programming language
Go
9
star
42

flow-evm-bridge

Repository for contracts supporting bridge between Flow <> EVM
Cadence
9
star
43

sdks

Tips and resources for building Flow SDKs and client libraries πŸ”§
Cadence
9
star
44

developer-portal

Source code for developers.flow.com
TypeScript
8
star
45

docs

Flow Developer Portal. Discover the developer ecosystem and master the Flow blockchain
TypeScript
8
star
46

cadence-lang.org

The home of the Cadence website
MDX
8
star
47

cadence-cookbook

JavaScript
8
star
48

flow-multisig

JavaScript
8
star
49

OWBSummer2020Project

OWB (Open World Builders) bootcamp summer 2020 cohort capstone projects submission
CSS
8
star
50

Flow-Working-Groups

8
star
51

casestudies

Learn more about building on Flow from teams that have already launched successful projects
7
star
52

BFTune

Byzantine Fault Tolerance (BFT) Testing Framework for Flow
7
star
53

cadence-style-guide

The Flow Team guide on how to write better Cadence code
7
star
54

twg

Tokenomics Working Group
6
star
55

flowkit

Go
6
star
56

flow-interaction-template-tools

TypeScript
6
star
57

flow-kmm

Kotlin Multiplatform Mobile (KMM) library for building Android and iOS applications on the Flow blockchain
Objective-C
5
star
58

scaffold-flow

🌊 forkable Flow dev stack focused on fast product iterations
JavaScript
5
star
59

flow-issue-box

A public repository dedicated to collecting issues and feedback from external contributors. The Issue Box πŸ—³οΈ is similar to a backlog, where the issue is later triaged and assigned to the proper team.
5
star
60

ccf

Cadence Compact Format (CCF) is a binary data format and alternative to JSON-CDC
4
star
61

token-cold-storage

JavaScript
4
star
62

cddl

A CDDL implementation in Go
Go
4
star
63

Offers

Cadence
4
star
64

full-observer-node-example

An example demonstrating the use of the Flow unstaked consensus follower
Go
4
star
65

flow-account-api

Go
4
star
66

faucet

Cadence
4
star
67

contract-updater

Enabling delayed contract updates to a wrapped account at or beyond a specified block height
Cadence
4
star
68

flow-validator

Run a Flow node and help secure the network
4
star
69

flow-playground-tutorials

Repository to contain and test tutorials, which are deployed to Playground and used in docs
Cadence
3
star
70

flow-public-key-indexer

A observer service for indexing flow Accounts and by their associated Keys.
Go
3
star
71

flow-cadence-eth-utils

Cadence
3
star
72

flow-cadence-hrt

Write your Cadence tests with human readable TOML
JavaScript
3
star
73

random-coin-toss

An example repo demonstrating safe use of onchain randomness
Cadence
3
star
74

blindninja

Blind Ninja is a composability-first fully onchain game on Flow
JavaScript
3
star
75

waterhose

Waterhose listens to Flow events and publishes them to Kafka
2
star
76

fcl-auth-android

A Kotlin library for the Flow Client Library (FCL) that enables Flow wallet authentication on Android devices
Kotlin
2
star
77

service-account

Cadence
2
star
78

fcl-six

Stored Interactions (SIX) for FCL
JavaScript
2
star
79

flow-scaffold-list

Scaffolds for starting Flow apps
2
star
80

hybrid-custody-scaffold

Starter template for working with HybridCustody contract suite
Cadence
2
star
81

fcl-contracts

Cadence contracts used by the Flow Client Library (FCL)
Cadence
2
star
82

crypto

Assembly
2
star
83

dex

2
star
84

gwg

The Flow Governance Working Group (GWG) is an open-for-all forum that plays a pivotal role in shaping the Flow ecosystem with a focus on discussing and resolving governance issues.
2
star
85

next-docs-v0

next-docs
JavaScript
1
star
86

storage-fees-scripts

1
star
87

unity-flow-sdk-api-docs

HTML
1
star
88

fusd

Cadence source code for the FUSD stablecoin on Flow
Cadence
1
star
89

band-oracle-contracts

Contracts and related for integration with Band protocol Oracle Network
Cadence
1
star
90

cadence-1-migrator

Cadence
1
star
91

fcl-gcp-kms-web

JavaScript
1
star
92

fcl-next-scaffold

JavaScript
1
star
93

wallet-wg

Flow Wallet Working Group
1
star
94

minting-nfts-in-a-set

Cadence Cookbook Recipe: Minting NFTs in a Set
Cadence
1
star
95

create-a-marketplace

Cadence Cookbook Recipe: Create a Marketplace
Cadence
1
star
96

metadata-views

Cadence Cookbook Recipe: Metadata Views
Cadence
1
star
97

create-a-topshot-play

Cadence Cookbook Recipe: Create a TopShot Play
Cadence
1
star
98

collection-for-holding-nfts

Cadence Cookbook Recipe: Collection for Holding NFTs
Cadence
1
star
99

add-a-play-to-topshot-set

Cadence Cookbook Recipe: Add a Play to TopShot Set
Cadence
1
star
100

minting-a-moment-in-topshot-set

Cadence Cookbook Recipe: Minting a Moment in TopShot Set
Cadence
1
star