ERC-1155 Tokens (Go)
This guide shows the core steps to use ULedger’s native ERC-1155-style token transactions with the ULedger Go SDK.
ERC-1155 tokens are multi-tokens: a single token collection can manage many token IDs, where each tokenId represents a different
asset type. Each tokenId can be fungible (quantities like tickets, credits, items) or non-fungible (unique editions),
all under the same token address.
ERC-1155 is commonly used for:
- game items and inventories (multiple item types under one collection)
- ticketing and event access (e.g., “General Admission”, “VIP”, “Backstage” as different IDs)
- mixed catalogs where you want standardized IDs and efficient mint/transfer patterns
In ULedger, ERC-1155-style tokens are supported as native protocol transactions (no ULVM smart contract required). That means you can manage a multi-token collection using standard transaction types such as:
CREATE_TOKEN— define token collection metadata (name,symbol,baseURI)MINT_MULTI_TOKEN— mint units for a giventokenIdTRANSFER_TOKEN— transfer atokenId+amountbetween walletsAPPROVE_TOKEN— grant a spender an allowanceTRANSFER_TOKEN(with payloadFrom) — transfer on behalf of an owner using an allowance/approvalBURN_TOKEN— destroy token units to reduce supply (if burnable)CONVERT_TOKEN— convert units of onetokenIdinto another (optional utility operation)
Because these actions are normal ULedger transactions, token operations inherit ULedger’s core capabilities: wallet-based identity, cryptographic signatures, tamper-evident history, and an auditable trail of token events across the chain.
Your wallet must be registered on-chain (CREATE_WALLET) before it can submit token transactions.
Make sure your wallet is registered.
1) Prerequisites
You need:
- A node endpoint (you can use a testnet endpoint:
https://tn-w-1.uledger.net/) - A
blockchainId(Testnet:08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2) - A wallet you can sign with (recommended: load from
.ukey) - A basic understanding that:
- Token Address = the
TransactionIdreturned byCREATE_TOKEN
- Token Address = the
2) Load a wallet
Load from a .ukey file instead of hardcoding keys:
w, err := wallet.LoadFromFile("./wallets/my_wallet.ukey", "")
if err != nil {
return fmt.Errorf("load wallet: %w", err)
}
3) Create a transaction session
Create a session bound to a node and wallet:
session, err := transaction.NewUL_TransactionSession(nodeEndpoint, w)
if err != nil {
return fmt.Errorf("create session: %w", err)
}
4) Create an ERC-1155 collection (CREATE_TOKEN)
4.1 Build the payload
func buildCreateERC1155Payload() ([]byte, error) {
return json.Marshal(transaction.CreateTokenPayload{
TokenType: transaction.ERC1155_TOKEN_TYPE,
Name: "Concert Tickets",
Symbol: "$CTIX",
BaseURI: "https://tickets.example.com/",
Mintable: true,
Burnable: true,
})
}
4.2 Submit the transaction
payloadBytes, err := buildCreateERC1155Payload()
if err != nil {
return err
}
input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: w.Address,
PayloadType: transaction.CREATE_TOKEN.String(),
Payload: string(payloadBytes),
}
tx, err := session.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("create collection tx: %w", err)
}
tokenAddress := tx.TransactionId // ✅ Save this
fmt.Println("Token address:", tokenAddress)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)
✅ The returned
tx.TransactionIdis used as the collection’s “token address” in future calls.
5) Mint tokens (MINT_MULTI_TOKEN)
Mint creates token units under a specific tokenId.
5.1 Build the payload
func buildMintERC1155Payload(tokenAddress, to string, tokenId uint64, amount uint64, tokenURI string) ([]byte, error) {
return json.Marshal(transaction.MintTokenPayload{
TokenAddress: tokenAddress,
To: to,
TokenId: tokenId,
Amount: amount,
TokenURI: tokenURI,
})
}
5.2 Submit the transaction
payloadBytes, err := buildMintERC1155Payload(
tokenAddress,
toAddress,
1, // tokenId
1000, // amount
"Ticket URIs!",
)
if err != nil {
return err
}
input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: w.Address,
PayloadType: transaction.MINT_MULTI_TOKEN.String(),
Payload: string(payloadBytes),
}
tx, err := session.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("mint tx: %w", err)
}
fmt.Println("Mint tx:", tx.TransactionId)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)
6) Transfer tokens (TRANSFER_TOKEN)
ERC-1155 transfers move a specific tokenId and amount.
6.1 Build the payload
func buildTransferERC1155Payload(tokenAddress, to string, tokenId uint64, amount uint64) ([]byte, error) {
return json.Marshal(transaction.TransferTokenPayload{
TokenAddress: tokenAddress,
To: to,
TokenId: tokenId,
Amount: amount,
})
}
6.2 Submit the transaction
payloadBytes, err := buildTransferERC1155Payload(tokenAddress, toAddress, 1, 5)
if err != nil {
return err
}
input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: w.Address,
PayloadType: transaction.TRANSFER_TOKEN.String(),
Payload: string(payloadBytes),
}
tx, err := session.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("transfer tx: %w", err)
}
fmt.Println("Transfer tx:", tx.TransactionId)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)
7) Approve a spender (APPROVE_TOKEN)
Approvals allow a spender to transfer tokens on behalf of the token owner (allowance-style).
7.1 Build the payload
func buildApproveERC1155Payload(tokenAddress, spender string, amount uint64) ([]byte, error) {
return json.Marshal(transaction.ApproveTokenPayload{
TokenAddress: tokenAddress,
Spender: spender,
Amount: amount,
})
}
7.2 Submit the transaction
payloadBytes, err := buildApproveERC1155Payload(tokenAddress, spenderAddress, 5000)
if err != nil {
return err
}
input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: w.Address, // token owner
PayloadType: transaction.APPROVE_TOKEN.String(),
Payload: string(payloadBytes),
}
tx, err := session.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("approve tx: %w", err)
}
fmt.Println("Approve tx:", tx.TransactionId)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)
8) Transfer using approval (TRANSFER_TOKEN with payload From)
This pattern submits a transfer where:
- the transaction signer (
input.From) is the spender - the payload From is the token owner whose balance is being moved
8.1 Build the payload
func buildTransferApprovalERC1155Payload(tokenAddress, to, owner string, amount uint64) ([]byte, error) {
return json.Marshal(transaction.TransferTokenPayload{
TokenAddress: tokenAddress,
To: to,
From: owner,
Amount: amount,
})
}
8.2 Submit the transaction
payloadBytes, err := buildTransferApprovalERC1155Payload(tokenAddress, finalRecipient, ownerAddress, 3000)
if err != nil {
return err
}
input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: spenderWallet.Address,
PayloadType: transaction.TRANSFER_TOKEN.String(),
Payload: string(payloadBytes),
}
spenderSession, err := transaction.NewUL_TransactionSession(nodeEndpoint, spenderWallet)
if err != nil {
return err
}
tx, err := spenderSession.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("transfer using approval tx: %w", err)
}
fmt.Println("Transfer (approval) tx:", tx.TransactionId)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)
9) Burn tokens (BURN_TOKEN)
9.1 Build the payload
func buildBurnERC1155Payload(tokenAddress string, amount uint64) ([]byte, error) {
return json.Marshal(transaction.BurnTokenPayload{
TokenAddress: tokenAddress,
Amount: amount,
})
}
9.2 Submit the transaction
payloadBytes, err := buildBurnERC1155Payload(tokenAddress, 5)
if err != nil {
return err
}
input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: w.Address,
PayloadType: transaction.BURN_TOKEN.String(),
Payload: string(payloadBytes),
}
tx, err := session.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("burn tx: %w", err)
}
fmt.Println("Burn tx:", tx.TransactionId)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)
10) Convert tokens (CONVERT_TOKEN)
CONVERT_TOKEN converts units of an existing tokenId into a new representation (based on your chain rules).
A common use is converting a token into a new state, such as "unused" → "used", by producing a new token URI and optionally burning the original units.
10.1 Build the payload
func buildConvertERC1155Payload(tokenAddress string, fromTokenId uint64, amount uint64) ([]byte, error) {
return json.Marshal(transaction.ConvertTokenPayload{
TokenAddress: tokenAddress,
FromTokenId: fromTokenId,
Amount: amount,
NewTokenURI: "https://commemorative.example.com/used_ticket",
PreserveTokens: false,
})
}
10.2 Submit the transaction
payloadBytes, err := buildConvertERC1155Payload(tokenAddress, 1, 5)
if err != nil {
return err
}
input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: w.Address,
PayloadType: transaction.CONVERT_TOKEN.String(),
Payload: string(payloadBytes),
}
tx, err := session.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("convert tx: %w", err)
}
fmt.Println("Convert tx:", tx.TransactionId)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)
11) Full example
This single example shows:
- Create collection
- Mint
tokenId=1withamount=1000 - Transfer
tokenId=1withamount=5 - Approve spender
- Transfer using approval
- Burn tokens
- Convert tokens
package main
import (
"encoding/json"
"fmt"
"github.com/ULedgerInc/golang-sdk/pkg/transaction"
"github.com/ULedgerInc/golang-sdk/pkg/wallet"
)
func main() {
nodeEndpoint := "http://localhost:8080"
blockchainId := "MyBlockchain1"
ownerWallet, err := wallet.LoadFromFile("./wallets/owner.ukey", "")
if err != nil { panic(err) }
spenderWallet, err := wallet.LoadFromFile("./wallets/spender.ukey", "")
if err != nil { panic(err) }
ownerSession, err := transaction.NewUL_TransactionSession(nodeEndpoint, ownerWallet)
if err != nil { panic(err) }
// 1) CREATE_TOKEN (ERC1155)
createPayload, _ := json.Marshal(transaction.CreateTokenPayload{
TokenType: transaction.ERC1155_TOKEN_TYPE,
Name: "Concert Tickets",
Symbol: "$CTIX",
BaseURI: "https://tickets.example.com/",
Mintable: true,
Burnable: true,
})
createTx, err := ownerSession.GenerateTransaction(transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: ownerWallet.Address,
PayloadType: transaction.CREATE_TOKEN.String(),
Payload: string(createPayload),
})
if err != nil { panic(err) }
tokenAddress := createTx.TransactionId
fmt.Println("Token address:", tokenAddress)
// 2) MINT_MULTI_TOKEN (tokenId=1, amount=1000)
mintPayload, _ := json.Marshal(transaction.MintTokenPayload{
TokenAddress: tokenAddress,
To: ownerWallet.Address,
TokenId: 1,
Amount: 1000,
TokenURI: "Ticket URIs!",
})
mintTx, err := ownerSession.GenerateTransaction(transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: ownerWallet.Address,
PayloadType: transaction.MINT_MULTI_TOKEN.String(),
Payload: string(mintPayload),
})
if err != nil { panic(err) }
fmt.Println("Mint tx:", mintTx.TransactionId)
// 3) TRANSFER_TOKEN (tokenId=1, amount=5)
transferPayload, _ := json.Marshal(transaction.TransferTokenPayload{
TokenAddress: tokenAddress,
To: spenderWallet.Address,
TokenId: 1,
Amount: 5,
})
transferTx, err := ownerSession.GenerateTransaction(transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: ownerWallet.Address,
PayloadType: transaction.TRANSFER_TOKEN.String(),
Payload: string(transferPayload),
})
if err != nil { panic(err) }
fmt.Println("Transfer tx:", transferTx.TransactionId)
// 4) APPROVE_TOKEN (approve spender)
approvePayload, _ := json.Marshal(transaction.ApproveTokenPayload{
TokenType: "", // not required for approve
TokenAddress: tokenAddress,
Spender: spenderWallet.Address,
Amount: 50,
})
approveTx, err := ownerSession.GenerateTransaction(transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: ownerWallet.Address,
PayloadType: transaction.APPROVE_TOKEN.String(),
Payload: string(approvePayload),
})
if err != nil { panic(err) }
fmt.Println("Approve tx:", approveTx.TransactionId)
// 5) TRANSFER_TOKEN using approval (spender spends owner allowance)
spenderSession, err := transaction.NewUL_TransactionSession(nodeEndpoint, spenderWallet)
if err != nil { panic(err) }
transferApprovalPayload, _ := json.Marshal(transaction.TransferTokenPayload{
TokenAddress: tokenAddress,
From: ownerWallet.Address,
To: "DESTINATION_ADDRESS", // replace
Amount: 10,
})
transferApprovalTx, err := spenderSession.GenerateTransaction(transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: spenderWallet.Address,
PayloadType: transaction.TRANSFER_TOKEN.String(),
Payload: string(transferApprovalPayload),
})
if err != nil { panic(err) }
fmt.Println("Transfer (approval) tx:", transferApprovalTx.TransactionId)
// 6) BURN_TOKEN
burnPayload, _ := json.Marshal(transaction.BurnTokenPayload{
TokenAddress: tokenAddress,
Amount: 5,
})
burnTx, err := ownerSession.GenerateTransaction(transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: ownerWallet.Address,
PayloadType: transaction.BURN_TOKEN.String(),
Payload: string(burnPayload),
})
if err != nil { panic(err) }
fmt.Println("Burn tx:", burnTx.TransactionId)
// 7) CONVERT_TOKEN
convertPayload, _ := json.Marshal(transaction.ConvertTokenPayload{
TokenAddress: tokenAddress,
FromTokenId: 1,
Amount: 5,
NewTokenURI: "https://commemorative.example.com/used_ticket",
PreserveTokens: false,
})
convertTx, err := ownerSession.GenerateTransaction(transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: ownerWallet.Address,
PayloadType: transaction.CONVERT_TOKEN.String(),
Payload: string(convertPayload),
})
if err != nil { panic(err) }
fmt.Println("Convert tx:", convertTx.TransactionId)
}