Saltar al contenido principal

Tokens ERC-1155 (Go)

Esta guía muestra los pasos principales para usar las transacciones de token ERC-1155 nativas de ULedger con el ULedger Go SDK.

Los tokens ERC-1155 son multi-tokens: una sola colección de tokens puede gestionar muchos IDs de token, donde cada tokenId representa un tipo de activo diferente. Cada tokenId puede ser fungible (cantidades como tickets, créditos, ítems) o no fungible (ediciones únicas), todo bajo la misma dirección de token.

ERC-1155 se usa comúnmente para:

  • ítems de juegos e inventarios (múltiples tipos de ítems bajo una colección)
  • ticketing y acceso a eventos (p. ej., "Entrada General", "VIP", "Backstage" como IDs diferentes)
  • catálogos mixtos donde se desean IDs estandarizados y patrones eficientes de mint/transfer

En ULedger, los tokens de estilo ERC-1155 son compatibles como transacciones nativas del protocolo (no se requiere un smart contract ULVM). Eso significa que puedes gestionar una colección multi-token usando tipos de transacción estándar como:

  • CREATE_TOKEN — definir los metadatos de la colección de tokens (name, symbol, baseURI)
  • MINT_MULTI_TOKEN — acuñar unidades para un tokenId dado
  • TRANSFER_TOKEN — transferir un tokenId + amount entre wallets
  • APPROVE_TOKEN — otorgar una asignación a un spender
  • TRANSFER_TOKEN (con payload From) — transferir en nombre de un propietario usando una asignación/aprobación
  • BURN_TOKEN — destruir unidades de token para reducir el suministro (si es quemable)
  • CONVERT_TOKEN — convertir unidades de un tokenId en otro (operación de utilidad opcional)

Dado que estas acciones son transacciones normales de ULedger, las operaciones de token heredan las capacidades principales de ULedger: identidad basada en wallet, firmas criptográficas, historial a prueba de manipulaciones y un registro auditable de eventos de token en la cadena.

info

Tu wallet debe estar registrada on-chain (CREATE_WALLET) antes de poder enviar transacciones de token. Asegúrate de que tu wallet esté registrada.


1) Prerequisitos

Necesitas:

  • Un endpoint de node (puedes usar un endpoint de testnet: https://tn-w-1.uledger.net/)
  • Un blockchainId (Testnet: 08c28f29a62819120958984b761ddf8ccb45951612731409873994958fd150a2)
  • Una wallet con la que puedas firmar (recomendado: cargar desde .ukey)
  • Un entendimiento básico de que:
    • Token Address = el TransactionId devuelto por CREATE_TOKEN

2) Cargar una wallet

Carga desde un archivo .ukey en lugar de codificar las claves directamente:

w, err := wallet.LoadFromFile("./wallets/my_wallet.ukey", "")
if err != nil {
return fmt.Errorf("load wallet: %w", err)
}

3) Crear una sesión de transacción

Crea una sesión vinculada a un node y una wallet:

session, err := transaction.NewUL_TransactionSession(nodeEndpoint, w)
if err != nil {
return fmt.Errorf("create session: %w", err)
}

4) Crear una colección ERC-1155 (CREATE_TOKEN)

4.1 Construir el 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 Enviar la transacción

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 // ✅ Guarda esto
fmt.Println("Token address:", tokenAddress)
fmt.Println("Status:", tx.Status, "Output:", tx.Output)

✅ El tx.TransactionId devuelto se usa como la "token address" de la colección en llamadas futuras.


5) Acuñar tokens (MINT_MULTI_TOKEN)

Mint crea unidades de token bajo un tokenId específico.

5.1 Construir el 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 Enviar la transacción

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) Transferir tokens (TRANSFER_TOKEN)

Las transferencias ERC-1155 mueven un tokenId y amount específicos.

6.1 Construir el 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 Enviar la transacción

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) Aprobar un spender (APPROVE_TOKEN)

Las aprobaciones permiten a un spender transferir tokens en nombre del propietario del token (estilo de asignación).

7.1 Construir el payload

func buildApproveERC1155Payload(tokenAddress, spender string, amount uint64) ([]byte, error) {
return json.Marshal(transaction.ApproveTokenPayload{
TokenAddress: tokenAddress,
Spender: spender,
Amount: amount,
})
}

7.2 Enviar la transacción

payloadBytes, err := buildApproveERC1155Payload(tokenAddress, spenderAddress, 5000)
if err != nil {
return err
}

input := transaction.ULTransactionInput{
BlockchainId: blockchainId,
From: w.Address, // propietario del token
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) Transferir usando aprobación (TRANSFER_TOKEN con payload From)

Este patrón envía una transferencia donde:

  • el firmante de la transacción (input.From) es el spender
  • el payload From es el propietario del token cuyo saldo está siendo movido

8.1 Construir el 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 Enviar la transacción

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) Quemar tokens (BURN_TOKEN)

9.1 Construir el payload

func buildBurnERC1155Payload(tokenAddress string, amount uint64) ([]byte, error) {
return json.Marshal(transaction.BurnTokenPayload{
TokenAddress: tokenAddress,
Amount: amount,
})
}

9.2 Enviar la transacción

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) Convertir tokens (CONVERT_TOKEN)

CONVERT_TOKEN convierte unidades de un tokenId existente en una nueva representación (según las reglas de tu cadena). Un uso común es convertir un token a un nuevo estado, como "no usado" → "usado", produciendo un nuevo token URI y opcionalmente quemando las unidades originales.

10.1 Construir el 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 Enviar la transacción

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) Ejemplo completo

Este único ejemplo muestra:

  1. Crear la colección
  2. Acuñar tokenId=1 con amount=1000
  3. Transferir tokenId=1 con amount=5
  4. Aprobar un spender
  5. Transferir usando aprobación
  6. Quemar tokens
  7. Convertir 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 (aprobar spender)
approvePayload, _ := json.Marshal(transaction.ApproveTokenPayload{
TokenType: "", // no requerido para 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 usando aprobación (el spender gasta la asignación del propietario)
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", // reemplazar
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)
}