Skip to content

oliv3rdrt/mintlayer-quickstart

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mintlayer testnet quick-start

A small Go program that sends a confirmed transaction on the Mintlayer testnet, end to end: derive a key from a mnemonic, fetch UTXOs, build and sign a transfer, broadcast it, and wait for confirmation. It uses the official mintlayer/go-sdk and talks only to the public indexer over HTTP, so there's no node or wallet daemon to run.

I put this together to get hands-on with the SDK and understand the UTXO flow. Mintlayer is a Bitcoin sidechain, so it's UTXO-based (like Bitcoin) rather than account-based like Ethereum, and non-EVM. My notes from getting it working are at the bottom.

The flow: mnemonic → address → fetch UTXOs → build tx (recipient + change) → sign each input → broadcast → poll for confirmation → explorer link.

Prerequisites

  • Go 1.21+ (go version)
  • A throwaway testnet mnemonic. Don't use a mainnet one; it's a private key and gets passed on the command line.
  • Testnet coins from https://faucet.mintlayer.org (step 2).

Usage

1. Clone and run the tests (no funds needed)

git clone https://github.com/oliv3rdrt/mintlayer-quickstart.git
cd mintlayer-quickstart
go test ./src

TestBuildSignOffline builds and signs a real transaction against the SDK's embedded WASM crypto with a mocked indexer, so the whole path is covered before spending anything.

2. Find your address and fund it

go run ./src -mnemonic "your twelve word testnet mnemonic ..." \
             -amount 100000000 -broadcast=false

This prints spending from: tmt1q... and then reports there are no UTXOs yet. Copy the address, request coins at https://faucet.mintlayer.org, and give it a block to arrive.

To keep the mnemonic out of your shell history, export it instead (every command below also reads ML_MNEMONIC):

export ML_MNEMONIC="your twelve word testnet mnemonic ..."

3. Send a transaction and wait for it

go run ./src -amount 100000000 -wait
spending from: tmt1q...
no -to given, sending to self
found 1 UTXO(s), balance 200 ML
selected 1 input(s), total 200 ML, change 199.499 ML, fee 0.5 ML
signed tx id: <txid> (... bytes)
broadcast, tx id: <txid>
explorer: https://lovelace.explorer.mintlayer.org/tx/<txid>
waiting for confirmation...
confirmed: https://lovelace.explorer.mintlayer.org/tx/<txid>

Open the explorer link to verify it on-chain.

Flags

Flag Default Meaning
-mnemonic $ML_MNEMONIC BIP-39 mnemonic (12/24 words)
-amount required Amount in atoms (1 ML = 100,000,000,000 atoms)
-to your own address Recipient tmt1q... address
-fee 50000000000 (0.5 ML) Flat fee in atoms, taken from change
-indexer public Lovelace indexer Indexer base URL ($ML_INDEXER)
-wait off Poll until confirmed
-broadcast true Set -broadcast=false for a dry run: build and sign, print the hex, don't submit

Live integration test

src/integration_test.go does a real testnet transaction. It's behind the integration build tag and skips unless ML_MNEMONIC is set, so a normal go test never spends coins:

export ML_MNEMONIC="your funded testnet mnemonic ..."
go test -tags integration -run TestSendTestnetTransaction -v ./src

See .env.example for the supported environment variables.

Layout

src/main.go              build → sign → broadcast flow
src/transfer.go          coin/UTXO helpers (no crypto, no network)
src/transfer_test.go     unit tests, incl. an offline build+sign
src/integration_test.go  live testnet test (build tag: integration)

Notes from testing

Things I ran into, mostly small, in case they're useful to anyone else:

  • The SDK's send-coins example hardcodes Mainnet. On testnet you have to pass Testnet everywhere, otherwise you derive a mainnet-prefixed address that owns nothing and it fails with no obvious reason why.
  • Signing kept failing with invalid type: null, expected a map until I realised TxAdditionalInfo{} marshals its PoolInfo/OrderInfo maps as null. Initialising them as empty maps fixes it. This one cost me the most time because the error doesn't point at the cause.
  • I couldn't find the testnet indexer URL in the docs. I pulled it from the explorer subdomain (api-server-lovelace.mintlayer.org) and confirmed it with /api/v2/chain/tip. A short "testnet endpoints" table in the docs would help.
  • The REST indexer has no fee-rate endpoint (the node RPC does), so an indexer-only client can't look up the minimum fee. My first broadcast got rejected: min_relay_fee: 0.20300000000 for a 203-byte tx, i.e. about 0.001 ML/byte. Since I can't query that rate, I use a flat fee (0.5 ML by default) deducted from change, overridable with -fee.
  • The example sends all UTXOs into one output with no change, so it can't really do a partial send or pay an explicit fee. I added simple coin selection and a change output.

Overall the Go SDK was nice to work with: go get, embedded WASM, no CGO, and it built and ran first try. The rough edges are mostly docs and examples.

License

MIT.

About

Minimal Go example that builds, signs and broadcasts a transaction on the Mintlayer testnet using the official go-sdk

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages