Documentation
¶
Overview ¶
Package wallet provides hierarchical deterministic (HD) wallet functionality for the Zenon Network, including BIP39 mnemonic generation, BIP32/BIP44 key derivation, and encrypted keystore management.
The wallet package enables secure storage and management of Zenon Network keypairs using industry-standard cryptographic practices. Wallets are encrypted with Argon2 key derivation and stored as JSON keyfiles.
Basic Usage ¶
Create a new wallet with a random mnemonic:
manager, err := wallet.NewKeyStoreManager("./wallets")
if err != nil {
log.Fatal(err)
}
// Create new wallet with password protection
keystore, err := manager.CreateNew("my-secure-password", "main-wallet")
if err != nil {
log.Fatal(err)
}
fmt.Println("Mnemonic:", keystore.Mnemonic)
fmt.Println("Base address:", keystore.GetBaseAddress())
Key Derivation ¶
The wallet follows BIP44 derivation path: m/44'/73404'/account'/0'/0' where 73404 is Zenon's registered coin type.
Derive keypairs at different indices:
// Get default keypair (index 0) keypair0, err := keystore.GetKeyPair(0) address0, _ := keypair0.GetAddress() // Derive multiple addresses keypair1, _ := keystore.GetKeyPair(1) keypair2, _ := keystore.GetKeyPair(2)
Importing Existing Mnemonics ¶
Import a wallet from an existing BIP39 mnemonic:
mnemonic := "route become dream access impulse price inform obtain engage ski believe awful"
keystore, err := manager.CreateFromMnemonic(mnemonic, "password", "imported-wallet")
if err != nil {
log.Fatal(err)
}
Wallet Persistence ¶
Wallets are automatically saved as encrypted keyfiles. Load an existing wallet:
keystore, err := manager.ReadKeyStore("password", "main-wallet")
if err != nil {
log.Fatal(err)
}
// List all wallets in directory
wallets, err := manager.ListAllKeyStores()
for _, name := range wallets {
fmt.Println("Wallet:", name)
}
Cryptographic Operations ¶
Sign and verify messages with Ed25519:
keypair, _ := keystore.GetKeyPair(0)
message := []byte("Hello Zenon")
// Sign message
signature, err := keypair.Sign(message)
if err != nil {
log.Fatal(err)
}
// Verify signature
valid, err := keypair.Verify(signature, message)
if err != nil || !valid {
log.Fatal("Invalid signature")
}
Security Considerations ¶
- Mnemonics should be backed up securely and never shared - Passwords should be strong and unique - Keyfiles are encrypted but filesystem permissions should be restricted - Never commit keyfiles to version control
For more examples, see https://pkg.go.dev/github.com/0x3639/znn-sdk-go/wallet
Example ¶
Example demonstrates creating a new wallet with random mnemonic.
package main
import (
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
// Create temporary directory for example
tempDir, _ := os.MkdirTemp("", "wallet-example-*")
defer os.RemoveAll(tempDir)
// Create wallet manager
manager, err := wallet.NewKeyStoreManager(tempDir)
if err != nil {
log.Fatal(err)
}
// Create new wallet with random mnemonic
keystore, err := manager.CreateNew("secure-password", "my-wallet")
if err != nil {
log.Fatal(err)
}
// Display mnemonic (MUST be backed up securely!)
fmt.Println("Wallet created successfully")
// Verify mnemonic was generated
if len(keystore.Mnemonic) > 0 {
fmt.Println("Mnemonic generated")
}
// Get base address (first address, index 0)
_, err = keystore.GetBaseAddress()
if err == nil {
fmt.Println("Base address derived")
}
}
Output: Wallet created successfully Mnemonic generated Base address derived
Example (BulkAddressGeneration) ¶
Example_bulkAddressGeneration demonstrates efficient bulk address derivation.
package main
import (
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
tempDir, _ := os.MkdirTemp("", "wallet-bulk-*")
defer os.RemoveAll(tempDir)
manager, _ := wallet.NewKeyStoreManager(tempDir)
keystore, _ := manager.CreateNew("password", "bulk-wallet")
// Derive addresses 0-4 in one call
addresses, err := keystore.DeriveAddressesByRange(0, 5)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Generated %d addresses\n", len(addresses))
for i, addr := range addresses {
fmt.Printf("Address %d: %s...\n", i, addr.String()[:12])
}
}
Example (DeriveMultipleAddresses) ¶
Example_deriveMultipleAddresses demonstrates deriving multiple addresses from one wallet.
package main
import (
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
tempDir, _ := os.MkdirTemp("", "wallet-derive-*")
defer os.RemoveAll(tempDir)
manager, _ := wallet.NewKeyStoreManager(tempDir)
keystore, _ := manager.CreateNew("password", "multi-address-wallet")
// Derive first 3 addresses
for i := 0; i < 3; i++ {
keypair, err := keystore.GetKeyPair(i)
if err != nil {
log.Fatal(err)
}
address, _ := keypair.GetAddress()
fmt.Printf("Address %d: %s...\n", i, address.String()[:12])
}
// All addresses derived from same mnemonic
fmt.Println("All addresses from single mnemonic")
}
Example (FindAddress) ¶
Example_findAddress demonstrates searching for an address in the wallet.
package main
import (
"errors"
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
tempDir, _ := os.MkdirTemp("", "wallet-find-*")
defer os.RemoveAll(tempDir)
manager, _ := wallet.NewKeyStoreManager(tempDir)
keystore, _ := manager.CreateNew("password", "search-wallet")
// Get an address to search for
targetKeypair, _ := keystore.GetKeyPair(5)
targetAddr, _ := targetKeypair.GetAddress()
// Find which index this address belongs to
result, err := keystore.FindAddress(*targetAddr, 10)
if errors.Is(err, wallet.ErrAddressNotFound) {
fmt.Println("Address not found")
} else if err != nil {
log.Fatal(err)
} else {
fmt.Printf("Address found at index: %d\n", result.Index)
// Can use result.KeyPair to sign transactions
}
}
Output: Address found at index: 5
Example (ImportMnemonic) ¶
Example_importMnemonic demonstrates restoring a wallet from an existing mnemonic.
package main
import (
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
tempDir, _ := os.MkdirTemp("", "wallet-import-*")
defer os.RemoveAll(tempDir)
manager, err := wallet.NewKeyStoreManager(tempDir)
if err != nil {
log.Fatal(err)
}
// Import wallet from existing mnemonic
mnemonic := "route become dream access impulse price inform obtain engage ski believe awful"
keystore, err := manager.CreateFromMnemonic(mnemonic, "new-password", "imported-wallet")
if err != nil {
log.Fatal(err)
}
// Verify import succeeded
baseAddr, _ := keystore.GetBaseAddress()
fmt.Println("Wallet imported successfully")
fmt.Printf("Address: %s...\n", baseAddr.String()[:12])
// Same mnemonic always generates same addresses
fmt.Println("Mnemonic restored consistently")
}
Example (ListWallets) ¶
Example_listWallets demonstrates listing all wallets in a directory.
package main
import (
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
tempDir, _ := os.MkdirTemp("", "wallet-list-*")
defer os.RemoveAll(tempDir)
manager, _ := wallet.NewKeyStoreManager(tempDir)
// Create multiple wallets
manager.CreateNew("password", "wallet-1")
manager.CreateNew("password", "wallet-2")
manager.CreateNew("password", "wallet-3")
// List all wallets
wallets, err := manager.ListAllKeyStores()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d wallets:\n", len(wallets))
for _, name := range wallets {
fmt.Printf("- %s\n", name)
}
}
Example (SaveAndLoadWallet) ¶
Example_saveAndLoadWallet demonstrates wallet persistence.
package main
import (
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
tempDir, _ := os.MkdirTemp("", "wallet-persist-*")
defer os.RemoveAll(tempDir)
manager, _ := wallet.NewKeyStoreManager(tempDir)
// Create and save wallet
keystore1, _ := manager.CreateNew("password123", "persistent-wallet")
addr1, _ := keystore1.GetBaseAddress()
fmt.Printf("Created wallet: %s...\n", addr1.String()[:12])
// Load wallet from disk
keystore2, err := manager.ReadKeyStore("password123", "persistent-wallet")
if err != nil {
log.Fatal(err)
}
addr2, _ := keystore2.GetBaseAddress()
fmt.Printf("Loaded wallet: %s...\n", addr2.String()[:12])
// Verify they match
if addr1.String() == addr2.String() {
fmt.Println("Wallet persisted correctly")
}
}
Example (SignAndVerify) ¶
Example_signAndVerify demonstrates cryptographic signing with a keypair.
package main
import (
"fmt"
"log"
"os"
"github.com/0x3639/znn-sdk-go/wallet"
)
func main() {
tempDir, _ := os.MkdirTemp("", "wallet-sign-*")
defer os.RemoveAll(tempDir)
manager, _ := wallet.NewKeyStoreManager(tempDir)
keystore, _ := manager.CreateNew("password", "signing-wallet")
// Get keypair for signing
keypair, _ := keystore.GetKeyPair(0)
// Sign a message
message := []byte("Hello Zenon Network")
signature, err := keypair.Sign(message)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Signature length: %d bytes\n", len(signature))
// Verify signature
valid, err := keypair.Verify(signature, message)
if err != nil {
log.Fatal(err)
}
if valid {
fmt.Println("Signature verified successfully")
} else {
fmt.Println("Signature verification failed")
}
}
Output: Signature length: 64 bytes Signature verified successfully
Index ¶
- Constants
- Variables
- func DeriveKey(path string, seedHex string) ([]byte, error)
- func EntropyToMnemonic(entropy []byte) (string, error)
- func GenerateMnemonic(strength int) (string, error)
- func GeneratePublicKey(privateKey []byte) ([]byte, error)
- func GetDerivationAccount(account int) string
- func IsValidWord(word string) bool
- func MnemonicToEntropy(mnemonic string) ([]byte, error)
- func MnemonicToSeed(mnemonic string, passphrase string) []byte
- func NewWalletError(message string) error
- func ValidateMnemonic(words []string) bool
- func ValidateMnemonicString(mnemonic string) bool
- func ValidatePassword(password string) error
- type Argon2Params
- type CryptoParams
- type EncryptedFile
- type FindResponse
- type KeyData
- type KeyPair
- func (kp *KeyPair) Destroy()
- func (kp *KeyPair) GetAddress() (*types.Address, error)
- func (kp *KeyPair) GetPrivateKey() []byte
- func (kp *KeyPair) GetPublicKey() ([]byte, error)
- func (kp *KeyPair) Sign(message []byte) ([]byte, error)
- func (kp *KeyPair) Verify(signature []byte, message []byte) (bool, error)
- type KeyStore
- func FromEncryptedFile(ef *EncryptedFile, password string) (*KeyStore, error)
- func NewKeyStoreFromEntropy(entropy []byte) (*KeyStore, error)
- func NewKeyStoreFromMnemonic(mnemonic string) (*KeyStore, error)
- func NewKeyStoreFromSeed(seedHex string) (*KeyStore, error)
- func NewKeyStoreRandom() (*KeyStore, error)
- func (ks *KeyStore) DeriveAddressesByRange(left, right int) ([]*types.Address, error)
- func (ks *KeyStore) FindAddress(address types.Address, maxAccounts int) (*FindResponse, error)
- func (ks *KeyStore) GetBaseAddress() (*types.Address, error)
- func (ks *KeyStore) GetKeyPair(account int) (*KeyPair, error)
- func (ks *KeyStore) ToEncryptedFile(password string, metadata map[string]interface{}) (*EncryptedFile, error)
- type KeyStoreManager
- func (m *KeyStoreManager) CreateFromMnemonic(mnemonic, passphrase, name string) (*KeyStore, error)
- func (m *KeyStoreManager) CreateNew(passphrase, name string) (*KeyStore, error)
- func (m *KeyStoreManager) FindKeyStore(name string) (string, error)
- func (m *KeyStoreManager) GetKeystoreInfo(keyStoreFile string) (map[string]interface{}, error)
- func (m *KeyStoreManager) ListAllKeyStores() ([]string, error)
- func (m *KeyStoreManager) ReadKeyStore(password string, keyStoreFile string) (*KeyStore, error)
- func (m *KeyStoreManager) SaveKeyStore(store *KeyStore, password, name string) error
- type PasswordStrength
- type WalletError
Examples ¶
Constants ¶
const ( // HardenedKeyStart is the index at which hardened keys start (2^31) HardenedKeyStart = 0x80000000 // Ed25519Curve is the curve name for SLIP-0010 Ed25519Curve = "ed25519 seed" )
const ( // BaseAddressKey is the JSON key for the base address in wallet metadata BaseAddressKey = "baseAddress" // WalletTypeKey is the JSON key for the wallet type in wallet metadata WalletTypeKey = "walletType" // KeyStoreWalletType is the type identifier for keystore wallets KeyStoreWalletType = "keystore" // DefaultMaxIndex is the maximum address index to search DefaultMaxIndex = 10000 )
const ( // CoinType is the BIP44 coin type for Zenon (73404') CoinType = "73404" // DerivationPath is the base BIP44 path for Zenon wallets DerivationPath = "m/44'/" + CoinType + "'" )
const (
// MinPasswordLength is the minimum recommended password length for wallet encryption
MinPasswordLength = 8
)
Variables ¶
var ( ErrWalletManagerStopped = errors.New("wallet manager has not started") ErrIncorrectPassword = errors.New("incorrect password") ErrInvalidMnemonic = errors.New("invalid mnemonic") ErrInvalidEntropy = errors.New("invalid entropy") ErrWalletNotFound = errors.New("wallet not found") ErrWalletAlreadyExists = errors.New("wallet already exists") ErrInvalidKeyStore = errors.New("invalid keystore") ErrInvalidPrivateKey = errors.New("invalid private key") ErrAddressNotFound = errors.New("address not found in wallet") ErrKeystoreNotFound = errors.New("keystore not found") )
Common wallet errors
Functions ¶
func DeriveKey ¶
DeriveKey is a convenience function that derives a key from a path and seed and returns the Ed25519 private key
func EntropyToMnemonic ¶
EntropyToMnemonic converts entropy bytes to a mnemonic
func GenerateMnemonic ¶
GenerateMnemonic generates a BIP39 mnemonic with the given entropy strength strength must be 128, 160, 192, 224, or 256 bits 128 bits = 12 words, 256 bits = 24 words
func GeneratePublicKey ¶
GeneratePublicKey is a static method that generates a public key from a private key
func GetDerivationAccount ¶
GetDerivationAccount returns the BIP44 derivation path for a given account index For example: account 0 returns "m/44'/73404'/0'"
func IsValidWord ¶
IsValidWord checks if a word is in the BIP39 wordlist
func MnemonicToEntropy ¶
MnemonicToEntropy converts a mnemonic to its entropy bytes
func MnemonicToSeed ¶
MnemonicToSeed converts a mnemonic to a seed for key derivation passphrase can be empty string
func NewWalletError ¶
NewWalletError creates a new wallet error
func ValidateMnemonic ¶
ValidateMnemonic validates a BIP39 mnemonic phrase
func ValidateMnemonicString ¶
ValidateMnemonicString validates a BIP39 mnemonic phrase from a string
func ValidatePassword ¶ added in v0.1.3
ValidatePassword checks if a password meets minimum security requirements.
Requirements:
- Minimum 8 characters (configurable via MinPasswordLength)
- At least one character from any category (to prevent all-same-char passwords)
This function returns an error if the password doesn't meet requirements. For a more detailed analysis, use AnalyzePasswordStrength.
Example:
err := ValidatePassword("mypassword123")
if err != nil {
fmt.Println("Password too weak:", err)
}
Types ¶
type Argon2Params ¶
type Argon2Params struct {
Salt string `json:"salt"` // Hex encoded
}
Argon2Params contains Argon2 key derivation parameters
type CryptoParams ¶
type CryptoParams struct {
Argon2Params *Argon2Params `json:"argon2Params"`
CipherData string `json:"cipherData"` // Hex encoded
CipherName string `json:"cipherName"` // "aes-256-gcm"
Kdf string `json:"kdf"` // "argon2.IDKey"
Nonce string `json:"nonce"` // Hex encoded
}
CryptoParams contains encryption parameters
type EncryptedFile ¶
type EncryptedFile struct {
Metadata map[string]interface{} `json:",inline"`
Crypto *CryptoParams `json:"crypto"`
Timestamp int64 `json:"timestamp"`
Version int `json:"version"`
}
EncryptedFile represents an encrypted wallet file
func Encrypt ¶
func Encrypt(data []byte, password string, metadata map[string]interface{}) (*EncryptedFile, error)
Encrypt creates an encrypted file from data and password
func FromJSON ¶
func FromJSON(data []byte) (*EncryptedFile, error)
FromJSON deserializes an encrypted file from JSON
func (*EncryptedFile) Decrypt ¶
func (ef *EncryptedFile) Decrypt(password string) ([]byte, error)
Decrypt decrypts the encrypted file with the given password
func (*EncryptedFile) ToJSON ¶
func (ef *EncryptedFile) ToJSON() ([]byte, error)
ToJSON serializes the encrypted file to JSON
type FindResponse ¶
FindResponse represents the result of finding an address in the keystore
type KeyData ¶
KeyData represents a BIP32 extended key (private key + chain code)
func DerivePath ¶
DerivePath derives a key from a BIP44 path string like "m/44'/73404'/0'"
func GetMasterKeyFromSeed ¶
GetMasterKeyFromSeed derives the master key from a seed using SLIP-0010 This follows the SLIP-0010 specification for Ed25519
func (*KeyData) GetPublicKey ¶
GetPublicKey derives the Ed25519 public key from the key data
type KeyPair ¶
type KeyPair struct {
// contains filtered or unexported fields
}
KeyPair represents an Ed25519 key pair with address
func NewKeyPair ¶
NewKeyPair creates a new KeyPair from a private key The public key and address will be derived lazily
func NewKeyPairFromSeed ¶
NewKeyPairFromSeed creates a KeyPair from a 32-byte seed
func (*KeyPair) Destroy ¶ added in v0.1.3
func (kp *KeyPair) Destroy()
Destroy securely zeros out the private key from memory This method should be called when the KeyPair is no longer needed to prevent the private key from lingering in memory.
IMPORTANT: After calling Destroy(), the KeyPair should not be used for any operations. Attempting to use it will result in undefined behavior.
Example:
kp, _ := NewKeyPairFromSeed(seed) defer kp.Destroy() // Ensure cleanup even if function panics // ... use keypair for signing ...
func (*KeyPair) GetAddress ¶
GetAddress returns the Zenon address, deriving it if necessary
func (*KeyPair) GetPrivateKey ¶
GetPrivateKey returns the private key bytes
func (*KeyPair) GetPublicKey ¶
GetPublicKey returns the public key, deriving it if necessary
type KeyStore ¶
KeyStore represents a hierarchical deterministic wallet
func FromEncryptedFile ¶
func FromEncryptedFile(ef *EncryptedFile, password string) (*KeyStore, error)
FromEncryptedFile decrypts an EncryptedFile to a KeyStore
func NewKeyStoreFromEntropy ¶
NewKeyStoreFromEntropy creates a KeyStore from entropy bytes
func NewKeyStoreFromMnemonic ¶
NewKeyStoreFromMnemonic creates a KeyStore from a BIP39 mnemonic
func NewKeyStoreFromSeed ¶
NewKeyStoreFromSeed creates a KeyStore from a seed
func NewKeyStoreRandom ¶
NewKeyStoreRandom creates a new KeyStore with random entropy (256 bits)
func (*KeyStore) DeriveAddressesByRange ¶
DeriveAddressesByRange derives multiple addresses efficiently in a single operation.
This is useful for:
- Displaying multiple addresses to the user
- Searching for addresses with specific properties
- Generating address pools for services
The range is [left, right) - includes left, excludes right.
Parameters:
- left: Starting account index (inclusive)
- right: Ending account index (exclusive)
Returns a slice of addresses in order, or an error if derivation fails.
Example:
// Derive first 5 addresses (indices 0-4)
addresses, err := keystore.DeriveAddressesByRange(0, 5)
if err != nil {
log.Fatal(err)
}
for i, addr := range addresses {
fmt.Printf("Address %d: %s\n", i, addr)
}
Example output:
Address 0: z1qqjnwjjpnue8xmmpanz6csze6tcmtzzdtfsww7 Address 1: z1qqga8s8rkypgsg5qg2g7rp68nqh3r4lkm54tta ...
func (*KeyStore) FindAddress ¶
FindAddress searches for a specific address within the keystore by trying account indices sequentially until found or maxAccounts is reached.
This is useful when you know an address belongs to this wallet but don't know which account index it uses. Common scenarios:
- Finding the account index for an address shown in a block explorer
- Locating which derivation path was used for a transaction
- Verifying an address belongs to this wallet
Parameters:
- address: The Zenon address to search for
- maxAccounts: Maximum number of indices to check (0 uses DefaultMaxIndex)
Returns FindResponse containing the account index and keypair, or ErrAddressNotFound.
Example:
// Search for address in first 100 accounts
targetAddr := types.ParseAddressPanic("z1qqjnwjjpnue8xmmpanz6csze6tcmtzzdtfsww7")
result, err := keystore.FindAddress(targetAddr, 100)
if err == wallet.ErrAddressNotFound {
fmt.Println("Address not found in this wallet")
} else if err != nil {
log.Fatal(err)
} else {
fmt.Printf("Found at index %d\n", result.Index)
// Use result.KeyPair to sign transactions
}
Performance note: This is a linear search. If maxAccounts is large, it may take time.
func (*KeyStore) GetBaseAddress ¶
GetBaseAddress returns the address at account index 0
func (*KeyStore) GetKeyPair ¶
GetKeyPair derives a keypair at the specified BIP44 account index.
The derivation follows BIP44 path: m/44'/73404'/account'/0'/0' where:
- 44 is the BIP44 standard
- 73404 is Zenon's registered coin type
- account is the index you specify
Each account index generates a unique address from the same mnemonic/seed. This allows deriving multiple addresses from a single backup mnemonic.
Parameters:
- account: Account index (0 for first address, 1 for second, etc.)
Returns a KeyPair that can:
- Get the Zenon address
- Sign transactions
- Access public/private keys
Example:
// Get first address (index 0 - this is the default/base address)
keypair0, err := keystore.GetKeyPair(0)
if err != nil {
log.Fatal(err)
}
addr0, _ := keypair0.GetAddress()
fmt.Println("First address:", addr0)
// Get second address (index 1)
keypair1, _ := keystore.GetKeyPair(1)
addr1, _ := keypair1.GetAddress()
fmt.Println("Second address:", addr1)
Note: GetKeyPair(0) returns the base address - the primary address for this wallet.
func (*KeyStore) ToEncryptedFile ¶
func (ks *KeyStore) ToEncryptedFile(password string, metadata map[string]interface{}) (*EncryptedFile, error)
ToEncryptedFile encrypts the keystore to an EncryptedFile
type KeyStoreManager ¶
type KeyStoreManager struct {
WalletPath string
}
KeyStoreManager manages keystore files in a directory
func NewKeyStoreManager ¶
func NewKeyStoreManager(walletPath string) (*KeyStoreManager, error)
NewKeyStoreManager creates a new keystore manager for managing encrypted wallet files in the specified directory.
The manager handles:
- Creating new wallets with random mnemonics
- Importing wallets from existing mnemonics
- Saving encrypted keystore files
- Loading encrypted keystore files
- Listing all wallets in the directory
Parameters:
- walletPath: Directory path where keystore files will be stored
The directory will be created with 0700 permissions if it doesn't exist, ensuring only the owner can read/write wallet files.
Returns a KeyStoreManager instance or an error if directory creation fails.
Example:
manager, err := wallet.NewKeyStoreManager("./my-wallets")
if err != nil {
log.Fatal(err)
}
// Create a new wallet
keystore, _ := manager.CreateNew("password123", "main-wallet")
fmt.Println("Mnemonic:", keystore.Mnemonic)
func (*KeyStoreManager) CreateFromMnemonic ¶
func (m *KeyStoreManager) CreateFromMnemonic(mnemonic, passphrase, name string) (*KeyStore, error)
CreateFromMnemonic imports a wallet from an existing BIP39 mnemonic phrase and saves it as an encrypted keystore file.
Use this method to:
- Restore a wallet from a backup mnemonic
- Import a wallet from another device
- Migrate from another Zenon wallet application
The mnemonic must be a valid BIP39 phrase (12 or 24 words). The same mnemonic will always generate the same addresses.
Parameters:
- mnemonic: Valid BIP39 mnemonic phrase (space-separated words)
- passphrase: Password to encrypt the keystore (can be different from original)
- name: Filename for the keystore
Returns the imported KeyStore or an error if the mnemonic is invalid.
Example:
manager, _ := wallet.NewKeyStoreManager("./wallets")
mnemonic := "route become dream access impulse price inform obtain engage ski believe awful"
keystore, err := manager.CreateFromMnemonic(mnemonic, "new-password", "imported-wallet")
if err != nil {
log.Fatal(err)
}
// Verify it matches expected address
address, _ := keystore.GetBaseAddress()
fmt.Println("Restored address:", address)
func (*KeyStoreManager) CreateNew ¶
func (m *KeyStoreManager) CreateNew(passphrase, name string) (*KeyStore, error)
CreateNew generates a new wallet with a random BIP39 mnemonic and saves it as an encrypted keystore file.
This is the primary method for creating new Zenon wallets. It:
- Generates a cryptographically secure 24-word BIP39 mnemonic
- Derives the master seed from the mnemonic
- Encrypts the keystore with the provided passphrase using Argon2
- Saves the encrypted keystore to a file
Parameters:
- passphrase: Password to encrypt the keystore (must be non-empty)
- name: Filename for the keystore (e.g., "main-wallet")
Returns the created KeyStore containing the mnemonic and seed, or an error.
IMPORTANT: The mnemonic must be securely backed up. It's the only way to recover the wallet if the keystore file is lost.
Example:
manager, _ := wallet.NewKeyStoreManager("./wallets")
keystore, err := manager.CreateNew("secure-password", "my-wallet")
if err != nil {
log.Fatal(err)
}
// IMPORTANT: Back up this mnemonic securely!
fmt.Println("Mnemonic:", keystore.Mnemonic)
fmt.Println("Base address:", keystore.GetBaseAddress())
func (*KeyStoreManager) FindKeyStore ¶
func (m *KeyStoreManager) FindKeyStore(name string) (string, error)
FindKeyStore searches for a keystore file by name Returns the filename if found, empty string if not found
func (*KeyStoreManager) GetKeystoreInfo ¶
func (m *KeyStoreManager) GetKeystoreInfo(keyStoreFile string) (map[string]interface{}, error)
GetKeystoreInfo reads metadata from a keystore file without decrypting
func (*KeyStoreManager) ListAllKeyStores ¶
func (m *KeyStoreManager) ListAllKeyStores() ([]string, error)
ListAllKeyStores returns all keystore files in the directory
func (*KeyStoreManager) ReadKeyStore ¶
func (m *KeyStoreManager) ReadKeyStore(password string, keyStoreFile string) (*KeyStore, error)
ReadKeyStore loads and decrypts an existing keystore file from the managed directory.
This method:
- Reads the encrypted keystore file
- Parses the JSON structure
- Decrypts using the provided password
- Returns the KeyStore ready for use
Parameters:
- password: Passphrase used when the keystore was created/saved
- keyStoreFile: Filename of the keystore (not full path, just the name)
Returns the decrypted KeyStore or an error if:
- File doesn't exist
- Password is incorrect
- File is corrupted
Example:
manager, _ := wallet.NewKeyStoreManager("./wallets")
keystore, err := manager.ReadKeyStore("my-password", "main-wallet")
if err != nil {
log.Fatal("Failed to load wallet:", err)
}
// Use the keystore
keypair, _ := keystore.GetKeyPair(0)
address, _ := keypair.GetAddress()
fmt.Println("Address:", address)
func (*KeyStoreManager) SaveKeyStore ¶
func (m *KeyStoreManager) SaveKeyStore(store *KeyStore, password, name string) error
SaveKeyStore encrypts a keystore and saves it to a file in the managed directory.
The keystore is encrypted using Argon2 key derivation with the provided password. The file is saved with 0600 permissions (readable/writable only by owner).
Parameters:
- store: KeyStore instance to save
- password: Passphrase for encryption (must be non-empty)
- name: Filename for the keystore
Returns an error if encryption or file writing fails.
Example:
// Create keystore in memory
keystore, _ := wallet.NewKeyStoreRandom()
// Save to file
manager, _ := wallet.NewKeyStoreManager("./wallets")
err := manager.SaveKeyStore(keystore, "secure-password", "backup-wallet")
if err != nil {
log.Fatal(err)
}
type PasswordStrength ¶ added in v0.1.3
type PasswordStrength int
PasswordStrength represents the strength level of a password
const ( // PasswordWeak indicates a password that doesn't meet minimum requirements PasswordWeak PasswordStrength = iota // PasswordModerate indicates a password that meets basic requirements PasswordModerate // PasswordStrong indicates a password with good character diversity PasswordStrong // PasswordVeryStrong indicates a password with excellent character diversity PasswordVeryStrong )
func AnalyzePasswordStrength ¶ added in v0.1.3
func AnalyzePasswordStrength(password string) PasswordStrength
AnalyzePasswordStrength provides a detailed analysis of password strength.
Strength scoring:
- Weak: < 8 chars OR all same character
- Moderate: >= 8 chars with one character class (e.g., all lowercase)
- Strong: >= 8 chars with two character classes (e.g., letters + numbers)
- Very Strong: >= 12 chars with three or more character classes
Character classes considered:
- Lowercase letters (a-z)
- Uppercase letters (A-Z)
- Digits (0-9)
- Special characters (punctuation, symbols, spaces)
Returns the strength level. Use ValidatePassword for simple pass/fail checking.
Example:
strength := AnalyzePasswordStrength("MyP@ssw0rd123")
fmt.Println("Strength:", strength.String()) // Output: "Very Strong"
func (PasswordStrength) String ¶ added in v0.1.3
func (s PasswordStrength) String() string
String returns the string representation of PasswordStrength
type WalletError ¶
type WalletError struct {
Message string
}
WalletError represents a wallet-related error
func (*WalletError) Error ¶
func (e *WalletError) Error() string