Skip to main content

Wallets – Go SDK Reference

Overview

The wallet module in the Go SDK is responsible for:

  • Representing a ULedger wallet (UL_Wallet)
  • Generating wallets from mnemonics, keys, or JSON
  • Persisting wallets to disk (.ukey files)
  • Reconstructing wallets from stored data
  • Managing BIP-39 entropy and mnemonics

A wallet combines:

  • An address (derived from the public key)
  • Permission groups (AuthGroups)
  • A cryptographic key pair (crypto.ULKey) used to sign transactions

Core types

UL_Wallet

type UL_Wallet struct {
Address string `json:"address"`
Enabled bool `json:"enabled"`
Parent string `json:"parent"`
AuthGroups map[string]UL_AuthPermission `json:"authGroups"`
key crypto.ULKey `json:"-"`
}
  • Address – wallet address used on-chain and in APIs.
  • Enabled – whether this wallet is currently active.
  • Parent – parent wallet address (for parent/child hierarchies).
  • AuthGroups – logical permission groups.
  • key – in-memory cryptographic key (not serialized).

UL_AuthPermission

type UL_AuthPermission struct {
Create bool `json:"create"`
Read bool `json:"read"`
Update bool `json:"update"`
Delete bool `json:"delete"`
}

Defines CRUD permissions for a given group name (e.g. "Wallet" or "wallet").

WalletData (persistence shape)

type WalletData struct {
Address string `json:"address"`
Enabled bool `json:"enabled"`
Parent string `json:"parent"`
AuthGroups map[string]UL_AuthPermission `json:"authGroups"`
Mnemonic string `json:"mnemonic"`
KeyType crypto.KeyType `json:"keyType"`
PublicKeyHex string `json:"publicKeyHex"`
PrivateKeyHex string `json:"privateKeyHex"`
}

This is the JSON structure used when saving/loading wallets (e.g. from .ukey files).

Auth group name constant

const (
WALLET_GROUP_NAME = "wallet"
)

A default group name you can use for wallet-related permissions.


Accessing the key

(*UL_Wallet).GetKey

func (w *UL_Wallet) GetKey() crypto.ULKey

Returns the underlying crypto.ULKey, which is used to:

  • Determine the key type (GetType)
  • Get public/private key hex
  • Sign transaction commitments

This is what the transaction session uses when it calls wallet.GetKey().SignData(...).


Creating wallets

FromJson

func FromJson(data string, passphrase string) (*UL_Wallet, error)

Creates a UL_Wallet from a JSON string that matches the WalletData structure.

What it does:

  1. Unmarshals data into WalletData.

  2. Creates a UL_Wallet with:

    • Address, Parent, Enabled, AuthGroups from JSON.
  3. Uses KeyType to get a concrete crypto.ULKey.

  4. Calls:

    • GeneratePublicKeyFromHex(false, PublicKeyHex)
    • GeneratePrivateKeyFromHex(PrivateKeyHex)

If key reconstruction fails, an error is returned.

Used in your transaction CLI to load wallets from files (or JSON).


GetWalletFromHex

func GetWalletFromHex(
publicKeyHex, privateKeyHex string,
keyType crypto.KeyType,
) (UL_Wallet, error)

Creates a wallet directly from given key material.

Steps:

  1. Gets a crypto.ULKey for the given keyType.
  2. Calls GeneratePublicKeyFromHex(false, publicKeyHex).
  3. Calls GeneratePrivateKeyFromHex(privateKeyHex).
  4. Computes the address as ParseAddress(key.GetPublicKeyHex(false)).
  5. Returns a UL_Wallet with:
    • Address set to the derived address
    • key set to the constructed key

From the tests:

  • Valid key → non-empty address

  • You can verify private key round-trips correctly:

    if !strings.EqualFold(wallet.key.GetPrivateKeyHex(), privateKeyHex) {
    // mismatch
    }

ParseAddress

func ParseAddress(publicKeyHex string) string

Derives the wallet address from the hex-encoded public key.

Algorithm:

  1. Lowercases the public key hex.
  2. Computes sha256 over the bytes of the lowercase string.
  3. Encodes the hash as hex.

This deterministic function is used both when generating new wallets and when reconstructing from existing keys.


GenerateFromMnemonic

func GenerateFromMnemonic(
mnemonic string,
passphrase string,
keyType crypto.KeyType,
) (UL_Wallet, error)

Creates a wallet from a BIP-39 mnemonic.

Flow:

  1. Calls MnemonicToSeed(mnemonic, passphrase) to get a seed.
  2. Creates a crypto.ULKey based on keyType.
  3. Calls GenerateKeyFromSeed(seed) on the key.
  4. Derives the wallet address via ParseAddress(key.GetPublicKeyHex(false)).
  5. Returns a UL_Wallet with:
    • Address set
    • key populated (other fields like Enabled, Parent, AuthGroups are filled later)

GenerateNewWallet

func GenerateNewWallet(
passphrase string,
keyType crypto.KeyType,
parent string,
authGroups map[string]UL_AuthPermission,
entropy Entropy,
) (UL_Wallet, string, error)

Generates a brand new wallet + mnemonic.

Steps:

  1. Calls GenerateMnemonic(entropy) to get a BIP-39 phrase.

  2. Calls GenerateFromMnemonic(mnemonic, passphrase, keyType) to derive a key.

  3. Sets:

    • wallet.Parent = parent
    • wallet.Enabled = true
    • wallet.AuthGroups = authGroups
  4. Returns:

    • UL_Wallet
    • mnemonic (string)
    • error

This is what your “Generate Wallet” CLI command ultimately wraps.


Saving and loading wallets

(*UL_Wallet).SaveToFile

func (w *UL_Wallet) SaveToFile(
filePath string,
mnemonic string,
includePrivateKey bool,
) error

Persists a wallet to a .ukey file.

Behavior:

  • Ensures file path ends with .ukey.

  • Builds a WalletData with:

    • Address, Parent, Enabled
    • KeyType, Mnemonic
    • PublicKeyHex
    • AuthGroups
  • Includes PrivateKeyHex only if includePrivateKey == true.

  • Writes JSON to disk with 0600 permissions.

This allows you to choose between:

  • “Full” wallet files (include private key)
  • “Public-only” wallet files (no private key, for more secure distribution)

LoadFromFile

func LoadFromFile(
filePath string,
passphrase string,
) (UL_Wallet, error)

Reads a .ukey file and reconstructs a UL_Wallet.

Priority order:

  1. Mnemonic presentGenerateFromMnemonic(mnemonic, passphrase, KeyType)

  2. Else if private key present:

    • GetHasherByType(KeyType)
    • GetKeyByType(KeyType, hasher)
    • GeneratePublicKeyFromHex(false, PublicKeyHex)
    • GeneratePrivateKeyFromHex(PrivateKeyHex)
  3. Else (no mnemonic, no private key):

    • Uses KeyType + PublicKeyHex only (watch-only style)
    • No private key in memory

This lets you:

  • Recover full wallets from seed phrases
  • Rebuild wallets from known key pairs
  • Load watch-only wallets from public keys

Entropy and mnemonic utilities

The second file you showed is the BIP-39 helper layer used by GenerateNewWallet and GenerateFromMnemonic.

Entropy type & constants

type Entropy int

const (
Entropy128 Entropy = 128
Entropy160 Entropy = 160
Entropy192 Entropy = 192
Entropy224 Entropy = 224
Entropy256 Entropy = 256

// Default entropy size (256 bits = 24 words)
DefaultEntropy = Entropy256
)
  • Entropy is expressed in bits and maps to word counts:
    • 128 → 12 words
    • 160 → 15 words
    • 192 → 18 words
    • 224 → 21 words
    • 256 → 24 words

MakeEntropy

func MakeEntropy(i int) Entropy

Converts an integer (128, 160, 192, 224, 256) into the corresponding Entropy constant, defaulting to DefaultEntropy otherwise.


GenerateMnemonic

func GenerateMnemonic(entropySize Entropy) (string, error)

Generates a BIP-39 mnemonic phrase.

  • Valid entropy sizes: multiples of 32 between 128 and 256 bits.
  • Internally:
    • Uses crypto/rand to generate entropy.
    • Uses bip39.NewMnemonic(entropy) to derive the phrase.

Used by GenerateNewWallet.


MnemonicToSeed

func MnemonicToSeed(
mnemonic string,
passphrase string,
) ([]byte, error)

Converts a BIP-39 mnemonic + optional passphrase into a seed.

  • Validates the mnemonic via bip39.IsMnemonicValid.
  • Uses bip39.NewSeed(mnemonic, passphrase).

Used by GenerateFromMnemonic.


Validation and inspection helpers

func ValidateMnemonic(mnemonic string) bool
func GetWordList() []string
func GetWordIndex(word string) (int, error)
func GetWordCount(mnemonic string) int
func GetEntropySize(mnemonic string) (Entropy, error)
  • ValidateMnemonic – checks if a phrase is valid BIP-39.
  • GetWordList – returns the underlying BIP-39 dictionary.
  • GetWordIndex – finds a word’s index in that list.
  • GetWordCount – number of words in a phrase.
  • GetEntropySize – derives entropy size based on word count (12/15/18/21/24).

Example: programmatic wallet creation (reference)

Not a full tutorial, just a usage sketch tied to the API above:

package main

import (
"fmt"

"github.com/ULedgerInc/go-sdk/pkg/crypto"
"github.com/ULedgerInc/go-sdk/pkg/wallet"
)

func main() {
passphrase := "optional-passphrase"

auth := map[string]wallet.UL_AuthPermission{
"Wallet": {Create: true, Read: true, Update: true, Delete: false},
}

w, mnemonic, err := wallet.GenerateNewWallet(
passphrase,
crypto.KeyTypeSecp256k1,
"", // parent
auth, // auth groups
wallet.Entropy256, // 24 words
)
if err != nil {
panic(err)
}

fmt.Println("Address:", w.Address)
fmt.Println("Mnemonic:", mnemonic)

if err := w.SaveToFile("./wallets/my-wallet.ukey", mnemonic, true); err != nil {
panic(err)
}
}

You can then load it later with `LoadFromFile` or parse the stored JSON and use `FromJson`.