Stellar Cryptocurrency Tutorial: Making a payment with Go on the Testnet

Alexander Leon
3 min readFeb 11, 2018

I wanted to share with you all a working example. When I was first following the tutorials at stellar.org, I noticed I had to do a lot of piecing together of the different bits of documentation. Hopefully this’ll save you some time so you can move on to explore more interesting bits of the Stellar ecosystem.

Enter the Testnet(s)

The pubnet is the production environment. If you make a transaction there, it’s for real. The testnet is the environment where we try out stuff with fake lumens/assets. There’s a public testnet (pubtestnet?) that is openly accessible to anyone and doesn’t require any special codes to access. You can also make a private testnet instance using the official Docker image. We are going to use the public one today.

Plan of Action

  1. Make an account
  2. Make another account
  3. Give them each a bunch of fake lumens
  4. Have Account A send Account B some money
  5. Ensure money was sent/received

Accounts

Let’s make our accounts. To do so, we will invoke keypair.Random() from the go-sdk. This function will generate a seed which will in turn generate a private/public key pair.

// stellar_payment.gopackage main
import (
"log"
"github.com/stellar/go/keypair"
)
func main() {
sourcePair, err := keypair.Random()
if err != nil {
log.Fatal(err)
}
destinationPair, err := keypair.Random()
if err != nil {
log.Fatal(err)
}
}

Cool. We just generated two accounts. Feel free to inspect their values to make sure it worked. This should return a string for instance (pstt: make sure to run ‘go get’ to install dependencies):

log.Println(sourcePair.Address())

Load ’em up

These accounts are pretty useless when not holding any lumens. In fact, most transactions will fail, so let’s fill them up with some hard-earned fake lumens.

Step 1: Add a fillAccounts function:

func fillAccounts(addresses [2]string) {
for _, address := range addresses {
friendBotResp, err := http.Get("https://horizon-testnet.stellar.org/friendbot?addr=" + address)
if err != nil {
log.Fatal(err)
}
defer friendBotResp.Body.Close()
}
}

Step 2: Add missing dependencies (and run ‘go get’):

"github.com/stellar/go/clients/horizon"
"net/http"

Step 3: In our main() function, let’s make an array of addresses and call our new function:

addresses := [2]string{sourcePair.Address(), destinationPair.Address()}

fillAccounts(addresses)

Run it! Did you see fireworks? No? Maybe we need a way to see our account balances.

Add a logBalances function like so:

func logBalances(addresses [2]string) {
for _, address := range addresses {
account, err := horizon.DefaultTestNetClient.LoadAccount(address)
if err != nil {
log.Fatal(err)
}
log.Println("Balances for address:", address)
for _, balance := range account.Balances {
log.Println(balance)
}
}
}

and call it in the main() function:

logBalances(addresses)

OK. This time you should see that our accounts do in fact have lumens.

Let’s have one account send lumens to the other. I’ll just give you the code. If you want to dig deeper into what’s happening in our transaction request, there’s plenty of documentation at stellar.org. Here goes:

func sendLumens(amount string, sourceSeed string, destinationAddress string) {
tx, err := build.Transaction(
build.SourceAccount{sourceSeed},
build.TestNetwork,
build.AutoSequence{SequenceProvider: horizon.DefaultTestNetClient},
build.Payment(
build.Destination{AddressOrSeed: destinationAddress},
build.NativeAmount{Amount: amount},
),
)

if err != nil {
panic(err)
}

txe, err := tx.Sign(sourceSeed)
if err != nil {
panic(err)
}

txeB64, err := txe.Base64()
if err != nil {
panic(err)
}

resp, err := horizon.DefaultTestNetClient.SubmitTransaction(txeB64)
if err != nil {
panic(err)
}

log.Println("Successfully sent", amount, "lumens to", destinationAddress,". Hash:", resp.Hash)
}

Add the missing dependency + run ‘go get’:

"github.com/stellar/go/build"

Call the new function from the main() function:

sendLumens("100", sourcePair.Seed(), destinationPair.Address())

Nice. Hopefully you got a success message with some info about the transaction. Want to see the new account balances? Let’s log the balances again:

logBalances(addresses)

Unrelated PSA: Looking for a new high paying software development job? Send me your resume to alexleondeveloper@gmail.com and I’ll get back to you!

Welp. That’s all I have to share right now. If you missed something, check out the complete code here: https://github.com/alien35/stellar-tutorial/blob/master/stellar_pay.go

--

--

Alexander Leon

I help developers with easy-to-understand technical articles encompassing System Design, Algorithms, Cutting-Edge tech, and misc.