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 (
.ukeyfiles) - 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:
-
Unmarshals
dataintoWalletData. -
Creates a
UL_Walletwith:Address,Parent,Enabled,AuthGroupsfrom JSON.
-
Uses
KeyTypeto get a concretecrypto.ULKey. -
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:
- Gets a
crypto.ULKeyfor the givenkeyType. - Calls
GeneratePublicKeyFromHex(false, publicKeyHex). - Calls
GeneratePrivateKeyFromHex(privateKeyHex). - Computes the address as
ParseAddress(key.GetPublicKeyHex(false)). - Returns a
UL_Walletwith:Addressset to the derived addresskeyset 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:
- Lowercases the public key hex.
- Computes
sha256over the bytes of the lowercase string. - 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:
- Calls
MnemonicToSeed(mnemonic, passphrase)to get a seed. - Creates a
crypto.ULKeybased onkeyType. - Calls
GenerateKeyFromSeed(seed)on the key. - Derives the wallet address via
ParseAddress(key.GetPublicKeyHex(false)). - Returns a
UL_Walletwith:Addresssetkeypopulated (other fields likeEnabled,Parent,AuthGroupsare 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:
-
Calls
GenerateMnemonic(entropy)to get a BIP-39 phrase. -
Calls
GenerateFromMnemonic(mnemonic, passphrase, keyType)to derive a key. -
Sets:
wallet.Parent = parentwallet.Enabled = truewallet.AuthGroups = authGroups
-
Returns:
UL_Walletmnemonic(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
WalletDatawith:Address,Parent,EnabledKeyType,MnemonicPublicKeyHexAuthGroups
-
Includes
PrivateKeyHexonly ifincludePrivateKey == true. -
Writes JSON to disk with
0600permissions.
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:
-
Mnemonic present →
GenerateFromMnemonic(mnemonic, passphrase, KeyType) -
Else if private key present:
GetHasherByType(KeyType)GetKeyByType(KeyType, hasher)GeneratePublicKeyFromHex(false, PublicKeyHex)GeneratePrivateKeyFromHex(PrivateKeyHex)
-
Else (no mnemonic, no private key):
- Uses
KeyType+PublicKeyHexonly (watch-only style) - No private key in memory
- Uses
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/randto generate entropy. - Uses
bip39.NewMnemonic(entropy)to derive the phrase.
- Uses
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`.