Transactions – Go SDK Reference
Overview
The Go SDK exposes a small set of types and methods to:
- Load a wallet
- Open a transaction session against a node
- Build, sign, and submit a transaction
- Inspect the resulting transaction and its status
This page documents those core types and methods for quick reference. Tutorials and end-to-end examples will live in separate pages.
Imports
import (
"github.com/ULedgerInc/go-sdk/pkg/wallet"
"github.com/ULedgerInc/go-sdk/pkg/transaction"
)
Wallet loading
wallet.FromJson
func FromJson(raw string, passphrase string) (UL_Wallet, error)
Loads an encrypted or plain wallet from a JSON string and returns a UL_Wallet instance, which is then used to sign transactions.
Used in your CLI:
w, err := wallet.FromJson(rawWallet, passphrase)
if err != nil {
return fmt.Errorf("error loading wallet: %w", err)
}
fmt.Printf("Loaded wallet: %+v\n", w)
The returned UL_Wallet exposes:
Address– the wallet’s addressGetKey()– returns the underlying key, used to sign commitments and discoverKeyType.
Transaction session
Type: UL_TransactionSession
type UL_TransactionSession struct {
nodeEndpoint string
suggestor string
wallet wallet.UL_Wallet
}
A transaction session encapsulates:
- The node endpoint (base URL of the node)
- The suggestor (node ID used for the transaction)
- The wallet used to sign the transaction
You typically obtain it via the constructor:
transaction.NewUL_TransactionSession
func NewUL_TransactionSession(
nodeEndpoint string,
wallet wallet.UL_Wallet,
) (UL_TransactionSession, error)
What it does:
- Calls
GET {nodeEndpoint}/healthto obtain node metadata (nodeId, version, chains info). - Calls
GET {nodeEndpoint}/blockchainsto ensure at least one blockchain is available. - Returns a
UL_TransactionSessionwith:nodeEndpointsetsuggestorset to the node IDwalletset to the providedUL_Wallet
Example (simplified from your CLI):
session, err := transaction.NewUL_TransactionSession(
testConfig.NodeEndpoints[n],
*wallet,
)
if err != nil {
return fmt.Errorf("error creating transaction session: %w", err)
}
(*UL_TransactionSession).GenerateTransaction
func (session *UL_TransactionSession) GenerateTransaction(
input ULTransactionInput,
) (ULTransaction, error)
High-level responsibilities:
-
Populate metadata on
ULTransactionInput:- Sets
input.Suggestortosession.suggestor - Sets
input.SenderTimestampto current UTC time - For non-
CREATE_WALLETand non-ALTER_WALLETpayloads, setsinput.Fromtosession.wallet.Address - Sets
input.KeyTypebased onsession.wallet.GetKey().GetType()
- Sets
-
Compute commitment & payload root:
-
For
DEPLOY_SMART_CONTRACT,UPGRADE_SMART_CONTRACT,TX_CREATE_WALLET,TX_ALTER_WALLET:- Calls
input.GetUnboundCommitment(hasher) - Sets
input.PayloadRootto the returned root (hex-encoded)
- Calls
-
For other transaction types:
- Calls
input.GetSignatureCommitment(hasher, true)to build a Merkle commitment - Calls
input.HashSignatureCommitment(hasher, commitment)to get the commitment hash - Sets
input.PayloadRootto the Merkle payload root
- Calls
-
-
Sign the commitment:
- Signs the commitment with
session.wallet.GetKey().SignData(commitment) - Sets
input.SenderSignaturewith the hex-encoded signature
- Signs the commitment with
-
Submit to the node:
-
POSTs JSON to:
POST {nodeEndpoint}/blockchains/{blockchainId}/transactions -
Expects
200 OKor201 Created -
Unmarshals the response into a
ULTransaction
-
Example (from your CLI):
tx, err := session.GenerateTransaction(input)
if err != nil {
return fmt.Errorf("error generating transaction: %w", err)
}
if tx.TransactionId == "" {
return fmt.Errorf("generated transaction has empty transaction ID")
}
fmt.Printf("Transaction: %+v\n", tx)
Transaction types
ULTransactionInput
Fields used to create a transaction:
type ULTransactionInput struct {
BlockchainId string `json:"blockchainId"`
To string `json:"to"`
From string `json:"from"`
Payload string `json:"payload"`
SenderSignature string `json:"senderSignature"`
PayloadType string `json:"payloadType"`
Suggestor string `json:"suggestor"`
SenderTimestamp time.Time `json:"senderTimestamp"`
PayloadRoot string `json:"payloadRoot"`
KeyType crypto.KeyType `json:"keyType"`
}
Typical usage for a DATA transaction:
input := transaction.ULTransactionInput{
Payload: fmt.Sprintf("test %v %d", wallet.Address, n*i),
From: wallet.Address, // overridden by session for most types
To: wallet.Address,
BlockchainId: blockchainId,
PayloadType: transaction.TX_DATA.String(),
}
Most fields are filled by GenerateTransaction (signature, timestamps, suggestor, key type, and PayloadRoot).
ULTransactionOutput
Fields returned by the node:
type ULTransactionOutput struct {
TransactionId string `json:"transactionId"`
BlockHeight int `json:"blockHeight"`
Clock VectorClock `json:"vectorClock"`
Timestamp Timestamp `json:"timestamp"`
Version string `json:"version"`
Weight int `json:"weight"`
Status string `json:"status"`
Output string `json:"output"`
Proof string `json:"proof"`
ProofVersion string `json:"proofVersion"`
}
ULTransaction
type ULTransaction struct {
ULTransactionInput
ULTransactionOutput
}
Combines both the input fields (what you requested) and the output fields (what the node returned).
Transaction helpers & interfaces
Transaction interface
type Transaction interface {
GetVectorClock() VectorClock
GetTimestamp() Timestamp
GetTransactionId() string
GetTransactionSignatureBody() string
SetTransactionWeight()
}
ULTransaction implements this interface (except GetTransactionSignatureBody, which is not shown in the provided snippet but is part of the conceptual contract).
Methods on *ULTransaction
func (t *ULTransaction) GetVectorClock() VectorClock
func (t *ULTransaction) GetTimestamp() Timestamp
func (t *ULTransaction) GetTransactionId() string
func (t *ULTransaction) SetTransactionWeight()
func (t *ULTransaction) ToBytes() ([]byte, error)
GetVectorClock()– returns the causal vector clock for this transaction.GetTimestamp()– returns theTimestampstruct (exact & approximate times).GetTransactionId()– returns the node-assigned transaction ID.SetTransactionWeight()– recomputes and setst.Weightbased on field lengths.ToBytes()– marshals the transaction to JSON bytes.
TransactionFromBytes
func TransactionFromBytes(data []byte) (*ULTransaction, error)
Deserializes a JSON byte slice into a ULTransaction.
Transaction enums & parsing helpers
Status: UL_TransactionStatus
type UL_TransactionStatus int
const (
INVALID_TX_STATUS UL_TransactionStatus = 0
TX_SUBMITTED UL_TransactionStatus = 1
TX_ACCEPTED UL_TransactionStatus = 2
TX_REJECTED UL_TransactionStatus = 3
)
func (ts UL_TransactionStatus) String() string
func ParseTransactionStatus(str string) (UL_TransactionStatus, error)
Type: ULTransactionType
type ULTransactionType int
const (
INVALID_TX_TYPE ULTransactionType = iota
TX_DATA
TX_CREATE_WALLET
TX_ALTER_WALLET
DEPLOY_SMART_CONTRACT
INVOKE_SMART_CONTRACT
UPGRADE_SMART_CONTRACT
ROLLBACK_SMART_CONTRACT
)
func (tt ULTransactionType) String() string
func ParseTransactionType(str string) (ULTransactionType, error)
Common values:
TX_DATA– generic data transactionTX_CREATE_WALLET/TX_ALTER_WALLET– wallet-management transactionsDEPLOY_SMART_CONTRACT,INVOKE_SMART_CONTRACT,UPGRADE_SMART_CONTRACT,ROLLBACK_SMART_CONTRACT– smart-contract operations
Output: UL_TransactionOutput
type UL_TransactionOutput int
const (
INVALID_TX_OUTPUT UL_TransactionOutput = 0
TO_BE_PROCESSED UL_TransactionOutput = 1
TX_SUCCESS UL_TransactionOutput = 2
TX_REJECTED_BY_DUPLICATE UL_TransactionOutput = 3
TX_REJECTED_BY_UNEXISTING UL_TransactionOutput = 4
TX_REJECTED_BY_DISABLED UL_TransactionOutput = 5
TX_REJECTED_BY_UNAUTHORIZED UL_TransactionOutput = 6
TX_REJECTED_BY_INVALID_SIGNATURE UL_TransactionOutput = 7
TX_TRANSACTION_ERROR UL_TransactionOutput = 8
)
func (tt UL_TransactionOutput) String() string
func ParseTransactionOutput(str string) (UL_TransactionOutput, error)
These values correspond to the string Output field returned in ULTransactionOutput.Output.
Commitments & Merkle trees (advanced)
For advanced use cases where you need manual control over commitments or verification, the SDK exposes helpers on ULTransactionInput and Merkle tree builders.
Commitment helpers on *ULTransactionInput
func (t *ULTransactionInput) GetSignatureCommitment(
hasher hash.Hash,
computeRoot bool,
) (TransactionCommitment, error)
func (t *ULTransactionInput) GetUnboundCommitment(
hasher hash.Hash,
) ([]byte, error)
func (t *ULTransactionInput) HashSignatureCommitment(
hasher hash.Hash,
commitment TransactionCommitment,
) ([]byte, error)
Used internally by GenerateTransaction to:
- Construct Merkle roots over the payload
- Bind
BlockchainId,From,To,Suggestor, timestamp and payload root into a single commitment hash - Produce the data that is ultimately signed by the wallet key
Merkle helpers
func GenerateMerkleTreeWithHardBound(
payload []byte,
modulus *big.Int,
chunkSize int,
depth int,
hasher hash.Hash,
proofIndex uint64,
) ([]byte, [][]byte, []byte, uint64, error)
func GenerateMerkleTree(
payload []byte,
modulus *big.Int,
chunkSize int,
hasher hash.Hash,
proofIndex uint64,
) ([]byte, [][]byte, []byte, uint64, int, error)
These functions:
- Chunk the payload
- Build a Merkle tree
- Return:
- Merkle root
- Proof elements
- The chunk used for proofs
- Number of leaves
- (for
GenerateMerkleTree) the tree depth
Smart contract payloads & serializer
In addition to standard TX_DATA payloads, the SDK also exposes dedicated types and helpers for interacting with smart contracts, allowing you to model contract calls, upgrades, and rollbacks as JSON payloads that can be submitted through the same transaction flow.
Contract payload structs
type ContractArgs struct {
Value []byte `json:"value"`
}
type InvokeContractPayload struct {
FunctionName string `json:"functionName"`
Args []ContractArgs `json:"args"`
GasLimit uint64 `json:"gasLimit"`
}
type RollbackContractPayload struct {
TargetVersion uint64 `json:"targetVersion"`
RollbackReason string `json:"rollbackReason,omitempty"`
}
type UpgradeContractPayload struct {
NewSourceCode string `json:"newSourceCode"`
UpgradeReason string `json:"upgradeReason,omitempty"`
}
These are meant to be JSON-encoded and placed into ULTransactionInput.Payload when:
PayloadType == INVOKE_SMART_CONTRACT.String()PayloadType == UPGRADE_SMART_CONTRACT.String()PayloadType == ROLLBACK_SMART_CONTRACT.String()
Contract VM serializer
The serializer encodes Go values into the binary format expected by the ULedger smart-contract VM.
type ContractDataType byte
const (
TypeNull ContractDataType = 0
TypeBool ContractDataType = 1
TypeInt32 ContractDataType = 2
TypeInt64 ContractDataType = 3
TypeString ContractDataType = 4
TypeBytes ContractDataType = 5
TypeArray ContractDataType = 6
TypeMap ContractDataType = 7
TypeFloat32 ContractDataType = 8
TypeFloat64 ContractDataType = 9
)
func Encode(data interface{}) ([]byte, error)
func Decode(data []byte) (interface{}, error)
func GetType(data []byte) (ContractDataType, error)
At a high level:
Encode– takes Go values (bool,int32,string,[]byte,map[string]interface{},[]interface{}, etc.) and returns a binary blob for the VM.Decode– reverses that process (primarily useful for tools, tests, or off-chain decoding).GetType– inspects the first byte and returns the encodedContractDataType.
These tools are primarily used when constructing the arguments for smart-contract calls and will be covered more deeply in a dedicated “Smart contracts” guide.
This page is intended as a reference. For step-by-step guides see our tutorial section.