diff --git a/dexc/core.go b/dexc/core.go index dac856267..f477039c0 100644 --- a/dexc/core.go +++ b/dexc/core.go @@ -18,14 +18,18 @@ const ( // CustomDexWalletType is a keyword that identifies a custom Cryptopower // wallet used by the DEX client. CustomDexWalletType = "cryptopowerwallet" - // DexWalletIDConfigKey is the key that holds the wallet ID value in the + // WalletIDConfigKey is the key that holds the wallet ID value in the // settings map used to connect an existing Cryptopower wallet to the DEX // client. - DexWalletIDConfigKey = "walletid" - // DexDcrWalletAccountNameConfigKey is the key that holds the wallet account - // values in the settings map used to connect an existing dcr wallet to the + WalletIDConfigKey = "walletid" + // WalletAccountNameConfigKey is the key that holds the wallet account name + // in the settings map used to connect an existing Cryptopower wallet to the // DEX client. - DexDcrWalletAccountNameConfigKey = "account" + WalletAccountNameConfigKey = "account" + // WalletAccountNumberConfigKey is the key that holds the wallet account + // number in the settings map used to connect an existing Cryptopower wallet + // to the DEX client. + WalletAccountNumberConfigKey = "accountnumber" ) // DEXClient represents the Decred DEX client and embeds *core.Core. diff --git a/libwallet/assets/btc/dex-wallet.go b/libwallet/assets/btc/dex-wallet.go index e00b560ec..93c0c7941 100644 --- a/libwallet/assets/btc/dex-wallet.go +++ b/libwallet/assets/btc/dex-wallet.go @@ -16,34 +16,58 @@ import ( dexbtc "decred.org/dcrdex/client/asset/btc" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/gcs" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcwallet/chain" "github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/wallet" "github.com/btcsuite/btcwallet/wallet/txauthor" "github.com/btcsuite/btcwallet/wtxmgr" + "github.com/lightninglabs/neutrino" + "github.com/lightninglabs/neutrino/headerfs" ) // DEXWallet wraps *wallet.Wallet and implements dexbtc.BTCWallet. type DEXWallet struct { - *wallet.Wallet // Implements most of dexbtc.BTCWallet - asset *Asset + *wallet.Wallet + acct dexbtc.XCWalletAccount + spvService *btcChainService } var _ dexbtc.BTCWallet = (*DEXWallet)(nil) // NewDEXWallet returns a new *DEXWallet. -func NewDEXWallet(asset *Asset) *DEXWallet { +func NewDEXWallet(acct dexbtc.XCWalletAccount, w *wallet.Wallet, nc *chain.NeutrinoClient) *DEXWallet { return &DEXWallet{ - Wallet: asset.Internal().BTC, - asset: asset, + Wallet: w, + acct: acct, + spvService: &btcChainService{ + NeutrinoClient: nc, + }, } } // The below methods are not implemented by *wallet.Wallet, so must be // implemented by the BTCWallet implementation. +func (dw *DEXWallet) Start() (dexbtc.SPVService, error) { + return dw.spvService, nil +} + +func (dw *DEXWallet) Birthday() time.Time { + return dw.Manager.Birthday() +} + +func (dw *DEXWallet) SyncedTo() waddrmgr.BlockStamp { + return dw.Wallet.Manager.SyncedTo() +} + +func (dw *DEXWallet) AccountInfo() dexbtc.XCWalletAccount { + return dw.acct +} + func (dw *DEXWallet) WalletTransaction(txHash *chainhash.Hash) (*wtxmgr.TxDetails, error) { details, err := wallet.UnstableAPI(dw.Wallet).TxDetails(txHash) if err != nil { @@ -56,10 +80,6 @@ func (dw *DEXWallet) WalletTransaction(txHash *chainhash.Hash) (*wtxmgr.TxDetail return details, nil } -func (dw *DEXWallet) SyncedTo() waddrmgr.BlockStamp { - return dw.Wallet.Manager.SyncedTo() -} - func (dw *DEXWallet) SignTx(tx *wire.MsgTx) error { var prevPkScripts [][]byte var inputValues []btcutil.Amount @@ -104,28 +124,8 @@ func (dw *DEXWallet) BlockNotifications(ctx context.Context) <-chan *dexbtc.Bloc return ch } -func (dw *DEXWallet) RescanAsync() error { - return dw.asset.rescanAsync() -} - -func (dw *DEXWallet) ForceRescan() { - dw.asset.forceRescan() -} - -func (dw *DEXWallet) Start() (dexbtc.SPVService, error) { - return dw.asset.chainClient, nil -} - -func (dw *DEXWallet) Reconfigure(*asset.WalletConfig, string) (bool, error) { - return false, errors.New("Reconfigure not supported for Cyptopower btc wallet") -} - -func (dw *DEXWallet) Birthday() time.Time { - return dw.Manager.Birthday() -} - func (dw *DEXWallet) Peers() ([]*asset.WalletPeer, error) { - peers := dw.asset.chainClient.CS.Peers() + peers := dw.spvService.CS.Peers() var walletPeers []*asset.WalletPeer for i := range peers { p := peers[i] @@ -139,13 +139,63 @@ func (dw *DEXWallet) Peers() ([]*asset.WalletPeer, error) { } func (dw *DEXWallet) AddPeer(address string) error { - dw.asset.SetSpecificPeer(address) - return nil + return errors.New("AddPeer not implemented by DEX wallet") } func (dw *DEXWallet) RemovePeer(address string) error { - dw.asset.RemoveSpecificPeer(address) - return nil + return errors.New("RemovePeer not implemented by DEX wallet") +} + +func (dw *DEXWallet) RescanAsync() error { + return errors.New("RescanAsync not implemented for Cyptopower btc wallet") +} + +func (dw *DEXWallet) ForceRescan() {} + +func (dw *DEXWallet) Reconfigure(*asset.WalletConfig, string) (bool, error) { + return false, errors.New("Reconfigure not supported for Cyptopower btc wallet") +} + +// btcChainService wraps *chain.NeutrinoClient in order to translate the +// neutrino.ServerPeer to the SPVPeer interface type as required by the dex btc +// pkg. +type btcChainService struct { + *chain.NeutrinoClient +} + +var _ dexbtc.SPVService = (*btcChainService)(nil) + +func (s *btcChainService) Peers() []dexbtc.SPVPeer { + rawPeers := s.CS.Peers() + peers := make([]dexbtc.SPVPeer, 0, len(rawPeers)) + for _, p := range rawPeers { + peers = append(peers, p) + } + return peers +} + +func (s *btcChainService) AddPeer(addr string) error { + return s.CS.ConnectNode(addr, true) +} + +func (s *btcChainService) RemovePeer(addr string) error { + return s.CS.RemoveNodeByAddr(addr) +} + +func (s *btcChainService) BestBlock() (*headerfs.BlockStamp, error) { + return s.CS.BestBlock() +} + +func (s *btcChainService) GetBlock(blockHash chainhash.Hash, options ...neutrino.QueryOption) (*btcutil.Block, error) { + return s.CS.GetBlock(blockHash, options...) +} + +func (s *btcChainService) GetCFilter(blockHash chainhash.Hash, filterType wire.FilterType, options ...neutrino.QueryOption) (*gcs.Filter, error) { + return s.NeutrinoClient.CS.GetCFilter(blockHash, filterType, options...) +} + +func (s *btcChainService) Stop() error { + return s.CS.Stop() } // secretSource is used to locate keys and redemption scripts while signing a diff --git a/libwallet/assets/btc/rescan.go b/libwallet/assets/btc/rescan.go index a0602f2d1..0f9d5ea37 100644 --- a/libwallet/assets/btc/rescan.go +++ b/libwallet/assets/btc/rescan.go @@ -159,7 +159,7 @@ func (asset *Asset) rescanAsync() error { } log.Infof("Synchronizing wallet (%s) with network...", asset.GetWalletName()) - asset.Internal().BTC.SynchronizeRPC(asset.chainClient.NeutrinoClient) + asset.Internal().BTC.SynchronizeRPC(asset.chainClient) return nil } @@ -379,7 +379,7 @@ func (asset *Asset) getblockStamp(height int32) (*waddrmgr.BlockStamp, error) { return nil, fmt.Errorf("invalid block height provided: Error: %v", err) } - block, err := asset.chainClient.NeutrinoClient.GetBlock(startHash) + block, err := asset.chainClient.GetBlock(startHash) if err != nil { return nil, fmt.Errorf("invalid block hash provided: Error: %v", err) } diff --git a/libwallet/assets/btc/sync.go b/libwallet/assets/btc/sync.go index 86d63d526..763baad85 100644 --- a/libwallet/assets/btc/sync.go +++ b/libwallet/assets/btc/sync.go @@ -343,9 +343,7 @@ func (asset *Asset) prepareChain() error { return err } - asset.chainClient = &btcChainService{ - NeutrinoClient: chain.NewNeutrinoClient(asset.chainParams, chainService), - } + asset.chainClient = chain.NewNeutrinoClient(asset.chainParams, chainService) return nil } @@ -512,7 +510,7 @@ func (asset *Asset) startSync() error { log.Infof("Synchronizing wallet (%s) with network...", asset.GetWalletName()) // Initializes the goroutines handling chain notifications, rescan progress and handlers. - asset.Internal().BTC.SynchronizeRPC(asset.chainClient.NeutrinoClient) + asset.Internal().BTC.SynchronizeRPC(asset.chainClient) select { // Wait for 5 seconds so that all goroutines initialized in SynchronizeRPC() diff --git a/libwallet/assets/btc/wallet.go b/libwallet/assets/btc/wallet.go index c4dbf1ad4..43891eeee 100644 --- a/libwallet/assets/btc/wallet.go +++ b/libwallet/assets/btc/wallet.go @@ -9,7 +9,6 @@ import ( "sync" "time" - dexbtc "decred.org/dcrdex/client/asset/btc" "decred.org/dcrwallet/v3/errors" "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/btcutil" @@ -38,7 +37,7 @@ var _ sharedW.Asset = (*Asset)(nil) type Asset struct { *sharedW.Wallet - chainClient *btcChainService + chainClient *chain.NeutrinoClient chainParams *chaincfg.Params TxAuthoredInfo *TxAuthor @@ -74,47 +73,19 @@ const ( defaultDBTimeout = time.Duration(100) ) -// btcChainService wraps *chain.NeutrinoClient in order to translate the -// neutrino.ServerPeer to the SPVPeer interface type as required by the dex btc -// pkg. -type btcChainService struct { - *chain.NeutrinoClient +// neutrinoService is satisfied by *neutrino.ChainService. +type neutrinoService interface { + GetBlockHash(int64) (*chainhash.Hash, error) + BestBlock() (*headerfs.BlockStamp, error) + Peers() []*neutrino.ServerPeer + GetBlockHeight(hash *chainhash.Hash) (int32, error) + GetBlockHeader(*chainhash.Hash) (*wire.BlockHeader, error) + GetCFilter(blockHash chainhash.Hash, filterType wire.FilterType, options ...neutrino.QueryOption) (*gcs.Filter, error) + GetBlock(blockHash chainhash.Hash, options ...neutrino.QueryOption) (*btcutil.Block, error) + Stop() error } -func (s *btcChainService) Peers() []dexbtc.SPVPeer { - rawPeers := s.CS.Peers() - peers := make([]dexbtc.SPVPeer, 0, len(rawPeers)) - for _, p := range rawPeers { - peers = append(peers, p) - } - return peers -} - -func (s *btcChainService) AddPeer(addr string) error { - return s.CS.ConnectNode(addr, true) -} - -func (s *btcChainService) RemovePeer(addr string) error { - return s.CS.RemoveNodeByAddr(addr) -} - -func (s *btcChainService) BestBlock() (*headerfs.BlockStamp, error) { - return s.NeutrinoClient.CS.BestBlock() -} - -func (s *btcChainService) GetBlock(blockHash chainhash.Hash, options ...neutrino.QueryOption) (*btcutil.Block, error) { - return s.CS.GetBlock(blockHash, options...) -} - -func (s *btcChainService) GetCFilter(blockHash chainhash.Hash, filterType wire.FilterType, options ...neutrino.QueryOption) (*gcs.Filter, error) { - return s.CS.GetCFilter(blockHash, filterType, options...) -} - -func (s *btcChainService) Stop() error { - return s.CS.Stop() -} - -var _ dexbtc.SPVService = (*btcChainService)(nil) +var _ neutrinoService = (*neutrino.ChainService)(nil) // CreateNewWallet creates a new wallet for the BTC asset. func CreateNewWallet(pass *sharedW.AuthInfo, params *sharedW.InitParams) (sharedW.Asset, error) { @@ -205,11 +176,11 @@ func CreateWatchOnlyWallet(walletName, extendedPublicKey string, params *sharedW return btcWallet, nil } -// RestoreWallet accepts the seed, wallet pass information and the init parameters. -// It validates the network type passed by fetching the chain parameters -// associated with it for the BTC asset. It then generates the BTC loader interface -// that is passed to be used upstream while restoring the wallet in the -// shared wallet implemenation. +// RestoreWallet accepts the seed, wallet pass information and the init +// parameters. It validates the network type passed by fetching the chain +// parameters associated with it for the BTC asset. It then generates the BTC +// loader interface that is passed to be used upstream while restoring the +// wallet in the shared wallet implementation. // Immediately wallet restore is complete, the function to safely cancel network sync // is set. There after returning the restored wallet's interface. func RestoreWallet(seedMnemonic string, pass *sharedW.AuthInfo, params *sharedW.InitParams) (sharedW.Asset, error) { @@ -312,6 +283,10 @@ func (asset *Asset) SafelyCancelSync() { } } +func (asset *Asset) NeutrinoClient() *chain.NeutrinoClient { + return asset.chainClient +} + // IsSynced returns true if the wallet is synced. func (asset *Asset) IsSynced() bool { asset.syncData.mu.RLock() @@ -519,33 +494,6 @@ func (asset *Asset) SetSpecificPeer(address string) { }() } -func (asset *Asset) RemoveSpecificPeer(address string) { - sep := ";" - knownAddr := asset.ReadStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") - - addrs1, addrs2, found := strings.Cut(knownAddr, address) - if !found { - return - } - - addrs1 = strings.TrimSuffix(addrs1, sep) - addrs2 = strings.TrimPrefix(addrs2, sep) - addrs := addrs1 - if addrs1 == "" { - addrs = addrs2 - } else if addrs2 != "" { - addrs += sep + addrs2 - } - - asset.SaveUserConfigValue(sharedW.SpvPersistentPeerAddressesConfigKey, knownAddr) - go func() { - err := asset.reloadChainService() - if err != nil { - log.Error(err) - } - }() -} - // GetExtendedPubKey returns the extended public key of the given account, // to do that it calls btcwallet's AccountProperties method, using KeyScopeBIP0084 // and the account number. On failure it returns error. diff --git a/libwallet/assets/dcr/dex_wallet.go b/libwallet/assets/dcr/dex_wallet.go index 92abbcd93..2195926ca 100644 --- a/libwallet/assets/dcr/dex_wallet.go +++ b/libwallet/assets/dcr/dex_wallet.go @@ -542,7 +542,7 @@ func (dw *DEXWallet) AddressPrivKey(ctx context.Context, addr stdaddr.Address) ( // Part of the Wallet interface. func (dw *DEXWallet) Reconfigure(_ context.Context, _ *dexasset.WalletConfig, _ dex.Network, _ string) (restart bool, err error) { - return false, nil + return false, errors.New("Reconfigure not implemented by Cryptopower DEX wallet") } // These methods are part of Wallet interface but required only by the @@ -551,30 +551,30 @@ func (dw *DEXWallet) Reconfigure(_ context.Context, _ *dexasset.WalletConfig, _ // PurchaseTickets purchases n tickets. vspHost and vspPubKey only // needed for internal wallets. func (dw *DEXWallet) PurchaseTickets(ctx context.Context, n int, vspHost, vspPubKey string) ([]*dexasset.Ticket, error) { - return nil, nil + return nil, errors.New("PurchaseTickets not implemented by Cryptopower DEX wallet") } // Tickets returns current active ticket hashes up until they are voted // or revoked. Includes unconfirmed tickets. func (dw *DEXWallet) Tickets(ctx context.Context) ([]*dexasset.Ticket, error) { - return nil, nil + return nil, errors.New("Tickets not implemented by Cryptopower DEX wallet") } // VotingPreferences returns current voting preferences. func (dw *DEXWallet) VotingPreferences(ctx context.Context) ([]*walletjson.VoteChoice, []*dexasset.TBTreasurySpend, []*walletjson.TreasuryPolicyResult, error) { - return []*walletjson.VoteChoice{}, []*dexasset.TBTreasurySpend{}, []*walletjson.TreasuryPolicyResult{}, nil + return []*walletjson.VoteChoice{}, []*dexasset.TBTreasurySpend{}, []*walletjson.TreasuryPolicyResult{}, errors.New("VotingPreferences not implemented by Cryptopower DEX wallet") } // SetVotingPreferences sets preferences used when a ticket is chosen to // be voted on. func (dw *DEXWallet) SetVotingPreferences(ctx context.Context, choices, tspendPolicy, treasuryPolicy map[string]string) error { - return nil + return errors.New("SetVotingPreferences not implemented by Cryptopower DEX wallet") } func (dw *DEXWallet) SetTxFee(ctx context.Context, feePerKB dcrutil.Amount) error { - return nil + return errors.New("SetTxFee not implemented by Cryptopower DEX wallet") } func (dw *DEXWallet) StakeInfo(ctx context.Context) (*dcrwallet.StakeInfoData, error) { - return nil, nil + return nil, errors.New("StakeInfo not implemented by Cryptopower DEX wallet") } diff --git a/libwallet/assets_manager.go b/libwallet/assets_manager.go index 59e21c893..7ead139d8 100644 --- a/libwallet/assets_manager.go +++ b/libwallet/assets_manager.go @@ -950,12 +950,12 @@ func (mgr *AssetsManager) PrepareDexSupportForDCRWallet() error { // for use by the dex dcr ExchangeWallet. customWalletConfigOpts := []*asset.ConfigOption{ { - Key: dexc.DexWalletIDConfigKey, + Key: dexc.WalletIDConfigKey, DisplayName: "Wallet ID", Description: "ID of existing wallet to use", }, { - Key: dexc.DexDcrWalletAccountNameConfigKey, + Key: dexc.WalletAccountNameConfigKey, DisplayName: "Wallet Account Name", Description: "Account name of the selected wallet", }, @@ -971,7 +971,7 @@ func (mgr *AssetsManager) PrepareDexSupportForDCRWallet() error { // setup a dcr ExchangeWallet; it allows us to use an existing // wallet instance for wallet operations instead of json-rpc. var walletMaker = func(settings map[string]string, chainParams *dcrcfg.Params, logger dex.Logger) (dexDcr.Wallet, error) { - walletIDStr := settings[dexc.DexWalletIDConfigKey] + walletIDStr := settings[dexc.WalletIDConfigKey] walletID, err := strconv.Atoi(walletIDStr) if err != nil || walletID < 0 { return nil, fmt.Errorf("invalid wallet ID %q in settings", walletIDStr) @@ -992,7 +992,7 @@ func (mgr *AssetsManager) PrepareDexSupportForDCRWallet() error { } // Ensure the accountName exists. - accountName := settings[dexc.DexDcrWalletAccountNameConfigKey] + accountName := settings[dexc.WalletAccountNameConfigKey] if _, err = wallet.AccountNumber(accountName); err != nil { return nil, fmt.Errorf("error checking selected DEX account: %w", err) } @@ -1020,17 +1020,17 @@ func (mgr *AssetsManager) PrepareDexSupportForBTCWallet() error { // the dexbtc.ExchangeWalletSPV. customWalletConfigOpts := []*asset.ConfigOption{ { - Key: dexc.DexWalletIDConfigKey, + Key: dexc.WalletIDConfigKey, DisplayName: "Wallet ID", Description: "ID of existing wallet to use", }, { - Key: dexbtc.WalletAccountNameConfigKey, + Key: dexc.WalletAccountNameConfigKey, DisplayName: "Wallet Account Name", Description: "Account name of the selected wallet", }, { - Key: dexbtc.WalletAccountNumberConfigKey, + Key: dexc.WalletAccountNumberConfigKey, DisplayName: "Wallet Account Number", Description: "Account number of the selected wallet", }, @@ -1046,7 +1046,7 @@ func (mgr *AssetsManager) PrepareDexSupportForBTCWallet() error { // dexbtc.BTCWallet; it allows us to use an existing wallet instance for // wallet operations instead of json-rpc. var btcWalletConstructor = func(settings map[string]string, chainParams *btccfg.Params) (dexbtc.BTCWallet, error) { - walletIDStr := settings[dexc.DexWalletIDConfigKey] + walletIDStr := settings[dexc.WalletIDConfigKey] walletID, err := strconv.Atoi(walletIDStr) if err != nil || walletID < 0 { return nil, fmt.Errorf("invalid wallet ID %q in settings", walletIDStr) @@ -1066,20 +1066,29 @@ func (mgr *AssetsManager) PrepareDexSupportForBTCWallet() error { return nil, fmt.Errorf("cannot use watch only wallet for DEX trade") } + acct := dexbtc.XCWalletAccount{ + AccountName: settings[dexc.WalletAccountNameConfigKey], + } + // Ensure the wallet account name exists. - accountName := settings[dexbtc.WalletAccountNameConfigKey] - accountNumber, err := wallet.AccountNumber(accountName) + accountNumber, err := wallet.AccountNumber(acct.AccountName) if err != nil { - return nil, fmt.Errorf("error checking selected DEX account: %w", err) + return nil, fmt.Errorf("error checking selected DEX account name: %w", err) } - configAcctNumber, accountNumberStr := settings[dexbtc.WalletAccountNumberConfigKey], fmt.Sprint(accountNumber) - if configAcctNumber != accountNumberStr { + configAcctNumber, accountNumberStr := settings[dexc.WalletAccountNumberConfigKey], fmt.Sprint(accountNumber) + if configAcctNumber == accountNumberStr { + acctNumber, err := strconv.ParseInt(configAcctNumber, 10, 64) + if err != nil { + return nil, err + } + acct.AccountNumber = uint32(acctNumber) + } else { return nil, fmt.Errorf("config account number for wallet account(%s) does not match actual account number, expected %s got %s", - accountName, accountNumberStr, configAcctNumber) + acct.AccountName, accountNumberStr, configAcctNumber) } - return btc.NewDEXWallet(wallet.(*btc.Asset)), nil + return btc.NewDEXWallet(acct, wallet.Internal().BTC, wallet.(*btc.Asset).NeutrinoClient()), nil } err := dexbtc.RegisterCustomSPVWallet(btcWalletConstructor, def) diff --git a/ui/page/dcrdex/dex_onboarding_page.go b/ui/page/dcrdex/dex_onboarding_page.go index a3c723717..d3b520e9f 100644 --- a/ui/page/dcrdex/dex_onboarding_page.go +++ b/ui/page/dcrdex/dex_onboarding_page.go @@ -17,7 +17,6 @@ import ( "gioui.org/widget" "gioui.org/widget/material" - dexbtc "decred.org/dcrdex/client/asset/btc" "github.com/crypto-power/cryptopower/app" "github.com/crypto-power/cryptopower/dexc" sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" @@ -1046,18 +1045,11 @@ func (pg *DEXOnboarding) postBond() { postBondFn := func(walletPass string) { // Add bond wallet to core if it does not exist. if !pg.dexc.HasWallet(int32(bondAsset.ID)) { - cfg := map[string]string{ - dexc.DexWalletIDConfigKey: fmt.Sprintf("%d", asset.GetWalletID()), - } - selectedAcct := pg.bondSourceAccountSelector.SelectedAccount() - if asset.GetAssetType() == libutils.BTCWalletAsset { - cfg[dexbtc.WalletAccountNameConfigKey] = selectedAcct.Name - cfg[dexbtc.WalletAccountNumberConfigKey] = fmt.Sprint(selectedAcct.AccountNumber) - } else if asset.GetAssetType() == libutils.DCRWalletAsset { - // TODO: Remove this config value if using latest dex pkg - // version(i.e > 0.6.3). - cfg[dexc.DexDcrWalletAccountNameConfigKey] = selectedAcct.Name + cfg := map[string]string{ + dexc.WalletIDConfigKey: fmt.Sprintf("%d", asset.GetWalletID()), + dexc.WalletAccountNameConfigKey: selectedAcct.Name, + dexc.WalletAccountNumberConfigKey: fmt.Sprint(selectedAcct.AccountNumber), } err := pg.dexc.AddWallet(*postBond.Asset, cfg, pg.dexPass, []byte(walletPass))