-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
36de1eb
commit 0a6d9b4
Showing
6 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package main | ||
|
||
import "C" | ||
import "decred.org/dcrwallet/v3/wallet/udb" | ||
|
||
//export currentReceiveAddress | ||
func currentReceiveAddress(walletName *C.char) *C.char { | ||
w, ok := loadedWallet(walletName) | ||
if !ok { | ||
return nil | ||
} | ||
|
||
// Don't return an address if not synced! | ||
if !w.IsSynced() { | ||
w.log.Trace("currentReceiveAddress requested on an unsynced wallet") | ||
return nil | ||
} | ||
|
||
addr, err := w.CurrentAddress(udb.DefaultAccountNum) | ||
if err != nil { | ||
w.log.Errorf("w.CurrentAddress error: %v", err) | ||
return nil | ||
} | ||
|
||
return cString(addr.String()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// A pacakge that exports Decred wallet functionalities as go code that can be | ||
// compiled into a c-shared libary. Must be a main package, with an empty main | ||
// function. And functions to be exported must have an "//export {fnName}" | ||
// comment. | ||
// | ||
// Build cmd: go build -buildmode=c-archive -o {path_to_generated_library} ./cgo | ||
// E.g. go build -buildmode=c-archive -o ./build/libdcrwallet.a ./cgo. | ||
|
||
package main | ||
|
||
import "C" | ||
import ( | ||
"context" | ||
"sync" | ||
|
||
"github.com/decred/slog" | ||
"github.com/itswisdomagain/libwallet/asset/dcr" | ||
"github.com/itswisdomagain/libwallet/assetlog" | ||
) | ||
|
||
var ( | ||
ctx context.Context | ||
cancelCtx context.CancelFunc | ||
wg sync.WaitGroup | ||
|
||
logBackend *parentLogger | ||
log slog.Logger | ||
|
||
walletsMtx sync.RWMutex | ||
wallets map[string]*wallet | ||
) | ||
|
||
//export initialize | ||
func initialize(cLogDir *C.char) *C.char { | ||
walletsMtx.Lock() | ||
defer walletsMtx.Unlock() | ||
if wallets != nil { | ||
return cString("duplicate initialization") | ||
} | ||
|
||
logDir := goString(cLogDir) | ||
logSpinner, err := assetlog.NewRotator(logDir, "dcrwallet.log") | ||
if err != nil { | ||
return cStringF("error initializing log rotator: %v", err) | ||
} | ||
|
||
logBackend = newParentLogger(logSpinner) | ||
err = dcr.InitGlobalLogging(logDir, logBackend) | ||
if err != nil { | ||
return cStringF("error initializing logger for external pkgs: %v", err) | ||
} | ||
|
||
log = logBackend.SubLogger("[APP]") | ||
log.SetLevel(slog.LevelTrace) | ||
|
||
ctx, cancelCtx = context.WithCancel(context.Background()) | ||
wallets = make(map[string]*wallet) | ||
|
||
log.Info("libwallet cgo initialized") | ||
return nil | ||
} | ||
|
||
//export shutdown | ||
func shutdown() { | ||
walletsMtx.Lock() | ||
for _, wallet := range wallets { | ||
if err := wallet.CloseWallet(); err != nil { | ||
wallet.log.Errorf("close wallet error: %v", err) | ||
} | ||
} | ||
wallets = nil // cannot be reused unless initialize is called again. | ||
walletsMtx.Unlock() | ||
|
||
// Stop all remaining background processes and wait for them to stop. | ||
cancelCtx() | ||
wg.Wait() | ||
|
||
// Close the logger backend as the last step. | ||
logBackend.Close() | ||
} | ||
|
||
func main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/decred/slog" | ||
"github.com/jrick/logrotate/rotator" | ||
) | ||
|
||
type parentLogger struct { | ||
*slog.Backend | ||
rotator *rotator.Rotator | ||
} | ||
|
||
func newParentLogger(rotator *rotator.Rotator) *parentLogger { | ||
return &parentLogger{ | ||
Backend: slog.NewBackend(rotator), | ||
rotator: rotator, | ||
} | ||
} | ||
|
||
func (pl *parentLogger) SubLogger(name string) slog.Logger { | ||
return pl.Logger(name) | ||
} | ||
|
||
func (pl *parentLogger) Close() error { | ||
return pl.rotator.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package main | ||
|
||
import "C" | ||
import ( | ||
"fmt" | ||
) | ||
|
||
func loadedWallet(cName *C.char) (*wallet, bool) { | ||
walletsMtx.Lock() | ||
defer walletsMtx.Unlock() | ||
|
||
name := goString(cName) | ||
w, ok := wallets[name] | ||
if !ok { | ||
log.Debugf("attempted to use an unloaded wallet %q", name) | ||
} | ||
return w, ok | ||
} | ||
|
||
func cString(str string) *C.char { | ||
return C.CString(str) | ||
} | ||
|
||
func cStringF(format string, a ...any) *C.char { | ||
return C.CString(fmt.Sprintf(format, a...)) | ||
} | ||
|
||
func cError(err error) *C.char { | ||
return C.CString(err.Error()) | ||
} | ||
|
||
func goString(cstr *C.char) string { | ||
return C.GoString(cstr) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package main | ||
|
||
import "C" | ||
import ( | ||
"encoding/json" | ||
|
||
"github.com/decred/slog" | ||
"github.com/itswisdomagain/libwallet/asset" | ||
"github.com/itswisdomagain/libwallet/asset/dcr" | ||
) | ||
|
||
const emptyJsonObject = "{}" | ||
|
||
type wallet struct { | ||
*dcr.Wallet | ||
log slog.Logger | ||
} | ||
|
||
//export createWallet | ||
func createWallet(cName, cDataDir, cNet, cPass *C.char) *C.char { | ||
walletsMtx.Lock() | ||
defer walletsMtx.Unlock() | ||
if wallets == nil { | ||
return cString("libwallet is not initialized") | ||
} | ||
|
||
name := goString(cName) | ||
if _, exists := wallets[name]; exists { | ||
return cStringF("wallet already exists with name: %q", name) | ||
} | ||
|
||
network, err := asset.NetFromString(goString(cNet)) | ||
if err != nil { | ||
return cError(err) | ||
} | ||
|
||
logger := logBackend.Logger("[" + name + "]") | ||
logger.SetLevel(slog.LevelTrace) | ||
params := asset.CreateWalletParams{ | ||
OpenWalletParams: asset.OpenWalletParams{ | ||
Net: network, | ||
DataDir: goString(cDataDir), | ||
DbDriver: "bdb", // use badgerdb for mobile! | ||
Logger: logger, | ||
}, | ||
Pass: []byte(goString(cPass)), | ||
} | ||
w, err := dcr.CreateWallet(ctx, params, nil) | ||
if err != nil { | ||
return cError(err) | ||
} | ||
|
||
wallets[name] = &wallet{ | ||
Wallet: w, | ||
log: logger, | ||
} | ||
return nil | ||
} | ||
|
||
//export loadWallet | ||
func loadWallet(cName, cDataDir, cNet *C.char) *C.char { | ||
walletsMtx.Lock() | ||
defer walletsMtx.Unlock() | ||
if wallets == nil { | ||
return cString("libwallet is not initialized") | ||
} | ||
|
||
name := goString(cName) | ||
if _, exists := wallets[name]; exists { | ||
return nil // not an error, already loaded | ||
} | ||
|
||
network, err := asset.NetFromString(goString(cNet)) | ||
if err != nil { | ||
return cError(err) | ||
} | ||
|
||
logger := logBackend.Logger("[" + name + "]") | ||
logger.SetLevel(slog.LevelTrace) | ||
params := asset.OpenWalletParams{ | ||
Net: network, | ||
DataDir: goString(cDataDir), | ||
DbDriver: "bdb", // use badgerdb for mobile! | ||
Logger: logger, | ||
} | ||
w, err := dcr.LoadWallet(ctx, params) | ||
if err != nil { | ||
return cError(err) | ||
} | ||
|
||
if err = w.OpenWallet(ctx); err != nil { | ||
return cError(err) | ||
} | ||
|
||
wallets[name] = &wallet{ | ||
Wallet: w, | ||
log: logger, | ||
} | ||
return nil | ||
} | ||
|
||
//export walletSeed | ||
func walletSeed(name, pass *C.char) *C.char { | ||
w, ok := loadedWallet(name) | ||
if !ok { | ||
return nil | ||
} | ||
|
||
seed, err := w.DecryptSeed([]byte(goString(pass))) | ||
if err != nil { | ||
w.log.Errorf("w.RevealSeed error: %v", err) | ||
return nil | ||
} | ||
|
||
return cString(seed) | ||
} | ||
|
||
//export walletBalance | ||
func walletBalance(name *C.char) *C.char { | ||
w, ok := loadedWallet(name) | ||
if !ok { | ||
return cString(emptyJsonObject) | ||
} | ||
|
||
balMap := map[string]float64{ | ||
"confirmed": 0, | ||
"unconfirmed": 0, | ||
} | ||
|
||
bals, err := w.AccountBalances(ctx, 0) | ||
if err != nil { | ||
w.log.Errorf("w.AccountBalances error: %v", err) | ||
} else { | ||
for _, bal := range bals { | ||
balMap["confirmed"] += bal.Spendable.ToCoin() | ||
balMap["unconfirmed"] += bal.Total.ToCoin() - bal.Spendable.ToCoin() | ||
} | ||
} | ||
|
||
balJson, err := json.Marshal(balMap) | ||
if err != nil { | ||
w.log.Errorf("marshal balMap error: %v", err) | ||
return cString(emptyJsonObject) | ||
} | ||
|
||
return cString(string(balJson)) | ||
} |