Skip to content

Commit

Permalink
add live data to dex onboarding page
Browse files Browse the repository at this point in the history
Signed-off-by: Philemon Ukane <ukanephilemon@gmail.com>
  • Loading branch information
ukane-philemon committed Nov 30, 2023
1 parent bed42b5 commit 6c2b2d7
Show file tree
Hide file tree
Showing 24 changed files with 2,168 additions and 1,062 deletions.
33 changes: 15 additions & 18 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type config struct {
Quiet bool `short:"q" long:"quiet" description:"Easy way to set debuglevel to error"`
SpendUnconfirmed bool `long:"spendunconfirmed" description:"Allow the assetsManager to use transactions that have not been confirmed"`
Profile int `long:"profile" description:"Runs local web server for profiling"`

net libutils.NetworkType
}

func defaultConfig(defaultHomeDir string) config {
Expand Down Expand Up @@ -158,7 +160,6 @@ func loadConfig() (*config, error) {
if _, err := os.Stat(cfg.ConfigFile); os.IsNotExist(err) {
// Non-default config file must exist
if defaultCfg.ConfigFile != cfg.ConfigFile {
fmt.Fprintln(os.Stderr, err)
return loadConfigError(err)
}
// Warn about missing default config file, but continue
Expand All @@ -169,7 +170,6 @@ func loadConfig() (*config, error) {
err = flags.NewIniParser(parser).ParseFile(cfg.ConfigFile)
if err != nil {
if _, ok := err.(*os.PathError); !ok {
fmt.Fprintln(os.Stderr, err)
parser.WriteHelp(os.Stderr)
return loadConfigError(err)
}
Expand Down Expand Up @@ -200,10 +200,7 @@ func loadConfig() (*config, error) {
}
}

str := "%s: failed to create home directory: %v"
err := fmt.Errorf(str, funcName, err)
fmt.Fprintln(os.Stderr, err)
return nil, err
return nil, fmt.Errorf("%s: failed to create home directory: %v", funcName, err)
}

// If a non-default appdata folder is specified, it may be necessary to
Expand All @@ -218,7 +215,6 @@ func loadConfig() (*config, error) {
// succeeds. This prevents the warning on help messages and invalid
// options.
if configFileError != nil {
fmt.Printf("%v\n", configFileError)
return loadConfigError(configFileError)
}

Expand All @@ -230,28 +226,29 @@ func loadConfig() (*config, error) {
if cfg.MaxLogZips < 0 {
cfg.MaxLogZips = 0
}
net := cfg.Network
if net == "testnet" {
net = "testnet3"
}
logDir := filepath.Join(cfg.LogDir, net)
initLogRotator(logDir, cfg.MaxLogZips)

// Special show command to list supported subsystems and exit.
if cfg.DebugLevel == "show" {
fmt.Println("Supported subsystems", supportedSubsystems())
os.Exit(0)
cfg.net = libutils.ToNetworkType(cfg.Network)
if cfg.net == libutils.Unknown {
return loadConfigError(fmt.Errorf("network type is not supported: %s", cfg.Network))
}

// Parse, validate, and set debug log level(s).
if cfg.Quiet {
cfg.DebugLevel = "error"
}

cfg.Network = string(cfg.net)
cfg.LogDir = filepath.Join(cfg.LogDir, cfg.Network)

// Special show command to list supported subsystems and exit.
if cfg.DebugLevel == "show" {
fmt.Println("Supported subsystems", supportedSubsystems())
os.Exit(0)
}

// Parse, validate, and set debug log level(s).
if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil {
err = fmt.Errorf("%s: %v", funcName, err.Error())
fmt.Fprintln(os.Stderr, err)
parser.WriteHelp(os.Stderr)
return loadConfigError(err)
}
Expand Down
127 changes: 127 additions & 0 deletions dexc/core.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package dexc

import (
"context"
"fmt"
"path/filepath"
"sync"
"time"

"decred.org/dcrdex/client/core"
"decred.org/dcrdex/dex"
libutils "github.com/crypto-power/cryptopower/libwallet/utils"
)

// DEXClient represents the Decred DEX client and embeds *core.Core.
type DEXClient struct {
*core.Core

shutdownChan <-chan struct{}
bondBufMtx sync.Mutex
bondBufferCache map[uint32]valStamp
log dex.Logger
}

func (dc *DEXClient) SetDEXPassword(pw []byte, seed []byte) error {
return dc.InitializeClient(pw, seed)
}

func (dc *DEXClient) IsDEXPasswordSet() bool {
return dc.IsInitialized()
}

// WaitForShutdown returns a chan that will be closed if core exits.
func (dc *DEXClient) WaitForShutdown() <-chan struct{} {
return dc.shutdownChan
}

type valStamp struct {
val uint64
stamp time.Time
}

// BondsFeeBuffer is a caching helper for the bonds fee buffer to assist the
// frontend by stabilizing this value for up to 45 minutes from the last request
// for a given asset and because (*Core).BondsFeeBuffer returns a fresh fee
// buffer based on a current (but padded) fee rate estimate. Values for a given
// asset are cached for 45 minutes. These values are meant to provide a sensible
// but well-padded fee buffer for bond transactions now and well into the
// future, so a long expiry is appropriate.
func (dc *DEXClient) BondsFeeBuffer(assetID uint32) (feeBuffer uint64) {
const expiry = 45 * time.Minute
dc.bondBufMtx.Lock()
defer dc.bondBufMtx.Unlock()
if buf, ok := dc.bondBufferCache[assetID]; ok && time.Since(buf.stamp) < expiry {
dc.log.Tracef("Using cached bond fee buffer (%v old): %d",
time.Since(buf.stamp), feeBuffer)
return buf.val
}

feeBuffer, err := dc.Core.BondsFeeBuffer(assetID)
if err != nil {
dc.log.Error("Error fetching bond fee buffer: %v", err)
return 0
}

dc.log.Tracef("Obtained fresh bond fee buffer: %d", feeBuffer)
dc.bondBufferCache[assetID] = valStamp{feeBuffer, time.Now()}

return feeBuffer
}

func Start(ctx context.Context, root, lang, logDir, logLvl string, net libutils.NetworkType, maxLogZips int) (*DEXClient, error) {
dexNet, err := parseDEXNet(net)
if err != nil {
return nil, fmt.Errorf("error parsing network: %w", err)
}

logger, logCloser, err := newDexLogger(logDir, logLvl, maxLogZips)
if err != nil {
return nil, err
}

dbPath := filepath.Join(root, "dexc.db")
cfg := &core.Config{
DBPath: dbPath,
Net: dexNet,
Logger: logger,
Language: lang,
UnlockCoinsOnLogin: false, // TODO: Make configurable.
}

clientCore, err := core.New(cfg)
if err != nil {
return nil, fmt.Errorf("failed to initialize dex core: %w", err)
}

shutdownChan := make(chan struct{})
dc := &DEXClient{
Core: clientCore,
bondBufferCache: make(map[uint32]valStamp),
shutdownChan: shutdownChan,
log: logger,
}

// Use a goroutine to start dex core as it'll block until dex core exits.
go func() {
dc.Run(ctx)
close(shutdownChan)
dc.Core = nil
logCloser()
}()

return dc, nil
}

func parseDEXNet(net libutils.NetworkType) (dex.Network, error) {
switch net {
case libutils.Mainnet:
return dex.Mainnet, nil
case libutils.Testnet:
return dex.Testnet, nil
case libutils.Regression, libutils.Simulation:
return dex.Simnet, nil
default:
return 0, fmt.Errorf("unknown network %s", net)
}
}
37 changes: 37 additions & 0 deletions dexc/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package dexc

import (
"fmt"
"os"
"path/filepath"

"decred.org/dcrdex/dex"
libutils "github.com/crypto-power/cryptopower/libwallet/utils"
"github.com/jrick/logrotate/rotator"
)

var dexLogFile = "dexc.log"

// newDexLogger initializes a new dex.Logger.
func newDexLogger(logDir, lvl string, maxRolls int) (dex.Logger, func(), error) {
err := os.MkdirAll(logDir, libutils.UserFilePerm)
if err != nil {
return nil, nil, fmt.Errorf("failed to create log directory: %w", err)
}

r, err := rotator.New(filepath.Join(logDir, dexLogFile), 32*1024, false, maxRolls)
if err != nil {
return nil, nil, fmt.Errorf("failed to create file rotator: %w", err)
}

logCloser := func() {
r.Close()
}

l, err := dex.NewLoggerMaker(r, lvl, true /* TODO: Make configurable */)
if err != nil {
return nil, nil, fmt.Errorf("Failed to initialize log: %w", err)
}

return l.NewLogger("DEXC"), logCloser, nil
}

0 comments on commit 6c2b2d7

Please sign in to comment.