Skip to content

Create Publication

We are looking for publications that demonstrate building dApps or smart contracts!
See the full list of Gitcoin bounties that are eligible for rewards.

Your First Transaction

This section is a quick start guide for sending your first transaction on the Algorand TestNet network using the Go programming language. This guide installs the Go SDK, creates an account and submits a payment transaction. This guide also installs Algorand Sandbox, which provides required infrastructure for development and testing.

Info

If you are a visual learner, try our live demo or watch a video walkthrough explaining all the code in the steps below.

Install Algorand Sandbox

Algorand Sandbox is developer-focused tool for quickly spinning up the Algorand infrastructure portion of your development environment. It uses Docker to provide an algod instance for connecting to the network of your choosing and an indexer instance for querying blockchain data. APIs are exposed by both instances for client access provided within the SDK. Read more about Algorand networks, their capabilities and intended use.

Prerequisites

From a terminal window, install Algorand Sandbox connected to TestNet:

git clone https://github.com/algorand/sandbox.git
cd sandbox
./sandbox up testnet

Warning

The Algorand Sandbox installation may take a few minutes to complete in order to catch up to the current round on TestNet. To learn more about fast catchup, see Sync Node Network using Fast Catchup.

Info

The indexer is enabled only for private networks. Therefore, all blockchain queries in this guide will use the algod API.

Install Go SDK

Algorand provides an SDK for Go.

Prerequisites

From a terminal window, install the Go SDK:

go get -u github.com/algorand/go-algorand-sdk/...

The SDK is installed and can now interact with the running Algorand Sandbox environment, as configured above.

Create account

In order to interact with the Algorand blockchain, you must have a funded account on the network. To quickly create an account on Algorand TestNet create a new file yourFirstTransaction.go and insert the following code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
    "context"
    json "encoding/json"
    "errors"
    "fmt"
    "strings"

    "github.com/algorand/go-algorand-sdk/client/v2/algod"
    "github.com/algorand/go-algorand-sdk/client/v2/common/models"
    "github.com/algorand/go-algorand-sdk/crypto"
    "github.com/algorand/go-algorand-sdk/mnemonic"
    "github.com/algorand/go-algorand-sdk/transaction"
)

// TODO: insert additional utility functions here

func main() {
    // Create account
    account := crypto.GenerateAccount()
    passphrase, err := mnemonic.FromPrivateKey(account.PrivateKey)
    myAddress := account.Address.String()

    if err != nil {
        fmt.Printf("Error creating transaction: %s\n", err)
    } else {
        fmt.Printf("My address: %s\n", myAddress)
        fmt.Printf("My passphrase: %s\n", passphrase)
        fmt.Println("--> Copy down your address and passpharse for future use.")
        fmt.Println("--> Once secured, press ENTER key to continue...")
        fmt.Scanln()
    }

    // TODO: insert additional codeblocks here
}

Note

Lines 17 and 35 contain TODO: comments about inserting additional code. As you proceed with this guide, ensure the line numbers remain in sync.

Tip

Make sure to save the generated address and passphrase in a secure location, as they will be used later on.

Warning

Never share your mnemonic passphrase or private keys. Production environments require stringent private key management. For more information on key management in community Wallets, click here. For the open source Algorand Wallet, click here.

Fund account

The code below prompts to fund the newly generated account. Before sending transactions to the Algorand network, the account must be funded to cover the minimal transaction fees that exist on Algorand. To fund the account use the Algorand TestNet faucet.

35
36
37
38
// Fund account
fmt.Println("Fund the created account using the Algorand TestNet faucet:\n--> https://dispenser.testnet.aws.algodev.network?account=" + myAddress)
fmt.Println("--> Once funded, press ENTER key to continue...")
fmt.Scanln()

Info

All Algorand accounts require a minimum balance to be registered in the ledger. To read more about Algorand minimum balance see Account Overview

Instantiate client

You must instantiate a client prior to making calls to the API endpoints. The Go SDK implements the client natively using the following code:

40
41
42
43
44
45
46
47
48
// instantiate algod client to Algorand Sandbox
const algodAddress = "http://localhost:4001"
const algodToken = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

algodClient, err := algod.MakeClient(algodAddress, algodToken)
if err != nil {
    fmt.Printf("Issue with creating algod client: %s\n", err)
    return
}

Info

This guide provides values for algodAddress and algodToken as specified by Algorand Sandbox. If you want to connect to a third-party service provider, see Purestake or AlgoExplorer Developer API and adjust these values accordingly.

Check account balance

Before moving on to the next step, make sure your account has been funded by the faucet.

50
51
52
53
54
55
56
57
58
59
60
//Check account balance
fmt.Printf("My address: %s\n", myAddress)

accountInfo, err := algodClient.AccountInformation(myAddress).Do(context.Background())
if err != nil {
    fmt.Printf("Error getting account info: %s\n", err)
    return
}
fmt.Printf("Account balance: %d microAlgos\n", accountInfo.Amount)
fmt.Println("--> Ensure balance greater than 0, press ENTER key to continue...")
fmt.Scanln()

Build transaction

Communication with the Algorand network is performed using transactions. Create a payment transaction sending 9 ALGO from your account to the TestNet faucet address:

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Construct the transaction
txParams, err := algodClient.SuggestedParams().Do(context.Background())
if err != nil {
    fmt.Printf("Error getting suggested tx params: %s\n", err)
    return
}
fromAddr := myAddress
toAddr := "GD64YIY3TWGDMCNPP553DZPPR6LDUSFQOIJVFDPPXWEG3FVOJCCDBBHU5A"
var amount uint64 = 9000000
var minFee uint64 = 1000
note := []byte("Hello World")
genID := txParams.GenesisID
genHash := txParams.GenesisHash
firstValidRound := uint64(txParams.FirstRoundValid)
lastValidRound := uint64(txParams.LastRoundValid)
txn, err := transaction.MakePaymentTxnWithFlatFee(fromAddr, toAddr, minFee, amount, firstValidRound, lastValidRound, note, "", genID, genHash)
if err != nil {
    fmt.Printf("Error creating transaction: %s\n", err)
    return
}

Info

Algorand supports many transaction types. To see what types are supported see Transactions.

Watch Video

Sign transaction

Before the transaction is considered valid, it must be signed by a private key. Use the following code to sign the transaction.

83
84
85
86
87
88
89
// Sign the transaction
txID, signedTxn, err := crypto.SignTransaction(account.PrivateKey, txn)
if err != nil {
    fmt.Printf("Failed to sign transaction: %s\n", err)
    return
}
fmt.Printf("Signed txid: %s\n", txID)

Info

Algorand provides many ways to sign transactions. To see other ways see Authorization.

Watch Video

Submit transaction

The signed transaction can now be broadcast to the network for validation and inclusion in a future block. The waitForConfirmation method polls the algod node for the transaction ID to ensure it succeeded.

 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
// Submit the transaction
sendResponse, err := algodClient.SendRawTransaction(signedTxn).Do(context.Background())
if err != nil {
    fmt.Printf("failed to send transaction: %s\n", err)
    return
}
fmt.Printf("Submitted transaction %s\n", sendResponse)

// Wait for confirmation
confirmedTxn, err := waitForConfirmation(txID, algodClient, 4)
if err != nil {
    fmt.Printf("Error waiting for confirmation on txID: %s\n", txID)
    return
}

Display completed transaction

Finally, we can query the blockchain for the committed transaction data and display in on the command line.

106
107
108
109
110
111
112
// Display completed transaction
txnJSON, err := json.MarshalIndent(confirmedTxn.Transaction.Txn, "", "\t")
if err != nil {
    fmt.Printf("Can not marshall txn data: %s\n", err)
}
fmt.Printf("Transaction information: %s\n", txnJSON)
fmt.Printf("Decoded note: %s\n", string(confirmedTxn.Transaction.Txn.Note))

Add utility functions

The utility function waitForConfirmation should be inserted between your imports and main() code blocks:

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Utility function that waits for a given txId to be confirmed by the network
func waitForConfirmation(txID string, client *algod.Client, timeout uint64) (models.PendingTransactionInfoResponse, error) {
    pt := new(models.PendingTransactionInfoResponse)
    if client == nil || txID == "" || timeout < 0 {
        fmt.Printf("Bad arguments for waitForConfirmation")
        var msg = errors.New("Bad arguments for waitForConfirmation")
        return *pt, msg

    }

    status, err := client.Status().Do(context.Background())
    if err != nil {
        fmt.Printf("error getting algod status: %s\n", err)
        var msg = errors.New(strings.Join([]string{"error getting algod status: "}, err.Error()))
        return *pt, msg
    }
    startRound := status.LastRound + 1
    currentRound := startRound

    for currentRound < (startRound + timeout) {

        *pt, _, err = client.PendingTransactionInformation(txID).Do(context.Background())
        if err != nil {
            fmt.Printf("error getting pending transaction: %s\n", err)
            var msg = errors.New(strings.Join([]string{"error getting pending transaction: "}, err.Error()))
            return *pt, msg
        }
        if pt.ConfirmedRound > 0 {
            fmt.Printf("Transaction "+txID+" confirmed in round %d\n", pt.ConfirmedRound)
            return *pt, nil
        }
        if pt.PoolError != "" {
            fmt.Printf("There was a pool error, then the transaction has been rejected!")
            var msg = errors.New("There was a pool error, then the transaction has been rejected")
            return *pt, msg
        }
        fmt.Printf("waiting for confirmation\n")
        status, err = client.StatusAfterBlock(currentRound).Do(context.Background())
        currentRound++
    }
    msg := errors.New("Tx not found in round range")
    return *pt, msg
}

Run the program

Save your file and execute the program:

go run yourFirstTransaction.go

Warning

In order for your transaction to be successful, you must fund the generated account during runtime.

Info

View the confirmed transaction in your web browser by clicking the link to these third-party block explorers and inserting the transactionID within their search bar:

Complete example

If you have any trouble compiling or running your program, please check the complete example below which details how to quickly submit your first transaction.

Run Code

Watch Video

Setting up your editor/framework

The Algorand community provides many editors, frameworks, and plugins that can be used to work with the Algorand Network. Tutorials have been created for configuring each of these for use with Algorand. Select your Editor preference below.