Skip to content

Commit

Permalink
cgo: Allow getting addrs when not synced
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeGruffins committed Feb 13, 2025
1 parent 82ed8a8 commit e02273a
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 41 deletions.
21 changes: 11 additions & 10 deletions cgo/addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ func currentReceiveAddress(cName *C.char) *C.char {
return errCResponse("wallet with name %q is not loaded", goString(cName))
}

// Don't return an address if not synced!
synced, _ := w.IsSynced(w.ctx)
if !synced {
return errCResponseWithCode(ErrCodeNotSynced, "currentReceiveAddress requested on an unsynced wallet")
if !w.allowUnsyncedAddrs {
synced, _ := w.IsSynced(w.ctx)
if !synced {
return errCResponseWithCode(ErrCodeNotSynced, "currentReceiveAddress requested on an unsynced wallet")
}
}

addr, err := w.CurrentAddress(udb.DefaultAccountNum)
Expand All @@ -39,10 +40,11 @@ func newExternalAddress(cName *C.char) *C.char {
return errCResponse("wallet with name %q is not loaded", goString(cName))
}

// Don't return an address if not synced!
synced, _ := w.IsSynced(w.ctx)
if !synced {
return errCResponseWithCode(ErrCodeNotSynced, "newExternalAddress requested on an unsynced wallet")
if !w.allowUnsyncedAddrs {
synced, _ := w.IsSynced(w.ctx)
if !synced {
return errCResponseWithCode(ErrCodeNotSynced, "newExternalAddress requested on an unsynced wallet")
}
}

_, err := w.NewExternalAddress(w.ctx, udb.DefaultAccountNum)
Expand Down Expand Up @@ -158,9 +160,8 @@ func addresses(cName, cNUsed, cNUnused *C.char) *C.char {
Unused: []string{},
Index: index,
}
// Avoid returning unused addresses if we are not synced.
synced, _ := w.IsSynced(w.ctx)
if synced {
if synced || w.allowUnsyncedAddrs {
res.Unused = unused
}

Expand Down
9 changes: 8 additions & 1 deletion cgo/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,19 +163,26 @@ func listTransactions(cName, cFrom, cCount *C.char) *C.char {
if err != nil {
return errCResponse("unable to get transactions: %v", err)
}
_, blockHeight := w.MainWallet().MainChainTip(w.ctx)
ltRes := make([]*ListTransactionRes, len(res))
for i, ltw := range res {
// Use earliest of receive time or block time if the transaction is mined.
receiveTime := ltw.TimeReceived
if ltw.BlockTime < ltw.TimeReceived {
if ltw.BlockTime != 0 && ltw.BlockTime < ltw.TimeReceived {
receiveTime = ltw.BlockTime
}

var height int64
if ltw.Confirmations > 0 {
height = int64(blockHeight) - ltw.Confirmations + 1
}

lt := &ListTransactionRes{
Address: ltw.Address,
Amount: ltw.Amount,
Category: ltw.Category,
Confirmations: ltw.Confirmations,
Height: height,
Fee: ltw.Fee,
Time: receiveTime,
TxID: ltw.TxID,
Expand Down
14 changes: 14 additions & 0 deletions cgo/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ type ListTransactionRes struct {
Amount float64 `json:"amount"`
Category string `json:"category"`
Confirmations int64 `json:"confirmations"`
Height int64 `json:"height"`
Fee *float64 `json:"fee,omitempty"`
Time int64 `json:"time"`
TxID string `json:"txid"`
Expand All @@ -153,3 +154,16 @@ type AddressesRes struct {
Unused []string `json:"unused"`
Index uint32 `json:"index"`
}

type Config struct {
Name string `json:"name"`
// Allow getting unused addresses when not synced.
AllowUnsyncedAddrs bool `json:"unsyncedaddrs"`
Net string `json:"net"`
DataDir string `json:"datadir"`
// Only needed during creation.
Pass string `json:"pass"`
Mnemonic string `json:"mnemonic"`
// Only needed during watching only creation.
PubKey string `json:"pubkey"`
}
81 changes: 51 additions & 30 deletions cgo/walletloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,29 @@ type wallet struct {
syncStatusMtx sync.RWMutex
syncStatusCode SyncStatusCode
targetHeight, cfiltersHeight, headersHeight, rescanHeight, numPeers int
rescanning bool
rescanning, allowUnsyncedAddrs bool
}

//export createWallet
func createWallet(cName, cDataDir, cNet, cPass, cMnemonic *C.char) *C.char {
func createWallet(cConfig *C.char) *C.char {
walletsMtx.Lock()
defer walletsMtx.Unlock()
if !initialized {
return errCResponse("libwallet is not initialized")
}

name := goString(cName)
configJSON := goString(cConfig)
var cfg Config
if err := json.Unmarshal([]byte(configJSON), &cfg); err != nil {
return errCResponse("malformed config: %v", err)
}

name := cfg.Name
if _, exists := wallets[name]; exists {
return errCResponse("wallet already exists with name: %q", name)
}

network, err := asset.NetFromString(goString(cNet))
network, err := asset.NetFromString(cfg.Net)
if err != nil {
return errCResponse("%v", err)
}
Expand All @@ -51,17 +57,16 @@ func createWallet(cName, cDataDir, cNet, cPass, cMnemonic *C.char) *C.char {
params := asset.CreateWalletParams{
OpenWalletParams: asset.OpenWalletParams{
Net: network,
DataDir: goString(cDataDir),
DataDir: cfg.DataDir,
DbDriver: "bdb", // use badgerdb for mobile!
Logger: logger,
},
Pass: []byte(goString(cPass)),
Pass: []byte(cfg.Pass),
}

mnemonicStr := goString(cMnemonic)
var recoveryConfig *asset.RecoveryCfg
if mnemonicStr != "" {
seed, birthday, err := mnemonic.DecodeMnemonic(mnemonicStr)
if cfg.Mnemonic != "" {
seed, birthday, err := mnemonic.DecodeMnemonic(cfg.Mnemonic)
if err != nil {
return errCResponse("unable to decode wallet mnemonic: %v", err)
}
Expand All @@ -70,6 +75,7 @@ func createWallet(cName, cDataDir, cNet, cPass, cMnemonic *C.char) *C.char {
Birthday: birthday,
}
}

walletCtx, cancel := context.WithCancel(mainCtx)

w, err := dcr.CreateWallet(walletCtx, params, recoveryConfig)
Expand All @@ -79,28 +85,35 @@ func createWallet(cName, cDataDir, cNet, cPass, cMnemonic *C.char) *C.char {
}

wallets[name] = &wallet{
Wallet: w,
log: logger,
ctx: walletCtx,
cancelCtx: cancel,
Wallet: w,
log: logger,
ctx: walletCtx,
cancelCtx: cancel,
allowUnsyncedAddrs: cfg.AllowUnsyncedAddrs,
}
return successCResponse("wallet created")
}

//export createWatchOnlyWallet
func createWatchOnlyWallet(cName, cDataDir, cNet, cPub *C.char) *C.char {
func createWatchOnlyWallet(cConfig *C.char) *C.char {
walletsMtx.Lock()
defer walletsMtx.Unlock()
if !initialized {
return errCResponse("libwallet is not initialized")
}

name := goString(cName)
configJSON := goString(cConfig)
var cfg Config
if err := json.Unmarshal([]byte(configJSON), &cfg); err != nil {
return errCResponse("malformed config: %v", err)
}

name := cfg.Name
if _, exists := wallets[name]; exists {
return errCResponse("wallet already exists with name: %q", name)
}

network, err := asset.NetFromString(goString(cNet))
network, err := asset.NetFromString(cfg.Net)
if err != nil {
return errCResponse("%v", err)
}
Expand All @@ -110,43 +123,50 @@ func createWatchOnlyWallet(cName, cDataDir, cNet, cPub *C.char) *C.char {
params := asset.CreateWalletParams{
OpenWalletParams: asset.OpenWalletParams{
Net: network,
DataDir: goString(cDataDir),
DataDir: cfg.DataDir,
DbDriver: "bdb",
Logger: logger,
},
}

walletCtx, cancel := context.WithCancel(mainCtx)

w, err := dcr.CreateWatchOnlyWallet(walletCtx, goString(cPub), params)
w, err := dcr.CreateWatchOnlyWallet(walletCtx, cfg.PubKey, params)
if err != nil {
cancel()
return errCResponse("%v", err)
}

wallets[name] = &wallet{
Wallet: w,
log: logger,
ctx: walletCtx,
cancelCtx: cancel,
Wallet: w,
log: logger,
ctx: walletCtx,
cancelCtx: cancel,
allowUnsyncedAddrs: cfg.AllowUnsyncedAddrs,
}
return successCResponse("wallet created")
}

//export loadWallet
func loadWallet(cName, cDataDir, cNet *C.char) *C.char {
func loadWallet(cConfig *C.char) *C.char {
walletsMtx.Lock()
defer walletsMtx.Unlock()
if !initialized {
return errCResponse("libwallet is not initialized")
}

name := goString(cName)
configJSON := goString(cConfig)
var cfg Config
if err := json.Unmarshal([]byte(configJSON), &cfg); err != nil {
return errCResponse("malformed config: %v", err)
}

name := cfg.Name
if _, exists := wallets[name]; exists {
return successCResponse("wallet already loaded") // not an error, already loaded
}

network, err := asset.NetFromString(goString(cNet))
network, err := asset.NetFromString(cfg.Net)
if err != nil {
return errCResponse("%v", err)
}
Expand All @@ -155,7 +175,7 @@ func loadWallet(cName, cDataDir, cNet *C.char) *C.char {
logger.SetLevel(slog.LevelTrace)
params := asset.OpenWalletParams{
Net: network,
DataDir: goString(cDataDir),
DataDir: cfg.DataDir,
DbDriver: "bdb", // use badgerdb for mobile!
Logger: logger,
}
Expand All @@ -174,10 +194,11 @@ func loadWallet(cName, cDataDir, cNet *C.char) *C.char {
}

wallets[name] = &wallet{
Wallet: w,
log: logger,
ctx: walletCtx,
cancelCtx: cancel,
Wallet: w,
log: logger,
ctx: walletCtx,
cancelCtx: cancel,
allowUnsyncedAddrs: cfg.AllowUnsyncedAddrs,
}
return successCResponse("wallet %q loaded", name)
}
Expand Down

0 comments on commit e02273a

Please sign in to comment.