flow

package module
v0.4.4 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2020 License: Apache-2.0 Imports: 11 Imported by: 0

README

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.

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/portto/blocto-flow-go-sdk
Generating Keys

Flow uses ECDSA key pairs 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 on the P-256 curve:

import "github.com/portto/blocto-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 elliptic curve. Flow also supports the secp256k1 curve used by Bitcoin and Ethereum.

Here's how to generate an ECDSA private key on 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/portto/blocto-flow-go-sdk"
    "github.com/portto/blocto-flow-go-sdk/crypto"
    "github.com/portto/blocto-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.ID, payerKey.SequenceNumber).
    SetPayer(payer)

err = tx.SignEnvelope(payer, payerKey.ID, 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/portto/blocto-flow-go-sdk"
    "github.com/portto/blocto-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.ID, 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 hardware keys stored in a 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 := crypto.NewInMemorySigner(myPrivateKey, myAccountKey.HashAlgo)

err := tx.SignEnvelope(myAddress, myAccountKey.ID, 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.


  • 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 1.0
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.ID, key1.SequenceNumber).
    SetPayer(account1.Address).
    AddAuthorizer(account1.Address)

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

Full Runnable Example


  • Proposer, payer and authorizer are the same account (0x01).
  • Only the envelope must be signed.
  • Each key has weight 0.5, so two signatures are required.
Account Key ID Weight
0x01 1 0.5
0x01 2 0.5
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.ID, key1.SequenceNumber).
    SetPayer(account1.Address).
    AddAuthorizer(account1.Address)

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

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

Full Runnable Example


  • 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 1.0
0x02 3 1.0
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.ID, key1.SequenceNumber).
    SetPayer(account2.Address).
    AddAuthorizer(account1.Address)

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

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

Full Runnable Example


  • 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 0.5
0x01 2 0.5
0x02 3 0.5
0x02 4 0.5
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.ID, key1.SequenceNumber).
    SetPayer(account2.Address).
    AddAuthorizer(account1.Address)

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

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

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

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

Full Runnable Example

Sending a Transaction

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

import "github.com/portto/blocto-flow-go-sdk/client"

// 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.ExecuteScript(ctx, script)
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/portto/blocto-flow-go-sdk/client"

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/portto/blocto-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.

Documentation

Overview

Package flow provides libraries and tools for building Go applications on Flow.

Index

Examples

Constants

View Source
const (
	EventAccountCreated string = "flow.AccountCreated"
	EventAccountUpdated string = "flow.AccountUpdated"
)

List of built-in account event types.

View Source
const AccountKeyWeightThreshold int = 1000

AccountKeyWeightThreshold is the total key weight required to authorize access to an account.

View Source
const AddressLength = (linearCodeN + 7) >> 3

AddressLength is the size of an account address in bytes.

Variables

View Source
var DefaultHasher crypto.Hasher

DefaultHasher is the default hasher used by Flow.

View Source
var EmptyAddress = Address{}

EmptyAddress is the empty address (0x0000000000000000).

View Source
var EmptyID = Identifier{}

EmptyID is the empty identifier.

Functions

This section is empty.

Types

type Account

type Account struct {
	Address Address
	Balance uint64
	Code    []byte
	Keys    []*AccountKey
}

An Account is an account on the Flow network.

type AccountCreatedEvent

type AccountCreatedEvent Event

An AccountCreatedEvent is emitted when a transaction creates a new Flow account.

This event contains the following fields: - Address: Address

func (AccountCreatedEvent) Address

func (evt AccountCreatedEvent) Address() Address

Address returns the address of the newly-created account.

type AccountKey

type AccountKey struct {
	ID             int
	PublicKey      crypto.PublicKey
	SigAlgo        crypto.SignatureAlgorithm
	HashAlgo       crypto.HashAlgorithm
	Weight         int
	SequenceNumber uint64
}

An AccountKey is a public key associated with an account.

func DecodeAccountKey

func DecodeAccountKey(b []byte) (*AccountKey, error)

DecodeAccountKey decodes the RLP byte representation of an account key.

func NewAccountKey

func NewAccountKey() *AccountKey

NewAccountKey returns an empty account key.

func (AccountKey) Encode

func (a AccountKey) Encode() []byte

Encode returns the canonical RLP byte representation of this account key.

func (*AccountKey) FromPrivateKey

func (a *AccountKey) FromPrivateKey(privKey crypto.PrivateKey) *AccountKey

FromPrivateKey sets the public key and signature algorithm based on the provided private key.

func (*AccountKey) SetHashAlgo

func (a *AccountKey) SetHashAlgo(hashAlgo crypto.HashAlgorithm) *AccountKey

SetHashAlgo sets the hash algorithm for this account key.

func (*AccountKey) SetPublicKey

func (a *AccountKey) SetPublicKey(pubKey crypto.PublicKey) *AccountKey

SetPublicKey sets the public key for this account key.

func (*AccountKey) SetSigAlgo

func (a *AccountKey) SetSigAlgo(sigAlgo crypto.SignatureAlgorithm) *AccountKey

SetSigAlgo sets the signature algorithm for this account key.

func (*AccountKey) SetWeight

func (a *AccountKey) SetWeight(weight int) *AccountKey

SetWeight sets the weight for this account key.

func (AccountKey) Validate

func (a AccountKey) Validate() error

Validate returns an error if this account key is invalid.

An account key can be invalid for the following reasons: - It specifies an incompatible signature/hash algorithm pairing - (TODO) It specifies a negative key weight

type Address

type Address [AddressLength]byte

Address represents the 8 byte address of an account.

func BytesToAddress

func BytesToAddress(b []byte) Address

BytesToAddress returns Address with value b.

If b is larger than 8, b will be cropped from the left. If b is smaller than 8, b will be appended by zeroes at the front.

func HexToAddress

func HexToAddress(h string) Address

HexToAddress converts a hex string to an Address.

func ServiceAddress

func ServiceAddress(chain ChainID) Address

ServiceAddress is the first generated account address.

func (Address) Bytes

func (a Address) Bytes() []byte

Bytes returns the byte representation of the address.

func (Address) Hex

func (a Address) Hex() string

Hex returns the hex string representation of the address.

func (*Address) IsValid

func (a *Address) IsValid(chain ChainID) bool

IsValid returns true if a given address is a valid account address, and false otherwise.

This is an off-chain check that only tells whether the address format is valid. If the function returns true, this does not mean a Flow account with this address has been generated. Such a test would require an on-chain check.

func (Address) MarshalJSON

func (a Address) MarshalJSON() ([]byte, error)

func (Address) String

func (a Address) String() string

String returns the string representation of the address.

func (*Address) UnmarshalJSON

func (a *Address) UnmarshalJSON(data []byte) error

type AddressGenerator

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

An AddressGenerator uses a deterministic algorithm to generate Flow addresses.

func NewAddressGenerator

func NewAddressGenerator(chainID ChainID) *AddressGenerator

NewAddressGenerator creates a new address generator for the given chain ID, starting from the zero address state.

Addresses are generated for a specific network (Flow mainnet, testnet, etc).

Each addressing state is mapped to exactly one address, meaning there are as many addresses as states. State values are incremented from 0 to 2^k-1.

func (*AddressGenerator) Address

func (gen *AddressGenerator) Address() Address

Address generates an account address at the current addressing state.

func (*AddressGenerator) Next

func (gen *AddressGenerator) Next() *AddressGenerator

Next increments the addressing state.

State values are incremented from 0 to 2^k-1.

func (*AddressGenerator) NextAddress

func (gen *AddressGenerator) NextAddress() Address

NextAddress increments the addressing state and generates an account address.

func (*AddressGenerator) SetIndex

func (gen *AddressGenerator) SetIndex(i uint) *AddressGenerator

SetIndex fast-forwards or rewinds the addressing state to the given index.

type Block

type Block struct {
	BlockHeader
	BlockPayload
}

Block is a set of state mutations applied to the Flow blockchain.

type BlockHeader

type BlockHeader struct {
	ID        Identifier
	ParentID  Identifier
	Height    uint64
	Timestamp time.Time
}

BlockHeader is a summary of a full block.

type BlockPayload

type BlockPayload struct {
	CollectionGuarantees []*CollectionGuarantee
	Seals                []*BlockSeal
}

BlockPayload is the full contents of a block.

A payload contains the collection guarantees and seals for a block.

type BlockSeal

type BlockSeal struct{}

TODO: define block seal struct

type ChainID

type ChainID string

A ChainID is a unique identifier for a specific Flow network instance.

Chain IDs are used used to prevent replay attacks and to support network-specific address generation.

const Emulator ChainID = "flow-emulator"

Emulator is the chain ID for the emulated node chain.

const Mainnet ChainID = "flow-mainnet"

Mainnet is the chain ID for the mainnet node chain.

const Testnet ChainID = "flow-testnet"

Testnet is the chain ID for the testnet node chain.

func (ChainID) String

func (id ChainID) String() string

type Collection

type Collection struct {
	TransactionIDs []Identifier
}

A Collection is a list of transactions bundled together for inclusion in a block.

func (Collection) Encode

func (c Collection) Encode() []byte

Encode returns the canonical RLP byte representation of this collection.

func (Collection) ID

func (c Collection) ID() Identifier

ID returns the canonical SHA3-256 hash of this collection.

type CollectionGuarantee

type CollectionGuarantee struct {
	CollectionID Identifier
}

A CollectionGuarantee is an attestation signed by the nodes that have guaranteed a collection.

type Event

type Event struct {
	// Type is the qualified event type.
	Type string
	// TransactionID is the ID of the transaction this event was emitted from.
	TransactionID Identifier
	// TransactionIndex is the index of the transaction this event was emitted from, within its containing block.
	TransactionIndex int
	// EventIndex is the index of the event within the transaction it was emitted from.
	EventIndex int
	// Value contains the event data.
	Value cadence.Event
}

func (Event) Encode

func (e Event) Encode() []byte

Encode returns the canonical RLP byte representation of this event.

func (Event) ID

func (e Event) ID() string

ID returns the canonical SHA3-256 hash of this event.

func (Event) String

func (e Event) String() string

String returns the string representation of this event.

type Identifier

type Identifier [32]byte

An Identifier is a 32-byte unique identifier for an entity.

func BytesToID

func BytesToID(b []byte) Identifier

BytesToID constructs an identifier from a byte slice.

func HashToID

func HashToID(hash []byte) Identifier

func HexToID

func HexToID(h string) Identifier

HexToID constructs an identifier from a hexadecimal string.

func (Identifier) Bytes

func (i Identifier) Bytes() []byte

Bytes returns the bytes representation of this identifier.

func (Identifier) Hex

func (i Identifier) Hex() string

Hex returns the hexadecimal string representation of this identifier.

func (Identifier) String

func (i Identifier) String() string

String returns the string representation of this identifier.

type ProposalKey

type ProposalKey struct {
	Address        Address
	KeyID          int
	SequenceNumber uint64
}

A ProposalKey is the key that specifies the proposal key and sequence number for a transaction.

type Transaction

type Transaction struct {
	Script             []byte
	Arguments          []cadence.Value
	ReferenceBlockID   Identifier
	GasLimit           uint64
	ProposalKey        ProposalKey
	Payer              Address
	Authorizers        []Address
	PayloadSignatures  []TransactionSignature
	EnvelopeSignatures []TransactionSignature
}

A Transaction is a full transaction object containing a payload and signatures.

Example
addresses := test.AddressGenerator()

// Mock user accounts

adrianLaptopKey := &flow.AccountKey{
	ID:             3,
	SequenceNumber: 42,
}

adrianPhoneKey := &flow.AccountKey{ID: 2}
addressA := addresses.New()

adrian := flow.Account{
	Address: addressA,
	Keys: []*flow.AccountKey{
		adrianLaptopKey,
		adrianPhoneKey,
	},
}

blaineHardwareKey := &flow.AccountKey{ID: 7}
addressB := addresses.New()

blaine := flow.Account{
	Address: addressB,
	Keys: []*flow.AccountKey{
		blaineHardwareKey,
	},
}

// Transaction preparation

tx := flow.NewTransaction().
	SetScript([]byte(`transaction { execute { log("Hello, World!") } }`)).
	SetReferenceBlockID(flow.Identifier{0x01, 0x02}).
	SetGasLimit(42).
	SetProposalKey(adrian.Address, adrianLaptopKey.ID, adrianLaptopKey.SequenceNumber).
	SetPayer(blaine.Address).
	AddAuthorizer(adrian.Address)

fmt.Printf("Transaction ID (before signing): %s\n\n", tx.ID())

// Signing

err := tx.SignPayload(adrian.Address, adrianLaptopKey.ID, test.MockSigner([]byte{1}))
if err != nil {
	panic(err)
}

err = tx.SignPayload(adrian.Address, adrianPhoneKey.ID, test.MockSigner([]byte{2}))
if err != nil {
	panic(err)
}

err = tx.SignEnvelope(blaine.Address, blaineHardwareKey.ID, test.MockSigner([]byte{3}))
if err != nil {
	panic(err)
}

fmt.Println("Payload signatures:")
for _, sig := range tx.PayloadSignatures {
	fmt.Printf(
		"Address: %s, Key ID: %d, Signature: %x\n",
		sig.Address,
		sig.KeyID,
		sig.Signature,
	)
}
fmt.Println()

fmt.Println("Envelope signatures:")
for _, sig := range tx.EnvelopeSignatures {
	fmt.Printf(
		"Address: %s, Key ID: %d, Signature: %x\n",
		sig.Address,
		sig.KeyID,
		sig.Signature,
	)
}
fmt.Println()

fmt.Printf("Transaction ID (after signing): %s\n", tx.ID())
Output:

Transaction ID (before signing): 8c362dd8b7553d48284cecc94d2ab545d513b29f930555632390fff5ca9772ee

Payload signatures:
Address: f8d6e0586b0a20c7, Key ID: 2, Signature: 02
Address: f8d6e0586b0a20c7, Key ID: 3, Signature: 01

Envelope signatures:
Address: ee82856bf20e2aa6, Key ID: 7, Signature: 03

Transaction ID (after signing): d1a2c58aebfce1050a32edf3568ec3b69cb8637ae090b5f7444ca6b2a8de8f8b

func NewTransaction

func NewTransaction() *Transaction

NewTransaction initializes and returns an empty transaction.

func (*Transaction) AddArgument

func (t *Transaction) AddArgument(arg cadence.Value) *Transaction

AddArgument adds a Cadence argument to this transaction.

func (*Transaction) AddAuthorizer

func (t *Transaction) AddAuthorizer(address Address) *Transaction

AddAuthorizer adds an authorizer account to this transaction.

func (*Transaction) AddEnvelopeSignature

func (t *Transaction) AddEnvelopeSignature(address Address, keyID int, sig []byte) *Transaction

AddEnvelopeSignature adds an envelope signature to the transaction for the given address and key ID.

func (*Transaction) AddPayloadSignature

func (t *Transaction) AddPayloadSignature(address Address, keyID int, sig []byte) *Transaction

AddPayloadSignature adds a payload signature to the transaction for the given address and key ID.

func (*Transaction) DecodeFromBytes

func (t *Transaction) DecodeFromBytes(bs []byte) error

DecodeFromBytes un-serializes from raw data to the full transaction data

func (*Transaction) Encode

func (t *Transaction) Encode() []byte

Encode serializes the full transaction data including the payload and all signatures.

func (*Transaction) EnvelopeMessage

func (t *Transaction) EnvelopeMessage() []byte

EnvelopeMessage returns the signable message for the transaction envelope.

This message is only signed by the payer account.

func (*Transaction) ID

func (t *Transaction) ID() Identifier

ID returns the canonical SHA3-256 hash of this transaction.

func (*Transaction) PayloadMessage

func (t *Transaction) PayloadMessage() []byte

func (*Transaction) SetGasLimit

func (t *Transaction) SetGasLimit(limit uint64) *Transaction

SetGasLimit sets the gas limit for this transaction.

func (*Transaction) SetPayer

func (t *Transaction) SetPayer(address Address) *Transaction

SetPayer sets the payer account for this transaction.

func (*Transaction) SetProposalKey

func (t *Transaction) SetProposalKey(address Address, keyID int, sequenceNum uint64) *Transaction

SetProposalKey sets the proposal key and sequence number for this transaction.

The first two arguments specify the account key to be used, and the last argument is the sequence number being declared.

func (*Transaction) SetReferenceBlockID

func (t *Transaction) SetReferenceBlockID(blockID Identifier) *Transaction

SetReferenceBlockID sets the reference block ID for this transaction.

func (*Transaction) SetScript

func (t *Transaction) SetScript(script []byte) *Transaction

SetScript sets the Cadence script for this transaction.

func (*Transaction) SignEnvelope

func (t *Transaction) SignEnvelope(address Address, keyID int, signer crypto.Signer) error

SignEnvelope signs the full transaction (payload + payload signatures) with the specified account key.

The resulting signature is combined with the account address and key ID before being added to the transaction.

This function returns an error if the signature cannot be generated.

func (*Transaction) SignPayload

func (t *Transaction) SignPayload(address Address, keyID int, signer crypto.Signer) error

SignPayload signs the transaction payload with the specified account key.

The resulting signature is combined with the account address and key ID before being added to the transaction.

This function returns an error if the signature cannot be generated.

type TransactionResult

type TransactionResult struct {
	Status TransactionStatus
	Error  error
	Events []Event
}

type TransactionSignature

type TransactionSignature struct {
	Address     Address
	SignerIndex int
	KeyID       int
	Signature   []byte
}

A TransactionSignature is a signature associated with a specific account key.

type TransactionStatus

type TransactionStatus int

TransactionStatus represents the status of a transaction.

const (
	// TransactionStatusUnknown indicates that the transaction status is not known.
	TransactionStatusUnknown TransactionStatus = iota
	// TransactionStatusPending is the status of a pending transaction.
	TransactionStatusPending
	// TransactionStatusFinalized is the status of a finalized transaction.
	TransactionStatusFinalized
	// TransactionStatusExecuted is the status of an executed transaction.
	TransactionStatusExecuted
	// TransactionStatusSealed is the status of a sealed transaction.
	TransactionStatusSealed
)

func (TransactionStatus) String

func (s TransactionStatus) String() string

String returns the string representation of a transaction status.

Directories

Path Synopsis
Package client provides a Go client for the Flow Access gRPC API.
Package client provides a Go client for the Flow Access gRPC API.
Package templates provides functions for generating common Cadence scripts.
Package templates provides functions for generating common Cadence scripts.

Jump to

Keyboard shortcuts

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