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 present → GenerateFromMnemonic(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`.