func (l *Loader) WalletExists() (bool, error) {
	dbPath := filepath.Join(l.dbDirPath, walletDbName)
	return fileExists(dbPath)
}
WalletExists returns whether a file exists at the loader's database path.
This may return an error for unexpected I/O failures.
package wallet
import (
	"errors"
	"os"
	"path/filepath"
	"sync"
	"time"
	"github.com/gcash/bchd/chaincfg"
	"github.com/gcash/bchwallet/internal/prompt"
	"github.com/gcash/bchwallet/waddrmgr"
	"github.com/gcash/bchwallet/walletdb"
)
const (
	walletDbName = "wallet.db"
)
var (
	ErrLoaded = errors.New("wallet already loaded")
	ErrNotLoaded = errors.New("wallet is not loaded")
	ErrExists = errors.New("wallet already exists")
)
type Loader struct {
	callbacks      []func(*Wallet)
	chainParams    *chaincfg.Params
	dbDirPath      string
	noFreelistSync bool
	recoveryWindow uint32
	wallet         *Wallet
	db             walletdb.DB
	mu             sync.Mutex
}
func NewLoader(chainParams *chaincfg.Params, dbDirPath string,
	noFreelistSync bool, recoveryWindow uint32) *Loader {
	waddrmgr.KeyScopeBIP0044.Coin = chainParams.HDCoinType
	waddrmgr.DefaultKeyScopes[0] = waddrmgr.KeyScopeBIP0044
	waddrmgr.ScopeAddrMap = map[waddrmgr.KeyScope]waddrmgr.ScopeAddrSchema{
		waddrmgr.KeyScopeBIP0044: {
			InternalAddrType: waddrmgr.PubKeyHash,
			ExternalAddrType: waddrmgr.PubKeyHash,
		},
	}
	return &Loader{
		chainParams:    chainParams,
		dbDirPath:      dbDirPath,
		noFreelistSync: noFreelistSync,
		recoveryWindow: recoveryWindow,
	}
}
func (l *Loader) onLoaded(w *Wallet, db walletdb.DB) {
	for _, fn := range l.callbacks {
		fn(w)
	}
	l.wallet = w
	l.db = db
	l.callbacks = nil  
}
func (l *Loader) RunAfterLoad(fn func(*Wallet)) {
	l.mu.Lock()
	if l.wallet != nil {
		w := l.wallet
		l.mu.Unlock()
		fn(w)
	} else {
		l.callbacks = append(l.callbacks, fn)
		l.mu.Unlock()
	}
}
func (l *Loader) CreateNewWallet(pubPassphrase, privPassphrase, seed []byte,
	bday time.Time) (*Wallet, error) {
	defer l.mu.Unlock()
	l.mu.Lock()
	if l.wallet != nil {
		return nil, ErrLoaded
	}
	dbPath := filepath.Join(l.dbDirPath, walletDbName)
	exists, err := fileExists(dbPath)
	if err != nil {
		return nil, err
	}
	if exists {
		return nil, ErrExists
	}
	err = os.MkdirAll(l.dbDirPath, 0700)
	if err != nil {
		return nil, err
	}
	db, err := walletdb.Create("bdb", dbPath, l.noFreelistSync)
	if err != nil {
		return nil, err
	}
	err = Create(
		db, pubPassphrase, privPassphrase, seed, l.chainParams, bday,
	)
	if err != nil {
		return nil, err
	}
	w, err := Open(db, pubPassphrase, nil, l.chainParams, l.recoveryWindow)
	if err != nil {
		return nil, err
	}
	w.Start()
	l.onLoaded(w, db)
	return w, nil
}
var errNoConsole = errors.New("db upgrade requires console access for additional input")
func noConsole() ([]byte, error) {
	return nil, errNoConsole
}
func (l *Loader) OpenExistingWallet(pubPassphrase []byte, canConsolePrompt bool) (*Wallet, error) {
	defer l.mu.Unlock()
	l.mu.Lock()
	if l.wallet != nil {
		return nil, ErrLoaded
	}
	if err := checkCreateDir(l.dbDirPath); err != nil {
		return nil, err
	}
	dbPath := filepath.Join(l.dbDirPath, walletDbName)
	db, err := walletdb.Open("bdb", dbPath, l.noFreelistSync)
	if err != nil {
		log.Errorf("Failed to open database: %v", err)
		return nil, err
	}
	var cbs *waddrmgr.OpenCallbacks
	if canConsolePrompt {
		cbs = &waddrmgr.OpenCallbacks{
			ObtainSeed:        prompt.ProvideSeed,
			ObtainPrivatePass: prompt.ProvidePrivPassphrase,
		}
	} else {
		cbs = &waddrmgr.OpenCallbacks{
			ObtainSeed:        noConsole,
			ObtainPrivatePass: noConsole,
		}
	}
	w, err := Open(db, pubPassphrase, cbs, l.chainParams, l.recoveryWindow)
	if err != nil {
		e := db.Close()
		if e != nil {
			log.Warnf("Error closing database: %v", e)
		}
		return nil, err
	}
	w.Start()
	l.onLoaded(w, db)
	return w, nil
}