We use necessary cookies for site function. For analytics and marketing, we need your consent. You can change your mind anytime. Privacy Policy

EduNode
Log InSign Up
One of the fastest payment networks meets one of the best backend languages
Go · Stellar · Tutorial

Payments, Smart Contracts, and a Terminal: A Go Developer's Guide to Stellar

Olvis GilOlvis Gil  ·  September 27, 2026  ·  9 min read

If you write Go services and need to move money on-chain, Stellar is the friendliest integration you will find this side of a REST API. There is an official SDK maintained by the Stellar Development Foundation — go-stellar-sdk — and a community CLI that wraps it for humans and scripts — stellar-go-cli. This guide goes from zero to a signed payment on testnet, then to a deployed Soroban smart contract, all without leaving the Go ecosystem.

Why Stellar, why Go — the 60-second pitch

Fast, deterministic finality

Ledgers close every ~5 seconds and confirmed transactions are final — no reorgs, no "wait N confirmations" logic in your service code.

Fees measured in fractions of a cent

A 100-stroop base fee (0.00001 XLM) makes micropayments, streaming payments, and machine-to-machine settlement actually viable.

Real-world assets built in

Native USDC, a built-in decentralized exchange, and anchor fiat rails mean a payment API is already half-built before you write a line.

An official, maintained Go SDK

go-stellar-sdk is maintained by the Stellar Development Foundation — txnbuild, Horizon and RPC clients, XDR primitives, plus ingestion and processor libraries for data pipelines.

Go is where payment backends live

Services, CLIs, daemons, ETL jobs — the places Go dominates are exactly the places blockchain integration code runs.

One bit of history worth knowing: the SDK repo used to be the SDF Go monorepo (github.com/stellar/go). In October 2025 it was refactored into a focused SDK — services like Horizon, Galexie, and Friendbot moved to their own repositories. If you find old imports using github.com/stellar/go/..., they resolve to the same codebase; new projects should use the go-stellar-sdk path.

Setup in 5 minutes

mkdir stellar-pay && cd stellar-pay
go mod init stellar-pay

# Official SDF SDK — the building blocks
go get github.com/stellar/go-stellar-sdk@latest

# Community CLI that wraps it — for terminal + scripting work
go install github.com/stellar-go-cli/stellar-go-cli/cmd/stellar-go-cli@latest

Next you need an account and test funds. Generate a keypair with keypair.Random() (or let the CLI create a wallet for you), then hit Friendbot — the testnet faucet:

# Generate a testnet keypair in code:
#   kp, _ := keypair.Random()
#   fmt.Println(kp.Address()) // G...
#   fmt.Println(kp.Seed())    // S...

# Then fund it with Friendbot (10,000 test XLM):
curl "https://friendbot.stellar.org/?addr=GABC...YOUR_ADDRESS"
Testnet ≠ mainnet. Friendbot coins are worthless — that is the point. Everything below runs on testnet; going live is a matter of swapping the Horizon/RPC endpoint and the network passphrase, not rewriting code.

Your first payment

Every Stellar transaction follows the same pipeline: load the source account (for its sequence number), describe operations, assemble the envelope, sign against the network passphrase, submit. Here is a complete payment in about 40 lines:

package main

import (
	"fmt"
	"log"

	"github.com/stellar/go-stellar-sdk/clients/horizonclient"
	"github.com/stellar/go-stellar-sdk/keypair"
	"github.com/stellar/go-stellar-sdk/network"
	"github.com/stellar/go-stellar-sdk/txnbuild"
)

func main() {
	// Testnet secret — never hardcode a real secret key
	kp := keypair.MustParseFull("SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
	client := horizonclient.DefaultTestNetClient

	// 1. Load the source account (gets the current sequence number)
	sourceAccount, err := client.AccountDetail(horizonclient.AccountRequest{
		AccountID: kp.Address(),
	})
	if err != nil {
		log.Fatal(err)
	}

	// 2. The operation: send 10 XLM
	payment := txnbuild.Payment{
		Destination: "GYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
		Amount:      "10",
		Asset:       txnbuild.NativeAsset{},
	}

	// 3. Assemble the transaction envelope
	tx, err := txnbuild.NewTransaction(txnbuild.TransactionParams{
		SourceAccount:        &sourceAccount,
		IncrementSequenceNum: true,
		BaseFee:              txnbuild.MinBaseFee,
		Preconditions: txnbuild.Preconditions{
			TimeBounds: txnbuild.NewTimeout(300),
		},
		Operations: []txnbuild.Operation{&payment},
	})
	if err != nil {
		log.Fatal(err)
	}

	// 4. Sign for the testnet passphrase and submit
	tx, err = tx.Sign(network.TestNetworkPassphrase, kp)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.SubmitTransaction(tx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Paid! Hash:", resp.Hash)
}

Run it and you get back a transaction hash — the payment is already final, roughly five seconds after submission. Swap txnbuild.NativeAsset{} for txnbuild.CreditAsset{Code: "USDC", Issuer: "..."} and the same code sends stablecoins. Batch operations into one transaction and you get atomic settlement of up to 100 payments for one base fee — the trick payroll and disbursement services are built on.

The terminal shortcut

Writing forty lines to test a payment idea is fine in a service; in a shell it is friction. stellar-go-cli wraps the SDK so the same operation is one command — and because it is a real binary, it composes with bash, cron, and CI:

# One-time setup
stellar-go-cli init
stellar-go-cli wallet connect --provider stellar --network stellar-testnet
stellar-go-cli wallet fund --network stellar-testnet   # Friendbot under the hood

# The same payment — one line, no boilerplate
stellar-go-cli pay send --to GYYYY... --amount 10 --asset XLM
stellar-go-cli wallet balance

Under the hood it is doing exactly what the Go program did — account lookup, txnbuild, signing, submission — plus the operational extras you end up wanting:swap quote/execute for DEX path payments, asset trust for trustlines, claimable balances for async payouts, and report iso20022 to export payments as banking-standard XML.

Know your supply chain: stellar-go-cli is a community project (Apache 2.0), not an SDF product. It was extracted from a commercial codebase and is young — pin a version, skim the source, and keep mainnet secrets in a signer rather than a config file.

Smart contracts

Stellar's contract platform is Soroban — contracts compile to WebAssembly and the canonical toolchain is Rust. Go's role is everything around the contract: deploying the WASM, invoking methods, simulating reads, and orchestrating workflows. From the terminal:

# Deploy a compiled Soroban WASM contract — pure Go, no stellar CLI needed
stellar-go-cli contract deploy --wasm hello_contract.wasm --network stellar-testnet
# → prints Contract ID (C...) and saves it to your config

# Call a method on it
stellar-go-cli contract invoke --fn increment

# Read-only call — simulated, nothing submitted on-chain
stellar-go-cli contract invoke --fn get_count --simulate

The same functionality lives in the CLI's public pkg/soroban package — a pure-Go RPC client you can import when you want contract calls inside a service rather than a script:

// The CLI's Soroban client is a public Go package you can import:
import (
	"context"

	"github.com/stellar-go-cli/stellar-go-cli/pkg/soroban"
	"github.com/stellar/go-stellar-sdk/keypair"
)

client := soroban.NewClientForNetwork("stellar-testnet")
defer client.Close()

kp := keypair.MustParseFull("S...")

// Submit a real invocation — simulate, assemble, sign, send, poll: done for you
res, err := client.Invoke(ctx, kp, "CDEF...CONTRACT_ID", "increment", nil)
// res.TxHash is your on-chain receipt

// Read-only path — simulation only, no fees, no signature needed
ret, err := client.SimulateOnly(ctx, "CDEF...CONTRACT_ID", "get_count", nil)

If you need full control, the official SDK exposes the same primitives directly: build a txnbuild.InvokeHostFunction operation, simulate it with clients/rpcclient to get the Soroban transaction data and auth entries, rebuild, sign, send, and poll GetTransaction until it lands. That is literally the loop the CLI runs for you — worth knowing, worth not typing by hand.

The disbursement angle: ISO 20022 for SDP-style flows

If you run disbursements or payroll on the Stellar Disbursement Platform, you already know the hard part is rarely the blockchain hop — it is the paperwork after it. NGOs and payroll providers routinely need to hand a pain.001 (batch disbursement initiation) or a camt.054 (settlement notification) to a bank, donor, or auditor — and today that usually means a hand-built spreadsheet. The CLI ships pkg/iso20022, a Go package that turns Stellar payments into ISO 20022 XML validated against the official XSDs:

  • pain.001 — one disbursement batch, N receivers (name, phone/email, or wallet handle as a proxy), with NbOfTxs/CtrlSum computed automatically
  • camt.054 — settlement notifications back to the org or donor
  • pacs.008/.002/.004/.009 — per-transaction and batch interbank messages
  • Stellar assets map to Ccy="XXX" with the asset code and issuer preserved in SplmtryData, so USDC from different issuers stays distinguishable — a detail that matters to compliance teams
import (
	"github.com/stellar-go-cli/stellar-go-cli/pkg/iso20022"
	"github.com/stellar-go-cli/stellar-go-cli/pkg/models"
)

// One batch disbursement, N receivers — NbOfTxs / CtrlSum computed for you
xmlDoc, err := iso20022.BuildPain001(
	[]*iso20022.CreditTransferInstruction{
		{
			Payment: &models.Payment{
				ID: "pay-001", To: "GRCVR1...", Amount: "10", Asset: "USDC",
			},
			Creditor: &iso20022.Party{
				Name: "Receiver One", Phone: "+221-77XXXXXXX",
			},
		},
	},
	&iso20022.Pain001Options{
		InitiatingParty: &iso20022.Party{Name: "Relief Org"},
		Debtor:          &iso20022.Party{AcctID: "GORG...", AgentBIC: "DEUTDEFF"},
	},
)

From the shell, stellar-go-cli report iso20022 --type pacs.008 does the same job over your payment history — which means it can slot into an SDP deployment two ways: as an integration inside the disbursement pipeline, or as a standalone CLI step run over the SDP API after a batch settles. If your org moves aid or payroll on Stellar and someone downstream is asking for ISO 20022 files, this is the shortest path from ledger entry to bank-grade XML.

Where to go next

Data pipelines. The SDK ships ingest and processors — libraries for parsing raw ledger data from Captive Core or a Galexie data lake. If you are building analytics, compliance reporting, or indexers, start there instead of scraping Horizon.

AI-assisted workflows. stellar-go-cli can run as an MCP server, exposing wallet, payment, and swap operations as tools that AI assistants can call:

# Expose wallet/pay/swap as tools for AI assistants
stellar-go-cli mcp                              # stdio — Claude Desktop, etc.
stellar-go-cli mcp --transport sse --port 3000  # SSE over HTTP for remote agents

Point your agent at it and "check my testnet balance and send 5 XLM to this address" becomes a real tool call — an early taste of agents that can hold and move money. Combined with our AI × blockchain article, that is a fun rabbit hole.

Keep learning. The Soroban course goes deeper on contract development, the stablecoin guide covers the assets your payments will probably carry, and the developer roadmap maps the rest of the journey.

Frequently asked questions

Is there an official Go SDK for Stellar?

Yes. github.com/stellar/go-stellar-sdk is maintained by the Stellar Development Foundation. It used to be the SDF Go monorepo (github.com/stellar/go); in October 2025 it was refactored into a focused SDK, while services like Horizon, Galexie, and Friendbot moved to their own repositories.

Can I write Stellar smart contracts in Go?

Soroban contracts compile to WebAssembly and the canonical toolchain is Rust — Go is not a supported contract language today. What Go does excel at is everything around the contract: deploying the WASM, invoking methods, simulating calls, and building services that orchestrate contract workflows.

What is the difference between Horizon and Stellar RPC?

Horizon is the REST API for the "classic" layer: accounts, payments, offers, history, and transaction submission. Stellar RPC is the leaner API used for Soroban: contract simulation, invocation, ledger entries, and events. Most payment apps talk to Horizon; contract-heavy apps talk to RPC; many use both.

Is stellar-go-cli an official SDF tool?

No — it is a community project (Apache 2.0) built on top of the official SDK. It was extracted from a commercial codebase and covers wallets, payments, swaps, Soroban deployment, ISO 20022 reporting, DIDs/VCs, and an MCP server for AI assistants.

Can it produce ISO 20022 files for banks or donors?

Yes — the CLI ships pkg/iso20022, a Go package that turns Stellar payments into XSD-valid ISO 20022 XML: pain.001 batch disbursement initiations, camt.054 settlement notifications, and pacs.008/002/004/009 interbank messages. It is aimed squarely at Stellar Disbursement Platform-style flows where an NGO or payroll provider must hand structured XML to a bank, donor, or auditor.

How do I test without real money?

Everything in this guide runs on testnet. Friendbot funds any testnet address with 10,000 test XLM for free. When you are ready for mainnet, the same code works — you just swap the client, network passphrase, and RPC endpoint to the public network.

References

[1] stellar/go-stellar-sdk — official SDF Go SDK

[2] stellar-go-cli/stellar-go-cli — community Go CLI for Stellar

[3] Stellar Developer Docs

[4] go-stellar-sdk on pkg.go.dev

Share this article
Olvis Gil
Olvis Gil

Founder of EduNode and MozartPay. Web3 educator, payment technology expert, and ISO standardisation contributor based in Vienna, Austria.