decred.org/dcrdex@v1.0.3/client/asset/dcr/config.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package dcr
     5  
     6  import (
     7  	"fmt"
     8  	"path/filepath"
     9  
    10  	"decred.org/dcrdex/dex"
    11  	"decred.org/dcrdex/dex/config"
    12  	"github.com/decred/dcrd/chaincfg/v3"
    13  	"github.com/decred/dcrd/dcrutil/v4"
    14  )
    15  
    16  const (
    17  	defaultMainnet  = "localhost:9110"
    18  	defaultTestnet3 = "localhost:19110"
    19  	defaultSimnet   = "localhost:19557"
    20  
    21  	// May 26, 2022
    22  	defaultWalletBirthdayUnix = 1653599386
    23  )
    24  
    25  var (
    26  	// A global *chaincfg.Params will be set if loadConfig completes without
    27  	// error.
    28  	dcrwHomeDir       = dcrutil.AppDataDir("dcrwallet", false)
    29  	defaultRPCCert    = filepath.Join(dcrwHomeDir, "rpc.cert")
    30  	defaultConfigPath = filepath.Join(dcrwHomeDir, "dcrwallet.conf")
    31  )
    32  
    33  type walletConfig struct {
    34  	UseSplitTx       bool    `ini:"txsplit"`
    35  	FallbackFeeRate  float64 `ini:"fallbackfee"`
    36  	FeeRateLimit     float64 `ini:"feeratelimit"`
    37  	RedeemConfTarget uint64  `ini:"redeemconftarget"`
    38  	ActivelyUsed     bool    `ini:"special_activelyUsed"` //injected by core
    39  	ApiFeeFallback   bool    `ini:"apifeefallback"`
    40  	GapLimit         uint32  `ini:"gaplimit"`
    41  }
    42  
    43  type rpcConfig struct {
    44  	PrimaryAccount string `ini:"account"`
    45  	UnmixedAccount string `ini:"unmixedaccount"`
    46  	TradingAccount string `ini:"tradingaccount"`
    47  	RPCUser        string `ini:"username"`
    48  	RPCPass        string `ini:"password"`
    49  	RPCListen      string `ini:"rpclisten"`
    50  	RPCCert        string `ini:"rpccert"`
    51  }
    52  
    53  func loadRPCConfig(settings map[string]string, network dex.Network) (*rpcConfig, *chaincfg.Params, error) {
    54  	cfg := new(rpcConfig)
    55  	chainParams, err := loadConfig(settings, network, cfg)
    56  	if err != nil {
    57  		return nil, nil, err
    58  	}
    59  
    60  	var defaultServer string
    61  	switch network {
    62  	case dex.Simnet:
    63  		defaultServer = defaultSimnet
    64  	case dex.Testnet:
    65  		defaultServer = defaultTestnet3
    66  	case dex.Mainnet:
    67  		defaultServer = defaultMainnet
    68  	default:
    69  		return nil, nil, fmt.Errorf("unknown network ID: %d", uint8(network))
    70  	}
    71  	if cfg.RPCListen == "" {
    72  		cfg.RPCListen = defaultServer
    73  	}
    74  	if cfg.RPCCert == "" {
    75  		cfg.RPCCert = defaultRPCCert
    76  	} else {
    77  		cfg.RPCCert = dex.CleanAndExpandPath(cfg.RPCCert)
    78  	}
    79  
    80  	if cfg.PrimaryAccount == "" {
    81  		cfg.PrimaryAccount = defaultAccountName
    82  	}
    83  
    84  	// Both UnmixedAccount and TradingAccount must be provided if primary
    85  	// account is a mixed account. Providing one but not the other is bad
    86  	// configuration. If set, the account names will be validated on Connect.
    87  	if (cfg.UnmixedAccount == "") != (cfg.TradingAccount == "") {
    88  		return nil, nil, fmt.Errorf("'Change Account Name' and 'Temporary Trading Account' MUST "+
    89  			"be set to treat %[1]q as a mixed account. If %[1]q is not a mixed account, values "+
    90  			"should NOT be set for 'Change Account Name' and 'Temporary Trading Account'",
    91  			cfg.PrimaryAccount)
    92  	}
    93  	if cfg.UnmixedAccount != "" {
    94  		switch {
    95  		case cfg.PrimaryAccount == cfg.UnmixedAccount:
    96  			return nil, nil, fmt.Errorf("Primary Account should not be the same as Change Account")
    97  		case cfg.PrimaryAccount == cfg.TradingAccount:
    98  			return nil, nil, fmt.Errorf("Primary Account should not be the same as Temporary Trading Account")
    99  		case cfg.TradingAccount == cfg.UnmixedAccount:
   100  			return nil, nil, fmt.Errorf("Temporary Trading Account should not be the same as Change Account")
   101  		}
   102  	}
   103  
   104  	return cfg, chainParams, nil
   105  }
   106  
   107  // loadConfig loads the Config from a settings map. If no values are found for
   108  // RPCListen or RPCCert in the specified file, default values will be used. If
   109  // there is no error, the module-level chainParams variable will be set
   110  // appropriately for the network.
   111  func loadConfig(settings map[string]string, network dex.Network, cfg any) (*chaincfg.Params, error) {
   112  	if err := config.Unmapify(settings, cfg); err != nil {
   113  		return nil, fmt.Errorf("error parsing config: %w", err)
   114  	}
   115  
   116  	return parseChainParams(network)
   117  }
   118  
   119  func parseChainParams(network dex.Network) (*chaincfg.Params, error) {
   120  	// Get network settings. Zero value is mainnet, but unknown non-zero cfg.Net
   121  	// is an error.
   122  	switch network {
   123  	case dex.Simnet:
   124  		return chaincfg.SimNetParams(), nil
   125  	case dex.Testnet:
   126  		return chaincfg.TestNet3Params(), nil
   127  	case dex.Mainnet:
   128  		return chaincfg.MainNetParams(), nil
   129  	default:
   130  		return nil, fmt.Errorf("unknown network ID: %d", uint8(network))
   131  	}
   132  }