Lesson 04 · Web3 with Go & Polygon
One of your mission's success criteria is literally: "Read a transaction on Polygonscan and explain what every field means." Today we do exactly that — but from Go. When a share sale settles, your backend will need to fetch the transaction, confirm it succeeded, and pull the details for a receipt or an audit log. Every field you learn here is a field your client's records will depend on.
From Lesson 03: a transaction is the only
thing that changes state. Once mined, it's identified forever by its hash
— a 32-byte fingerprint like 0x8f2c…a91b. Give go-ethereum that
hash and it hands you back the whole transaction.
to is empty, the transaction
is deploying a contract — that's how you'll create your share token.POL moved, in wei. A pure token transfer often has value
0 — the shares move in the data, not the value.transfer(0xABC, 40). Empty for a plain POL send.Grab any recent tx hash from Amoy Polygonscan and drop it in.
main.go
package main
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
client, err := ethclient.Dial("https://rpc-amoy.polygon.technology/")
if err != nil {
log.Fatalf("could not connect: %v", err)
}
defer client.Close()
ctx := context.Background()
hash := common.HexToHash("0xPUT_A_REAL_AMOY_TX_HASH_HERE")
tx, isPending, err := client.TransactionByHash(ctx, hash)
if err != nil {
log.Fatalf("could not fetch tx: %v", err)
}
fmt.Printf("pending? %v\n", isPending)
fmt.Printf("to: %v\n", tx.To()) // nil = contract creation
fmt.Printf("value: %s wei\n", tx.Value())
fmt.Printf("nonce: %d\n", tx.Nonce())
fmt.Printf("gas limit: %d\n", tx.Gas())
fmt.Printf("gas price: %s wei\n", tx.GasPrice())
fmt.Printf("data len: %d bytes\n", len(tx.Data()))
}
Notice something missing: the transaction object doesn't tell you if it succeeded.
A transaction and its receipt are two different things. The receipt is
written after execution and holds the outcome: status, gas actually used, and the
logs (events) the contract emitted. For your backend, Status == 1 is
the difference between "the shares moved" and "it reverted, do not update our records."
add to main.go
receipt, err := client.TransactionReceipt(ctx, hash)
if err != nil {
log.Fatalf("could not fetch receipt: %v", err)
}
fmt.Printf("status: %d (1 = success, 0 = reverted)\n", receipt.Status)
fmt.Printf("gas used: %d\n", receipt.GasUsed)
fmt.Printf("logs: %d event(s) emitted\n", len(receipt.Logs))
Logs are a preview of the future: when your share token emits a
Transfer event, that's how your backend will hear that a sale happened.
Status reveals it failed.
1. Where do you find whether a transaction succeeded?
2. A transaction with an empty to field is…
3. What is the nonce for?
4. A token transfer's details usually ride in the transaction's…
go-ethereum calls we used, from our backbone book.
I'm your teacher — ask me anything. Want to decode that data field into a
readable function call? Curious how "gas price" became "base fee + tip" after EIP-1559?
Want to open a real share-transfer tx together and read it line by line? Just ask.