Saltar al contenido principal

Wallets – Referencia del Go SDK

Descripción general

El módulo wallet en el Go SDK es responsable de:

  • Representar un wallet de ULedger (UL_Wallet)
  • Generar wallets a partir de mnemonics, keys o JSON
  • Persistir wallets en disco (archivos .ukey)
  • Reconstruir wallets desde datos almacenados
  • Gestionar la entropía BIP-39 y los mnemonics

Un wallet combina:

  • Una dirección (derivada de la clave pública)
  • Grupos de permisos (AuthGroups)
  • Un par de claves criptográficas (crypto.ULKey) usado para firmar transactions

Tipos principales

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 – dirección del wallet utilizada en la cadena y en las APIs.
  • Enabled – indica si este wallet está activo actualmente.
  • Parent – dirección del wallet padre (para jerarquías padre/hijo).
  • AuthGroups – grupos de permisos lógicos.
  • key – clave criptográfica en memoria (no serializada).

UL_AuthPermission

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

Define permisos CRUD para un nombre de grupo determinado (por ejemplo, "Wallet" o "wallet").

WalletData (estructura de persistencia)

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"`
}

Esta es la estructura JSON utilizada al guardar/cargar wallets (por ejemplo, desde archivos .ukey).

Constante de nombre de grupo de autenticación

const (
WALLET_GROUP_NAME = "wallet"
)

Un nombre de grupo predeterminado que puede usarse para permisos relacionados con wallets.


Acceso a la key

(*UL_Wallet).GetKey

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

Devuelve el crypto.ULKey subyacente, que se utiliza para:

  • Determinar el tipo de key (GetType)
  • Obtener el hex de la clave pública/privada
  • Firmar los compromisos de transactions

Esto es lo que usa la sesión de transaction cuando llama a wallet.GetKey().SignData(...).


Creación de wallets

FromJson

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

Crea un UL_Wallet a partir de una cadena JSON que coincide con la estructura WalletData.

Qué hace:

  1. Deserializa data en WalletData.

  2. Crea un UL_Wallet con:

    • Address, Parent, Enabled, AuthGroups del JSON.
  3. Usa KeyType para obtener un crypto.ULKey concreto.

  4. Llama a:

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

Si la reconstrucción de la key falla, se devuelve un error.

Usado en tu CLI de transactions para cargar wallets desde archivos (o JSON).


GetWalletFromHex

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

Crea un wallet directamente a partir del material de key proporcionado.

Pasos:

  1. Obtiene un crypto.ULKey para el keyType dado.
  2. Llama a GeneratePublicKeyFromHex(false, publicKeyHex).
  3. Llama a GeneratePrivateKeyFromHex(privateKeyHex).
  4. Calcula la dirección como ParseAddress(key.GetPublicKeyHex(false)).
  5. Devuelve un UL_Wallet con:
    • Address establecido en la dirección derivada
    • key establecido en la key construida

Desde las pruebas:

  • Key válida → dirección no vacía

  • Puedes verificar que la clave privada va y viene correctamente:

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

ParseAddress

func ParseAddress(publicKeyHex string) string

Deriva la dirección del wallet a partir de la clave pública codificada en hex.

Algoritmo:

  1. Convierte el hex de la clave pública a minúsculas.
  2. Calcula sha256 sobre los bytes de la cadena en minúsculas.
  3. Codifica el hash como hex.

Esta función determinista se usa tanto al generar nuevos wallets como al reconstruir a partir de claves existentes.


GenerateFromMnemonic

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

Crea un wallet a partir de un mnemonic BIP-39.

Flujo:

  1. Llama a MnemonicToSeed(mnemonic, passphrase) para obtener una semilla.
  2. Crea un crypto.ULKey basado en keyType.
  3. Llama a GenerateKeyFromSeed(seed) en la key.
  4. Deriva la dirección del wallet mediante ParseAddress(key.GetPublicKeyHex(false)).
  5. Devuelve un UL_Wallet con:
    • Address establecido
    • key poblado (otros campos como Enabled, Parent, AuthGroups se completan después)

GenerateNewWallet

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

Genera un nuevo wallet + mnemonic.

Pasos:

  1. Llama a GenerateMnemonic(entropy) para obtener una frase BIP-39.

  2. Llama a GenerateFromMnemonic(mnemonic, passphrase, keyType) para derivar una key.

  3. Establece:

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

    • UL_Wallet
    • mnemonic (string)
    • error

Esto es lo que el comando CLI de "Generar Wallet" envuelve en última instancia.


Guardar y cargar wallets

(*UL_Wallet).SaveToFile

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

Persiste un wallet en un archivo .ukey.

Comportamiento:

  • Asegura que la ruta del archivo termine con .ukey.

  • Construye un WalletData con:

    • Address, Parent, Enabled
    • KeyType, Mnemonic
    • PublicKeyHex
    • AuthGroups
  • Incluye PrivateKeyHex solo si includePrivateKey == true.

  • Escribe el JSON en disco con permisos 0600.

Esto te permite elegir entre:

  • Archivos de wallet "completos" (incluyen la clave privada)
  • Archivos de wallet "solo públicos" (sin clave privada, para distribución más segura)

LoadFromFile

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

Lee un archivo .ukey y reconstruye un UL_Wallet.

Orden de prioridad:

  1. Mnemonic presenteGenerateFromMnemonic(mnemonic, passphrase, KeyType)

  2. Si no, si clave privada presente:

    • GetHasherByType(KeyType)
    • GetKeyByType(KeyType, hasher)
    • GeneratePublicKeyFromHex(false, PublicKeyHex)
    • GeneratePrivateKeyFromHex(PrivateKeyHex)
  3. Si no (sin mnemonic, sin clave privada):

    • Usa solo KeyType + PublicKeyHex (estilo solo-lectura)
    • Sin clave privada en memoria

Esto te permite:

  • Recuperar wallets completos desde frases semilla
  • Reconstruir wallets desde pares de claves conocidos
  • Cargar wallets de solo lectura desde claves públicas

Utilidades de entropía y mnemonic

El segundo archivo mostrado es la capa auxiliar BIP-39 usada por GenerateNewWallet y GenerateFromMnemonic.

Tipo Entropy y constantes

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
)
  • La entropía se expresa en bits y se corresponde con conteos de palabras:
    • 128 → 12 palabras
    • 160 → 15 palabras
    • 192 → 18 palabras
    • 224 → 21 palabras
    • 256 → 24 palabras

MakeEntropy

func MakeEntropy(i int) Entropy

Convierte un entero (128, 160, 192, 224, 256) en la constante Entropy correspondiente, usando DefaultEntropy por defecto en cualquier otro caso.


GenerateMnemonic

func GenerateMnemonic(entropySize Entropy) (string, error)

Genera una frase mnemonic BIP-39.

  • Tamaños de entropía válidos: múltiplos de 32 entre 128 y 256 bits.
  • Internamente:
    • Usa crypto/rand para generar entropía.
    • Usa bip39.NewMnemonic(entropy) para derivar la frase.

Usado por GenerateNewWallet.


MnemonicToSeed

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

Convierte un mnemonic BIP-39 + passphrase opcional en una semilla.

  • Valida el mnemonic mediante bip39.IsMnemonicValid.
  • Usa bip39.NewSeed(mnemonic, passphrase).

Usado por GenerateFromMnemonic.


Helpers de validación e inspección

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 – verifica si una frase es BIP-39 válida.
  • GetWordList – devuelve el diccionario BIP-39 subyacente.
  • GetWordIndex – encuentra el índice de una palabra en esa lista.
  • GetWordCount – número de palabras en una frase.
  • GetEntropySize – deriva el tamaño de entropía según el conteo de palabras (12/15/18/21/24).

Ejemplo: creación programática de wallet (referencia)

No es un tutorial completo, solo un esbozo de uso vinculado a la API anterior:

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)
}
}

Luego puedes cargarlo con `LoadFromFile` o parsear el JSON almacenado y usar `FromJson`.