diff --git a/libwallet/assets/wallet/wallet_utils.go b/libwallet/assets/wallet/wallet_utils.go index 5071cbfc7..d22c7427e 100644 --- a/libwallet/assets/wallet/wallet_utils.go +++ b/libwallet/assets/wallet/wallet_utils.go @@ -253,3 +253,19 @@ func backupFile(fileName string, suffix int) (newName string, err error) { return newName, nil } + +// Balances returns the spendable balance and total balance of the wallet. +func Balances(w Asset) (AssetAmount, AssetAmount, error) { + accountsResult, err := w.GetAccountsRaw() + if err != nil { + return w.ToAmount(0), w.ToAmount(0), err + } + + var totalSpendable, totalBalance int64 + for _, account := range accountsResult.Accounts { + totalSpendable += account.Balance.Spendable.ToInt() + totalBalance += account.Balance.Total.ToInt() + } + + return w.ToAmount(totalSpendable), w.ToAmount(totalBalance), nil +} diff --git a/libwallet/assets_config.go b/libwallet/assets_config.go index dde205d30..7ba47edfd 100644 --- a/libwallet/assets_config.go +++ b/libwallet/assets_config.go @@ -156,6 +156,16 @@ func (mgr *AssetsManager) SetCurrencyConversionExchange(xc string) { }() } +// ExchangeRateFetchingEnabled returns true if privacy mode isn't turned on and +// a valid exchange rate source is configured. +func (mgr *AssetsManager) ExchangeRateFetchingEnabled() bool { + if mgr.IsPrivacyModeOn() { + return false + } + xc := mgr.GetCurrencyConversionExchange() + return xc != "" && xc != values.DefaultExchangeValue +} + // GetLanguagePreference returns the language preference. func (mgr *AssetsManager) GetLanguagePreference() string { var lang string diff --git a/libwallet/assets_manager.go b/libwallet/assets_manager.go index 3c4c18a76..303596b51 100644 --- a/libwallet/assets_manager.go +++ b/libwallet/assets_manager.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "sort" "strconv" "time" @@ -490,6 +491,15 @@ func (mgr *AssetsManager) sortWallets(assetType utils.AssetType) []sharedW.Asset normalWallets = append(normalWallets, wallet) } } + + // Sort both lists by wallet ID. + sort.Slice(normalWallets, func(i, j int) bool { + return normalWallets[i].GetWalletID() < normalWallets[j].GetWalletID() + }) + sort.Slice(watchOnlyWallets, func(i, j int) bool { + return watchOnlyWallets[i].GetWalletID() < watchOnlyWallets[j].GetWalletID() + }) + return append(normalWallets, watchOnlyWallets...) } @@ -780,3 +790,37 @@ func (mgr *AssetsManager) BlockExplorerURLForTx(assetType utils.AssetType, txHas func (mgr *AssetsManager) LogFile() string { return filepath.Join(mgr.params.LogDir, LogFilename) } + +func (mgr *AssetsManager) DCRHDPrefix() string { + switch mgr.NetType() { + case utils.Testnet: + return dcr.TestnetHDPath + case utils.Mainnet: + return dcr.MainnetHDPath + default: + return "" + } +} + +func (mgr *AssetsManager) BTCHDPrefix() string { + switch mgr.NetType() { + case utils.Testnet: + return btc.TestnetHDPath + case utils.Mainnet: + return btc.MainnetHDPath + default: + return "" + } +} + +// LTC HDPrefix returns the HD path prefix for the Litecoin wallet network. +func (mgr *AssetsManager) LTCHDPrefix() string { + switch mgr.NetType() { + case utils.Testnet: + return ltc.TestnetHDPath + case utils.Mainnet: + return ltc.MainnetHDPath + default: + return "" + } +} diff --git a/ui/load/appinfo.go b/ui/load/appinfo.go index 73fee6b54..de8106d35 100644 --- a/ui/load/appinfo.go +++ b/ui/load/appinfo.go @@ -1,6 +1,10 @@ package load -import "time" +import ( + "time" + + "github.com/crypto-power/cryptopower/libwallet" +) // TODO: This should ultimately replace Load, acting as the container for all // properties and methods that every app page and window relies on. Should @@ -9,14 +13,17 @@ type AppInfo struct { version string buildDate time.Time startUpTime time.Time + + AssetsManager *libwallet.AssetsManager } // StartApp returns an instance of AppInfo with the startUpTime set to the current time. -func StartApp(version string, buildDate time.Time) *AppInfo { +func StartApp(version string, buildDate time.Time, assetsManager *libwallet.AssetsManager) *AppInfo { return &AppInfo{ - version: version, - buildDate: buildDate, - startUpTime: time.Now(), + version: version, + buildDate: buildDate, + startUpTime: time.Now(), + AssetsManager: assetsManager, } } diff --git a/ui/load/load.go b/ui/load/load.go index 894dfd28e..716298fbc 100644 --- a/ui/load/load.go +++ b/ui/load/load.go @@ -9,6 +9,7 @@ import ( "golang.org/x/text/message" "github.com/crypto-power/cryptopower/app" + sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" "github.com/crypto-power/cryptopower/ui/assets" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/notification" @@ -29,7 +30,6 @@ type Load struct { Theme *cryptomaterial.Theme - WL *WalletLoad Printer *message.Printer Network string CurrentAppWidth int @@ -39,11 +39,13 @@ type Load struct { DarkModeSettingChanged func(bool) LanguageSettingChanged func() CurrencySettingChanged func() - ToggleSync func(NeedUnlockRestore) + + // TODO: Kill this property! + ToggleSync func(sharedW.Asset, NeedUnlockRestore) } func (l *Load) RefreshTheme(window app.WindowNavigator) { - isDarkModeOn := l.WL.AssetsManager.IsDarkModeOn() + isDarkModeOn := l.AssetsManager.IsDarkModeOn() l.Theme.SwitchDarkMode(isDarkModeOn, assets.DecredIcons) l.DarkModeSettingChanged(isDarkModeOn) l.LanguageSettingChanged() diff --git a/ui/load/wallet.go b/ui/load/wallet.go deleted file mode 100644 index c2e02c785..000000000 --- a/ui/load/wallet.go +++ /dev/null @@ -1,188 +0,0 @@ -package load - -import ( - "errors" - "fmt" - "sort" - - "github.com/crypto-power/cryptopower/libwallet" - "github.com/crypto-power/cryptopower/libwallet/assets/btc" - "github.com/crypto-power/cryptopower/libwallet/assets/dcr" - "github.com/crypto-power/cryptopower/libwallet/assets/ltc" - sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" - "github.com/crypto-power/cryptopower/libwallet/utils" -) - -type WalletItem struct { - Wallet sharedW.Asset - TotalBalance sharedW.AssetAmount -} - -type WalletLoad struct { - AssetsManager *libwallet.AssetsManager - TxAuthor dcr.TxAuthor - - SelectedWallet *WalletItem - SelectedAccount *int -} - -// AllSortedWalletList returns all the wallets currently loaded on app startup. -func (wl *WalletLoad) AllSortedWalletList() []sharedW.Asset { - wallets := wl.SortedWalletList(utils.DCRWalletAsset) - wallets = append(wallets, wl.SortedWalletList(utils.BTCWalletAsset)...) - wallets = append(wallets, wl.SortedWalletList(utils.LTCWalletAsset)...) - return wallets -} - -// SortedWalletList can return sorted wallets based on the current selected wallet -// type of on the basis of the provided asset type variadic variable. -func (wl *WalletLoad) SortedWalletList(assetType ...utils.AssetType) []sharedW.Asset { - var wallets []sharedW.Asset - if len(assetType) > 0 { - wallets = wl.getAssets(assetType[0]) - } else { - // On app start up SelectedWallet is usually not set thus the else use. - wallets = wl.getAssets() - } - - if wallets == nil { - return nil - } - - sort.Slice(wallets, func(i, j int) bool { - return wallets[i].GetWalletID() < wallets[j].GetWalletID() && !wallets[i].IsWatchingOnlyWallet() - }) - - return wallets -} - -func (wl *WalletLoad) TotalWalletsBalance() (sharedW.AssetAmount, error) { - totalBalance := int64(0) - wallets := wl.getAssets() - if wallets == nil { - return wl.nilAmount(), nil - } - - for _, w := range wallets { - accountsResult, err := w.GetAccountsRaw() - if err != nil { - return wl.nilAmount(), err - } - totalBalance += wl.getAssetTotalbalance(accountsResult).ToInt() - } - return wl.SelectedWallet.Wallet.ToAmount(totalBalance), nil -} - -func (wl *WalletLoad) getAssets(assetType ...utils.AssetType) []sharedW.Asset { - var wType utils.AssetType - if len(assetType) > 0 { - wType = assetType[0] - } else { - // On app start up SelectedWallet is usually not set thus the else use. - wType = wl.SelectedWallet.Wallet.GetAssetType() - } - - switch wType { - case utils.BTCWalletAsset: - return wl.AssetsManager.AllBTCWallets() - case utils.DCRWalletAsset: - return wl.AssetsManager.AllDCRWallets() - case utils.LTCWalletAsset: - return wl.AssetsManager.AllLTCWallets() - default: - return nil - } -} - -func (wl *WalletLoad) TotalWalletBalance(walletID int) (sharedW.AssetAmount, error) { - wallet := wl.AssetsManager.WalletWithID(walletID) - if wallet == nil { - return wl.nilAmount(), errors.New(utils.ErrNotExist) - } - - accountsResult, err := wallet.GetAccountsRaw() - if err != nil { - return wl.nilAmount(), err - } - - return wl.getAssetTotalbalance(accountsResult), nil -} - -func (wl *WalletLoad) SpendableWalletBalance(walletID int) (sharedW.AssetAmount, error) { - wallet := wl.AssetsManager.WalletWithID(walletID) - if wallet == nil { - return wl.nilAmount(), errors.New(utils.ErrNotExist) - } - - accountsResult, err := wallet.GetAccountsRaw() - if err != nil { - return wl.nilAmount(), err - } - return wl.getAssetSpendablebalance(accountsResult), nil -} - -func (wl *WalletLoad) DCRHDPrefix() string { - switch wl.AssetsManager.NetType() { - case utils.Testnet: - return dcr.TestnetHDPath - case utils.Mainnet: - return dcr.MainnetHDPath - default: - return "" - } -} - -func (wl *WalletLoad) BTCHDPrefix() string { - switch wl.AssetsManager.NetType() { - case utils.Testnet: - return btc.TestnetHDPath - case utils.Mainnet: - return btc.MainnetHDPath - default: - return "" - } -} - -// LTC HDPrefix returns the HD path prefix for the Litecoin wallet network. -func (wl *WalletLoad) LTCHDPrefix() string { - switch wl.AssetsManager.NetType() { - case utils.Testnet: - return ltc.TestnetHDPath - case utils.Mainnet: - return ltc.MainnetHDPath - default: - return "" - } -} - -func (wl *WalletLoad) WalletDirectory() string { - return wl.SelectedWallet.Wallet.DataDir() -} - -func (wl *WalletLoad) DataSize() string { - v, err := wl.AssetsManager.RootDirFileSizeInBytes(wl.WalletDirectory()) - if err != nil { - return "Unknown" - } - return fmt.Sprintf("%f GB", float64(v)*1e-9) -} - -func (wl *WalletLoad) nilAmount() sharedW.AssetAmount { - return wl.SelectedWallet.Wallet.ToAmount(-1) -} - -func (wl *WalletLoad) getAssetTotalbalance(accountsResult *sharedW.Accounts) sharedW.AssetAmount { - var totalBalance int64 - for _, account := range accountsResult.Accounts { - totalBalance += account.Balance.Total.ToInt() - } - return wl.SelectedWallet.Wallet.ToAmount(totalBalance) -} - -func (wl *WalletLoad) getAssetSpendablebalance(accountsResult *sharedW.Accounts) sharedW.AssetAmount { - var totalBalance int64 - for _, account := range accountsResult.Accounts { - totalBalance += account.Balance.Spendable.ToInt() - } - return wl.SelectedWallet.Wallet.ToAmount(totalBalance) -} diff --git a/ui/load/wallet_mapping.go b/ui/load/wallet_utils.go similarity index 52% rename from ui/load/wallet_mapping.go rename to ui/load/wallet_utils.go index d00409d2d..c6a08d705 100644 --- a/ui/load/wallet_mapping.go +++ b/ui/load/wallet_utils.go @@ -10,20 +10,8 @@ import ( sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" ) -// WalletMapping helps to call a function quickly no matter what currency it is, -// it is used for separate functions without an interface for general use -type WalletMapping struct { - sharedW.Asset -} - -func NewWalletMapping(asset sharedW.Asset) *WalletMapping { - return &WalletMapping{ - Asset: asset, - } -} - -func (w *WalletMapping) MixedAccountNumber() int32 { - switch asset := w.Asset.(type) { +func MixedAccountNumber(w sharedW.Asset) int32 { + switch asset := w.(type) { case *dcr.Asset: return asset.MixedAccountNumber() default: @@ -33,16 +21,16 @@ func (w *WalletMapping) MixedAccountNumber() int32 { // SetAPIFeeRate validates the string input its a number before sending it upstream. // It returns the string convert to int amount. -func (w *WalletMapping) SetAPIFeeRate(feerate string) (int64, error) { +func SetAPIFeeRate(w sharedW.Asset, feerate string) (int64, error) { var amount sharedW.AssetAmount var setUserFeeRate func(feeRatePerkvB sharedW.AssetAmount) error rate, err := strconv.ParseInt(feerate, 10, 64) if err != nil { - return 0, w.invalidParameter(feerate, "tx fee rate") + return 0, fmt.Errorf("(%v) not valid tx fee rate", feerate) } - switch asset := w.Asset.(type) { + switch asset := w.(type) { case *btc.Asset: amount = asset.ToAmount(rate) setUserFeeRate = asset.SetUserFeeRate @@ -50,28 +38,20 @@ func (w *WalletMapping) SetAPIFeeRate(feerate string) (int64, error) { amount = asset.ToAmount(rate) setUserFeeRate = asset.SetUserFeeRate default: - return 0, w.invalidWallet() + return 0, fmt.Errorf("(%v) wallet not supported", w.GetAssetType()) } err = setUserFeeRate(amount) return rate, err } -func (w *WalletMapping) GetAPIFeeRate() ([]sharedW.FeeEstimate, error) { - switch asset := w.Asset.(type) { +func GetAPIFeeRate(w sharedW.Asset) ([]sharedW.FeeEstimate, error) { + switch asset := w.(type) { case *btc.Asset: return asset.GetAPIFeeEstimateRate() case *ltc.Asset: return asset.GetAPIFeeEstimateRate() default: - return nil, w.invalidWallet() + return nil, fmt.Errorf("(%v) wallet not supported", w.GetAssetType()) } } - -func (w *WalletMapping) invalidWallet() error { - return fmt.Errorf("(%v) wallet not supported", w.Asset.GetAssetType()) -} - -func (w *WalletMapping) invalidParameter(v interface{}, vType string) error { - return fmt.Errorf("(%v) not valid %v", v, vType) -} diff --git a/ui/modal/create_watch_only_modal.go b/ui/modal/create_watch_only_modal.go index 82dc11eaf..3cf6f9741 100644 --- a/ui/modal/create_watch_only_modal.go +++ b/ui/modal/create_watch_only_modal.go @@ -128,7 +128,7 @@ func (cm *CreateWatchOnlyModal) Handle() { // Check if there are existing wallets with identical Xpub. // matchedWalletID == ID of the wallet whose xpub is identical to provided xpub. - matchedWalletID, err := cm.WL.AssetsManager.DCRWalletWithXPub(cm.extendedPubKey.Editor.Text()) + matchedWalletID, err := cm.AssetsManager.DCRWalletWithXPub(cm.extendedPubKey.Editor.Text()) if err != nil { log.Errorf("Error checking xpub: %v", err) cm.SetError(values.StringF(values.StrXpubKeyErr, err)) diff --git a/ui/page/components/asset_selector.go b/ui/page/components/asset_selector.go index df0035f0f..85624ffd0 100644 --- a/ui/page/components/asset_selector.go +++ b/ui/page/components/asset_selector.go @@ -74,7 +74,7 @@ func NewAssetTypeSelector(l *load.Load) *AssetTypeSelector { // SupportedAssetTypes returns a slice containing all the asset types // Currently supported. func (ats *AssetTypeSelector) SupportedAssetTypes() []*AssetTypeItem { - assetTypes := ats.WL.AssetsManager.AllAssetTypes() + assetTypes := ats.AssetsManager.AllAssetTypes() var assetType []*AssetTypeItem for _, at := range assetTypes { diff --git a/ui/page/components/coinformat.go b/ui/page/components/coinformat.go index 2c7d847e1..5068aa6d8 100644 --- a/ui/page/components/coinformat.go +++ b/ui/page/components/coinformat.go @@ -68,10 +68,10 @@ func formatBalance(gtx C, l *load.Load, amount string, mainTextSize unit.Sp, sca } func formatBalanceWithHiden(gtx C, l *load.Load, amount string, mainTextSize unit.Sp, textFont font.Weight, col color.NRGBA, isUSD bool) D { - isBalanceHidden := l.WL.AssetsManager.IsTotalBalanceVisible() + isBalanceHidden := l.AssetsManager.IsTotalBalanceVisible() txt := l.Theme.Label(mainTextSize, amount) if isUSD { - if !IsFetchExchangeRateAPIAllowed(l.WL) { + if !l.AssetsManager.ExchangeRateFetchingEnabled() { txt.Text = "$ --" } } diff --git a/ui/page/components/components.go b/ui/page/components/components.go index dc820bf6e..04ca38227 100644 --- a/ui/page/components/components.go +++ b/ui/page/components/components.go @@ -765,11 +765,11 @@ func CalculateMixedAccountBalance(selectedWallet *dcr.Asset) (*CummulativeWallet }, nil } -func CalculateTotalWalletsBalance(l *load.Load) (*CummulativeWalletsBalance, error) { +func CalculateTotalWalletsBalance(wallet sharedW.Asset) (*CummulativeWalletsBalance, error) { var totalBalance, spandableBalance, immatureReward, votingAuthority, immatureStakeGeneration, lockedByTickets, unConfirmed int64 - accountsResult, err := l.WL.SelectedWallet.Wallet.GetAccountsRaw() + accountsResult, err := wallet.GetAccountsRaw() if err != nil { return nil, err } @@ -779,7 +779,7 @@ func CalculateTotalWalletsBalance(l *load.Load) (*CummulativeWalletsBalance, err spandableBalance += account.Balance.Spendable.ToInt() immatureReward += account.Balance.ImmatureReward.ToInt() - if l.WL.SelectedWallet.Wallet.GetAssetType() == libutils.DCRWalletAsset { + if wallet.GetAssetType() == libutils.DCRWalletAsset { // Fields required only by DCR immatureStakeGeneration += account.Balance.ImmatureStakeGeneration.ToInt() lockedByTickets += account.Balance.LockedByTickets.ToInt() @@ -788,27 +788,23 @@ func CalculateTotalWalletsBalance(l *load.Load) (*CummulativeWalletsBalance, err } } - toAmount := func(v int64) sharedW.AssetAmount { - return l.WL.SelectedWallet.Wallet.ToAmount(v) - } - cumm := &CummulativeWalletsBalance{ - Total: toAmount(totalBalance), - Spendable: toAmount(spandableBalance), - ImmatureReward: toAmount(immatureReward), - ImmatureStakeGeneration: toAmount(immatureStakeGeneration), - LockedByTickets: toAmount(lockedByTickets), - VotingAuthority: toAmount(votingAuthority), - UnConfirmed: toAmount(unConfirmed), + Total: wallet.ToAmount(totalBalance), + Spendable: wallet.ToAmount(spandableBalance), + ImmatureReward: wallet.ToAmount(immatureReward), + ImmatureStakeGeneration: wallet.ToAmount(immatureStakeGeneration), + LockedByTickets: wallet.ToAmount(lockedByTickets), + VotingAuthority: wallet.ToAmount(votingAuthority), + UnConfirmed: wallet.ToAmount(unConfirmed), } return cumm, nil } -func calculateTotalAssetsBalance(l *load.Load) (map[libutils.AssetType]int64, error) { - wallets := l.WL.AssetsManager.AllWallets() - assetsTotalBalance := make(map[libutils.AssetType]int64) +func CalculateTotalAssetsBalance(l *load.Load) (map[libutils.AssetType]sharedW.AssetAmount, error) { + assetsTotalBalance := make(map[libutils.AssetType]sharedW.AssetAmount) + wallets := l.AssetsManager.AllWallets() for _, wal := range wallets { if wal.IsWatchingOnlyWallet() { continue @@ -819,31 +815,15 @@ func calculateTotalAssetsBalance(l *load.Load) (map[libutils.AssetType]int64, er return nil, err } + assetType := wal.GetAssetType() for _, account := range accountsResult.Accounts { - assetsTotalBalance[wal.GetAssetType()] += account.Balance.Total.ToInt() - } - } - - return assetsTotalBalance, nil -} - -func CalculateTotalAssetsBalance(l *load.Load) (map[libutils.AssetType]sharedW.AssetAmount, error) { - balances, err := calculateTotalAssetsBalance(l) - if err != nil { - return nil, err - } - - assetsTotalBalance := make(map[libutils.AssetType]sharedW.AssetAmount) - for assetType, balance := range balances { - switch assetType { - case libutils.BTCWalletAsset: - assetsTotalBalance[assetType] = l.WL.AssetsManager.AllBTCWallets()[0].ToAmount(balance) - case libutils.DCRWalletAsset: - assetsTotalBalance[assetType] = l.WL.AssetsManager.AllDCRWallets()[0].ToAmount(balance) - case libutils.LTCWalletAsset: - assetsTotalBalance[assetType] = l.WL.AssetsManager.AllLTCWallets()[0].ToAmount(balance) - default: - return nil, fmt.Errorf("Unsupported asset type: %s", assetType) + assetTotal, ok := assetsTotalBalance[assetType] + if ok { + assetTotal = wal.ToAmount(assetTotal.ToInt() + account.Balance.Total.ToInt()) + } else { + assetTotal = account.Balance.Total + } + assetsTotalBalance[assetType] = assetTotal } } @@ -852,7 +832,7 @@ func CalculateTotalAssetsBalance(l *load.Load) (map[libutils.AssetType]sharedW.A func CalculateAssetsUSDBalance(l *load.Load, assetsTotalBalance map[libutils.AssetType]sharedW.AssetAmount) (map[libutils.AssetType]float64, error) { usdBalance := func(bal sharedW.AssetAmount, market string) (float64, error) { - rate := l.WL.AssetsManager.RateSource.GetTicker(market) + rate := l.AssetsManager.RateSource.GetTicker(market) if rate == nil || rate.LastTradePrice <= 0 { return 0, fmt.Errorf("No rate information available") } @@ -931,13 +911,6 @@ func BrowserURLWidget(gtx C, l *load.Load, url string, copyRedirect *cryptomater ) } -// IsFetchExchangeRateAPIAllowed returns true if the exchange rate fetch API is -// allowed. -func IsFetchExchangeRateAPIAllowed(wl *load.WalletLoad) bool { - return wl.AssetsManager.GetCurrencyConversionExchange() != values.DefaultExchangeValue && - !wl.AssetsManager.IsPrivacyModeOn() -} - // DisablePageWithOverlay disables the provided page by highlighting a message why // the page is disabled and adding a background color overlay that blocks any // page event being triggered. diff --git a/ui/page/components/consensus_list.go b/ui/page/components/consensus_list.go index 7724055ad..7331bcb4a 100644 --- a/ui/page/components/consensus_list.go +++ b/ui/page/components/consensus_list.go @@ -8,7 +8,6 @@ import ( "gioui.org/unit" "github.com/crypto-power/cryptopower/libwallet/assets/dcr" - sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/values" @@ -19,7 +18,7 @@ type ConsensusItem struct { VoteButton cryptomaterial.Button } -func AgendaItemWidget(gtx C, l *load.Load, consensusItem *ConsensusItem) D { +func AgendaItemWidget(gtx C, l *load.Load, consensusItem *ConsensusItem, hasVotingWallet bool) D { gtx.Constraints.Min.X = gtx.Constraints.Max.X return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -33,7 +32,7 @@ func AgendaItemWidget(gtx C, l *load.Load, consensusItem *ConsensusItem) D { ) }), layout.Rigid(func(gtx C) D { - return layoutAgendaVoteAction(gtx, l, consensusItem) + return layoutAgendaVoteAction(gtx, l, consensusItem, hasVotingWallet) }), ) } @@ -123,18 +122,20 @@ func layoutAgendaDetails(l *load.Load, data string, weight ...font.Weight) layou } } -func layoutAgendaVoteAction(gtx C, l *load.Load, item *ConsensusItem) D { +func layoutAgendaVoteAction(gtx C, l *load.Load, item *ConsensusItem, hasVotingWallet bool) D { if item.Agenda.Status == dcr.AgendaStatusFinished.String() { return D{} } - gtx.Constraints.Min.X, gtx.Constraints.Max.X = gtx.Dp(unit.Dp(150)), gtx.Dp(unit.Dp(200)) - item.VoteButton.Background = l.Theme.Color.Gray3 - item.VoteButton.SetEnabled(false) - if item.Agenda.Status == dcr.AgendaStatusUpcoming.String() || item.Agenda.Status == dcr.AgendaStatusInProgress.String() { + canVote := hasVotingWallet && item.Agenda.Status == dcr.AgendaStatusUpcoming.String() || item.Agenda.Status == dcr.AgendaStatusInProgress.String() + item.VoteButton.SetEnabled(canVote) + if canVote { item.VoteButton.Background = l.Theme.Color.Primary - item.VoteButton.SetEnabled(true) + } else { + item.VoteButton.Background = l.Theme.Color.Gray3 } + + gtx.Constraints.Min.X, gtx.Constraints.Max.X = gtx.Dp(unit.Dp(150)), gtx.Dp(unit.Dp(200)) return layout.Inset{Top: values.MarginPadding15}.Layout(gtx, item.VoteButton.Layout) } @@ -153,15 +154,14 @@ func LayoutNoAgendasFound(gtx C, l *load.Load, syncing bool) D { }) } -func LoadAgendas(l *load.Load, selectedWallet sharedW.Asset, newestFirst bool) []*ConsensusItem { - agendas, err := l.WL.AssetsManager.AllVoteAgendas(newestFirst) +func LoadAgendas(l *load.Load, dcrWallet *dcr.Asset, newestFirst bool) []*ConsensusItem { + agendas, err := l.AssetsManager.AllVoteAgendas(newestFirst) if err != nil { return nil } - if selectedWallet != nil { - dcrUniqueImpl := selectedWallet.(*dcr.Asset) - walletChoices, err := dcrUniqueImpl.AgendaChoices("") + if dcrWallet != nil { + walletChoices, err := dcrWallet.AgendaChoices("") if err != nil { return nil } @@ -175,8 +175,6 @@ func LoadAgendas(l *load.Load, selectedWallet sharedW.Asset, newestFirst bool) [ agenda.VotingPreference = "abstain" } } - // TODO: When the wallet selection is cleared (i.e. no wallet is - // selected), also clear each agenda.VotingPreference value! } consensusItems := make([]*ConsensusItem, len(agendas)) diff --git a/ui/page/components/fee_rate_selector.go b/ui/page/components/fee_rate_selector.go index 81ba61ec2..d2e0c03ef 100644 --- a/ui/page/components/fee_rate_selector.go +++ b/ui/page/components/fee_rate_selector.go @@ -11,6 +11,7 @@ import ( "gioui.org/widget" "gioui.org/widget/material" "github.com/crypto-power/cryptopower/app" + sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" libutils "github.com/crypto-power/cryptopower/libwallet/utils" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" @@ -106,7 +107,7 @@ func (fs *FeeRateSelector) ShowSizeAndCost() *FeeRateSelector { } func (fs *FeeRateSelector) isFeerateAPIApproved() bool { - return fs.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.FeeRateHTTPAPI) + return fs.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.FeeRateHTTPAPI) } // Layout draws the UI components. @@ -245,7 +246,7 @@ func (fs *FeeRateSelector) Layout(gtx C) D { } // FetchFeeRate will fetch the fee rate from the HTTP API. -func (fs *FeeRateSelector) FetchFeeRate(window app.WindowNavigator, selectedWallet *load.WalletMapping) { +func (fs *FeeRateSelector) FetchFeeRate(window app.WindowNavigator, selectedWallet sharedW.Asset) { if fs.fetchingRate { return } @@ -254,7 +255,7 @@ func (fs *FeeRateSelector) FetchFeeRate(window app.WindowNavigator, selectedWall fs.fetchingRate = false }() - feeRates, err := selectedWallet.GetAPIFeeRate() + feeRates, err := load.GetAPIFeeRate(selectedWallet) if err != nil { return } @@ -289,7 +290,7 @@ func (fs *FeeRateSelector) FetchFeeRate(window app.WindowNavigator, selectedWall fields := strings.Fields(radiogroupbtns.Value) index, _ := strconv.Atoi(fields[0]) rate := strconv.Itoa(int(feeRates[index].Feerate.ToInt())) - rateInt, err := selectedWallet.SetAPIFeeRate(rate) + rateInt, err := load.SetAPIFeeRate(selectedWallet, rate) if err != nil { log.Error(err) return false @@ -309,13 +310,13 @@ func (fs *FeeRateSelector) FetchFeeRate(window app.WindowNavigator, selectedWall } // OnEditRateCliked is called when the edit feerate button is clicked. -func (fs *FeeRateSelector) OnEditRateClicked(selectedWallet *load.WalletMapping) { +func (fs *FeeRateSelector) OnEditRateClicked(selectedWallet sharedW.Asset) { fs.rateEditMode = !fs.rateEditMode if fs.rateEditMode { fs.EditRates.Text = values.String(values.StrSave) } else { rateStr := fs.ratesEditor.Editor.Text() - rateInt, err := selectedWallet.SetAPIFeeRate(rateStr) + rateInt, err := load.SetAPIFeeRate(selectedWallet, rateStr) if err != nil { fs.feeRateText = " - " } else { diff --git a/ui/page/components/nav_drawer.go b/ui/page/components/nav_drawer.go index e9ee4f056..093c380a3 100644 --- a/ui/page/components/nav_drawer.go +++ b/ui/page/components/nav_drawer.go @@ -2,136 +2,40 @@ package components import ( "gioui.org/layout" - "gioui.org/unit" "github.com/crypto-power/cryptopower/ui/cryptomaterial" - "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/values" ) -var ( - navDrawerMaximizedWidth = values.Size180 - navDrawerMinimizedWidth = values.MarginPadding100 -) - -type NavHandler struct { - Clickable *cryptomaterial.Clickable - Image *cryptomaterial.Image - ImageInactive *cryptomaterial.Image - Title string - PageID string -} - -type NavDrawer struct { - *load.Load - - AppNavBarItems []NavHandler - DCRDrawerNavItems []NavHandler - BTCDrawerNavItems []NavHandler - CurrentPage string - - axis layout.Axis - textSize unit.Sp - leftInset unit.Dp - width unit.Dp - alignment layout.Alignment - direction layout.Direction - - MinimizeNavDrawerButton cryptomaterial.IconButton - MaximizeNavDrawerButton cryptomaterial.IconButton - activeDrawerBtn cryptomaterial.IconButton - IsNavExpanded bool +type NavBarItem struct { + Clickable *cryptomaterial.Clickable + Image *cryptomaterial.Image + Title string + PageID string } -func (nd *NavDrawer) LayoutNavDrawer(gtx layout.Context, navItems []NavHandler) layout.Dimensions { - return cryptomaterial.LinearLayout{ - Width: gtx.Dp(nd.width), - Height: cryptomaterial.MatchParent, - Orientation: layout.Vertical, - Background: nd.Theme.Color.Surface, - }.Layout(gtx, - layout.Rigid(func(gtx C) D { - list := layout.List{Axis: layout.Vertical} - return list.Layout(gtx, len(navItems), func(gtx C, i int) D { - mGtx := gtx - background := nd.Theme.Color.Surface - - if nd.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() && (navItems[i].PageID == values.String(values.StrSend) || - navItems[i].PageID == values.String(values.StrAccountMixer)) { - return D{} - } - - if navItems[i].PageID == nd.CurrentPage { - background = nd.Theme.Color.Gray5 - } - return cryptomaterial.LinearLayout{ - Orientation: nd.axis, - Width: cryptomaterial.MatchParent, - Height: cryptomaterial.WrapContent, - Padding: layout.UniformInset(values.MarginPadding15), - Alignment: nd.alignment, - Direction: nd.direction, - Background: background, - Clickable: navItems[i].Clickable, - }.Layout(mGtx, - layout.Rigid(func(gtx C) D { - img := navItems[i].ImageInactive - if navItems[i].PageID == nd.CurrentPage { - img = navItems[i].Image - } - return img.Layout24dp(gtx) - }), - layout.Rigid(func(gtx C) D { - if !nd.IsNavExpanded { - return layout.Inset{ - Left: nd.leftInset, - }.Layout(gtx, func(gtx C) D { - textColor := nd.Theme.Color.GrayText1 - if navItems[i].PageID == nd.CurrentPage { - textColor = nd.Theme.Color.DeepBlue - } - txt := nd.Theme.Label(nd.textSize, navItems[i].Title) - txt.Color = textColor - return txt.Layout(gtx) - }) - } - - return D{} - }), - ) - }) - }), - layout.Flexed(1, func(gtx C) D { - gtx.Constraints.Min.X = gtx.Constraints.Max.X - return layout.SE.Layout(gtx, func(gtx C) D { - return nd.activeDrawerBtn.Layout(gtx) - }) - }), - ) -} - -func (nd *NavDrawer) LayoutTopBar(gtx layout.Context) layout.Dimensions { - card := nd.Theme.Card() +func LayoutNavigationBar(gtx layout.Context, theme *cryptomaterial.Theme, navItems []NavBarItem) layout.Dimensions { + card := theme.Card() card.Radius = cryptomaterial.Radius(20) - card.Color = nd.Theme.Color.Gray2 + card.Color = theme.Color.Gray2 padding8 := values.MarginPadding8 padding20 := values.MarginPadding20 return layout.Inset{Right: values.MarginPadding8}.Layout(gtx, func(gtx C) D { return card.Layout(gtx, func(gtx C) D { list := layout.List{Axis: layout.Horizontal} - return list.Layout(gtx, len(nd.AppNavBarItems), func(gtx C, i int) D { + return list.Layout(gtx, len(navItems), func(gtx C, i int) D { // The parent card has all border radius (tl, tr, bl, br) set to // 20. This requires setting it's children border so they // respects the parent border. radius := cryptomaterial.CornerRadius{TopLeft: 20, BottomLeft: 20} - if i+1 == len(nd.AppNavBarItems) { + if i+1 == len(navItems) { radius = cryptomaterial.CornerRadius{TopRight: 20, BottomRight: 20} } return cryptomaterial.LinearLayout{ Width: cryptomaterial.WrapContent, Height: cryptomaterial.WrapContent, Orientation: layout.Horizontal, - Clickable: nd.AppNavBarItems[i].Clickable, + Clickable: navItems[i].Clickable, Alignment: layout.Middle, Border: cryptomaterial.Border{ Radius: radius, @@ -144,7 +48,7 @@ func (nd *NavDrawer) LayoutTopBar(gtx layout.Context) layout.Dimensions { Left: padding20, Right: padding8, }.Layout(gtx, func(gtx C) D { - return layout.Center.Layout(gtx, nd.AppNavBarItems[i].Image.Layout24dp) + return layout.Center.Layout(gtx, navItems[i].Image.Layout24dp) }) }), layout.Rigid(func(gtx C) D { @@ -154,15 +58,15 @@ func (nd *NavDrawer) LayoutTopBar(gtx layout.Context) layout.Dimensions { Right: padding20, Left: values.MarginPadding0, }.Layout(gtx, func(gtx C) D { - return layout.Center.Layout(gtx, nd.Theme.Body1(nd.AppNavBarItems[i].Title).Layout) + return layout.Center.Layout(gtx, theme.Body1(navItems[i].Title).Layout) }) }), layout.Rigid(func(gtx C) D { - if i+1 == len(nd.AppNavBarItems) { + if i+1 == len(navItems) { return D{} } - verticalSeparator := nd.Theme.SeparatorVertical(int(gtx.Metric.PxPerDp*20.0), 2) - verticalSeparator.Color = nd.Theme.Color.DeepBlue + verticalSeparator := theme.SeparatorVertical(int(gtx.Metric.PxPerDp*20.0), 2) + verticalSeparator.Color = theme.Color.DeepBlue return verticalSeparator.Layout(gtx) }), ) @@ -170,22 +74,3 @@ func (nd *NavDrawer) LayoutTopBar(gtx layout.Context) layout.Dimensions { }) }) } - -func (nd *NavDrawer) DrawerToggled(min bool) { - if min { - nd.axis = layout.Vertical - nd.leftInset = values.MarginPadding0 - nd.width = navDrawerMinimizedWidth - nd.activeDrawerBtn = nd.MaximizeNavDrawerButton - nd.alignment = layout.Middle - nd.direction = layout.Center - } else { - nd.axis = layout.Horizontal - nd.textSize = values.TextSize16 - nd.leftInset = values.MarginPadding15 - nd.width = navDrawerMaximizedWidth - nd.activeDrawerBtn = nd.MinimizeNavDrawerButton - nd.alignment = layout.Start - nd.direction = layout.W - } -} diff --git a/ui/page/components/order_list.go b/ui/page/components/order_list.go index 4820dc0d1..9a6ac5862 100644 --- a/ui/page/components/order_list.go +++ b/ui/page/components/order_list.go @@ -141,7 +141,7 @@ func LayoutNoOrderHistory(gtx C, l *load.Load, syncing bool) D { func LoadOrders(l *load.Load, offset, limit int32, newestFirst bool, status ...api.Status) []*instantswap.Order { var orders []*instantswap.Order - orders, err := l.WL.AssetsManager.InstantSwap.GetOrdersRaw(offset, limit, newestFirst, status...) + orders, err := l.AssetsManager.InstantSwap.GetOrdersRaw(offset, limit, newestFirst, status...) if err != nil { log.Error(err) } diff --git a/ui/page/components/proposal_list.go b/ui/page/components/proposal_list.go index 3a8d1222c..b616963b4 100644 --- a/ui/page/components/proposal_list.go +++ b/ui/page/components/proposal_list.go @@ -206,7 +206,7 @@ func LayoutNoProposalsFound(gtx C, l *load.Load, syncing bool, category int32) D func LoadProposals(l *load.Load, category, offset, pageSize int32, newestFirst bool) []*ProposalItem { proposalItems := make([]*ProposalItem, 0) - proposals, err := l.WL.AssetsManager.Politeia.GetProposalsRaw(category, offset, pageSize, newestFirst) + proposals, err := l.AssetsManager.Politeia.GetProposalsRaw(category, offset, pageSize, newestFirst) if err == nil { for i := 0; i < len(proposals); i++ { proposal := proposals[i] diff --git a/ui/page/components/receive_modal.go b/ui/page/components/receive_modal.go index 240d7464f..3b9252c31 100644 --- a/ui/page/components/receive_modal.go +++ b/ui/page/components/receive_modal.go @@ -87,7 +87,7 @@ func NewReceiveModal(l *load.Load) *ReceiveModal { func (rm *ReceiveModal) OnResume() { rm.ctx, rm.ctxCancel = context.WithCancel(context.TODO()) - rm.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + rm.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { rm.sourceAccountSelector.SelectFirstValidAccount(selectedWallet) }) } @@ -135,7 +135,7 @@ func (rm *ReceiveModal) generateQRForAddress() { rm.addressEditor.Editor.SetText(rm.currentAddress) var imgOpt qrcode.ImageOption - switch rm.sourceWalletSelector.selectedWallet.Asset.GetAssetType() { + switch rm.sourceWalletSelector.selectedWallet.GetAssetType() { case "DCR": imgOpt = qrcode.WithLogoImage(rm.Theme.Icons.DCR) case "BTC": @@ -396,7 +396,7 @@ func (rm *ReceiveModal) initWalletSelectors() { }) rm.sourceAccountSelector.SelectFirstValidAccount(rm.sourceWalletSelector.SelectedWallet()) - rm.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + rm.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { rm.sourceAccountSelector.SelectFirstValidAccount(selectedWallet) rm.generateAddressAndQRCode() }) diff --git a/ui/page/components/restore_page.go b/ui/page/components/restore_page.go index bfa92ac9b..9889cda21 100644 --- a/ui/page/components/restore_page.go +++ b/ui/page/components/restore_page.go @@ -369,7 +369,7 @@ func (pg *Restore) restoreFromSeedEditor() { return } - walletWithSameSeed, err := pg.WL.AssetsManager.WalletWithSeed(pg.walletType, seedOrHex) + walletWithSameSeed, err := pg.AssetsManager.WalletWithSeed(pg.walletType, seedOrHex) if err != nil { log.Error(err) errMsg := values.String(values.StrInvalidHex) @@ -395,7 +395,7 @@ func (pg *Restore) restoreFromSeedEditor() { ShowWalletInfoTip(true). SetParent(pg). SetPositiveButtonCallback(func(walletName, password string, m *modal.CreatePasswordModal) bool { - _, err := pg.WL.AssetsManager.RestoreWallet(pg.walletType, pg.walletName, seedOrHex, password, sharedW.PassphraseTypePass) + _, err := pg.AssetsManager.RestoreWallet(pg.walletType, pg.walletName, seedOrHex, password, sharedW.PassphraseTypePass) if err != nil { errString := err.Error() if err.Error() == libutils.ErrExist { diff --git a/ui/page/components/seed_restore_page.go b/ui/page/components/seed_restore_page.go index a350531c0..b9370eff6 100644 --- a/ui/page/components/seed_restore_page.go +++ b/ui/page/components/seed_restore_page.go @@ -494,7 +494,7 @@ func (pg *SeedRestore) verifySeeds() bool { // Compare seed with existing wallets seed. On positive match abort import // to prevent duplicate wallet. walletWithSameSeed >= 0 if there is a match. - walletWithSameSeed, err := pg.WL.AssetsManager.WalletWithSeed(pg.walletType, pg.seedPhrase) + walletWithSameSeed, err := pg.AssetsManager.WalletWithSeed(pg.walletType, pg.seedPhrase) if err != nil { log.Error(err) return false @@ -566,7 +566,7 @@ func (pg *SeedRestore) HandleUserInteractions() { ShowWalletInfoTip(true). SetParent(pg). SetPositiveButtonCallback(func(walletName, password string, m *modal.CreatePasswordModal) bool { - _, err := pg.WL.AssetsManager.RestoreWallet(pg.walletType, pg.walletName, pg.seedPhrase, password, sharedW.PassphraseTypePass) + _, err := pg.AssetsManager.RestoreWallet(pg.walletType, pg.walletName, pg.seedPhrase, password, sharedW.PassphraseTypePass) if err != nil { errString := err.Error() if err.Error() == libutils.ErrExist { diff --git a/ui/page/components/select_asset_editor.go b/ui/page/components/select_asset_editor.go index 7bb2920fb..1ba7ce3f7 100644 --- a/ui/page/components/select_asset_editor.go +++ b/ui/page/components/select_asset_editor.go @@ -37,7 +37,7 @@ func (sae SelectAssetEditor) Layout(window app.WindowNavigator, gtx C) D { l := sae.Theme.SeparatorVertical(height, width) l.Color = sae.Theme.Color.Gray3 bg := sae.Theme.Color.White - if sae.WL.AssetsManager.IsDarkModeOn() { + if sae.AssetsManager.IsDarkModeOn() { bg = sae.Theme.Color.Background } return cryptomaterial.LinearLayout{ diff --git a/ui/page/components/vsp_selector.go b/ui/page/components/vsp_selector.go index a4d20a92b..9a6d8c801 100644 --- a/ui/page/components/vsp_selector.go +++ b/ui/page/components/vsp_selector.go @@ -21,6 +21,7 @@ import ( type VSPSelector struct { *load.Load + dcrWallet *dcr.Asset dialogTitle string @@ -29,9 +30,10 @@ type VSPSelector struct { selectedVSP *dcr.VSP } -func NewVSPSelector(l *load.Load) *VSPSelector { +func NewVSPSelector(l *load.Load, dcrWallet *dcr.Asset) *VSPSelector { v := &VSPSelector{ Load: l, + dcrWallet: dcrWallet, showVSPModal: l.Theme.NewClickable(true), } return v @@ -49,7 +51,7 @@ func (v *VSPSelector) Changed() bool { } func (v *VSPSelector) SelectVSP(vspHost string) { - for _, vsp := range v.WL.SelectedWallet.Wallet.(*dcr.Asset).KnownVSPs() { + for _, vsp := range v.dcrWallet.KnownVSPs() { if vsp.Host == vspHost { v.changed = true v.selectedVSP = vsp @@ -64,7 +66,7 @@ func (v *VSPSelector) SelectedVSP() *dcr.VSP { func (v *VSPSelector) handle(window app.WindowNavigator) { if v.showVSPModal.Clicked() { - modal := newVSPSelectorModal(v.Load). + modal := newVSPSelectorModal(v.Load, v.dcrWallet). title(values.String(values.StrVotingServiceProvider)). vspSelected(func(info *dcr.VSP) { v.SelectVSP(info.Host) @@ -143,13 +145,7 @@ type vspSelectorModal struct { isLoadingVSP bool } -func newVSPSelectorModal(l *load.Load) *vspSelectorModal { - impl := l.WL.SelectedWallet.Wallet.(*dcr.Asset) - if impl == nil { - log.Warn(values.ErrDCRSupportedOnly) - return nil - } - +func newVSPSelectorModal(l *load.Load, dcrWallet *dcr.Asset) *vspSelectorModal { v := &vspSelectorModal{ Load: l, Modal: l.Theme.ModalFloatTitle("VSPSelectorModal"), @@ -157,7 +153,7 @@ func newVSPSelectorModal(l *load.Load) *vspSelectorModal { inputVSP: l.Theme.Editor(new(widget.Editor), values.String(values.StrAddVSP)), addVSP: l.Theme.Button(values.String(values.StrSave)), vspList: l.Theme.NewClickableList(layout.Vertical), - dcrImpl: impl, + dcrImpl: dcrWallet, materialLoader: material.Loader(l.Theme.Base), } v.inputVSP.Editor.SingleLine = true diff --git a/ui/page/components/wallet_account_selector.go b/ui/page/components/wallet_account_selector.go index c8c3ba4ef..0cb10b867 100644 --- a/ui/page/components/wallet_account_selector.go +++ b/ui/page/components/wallet_account_selector.go @@ -40,15 +40,15 @@ type selectorModal struct { *load.Load *cryptomaterial.Modal - selectedWallet *load.WalletMapping + selectedWallet sharedW.Asset selectedAccount *sharedW.Account accountCallback func(*sharedW.Account) - walletCallback func(*load.WalletMapping) + walletCallback func(sharedW.Asset) accountIsValid func(*sharedW.Account) bool accountSelector bool infoActionText string dialogTitle string - onWalletClicked func(*load.WalletMapping) + onWalletClicked func(sharedW.Asset) onAccountClicked func(*sharedW.Account) walletsList layout.List selectorItems []*SelectorItem // A SelectorItem can either be a wallet or account @@ -70,7 +70,7 @@ func NewWalletAndAccountSelector(l *load.Load, assetType ...utils.AssetType) *Wa } ws.selectorModal = newSelectorModal(l, assetType...). - walletClicked(func(wallet *load.WalletMapping) { + walletClicked(func(wallet sharedW.Asset) { if ws.selectedWallet.GetWalletID() != wallet.GetWalletID() { ws.changed = true } @@ -117,7 +117,7 @@ func (ws *WalletAndAccountSelector) SetActionInfoText(text string) *WalletAndAcc // SelectFirstValidAccount transforms this widget into an Account selector and selects the first valid account from the // the wallet passed to this method. -func (ws *WalletAndAccountSelector) SelectFirstValidAccount(wallet *load.WalletMapping) error { +func (ws *WalletAndAccountSelector) SelectFirstValidAccount(wallet sharedW.Asset) error { if !ws.accountSelector { ws.accountSelector = true } @@ -152,7 +152,7 @@ func (ws *WalletAndAccountSelector) SetSelectedAsset(assetType ...utils.AssetTyp } ws.assetType = assetType - ws.selectedWallet = ws.selectorItems[0].item.(*load.WalletMapping) + ws.selectedWallet = ws.selectorItems[0].item.(sharedW.Asset) return true } @@ -160,7 +160,7 @@ func (ws *WalletAndAccountSelector) SelectedAsset() utils.AssetType { return ws.assetType[0] } -func (ws *WalletAndAccountSelector) SelectAccount(wallet *load.WalletMapping, accountNumber int32) error { +func (ws *WalletAndAccountSelector) SelectAccount(wallet sharedW.Asset, accountNumber int32) error { ws.accountSelector = true ws.SetSelectedWallet(wallet) @@ -201,7 +201,7 @@ func (ws *WalletAndAccountSelector) Title(title string) *WalletAndAccountSelecto return ws } -func (ws *WalletAndAccountSelector) WalletSelected(callback func(*load.WalletMapping)) *WalletAndAccountSelector { +func (ws *WalletAndAccountSelector) WalletSelected(callback func(sharedW.Asset)) *WalletAndAccountSelector { ws.walletCallback = callback return ws } @@ -224,11 +224,11 @@ func (ws *WalletAndAccountSelector) Handle(window app.WindowNavigator) { } } -func (ws *WalletAndAccountSelector) SetSelectedWallet(wallet *load.WalletMapping) { +func (ws *WalletAndAccountSelector) SetSelectedWallet(wallet sharedW.Asset) { ws.selectedWallet = wallet } -func (ws *WalletAndAccountSelector) SelectedWallet() *load.WalletMapping { +func (ws *WalletAndAccountSelector) SelectedWallet() sharedW.Asset { return ws.selectedWallet } @@ -412,21 +412,19 @@ func newSelectorModal(l *load.Load, assetType ...utils.AssetType) *selectorModal for _, asset := range assetType { switch asset { case utils.BTCWalletAsset: - wallets = append(wallets, sm.WL.AssetsManager.AllBTCWallets()...) + wallets = append(wallets, sm.AssetsManager.AllBTCWallets()...) case utils.DCRWalletAsset: - wallets = append(wallets, sm.WL.AssetsManager.AllDCRWallets()...) + wallets = append(wallets, sm.AssetsManager.AllDCRWallets()...) case utils.LTCWalletAsset: - wallets = append(wallets, sm.WL.AssetsManager.AllLTCWallets()...) + wallets = append(wallets, sm.AssetsManager.AllLTCWallets()...) } } if len(wallets) == 0 { - wallets = sm.WL.AssetsManager.AllWallets() + wallets = sm.AssetsManager.AllWallets() } - sm.selectedWallet = &load.WalletMapping{ - Asset: wallets[0], - } // Set the default wallet to wallet loaded by cryptopower. + sm.selectedWallet = wallets[0] // Set the default wallet to wallet loaded by cryptopower. sm.accountSelector = false sm.Modal.ShowScrollbar(true) @@ -444,13 +442,13 @@ func (sm *selectorModal) OnResume() { func (sm *selectorModal) setupWallet(assetType ...utils.AssetType) { selectorItems := make([]*SelectorItem, 0) - wallets := sm.WL.AssetsManager.AssetWallets(assetType...) + wallets := sm.AssetsManager.AssetWallets(assetType...) for _, wal := range wallets { if wal.IsWatchingOnlyWallet() && !sm.isWatchOnlyEnabled { continue } selectorItems = append(selectorItems, &SelectorItem{ - item: load.NewWalletMapping(wal), + item: wal, clickable: sm.Theme.NewClickable(true), }) } @@ -494,7 +492,7 @@ func (sm *selectorModal) Handle() { if sm.onAccountClicked != nil { sm.onAccountClicked(item) } - case *load.WalletMapping: + case sharedW.Asset: if sm.onWalletClicked != nil { sm.onWalletClicked(item) } @@ -522,7 +520,7 @@ func (sm *selectorModal) title(title string) *selectorModal { return sm } -func (sm *selectorModal) walletClicked(callback func(*load.WalletMapping)) *selectorModal { +func (sm *selectorModal) walletClicked(callback func(sharedW.Asset)) *selectorModal { sm.onWalletClicked = callback return sm } diff --git a/ui/page/components/wallet_setup_page.go b/ui/page/components/wallet_setup_page.go index e8090baac..659cfd0eb 100644 --- a/ui/page/components/wallet_setup_page.go +++ b/ui/page/components/wallet_setup_page.go @@ -96,7 +96,7 @@ func NewCreateWallet(l *load.Load, walletCreationSuccessCallback func(), assetTy } bg := l.Theme.Color.White - if l.WL.AssetsManager.IsDarkModeOn() { + if l.AssetsManager.IsDarkModeOn() { bg = l.Theme.Color.Background } pg.assetTypeSelector.SetBackground(bg) @@ -266,7 +266,7 @@ func (pg *CreateWallet) walletOptions(gtx C) D { BottomLeft: 8, } border := pg.Theme.Color.White - if pg.WL.AssetsManager.IsDarkModeOn() { + if pg.AssetsManager.IsDarkModeOn() { border = pg.Theme.Color.Background } item.border = cryptomaterial.Border{ @@ -280,7 +280,7 @@ func (pg *CreateWallet) walletOptions(gtx C) D { col = pg.Theme.Color.White title.Color = pg.Theme.Color.Primary - if pg.WL.AssetsManager.IsDarkModeOn() { + if pg.AssetsManager.IsDarkModeOn() { col = pg.Theme.Color.Gray2 title.Color = pg.Theme.Color.White } @@ -455,7 +455,7 @@ func (pg *CreateWallet) HandleUserInteractions() { switch *pg.assetTypeSelector.SelectedAssetType() { case libutils.DCRWalletAsset: - wal, err := pg.WL.AssetsManager.CreateNewDCRWallet(pg.walletName.Editor.Text(), pg.passwordEditor.Editor.Text(), sharedW.PassphraseTypePass) + wal, err := pg.AssetsManager.CreateNewDCRWallet(pg.walletName.Editor.Text(), pg.passwordEditor.Editor.Text(), sharedW.PassphraseTypePass) if err != nil { if err.Error() == libutils.ErrExist { pg.walletName.SetError(values.StringF(values.StrWalletExist, pg.walletName.Editor.Text())) @@ -477,7 +477,7 @@ func (pg *CreateWallet) HandleUserInteractions() { wal.SetBoolConfigValueForKey(sharedW.AccountMixerConfigSet, true) case libutils.BTCWalletAsset: - _, err := pg.WL.AssetsManager.CreateNewBTCWallet(pg.walletName.Editor.Text(), pg.passwordEditor.Editor.Text(), sharedW.PassphraseTypePass) + _, err := pg.AssetsManager.CreateNewBTCWallet(pg.walletName.Editor.Text(), pg.passwordEditor.Editor.Text(), sharedW.PassphraseTypePass) if err != nil { if err.Error() == libutils.ErrExist { pg.walletName.SetError(values.StringF(values.StrWalletExist, pg.walletName.Editor.Text())) @@ -490,7 +490,7 @@ func (pg *CreateWallet) HandleUserInteractions() { } case libutils.LTCWalletAsset: - _, err := pg.WL.AssetsManager.CreateNewLTCWallet(pg.walletName.Editor.Text(), pg.passwordEditor.Editor.Text(), sharedW.PassphraseTypePass) + _, err := pg.AssetsManager.CreateNewLTCWallet(pg.walletName.Editor.Text(), pg.passwordEditor.Editor.Text(), sharedW.PassphraseTypePass) if err != nil { if err.Error() == libutils.ErrExist { pg.walletName.SetError(values.StringF(values.StrWalletExist, pg.walletName.Editor.Text())) @@ -525,25 +525,25 @@ func (pg *CreateWallet) HandleUserInteractions() { switch *pg.assetTypeSelector.SelectedAssetType() { case libutils.DCRWalletAsset: var walletWithXPub int - walletWithXPub, err = pg.WL.AssetsManager.DCRWalletWithXPub(pg.watchOnlyWalletHex.Editor.Text()) + walletWithXPub, err = pg.AssetsManager.DCRWalletWithXPub(pg.watchOnlyWalletHex.Editor.Text()) if walletWithXPub == -1 { - _, err = pg.WL.AssetsManager.CreateNewDCRWatchOnlyWallet(pg.walletName.Editor.Text(), pg.watchOnlyWalletHex.Editor.Text()) + _, err = pg.AssetsManager.CreateNewDCRWatchOnlyWallet(pg.walletName.Editor.Text(), pg.watchOnlyWalletHex.Editor.Text()) } else { err = errors.New(values.String(values.StrXpubWalletExist)) } case libutils.BTCWalletAsset: var walletWithXPub int - walletWithXPub, err = pg.WL.AssetsManager.BTCWalletWithXPub(pg.watchOnlyWalletHex.Editor.Text()) + walletWithXPub, err = pg.AssetsManager.BTCWalletWithXPub(pg.watchOnlyWalletHex.Editor.Text()) if walletWithXPub == -1 { - _, err = pg.WL.AssetsManager.CreateNewBTCWatchOnlyWallet(pg.walletName.Editor.Text(), pg.watchOnlyWalletHex.Editor.Text()) + _, err = pg.AssetsManager.CreateNewBTCWatchOnlyWallet(pg.walletName.Editor.Text(), pg.watchOnlyWalletHex.Editor.Text()) } else { err = errors.New(values.String(values.StrXpubWalletExist)) } case libutils.LTCWalletAsset: var walletWithXPub int - walletWithXPub, err = pg.WL.AssetsManager.LTCWalletWithXPub(pg.watchOnlyWalletHex.Editor.Text()) + walletWithXPub, err = pg.AssetsManager.LTCWalletWithXPub(pg.watchOnlyWalletHex.Editor.Text()) if walletWithXPub == -1 { - _, err = pg.WL.AssetsManager.CreateNewLTCWatchOnlyWallet(pg.walletName.Editor.Text(), pg.watchOnlyWalletHex.Editor.Text()) + _, err = pg.AssetsManager.CreateNewLTCWatchOnlyWallet(pg.walletName.Editor.Text(), pg.watchOnlyWalletHex.Editor.Text()) } else { err = errors.New(values.String(values.StrXpubWalletExist)) } diff --git a/ui/page/dcrdex/dex_onboarding_page.go b/ui/page/dcrdex/dex_onboarding_page.go index d3c7b7d64..c941422b6 100644 --- a/ui/page/dcrdex/dex_onboarding_page.go +++ b/ui/page/dcrdex/dex_onboarding_page.go @@ -122,7 +122,7 @@ func NewDEXOnboarding(l *load.Load) *DEXOnboarding { currentStep: onboardingSetPassword, passwordEditor: newPasswordEditor(th, values.String(values.StrNewPassword)), confirmPasswordEditor: newPasswordEditor(th, values.String(values.StrConfirmPassword)), - serverDropDown: th.DropDown(knownDEXServers[l.WL.AssetsManager.NetType()], values.DEXServerDropdownGroup, 0), + serverDropDown: th.DropDown(knownDEXServers[l.AssetsManager.NetType()], values.DEXServerDropdownGroup, 0), addServerBtn: th.NewClickable(false), serverURLEditor: newTextEditor(th, values.String(values.StrServerURL), values.String(values.StrInputURL), false), serverCertEditor: newTextEditor(th, values.String(values.StrCertificateOPtional), values.String(values.StrInputCertificate), true), @@ -875,7 +875,7 @@ func (pg *DEXOnboarding) HandleUserInteractions() { } pg.currentStep = onBoardingStepAddServer - knownServers, ok := knownDEXServers[pg.WL.AssetsManager.NetType()] + knownServers, ok := knownDEXServers[pg.AssetsManager.NetType()] if ok && len(knownServers) > 0 && !pg.wantCustomServer { pg.currentStep = onboardingChooseServer } @@ -907,7 +907,7 @@ func (pg *DEXOnboarding) HandleUserInteractions() { pg.currentStep = onboardingPostBond pg.bondSourceWalletSelector = components.NewWalletAndAccountSelector(pg.Load /*, supportedAssets... TODO: Use assets provided by selected DEX server. */). Title(values.String(values.StrSelectWallet)). - WalletSelected(func(wm *load.WalletMapping) { + WalletSelected(func(wm sharedW.Asset) { if err := pg.bondSourceAccountSelector.SelectFirstValidAccount(wm); err != nil { log.Error(err) } diff --git a/ui/page/exchange/confirm_order_modal.go b/ui/page/exchange/confirm_order_modal.go index 40522e1c9..4979bb2a5 100644 --- a/ui/page/exchange/confirm_order_modal.go +++ b/ui/page/exchange/confirm_order_modal.go @@ -132,7 +132,7 @@ func (com *confirmOrderModal) confirmOrder() { err = com.constructTx(order.DepositAddress, order.InvoicedAmount) if err != nil { - com.WL.AssetsManager.InstantSwap.DeleteOrder(order) + com.AssetsManager.InstantSwap.DeleteOrder(order) com.SetError(err.Error()) com.SetLoading(false) return @@ -141,7 +141,7 @@ func (com *confirmOrderModal) confirmOrder() { // FOR DEVELOPMENT: Comment this block to prevent debit of account _, err = com.sourceWalletSelector.SelectedWallet().Broadcast(password, "") if err != nil { - com.WL.AssetsManager.InstantSwap.DeleteOrder(order) + com.AssetsManager.InstantSwap.DeleteOrder(order) com.SetError(err.Error()) com.SetLoading(false) return @@ -210,7 +210,7 @@ func (com *confirmOrderModal) Layout(gtx layout.Context) D { return components.LayoutOrderAmount(com.Load, gtx, com.orderData.fromCurrency.String(), com.orderData.invoicedAmount) }), layout.Rigid(func(gtx C) D { - sourceWallet := com.WL.AssetsManager.WalletWithID(com.orderData.sourceWalletID) + sourceWallet := com.AssetsManager.WalletWithID(com.orderData.sourceWalletID) sourceWalletName := sourceWallet.GetWalletName() sourceAccount, _ := sourceWallet.GetAccount(com.orderData.sourceAccountNumber) fromText := fmt.Sprintf(values.String(values.StrOrderSendingFrom), sourceWalletName, sourceAccount.Name) @@ -246,7 +246,7 @@ func (com *confirmOrderModal) Layout(gtx layout.Context) D { return components.LayoutOrderAmount(com.Load, gtx, com.orderData.toCurrency.String(), com.orderData.orderedAmount) }), layout.Rigid(func(gtx C) D { - destinationWallet := com.WL.AssetsManager.WalletWithID(com.orderData.destinationWalletID) + destinationWallet := com.AssetsManager.WalletWithID(com.orderData.destinationWalletID) destinationWalletName := destinationWallet.GetWalletName() destinationAccount, _ := destinationWallet.GetAccount(com.orderData.destinationAccountNumber) toText := fmt.Sprintf(values.String(values.StrOrderReceivingTo), destinationWalletName, destinationAccount.Name) @@ -338,7 +338,7 @@ func (com *confirmOrderModal) createOrder() (*instantswap.Order, error) { DestinationAddress: com.destinationAddress, } - order, err := com.WL.AssetsManager.InstantSwap.CreateOrder(com.exchange, data) + order, err := com.AssetsManager.InstantSwap.CreateOrder(com.exchange, data) if err != nil { return nil, err } diff --git a/ui/page/exchange/create_order_page.go b/ui/page/exchange/create_order_page.go index 4b4eb218e..319a2eb53 100644 --- a/ui/page/exchange/create_order_page.go +++ b/ui/page/exchange/create_order_page.go @@ -186,7 +186,7 @@ func NewCreateOrderPage(l *load.Load) *CreateOrderPage { pg.selectedExchange = es // Initialize a new exchange using the selected exchange server - exchange, err := pg.WL.AssetsManager.InstantSwap.NewExchangeServer(pg.selectedExchange.Server) + exchange, err := pg.AssetsManager.InstantSwap.NewExchangeServer(pg.selectedExchange.Server) if err != nil { log.Error(err) return @@ -264,7 +264,7 @@ func (pg *CreateOrderPage) OnNavigatedTo() { // once after it has been displayed. func (pg *CreateOrderPage) initPage() { pg.inited = true - pg.scheduler.SetChecked(pg.WL.AssetsManager.IsOrderSchedulerRunning()) + pg.scheduler.SetChecked(pg.AssetsManager.IsOrderSchedulerRunning()) pg.listenForNotifications() pg.loadOrderConfig() go pg.scroll.FetchScrollData(false, pg.ParentWindow()) @@ -397,7 +397,7 @@ func (pg *CreateOrderPage) HandleUserInteractions() { } if pg.refreshClickable.Clicked() { - go pg.WL.AssetsManager.InstantSwap.Sync(context.Background()) + go pg.AssetsManager.InstantSwap.Sync(context.Background()) } if pg.scheduler.Changed() { @@ -430,7 +430,7 @@ func (pg *CreateOrderPage) HandleUserInteractions() { }) pg.ParentWindow().ShowModal(orderSettingsModal) } else { - pg.WL.AssetsManager.StopScheduler() + pg.AssetsManager.StopScheduler() } } @@ -515,7 +515,7 @@ func (pg *CreateOrderPage) updateAssetSelection(selectedFromAsset []utils.AssetT // If the to and from asset are the same, select a new to asset. if selectedAsset == pg.toCurrency { // Get all available assets. - allAssets := pg.WL.AssetsManager.AllAssetTypes() + allAssets := pg.AssetsManager.AllAssetTypes() for _, asset := range allAssets { if asset != selectedAsset { @@ -548,7 +548,7 @@ func (pg *CreateOrderPage) updateAssetSelection(selectedFromAsset []utils.AssetT if selectedAsset == pg.fromCurrency { // Get all available assets. - allAssets := pg.WL.AssetsManager.AllAssetTypes() + allAssets := pg.AssetsManager.AllAssetTypes() for _, asset := range allAssets { if asset != selectedAsset { @@ -616,7 +616,7 @@ func (pg *CreateOrderPage) swapCurrency() { } func (pg *CreateOrderPage) isExchangeAPIAllowed() bool { - isAllowed := pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.ExchangeHTTPAPI) + isAllowed := pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.ExchangeHTTPAPI) if !isAllowed { pg.errMsg = values.StringF(values.StrNotAllowed, values.String(values.StrExchange)) } @@ -628,10 +628,10 @@ func (pg *CreateOrderPage) isExchangeAPIAllowed() bool { // functionality is disable till different asset type wallets are created. func (pg *CreateOrderPage) isMultipleAssetTypeWalletAvailable() bool { pg.errMsg = values.String(values.StrMinimumAssetType) - allWallets := len(pg.WL.AssetsManager.AllWallets()) - btcWallets := len(pg.WL.AssetsManager.AllBTCWallets()) - dcrWallets := len(pg.WL.AssetsManager.AllDCRWallets()) - ltcWallets := len(pg.WL.AssetsManager.AllLTCWallets()) + allWallets := len(pg.AssetsManager.AllWallets()) + btcWallets := len(pg.AssetsManager.AllBTCWallets()) + dcrWallets := len(pg.AssetsManager.AllDCRWallets()) + ltcWallets := len(pg.AssetsManager.AllLTCWallets()) if allWallets == 0 { // no wallets exist return false @@ -656,7 +656,7 @@ func (pg *CreateOrderPage) Layout(gtx C) D { var overlaySet bool var navBtn *cryptomaterial.Button - isTestNet := pg.Load.WL.AssetsManager.NetType() != libutils.Mainnet + isTestNet := pg.Load.AssetsManager.NetType() != libutils.Mainnet switch { case isTestNet: msg = values.String(values.StrNoExchangeOnTestnet) @@ -750,7 +750,7 @@ func (pg *CreateOrderPage) layout(gtx C) D { return title.Layout(gtx) }), layout.Rigid(func(gtx C) D { - if pg.WL.AssetsManager.IsOrderSchedulerRunning() { + if pg.AssetsManager.IsOrderSchedulerRunning() { return layout.Flex{ Axis: layout.Horizontal, }.Layout(gtx, @@ -761,7 +761,7 @@ func (pg *CreateOrderPage) layout(gtx C) D { }.Layout(gtx, pg.Theme.Icons.TimerIcon.Layout12dp) }), layout.Rigid(func(gtx C) D { - title := pg.Theme.Label(values.TextSize16, pg.WL.AssetsManager.GetShedulerRuntime()) + title := pg.Theme.Label(values.TextSize16, pg.AssetsManager.GetShedulerRuntime()) title.Color = pg.Theme.Color.GrayText2 return title.Layout(gtx) }), @@ -778,7 +778,7 @@ func (pg *CreateOrderPage) layout(gtx C) D { }.Layout(gtx, pg.scheduler.Layout) }), layout.Rigid(func(gtx C) D { - if pg.WL.AssetsManager.IsOrderSchedulerRunning() { + if pg.AssetsManager.IsOrderSchedulerRunning() { return layout.Inset{Left: values.MarginPadding4, Top: unit.Dp(2)}.Layout(gtx, func(gtx C) D { gtx.Constraints.Max.X = gtx.Dp(values.MarginPadding16) gtx.Constraints.Min.X = gtx.Constraints.Max.X @@ -918,7 +918,7 @@ func (pg *CreateOrderPage) layout(gtx C) D { return txt.Layout(gtx) }), layout.Rigid(func(gtx C) D { - ticker := pg.WL.AssetsManager.RateSource.GetTicker(fromCur + ext.MktSep + toCur) + ticker := pg.AssetsManager.RateSource.GetTicker(fromCur + ext.MktSep + toCur) if ticker == nil || ticker.LastTradePrice <= 0 { return D{} } @@ -933,7 +933,7 @@ func (pg *CreateOrderPage) layout(gtx C) D { rate = 1 / ticker.LastTradePrice } - binanceRate := values.StringF(values.StrCurrencyConverterRate, pg.WL.AssetsManager.RateSource.Name(), fromCur, rate, toCur) + binanceRate := values.StringF(values.StrCurrencyConverterRate, pg.AssetsManager.RateSource.Name(), fromCur, rate, toCur) txt := pg.Theme.Label(values.TextSize14, binanceRate) txt.Font.Weight = font.SemiBold txt.Color = pg.Theme.Color.Gray1 @@ -973,12 +973,12 @@ func (pg *CreateOrderPage) layout(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.End}.Layout(gtx, layout.Rigid(func(gtx C) D { var text string - if pg.WL.AssetsManager.InstantSwap.IsSyncing() { + if pg.AssetsManager.InstantSwap.IsSyncing() { text = values.String(values.StrSyncingState) } else { - text = values.String(values.StrUpdated) + " " + components.TimeAgo(pg.WL.AssetsManager.InstantSwap.GetLastSyncedTimeStamp()) + text = values.String(values.StrUpdated) + " " + components.TimeAgo(pg.AssetsManager.InstantSwap.GetLastSyncedTimeStamp()) - if pg.WL.AssetsManager.InstantSwap.GetLastSyncedTimeStamp() == 0 { + if pg.AssetsManager.InstantSwap.GetLastSyncedTimeStamp() == 0 { text = values.String(values.StrNeverSynced) } } @@ -997,7 +997,7 @@ func (pg *CreateOrderPage) layout(gtx C) D { Margin: layout.Inset{Left: values.MarginPadding10}, }.Layout(gtx, layout.Rigid(func(gtx C) D { - if pg.WL.AssetsManager.InstantSwap.IsSyncing() { + if pg.AssetsManager.InstantSwap.IsSyncing() { gtx.Constraints.Max.X = gtx.Dp(values.MarginPadding8) gtx.Constraints.Min.X = gtx.Constraints.Max.X return layout.Inset{Bottom: values.MarginPadding1}.Layout(gtx, pg.materialLoader.Layout) @@ -1134,7 +1134,7 @@ func (pg *CreateOrderPage) getExchangeRateInfo() error { To: toCur, Amount: libwallet.DefaultRateRequestAmount, // amount needs to be greater than 0 to get the exchange rate } - res, err := pg.WL.AssetsManager.InstantSwap.GetExchangeRateInfo(pg.exchange, params) + res, err := pg.AssetsManager.InstantSwap.GetExchangeRateInfo(pg.exchange, params) if err != nil { pg.exchangeRateInfo = values.String(values.StrFetchRateError) pg.rateError = true @@ -1158,36 +1158,32 @@ func (pg *CreateOrderPage) getExchangeRateInfo() error { // one if none existed before. func (pg *CreateOrderPage) loadOrderConfig() { sourceAccount, destinationAccount := int32(-1), int32(-1) - var sourceWallet, destinationWallet *load.WalletMapping + var sourceWallet, destinationWallet sharedW.Asset // isConfigUpdateRequired is set to true when updating the configuration is // necessary. var isConfigUpdateRequired bool - if pg.WL.AssetsManager.IsExchangeConfigSet() { + if pg.AssetsManager.IsExchangeConfigSet() { // Use preset exchange configuration. - exchangeConfig := pg.WL.AssetsManager.GetExchangeConfig() + exchangeConfig := pg.AssetsManager.GetExchangeConfig() pg.fromCurrency = exchangeConfig.SourceAsset pg.toCurrency = exchangeConfig.DestinationAsset - sourceWallet = &load.WalletMapping{ - Asset: pg.WL.AssetsManager.WalletWithID(int(exchangeConfig.SourceWalletID)), - } - destinationWallet = &load.WalletMapping{ - Asset: pg.WL.AssetsManager.WalletWithID(int(exchangeConfig.DestinationWalletID)), - } + sourceWallet = pg.AssetsManager.WalletWithID(int(exchangeConfig.SourceWalletID)) + destinationWallet = pg.AssetsManager.WalletWithID(int(exchangeConfig.DestinationWalletID)) sourceAccount = exchangeConfig.SourceAccountNumber destinationAccount = exchangeConfig.DestinationAccountNumber } - noSourceWallet := sourceWallet == nil || sourceWallet.Asset == nil - noDestinationWallet := destinationWallet == nil || destinationWallet.Asset == nil + noSourceWallet := sourceWallet == nil + noDestinationWallet := destinationWallet == nil if noSourceWallet || noDestinationWallet { // New exchange configuration will be generated using the set asset // types since none existed before. It two distinct asset type wallet // don't exist execution does get here. - wallets := pg.WL.AssetsManager.AllWallets() + wallets := pg.AssetsManager.AllWallets() if noSourceWallet { pg.fromCurrency = wallets[0].GetAssetType() } @@ -1234,7 +1230,7 @@ func (pg *CreateOrderPage) loadOrderConfig() { pg.sourceAccountSelector.SelectFirstValidAccount(sourceWallet) } - pg.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + pg.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { pg.sourceAccountSelector.SelectFirstValidAccount(selectedWallet) }) @@ -1270,7 +1266,7 @@ func (pg *CreateOrderPage) loadOrderConfig() { pg.destinationAccountSelector.SelectFirstValidAccount(destinationWallet) } - pg.destinationWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + pg.destinationWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { pg.destinationAccountSelector.SelectFirstValidAccount(selectedWallet) }) @@ -1294,7 +1290,7 @@ func (pg *CreateOrderPage) updateExchangeConfig() { DestinationAccountNumber: pg.destinationAccountSelector.SelectedAccount().Number, } - pg.WL.AssetsManager.SetExchangeConfig(configInfo) + pg.AssetsManager.SetExchangeConfig(configInfo) } func (pg *CreateOrderPage) listenForNotifications() { @@ -1302,9 +1298,9 @@ func (pg *CreateOrderPage) listenForNotifications() { return } - pg.WL.AssetsManager.InstantSwap.RemoveNotificationListener(CreateOrderPageID) // clear if any + pg.AssetsManager.InstantSwap.RemoveNotificationListener(CreateOrderPageID) // clear if any pg.OrderNotificationListener = listeners.NewOrderNotificationListener() - err := pg.WL.AssetsManager.InstantSwap.AddNotificationListener(pg.OrderNotificationListener, CreateOrderPageID) + err := pg.AssetsManager.InstantSwap.AddNotificationListener(pg.OrderNotificationListener, CreateOrderPageID) if err != nil { log.Errorf("Error adding instantswap notification listener: %v", err) return @@ -1319,13 +1315,13 @@ func (pg *CreateOrderPage) listenForNotifications() { pg.scroll.FetchScrollData(false, pg.ParentWindow()) pg.ParentWindow().Reload() case wallet.OrderSchedulerStarted: - pg.scheduler.SetChecked(pg.WL.AssetsManager.IsOrderSchedulerRunning()) + pg.scheduler.SetChecked(pg.AssetsManager.IsOrderSchedulerRunning()) case wallet.OrderSchedulerEnded: pg.scheduler.SetChecked(false) } case <-pg.ctx.Done(): - pg.WL.AssetsManager.RateSource.RemoveRateListener(CreateOrderPageID) - pg.WL.AssetsManager.InstantSwap.RemoveNotificationListener(CreateOrderPageID) + pg.AssetsManager.RateSource.RemoveRateListener(CreateOrderPageID) + pg.AssetsManager.InstantSwap.RemoveNotificationListener(CreateOrderPageID) close(pg.OrderNotifChan) pg.OrderNotificationListener = nil diff --git a/ui/page/exchange/exchange_selector.go b/ui/page/exchange/exchange_selector.go index a307cb3dd..ddb23faac 100644 --- a/ui/page/exchange/exchange_selector.go +++ b/ui/page/exchange/exchange_selector.go @@ -88,7 +88,7 @@ func (es *ExSelector) SupportedExchanges(server ...instantswap.Server) []*Exchan return []*Exchange{exchng} } - exchangeServers := es.WL.AssetsManager.InstantSwap.ExchangeServers() + exchangeServers := es.AssetsManager.InstantSwap.ExchangeServers() var exchange []*Exchange for _, exchangeServer := range exchangeServers { @@ -171,7 +171,7 @@ func (es *ExSelector) Layout(window app.WindowNavigator, gtx C) D { es.Handle(window) bg := es.Theme.Color.White - if es.WL.AssetsManager.IsDarkModeOn() { + if es.AssetsManager.IsDarkModeOn() { bg = es.Theme.Color.Background } diff --git a/ui/page/exchange/order_details_page.go b/ui/page/exchange/order_details_page.go index 3d4252071..c21c9e7b0 100644 --- a/ui/page/exchange/order_details_page.go +++ b/ui/page/exchange/order_details_page.go @@ -70,13 +70,13 @@ func NewOrderDetailsPage(l *load.Load, order *instantswap.Order) *OrderDetailsPa order.ExchangeServer.Config = instantswap.ExchangeConfig{} } - err := pg.WL.AssetsManager.InstantSwap.UpdateOrder(order) + err := pg.AssetsManager.InstantSwap.UpdateOrder(order) if err != nil { log.Errorf("Error updating legacy order: %v", err) } } - exchange, err := pg.WL.AssetsManager.InstantSwap.NewExchangeServer(order.ExchangeServer) + exchange, err := pg.AssetsManager.InstantSwap.NewExchangeServer(order.ExchangeServer) if err != nil { log.Error(err) } @@ -197,7 +197,7 @@ func (pg *OrderDetailsPage) layout(gtx C) D { return components.LayoutOrderAmount(pg.Load, gtx, pg.orderInfo.FromCurrency, pg.orderInfo.InvoicedAmount) }), layout.Rigid(func(gtx C) D { - sourceWallet := pg.WL.AssetsManager.WalletWithID(pg.orderInfo.SourceWalletID) + sourceWallet := pg.AssetsManager.WalletWithID(pg.orderInfo.SourceWalletID) sourceWalletName := sourceWallet.GetWalletName() sourceAccount, _ := sourceWallet.GetAccount(pg.orderInfo.SourceAccountNumber) fromText := fmt.Sprintf(values.String(values.StrOrderSendingFrom), sourceWalletName, sourceAccount.Name) @@ -232,7 +232,7 @@ func (pg *OrderDetailsPage) layout(gtx C) D { return components.LayoutOrderAmount(pg.Load, gtx, pg.orderInfo.ToCurrency, pg.orderInfo.OrderedAmount) }), layout.Rigid(func(gtx C) D { - destinationWallet := pg.WL.AssetsManager.WalletWithID(pg.orderInfo.DestinationWalletID) + destinationWallet := pg.AssetsManager.WalletWithID(pg.orderInfo.DestinationWalletID) destinationWalletName := destinationWallet.GetWalletName() destinationAccount, _ := destinationWallet.GetAccount(pg.orderInfo.DestinationAccountNumber) toText := fmt.Sprintf(values.String(values.StrOrderReceivingTo), destinationWalletName, destinationAccount.Name) @@ -299,7 +299,7 @@ func (pg *OrderDetailsPage) layout(gtx C) D { } func (pg *OrderDetailsPage) getOrderInfo(UUID string) (*instantswap.Order, error) { - orderInfo, err := pg.WL.AssetsManager.InstantSwap.GetOrderInfo(pg.exchange, UUID) + orderInfo, err := pg.AssetsManager.InstantSwap.GetOrderInfo(pg.exchange, UUID) if err != nil { return nil, err } diff --git a/ui/page/exchange/order_history_page.go b/ui/page/exchange/order_history_page.go index 7956a1a41..40ababe3e 100644 --- a/ui/page/exchange/order_history_page.go +++ b/ui/page/exchange/order_history_page.go @@ -104,7 +104,7 @@ func (pg *OrderHistoryPage) HandleUserInteractions() { } if pg.refreshClickable.Clicked() { - go pg.WL.AssetsManager.InstantSwap.Sync(pg.ctx) + go pg.AssetsManager.InstantSwap.Sync(pg.ctx) } } @@ -166,12 +166,12 @@ func (pg *OrderHistoryPage) layout(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.End}.Layout(gtx, layout.Rigid(func(gtx C) D { var text string - if pg.WL.AssetsManager.InstantSwap.IsSyncing() { + if pg.AssetsManager.InstantSwap.IsSyncing() { text = values.String(values.StrSyncingState) } else { - text = values.String(values.StrUpdated) + " " + components.TimeAgo(pg.WL.AssetsManager.InstantSwap.GetLastSyncedTimeStamp()) + text = values.String(values.StrUpdated) + " " + components.TimeAgo(pg.AssetsManager.InstantSwap.GetLastSyncedTimeStamp()) - if pg.WL.AssetsManager.InstantSwap.GetLastSyncedTimeStamp() == 0 { + if pg.AssetsManager.InstantSwap.GetLastSyncedTimeStamp() == 0 { text = values.String(values.StrNeverSynced) } } @@ -190,7 +190,7 @@ func (pg *OrderHistoryPage) layout(gtx C) D { Margin: layout.Inset{Left: values.MarginPadding10}, }.Layout(gtx, layout.Rigid(func(gtx C) D { - if pg.WL.AssetsManager.InstantSwap.IsSyncing() { + if pg.AssetsManager.InstantSwap.IsSyncing() { gtx.Constraints.Max.X = gtx.Dp(values.MarginPadding8) gtx.Constraints.Min.X = gtx.Constraints.Max.X return layout.Inset{Bottom: values.MarginPadding1}.Layout(gtx, pg.materialLoader.Layout) @@ -295,7 +295,7 @@ func (pg *OrderHistoryPage) listenForSyncNotifications() { return } pg.OrderNotificationListener = listeners.NewOrderNotificationListener() - err := pg.WL.AssetsManager.InstantSwap.AddNotificationListener(pg.OrderNotificationListener, OrderHistoryPageID) + err := pg.AssetsManager.InstantSwap.AddNotificationListener(pg.OrderNotificationListener, OrderHistoryPageID) if err != nil { log.Errorf("Error adding instanswap notification listener: %v", err) return @@ -310,7 +310,7 @@ func (pg *OrderHistoryPage) listenForSyncNotifications() { pg.ParentWindow().Reload() } case <-pg.ctx.Done(): - pg.WL.AssetsManager.InstantSwap.RemoveNotificationListener(OrderHistoryPageID) + pg.AssetsManager.InstantSwap.RemoveNotificationListener(OrderHistoryPageID) close(pg.OrderNotifChan) pg.OrderNotificationListener = nil diff --git a/ui/page/exchange/order_scheduler_modal.go b/ui/page/exchange/order_scheduler_modal.go index e17984dc2..32854050b 100644 --- a/ui/page/exchange/order_scheduler_modal.go +++ b/ui/page/exchange/order_scheduler_modal.go @@ -98,7 +98,7 @@ func newOrderSchedulerModalModal(l *load.Load, data *orderData) *orderSchedulerM osm.exchangeSelector.ExchangeSelected(func(es *Exchange) { // Initialize a new exchange using the selected exchange server - exchange, err := osm.WL.AssetsManager.InstantSwap.NewExchangeServer(es.Server) + exchange, err := osm.AssetsManager.InstantSwap.NewExchangeServer(es.Server) if err != nil { log.Error(err) return @@ -285,7 +285,7 @@ func (osm *orderSchedulerModal) Layout(gtx layout.Context) D { return txt.Layout(gtx) }), layout.Rigid(func(gtx C) D { - ticker := osm.WL.AssetsManager.RateSource.GetTicker(fromCur + ext.MktSep + toCur) + ticker := osm.AssetsManager.RateSource.GetTicker(fromCur + ext.MktSep + toCur) if ticker == nil || ticker.LastTradePrice <= 0 { return D{} } @@ -300,7 +300,7 @@ func (osm *orderSchedulerModal) Layout(gtx layout.Context) D { rate = 1 / ticker.LastTradePrice } - binanceRate := values.StringF(values.StrCurrencyConverterRate, osm.WL.AssetsManager.RateSource.Name(), fromCur, rate, toCur) + binanceRate := values.StringF(values.StrCurrencyConverterRate, osm.AssetsManager.RateSource.Name(), fromCur, rate, toCur) txt := osm.Theme.Label(values.TextSize14, binanceRate) txt.Font.Weight = font.SemiBold txt.Color = osm.Theme.Color.Gray1 @@ -389,7 +389,7 @@ func (osm *orderSchedulerModal) Layout(gtx layout.Context) D { txt := osm.Theme.Label(values.TextSize14, msg) txt.Alignment = text.Middle txt.Color = osm.Theme.Color.GrayText3 - if osm.WL.AssetsManager.IsDarkModeOn() { + if osm.AssetsManager.IsDarkModeOn() { txt.Color = osm.Theme.Color.Gray3 } return txt.Layout(gtx) @@ -485,7 +485,7 @@ func (osm *orderSchedulerModal) startOrderScheduler() { SpendingPassphrase: osm.passwordEditor.Editor.Text(), } - go osm.WL.AssetsManager.StartScheduler(context.Background(), params) + go osm.AssetsManager.StartScheduler(context.Background(), params) osm.Dismiss() osm.orderSchedulerStarted() @@ -503,7 +503,7 @@ func (osm *orderSchedulerModal) getExchangeRateInfo() error { To: toCur, Amount: libwallet.DefaultRateRequestAmount, // amount needs to be greater than 0 to get the exchange rate } - res, err := osm.WL.AssetsManager.InstantSwap.GetExchangeRateInfo(osm.exchange, params) + res, err := osm.AssetsManager.InstantSwap.GetExchangeRateInfo(osm.exchange, params) if err != nil { osm.rateError = true osm.fetchingRate = false diff --git a/ui/page/exchange/order_settings_modal.go b/ui/page/exchange/order_settings_modal.go index 45a3990d2..9ebff89cc 100644 --- a/ui/page/exchange/order_settings_modal.go +++ b/ui/page/exchange/order_settings_modal.go @@ -111,7 +111,7 @@ func (osm *orderSettingsModal) OnCancel(cancel func()) *orderSettingsModal { func (osm *orderSettingsModal) OnResume() { osm.ctx, osm.ctxCancel = context.WithCancel(context.TODO()) - osm.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + osm.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { osm.sourceAccountSelector.SelectFirstValidAccount(selectedWallet) }) @@ -121,7 +121,7 @@ func (osm *orderSettingsModal) OnResume() { } osm.addressEditor.Editor.SetText(address) - osm.destinationWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + osm.destinationWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { osm.destinationAccountSelector.SelectFirstValidAccount(selectedWallet) address, err := osm.destinationWalletSelector.SelectedWallet().CurrentAddress(osm.destinationAccountSelector.SelectedAccount().Number) if err != nil { @@ -168,7 +168,7 @@ func (osm *orderSettingsModal) Handle() { DestinationAccountNumber: params.destinationAccountSelector.SelectedAccount().Number, } - osm.WL.AssetsManager.SetExchangeConfig(configInfo) + osm.AssetsManager.SetExchangeConfig(configInfo) osm.settingsSaved(params) osm.Dismiss() } @@ -458,10 +458,10 @@ func (osm *orderSettingsModal) Layout(gtx layout.Context) D { } func (osm *orderSettingsModal) initWalletSelectors() { - if osm.WL.AssetsManager.IsExchangeConfigSet() { - exchangeConfig := osm.WL.AssetsManager.GetExchangeConfig() - sourceWallet := osm.WL.AssetsManager.WalletWithID(int(exchangeConfig.SourceWalletID)) - destinationWallet := osm.WL.AssetsManager.WalletWithID(int(exchangeConfig.DestinationWalletID)) + if osm.AssetsManager.IsExchangeConfigSet() { + exchangeConfig := osm.AssetsManager.GetExchangeConfig() + sourceWallet := osm.AssetsManager.WalletWithID(int(exchangeConfig.SourceWalletID)) + destinationWallet := osm.AssetsManager.WalletWithID(int(exchangeConfig.DestinationWalletID)) sourceCurrency := exchangeConfig.SourceAsset toCurrency := exchangeConfig.DestinationAsset @@ -476,10 +476,7 @@ func (osm *orderSettingsModal) initWalletSelectors() { osm.sourceWalletSelector = components.NewWalletAndAccountSelector(osm.Load, sourceCurrency). Title(values.String(values.StrSource)) - sourceW := &load.WalletMapping{ - Asset: sourceWallet, - } - osm.sourceWalletSelector.SetSelectedWallet(sourceW) + osm.sourceWalletSelector.SetSelectedWallet(sourceWallet) // Source account picker osm.sourceAccountSelector = components.NewWalletAndAccountSelector(osm.Load). @@ -490,7 +487,7 @@ func (osm *orderSettingsModal) initWalletSelectors() { }) osm.sourceAccountSelector.SelectAccount(osm.sourceWalletSelector.SelectedWallet(), exchangeConfig.SourceAccountNumber) - osm.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + osm.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { osm.sourceAccountSelector.SelectFirstValidAccount(selectedWallet) }) } @@ -506,10 +503,7 @@ func (osm *orderSettingsModal) initWalletSelectors() { Title(values.String(values.StrDestination)). EnableWatchOnlyWallets(true) - destW := &load.WalletMapping{ - Asset: destinationWallet, - } - osm.destinationWalletSelector.SetSelectedWallet(destW) + osm.destinationWalletSelector.SetSelectedWallet(destinationWallet) // Destination account picker osm.destinationAccountSelector = components.NewWalletAndAccountSelector(osm.Load). @@ -522,7 +516,7 @@ func (osm *orderSettingsModal) initWalletSelectors() { }) osm.destinationAccountSelector.SelectAccount(osm.destinationWalletSelector.SelectedWallet(), exchangeConfig.DestinationAccountNumber) - osm.destinationWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + osm.destinationWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { osm.destinationAccountSelector.SelectFirstValidAccount(selectedWallet) }) } @@ -541,7 +535,7 @@ func (osm *orderSettingsModal) initWalletSelectors() { }) osm.sourceAccountSelector.SelectFirstValidAccount(osm.sourceWalletSelector.SelectedWallet()) - osm.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + osm.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { osm.sourceAccountSelector.SelectFirstValidAccount(selectedWallet) }) @@ -560,7 +554,7 @@ func (osm *orderSettingsModal) initWalletSelectors() { }) osm.destinationAccountSelector.SelectFirstValidAccount(osm.destinationWalletSelector.SelectedWallet()) - osm.destinationWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + osm.destinationWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { osm.destinationAccountSelector.SelectFirstValidAccount(selectedWallet) }) } diff --git a/ui/page/governance/agenda_vote_modal.go b/ui/page/governance/agenda_vote_modal.go index 03d3fea98..918409a85 100644 --- a/ui/page/governance/agenda_vote_modal.go +++ b/ui/page/governance/agenda_vote_modal.go @@ -26,19 +26,13 @@ type agendaVoteModal struct { dcrImpl *dcr.Asset } -func newAgendaVoteModal(l *load.Load, agenda *dcr.Agenda, votechoice string, onPreferenceUpdated func()) *agendaVoteModal { - impl := l.WL.SelectedWallet.Wallet.(*dcr.Asset) - if impl == nil { - // log.Warn(values.ErrDCRSupportedOnly) - return nil - } - +func newAgendaVoteModal(l *load.Load, dcrWallet *dcr.Asset, agenda *dcr.Agenda, votechoice string, onPreferenceUpdated func()) *agendaVoteModal { avm := &agendaVoteModal{ agenda: agenda, CreatePasswordModal: modal.NewCreatePasswordModal(l), voteChoice: votechoice, onPreferenceUpdated: onPreferenceUpdated, - dcrImpl: impl, + dcrImpl: dcrWallet, } avm.EnableName(false) avm.EnableConfirmPassword(false) @@ -59,8 +53,7 @@ func newAgendaVoteModal(l *load.Load, agenda *dcr.Agenda, votechoice string, onP } func (avm *agendaVoteModal) OnResume() { - wl := load.NewWalletMapping(avm.WL.SelectedWallet.Wallet) - avm.accountSelector.SelectFirstValidAccount(wl) + avm.accountSelector.SelectFirstValidAccount(avm.dcrImpl) } // - Layout diff --git a/ui/page/governance/consensus_page.go b/ui/page/governance/consensus_page.go index c2fba5c1d..a2529807d 100644 --- a/ui/page/governance/consensus_page.go +++ b/ui/page/governance/consensus_page.go @@ -33,6 +33,9 @@ type ConsensusPage struct { // and the root WindowNavigator. *app.GenericPageModal + // TODO: Currently always nil. Implement a dcr wallet selector. + selectedDCRWallet *dcr.Asset + consensusItems []*components.ConsensusItem listContainer *widget.List @@ -90,14 +93,14 @@ func (pg *ConsensusPage) OnNavigatedTo() { } func (pg *ConsensusPage) isAgendaAPIAllowed() bool { - return pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) + return pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) } func (pg *ConsensusPage) OnNavigatedFrom() {} func (pg *ConsensusPage) agendaVoteChoiceModal(agenda *dcr.Agenda) { var voteChoices []string - consensusItems := components.LoadAgendas(pg.Load, nil, false) + consensusItems := components.LoadAgendas(pg.Load, pg.selectedDCRWallet, false) if len(consensusItems) > 0 { consensusItem := consensusItems[0] voteChoices = make([]string, len(consensusItem.Agenda.Choices)) @@ -129,7 +132,7 @@ func (pg *ConsensusPage) agendaVoteChoiceModal(agenda *dcr.Agenda) { SetPositiveButtonText(values.String(values.StrSave)). SetPositiveButtonCallback(func(isChecked bool, im *modal.InfoModal) bool { im.Dismiss() - voteModal := newAgendaVoteModal(pg.Load, agenda, radiogroupbtns.Value, func() { + voteModal := newAgendaVoteModal(pg.Load, pg.selectedDCRWallet, agenda, radiogroupbtns.Value, func() { pg.FetchAgendas() // re-fetch agendas when modal is dismissed }) pg.ParentWindow().ShowModal(voteModal) @@ -168,7 +171,7 @@ func (pg *ConsensusPage) HandleUserInteractions() { for pg.viewVotingDashboard.Clicked() { host := "https://voting.decred.org" - if pg.WL.AssetsManager.NetType() == libwallet.Testnet { + if pg.AssetsManager.NetType() == libwallet.Testnet { host = "https://voting.decred.org/testnet" } @@ -227,17 +230,16 @@ func (pg *ConsensusPage) HandleUserInteractions() { func (pg *ConsensusPage) FetchAgendas() { selectedType := pg.statusDropDown.Selected() - //TODO implement wallet selector. Currently, we are fetching and - // displaying all agenda. we will need to add some form of filter - // to switch between all agendas' or just agenda's for the selected - // wallet - // selectedWallet := pg.WL.SelectedWallet.Wallet + // TODO: pg.selectedDCRWallet is currently always nil. Implement wallet + // selector. It is impossible to vote on an agenda without a dcr wallet. + // Also, when the selected wallet changes, this method should be re-called, + // to fetch and display the newly selected wallet's vote choices. pg.isSyncing = true // Fetch (or re-fetch) agendas in background as this makes // a network call. Refresh the window once the call completes. go func() { - items := components.LoadAgendas(pg.Load, nil, true) + items := components.LoadAgendas(pg.Load, pg.selectedDCRWallet, true) agenda := dcr.AgendaStatusFromStr(selectedType) listItems := make([]*components.ConsensusItem, 0) if agenda == dcr.UnknownStatus { @@ -421,7 +423,10 @@ func (pg *ConsensusPage) layoutContent(gtx C) D { Margin: layout.Inset{Bottom: values.MarginPadding4, Top: values.MarginPadding4}, }. Layout2(gtx, func(gtx C) D { - return components.AgendaItemWidget(gtx, pg.Load, pg.consensusItems[i]) + // TODO: Implement dcr wallet selector to enable + // voting. + hasVotingWallet := pg.selectedDCRWallet != nil // Vote button will be disabled if nil. + return components.AgendaItemWidget(gtx, pg.Load, pg.consensusItems[i], hasVotingWallet) }) }) }) diff --git a/ui/page/governance/governance_page.go b/ui/page/governance/governance_page.go index 6fc5a7fbc..d7910c59a 100644 --- a/ui/page/governance/governance_page.go +++ b/ui/page/governance/governance_page.go @@ -66,7 +66,7 @@ func (pg *Page) OnNavigatedTo() { } func (pg *Page) isGovernanceAPIAllowed() bool { - return pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) + return pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) } // OnNavigatedFrom is called when the page is about to be removed from diff --git a/ui/page/governance/proposal_details_page.go b/ui/page/governance/proposal_details_page.go index baa092d39..e43960b95 100644 --- a/ui/page/governance/proposal_details_page.go +++ b/ui/page/governance/proposal_details_page.go @@ -14,6 +14,7 @@ import ( "github.com/crypto-power/cryptopower/app" "github.com/crypto-power/cryptopower/libwallet" + "github.com/crypto-power/cryptopower/libwallet/assets/dcr" "github.com/crypto-power/cryptopower/listeners" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" @@ -39,6 +40,8 @@ type ProposalDetails struct { // and the root WindowNavigator. *app.GenericPageModal + dcrWallet *dcr.Asset + *listeners.ProposalNotificationListener // not needed. ctx context.Context // page context @@ -132,7 +135,7 @@ func (pg *ProposalDetails) HandleUserInteractions() { for pg.viewInPoliteiaBtn.Clicked() { host := "https://proposals.decred.org/record/" + pg.proposal.Token - if pg.WL.AssetsManager.NetType() == libwallet.Testnet { + if pg.AssetsManager.NetType() == libwallet.Testnet { host = "https://test-proposals.decred.org/record/" + pg.proposal.Token } @@ -189,7 +192,7 @@ func (pg *ProposalDetails) listenForSyncNotifications() { return } pg.ProposalNotificationListener = listeners.NewProposalNotificationListener() - err := pg.WL.AssetsManager.Politeia.AddNotificationListener(pg.ProposalNotificationListener, ProposalDetailsPageID) + err := pg.AssetsManager.Politeia.AddNotificationListener(pg.ProposalNotificationListener, ProposalDetailsPageID) if err != nil { log.Errorf("Error adding politeia notification listener: %v", err) return @@ -200,7 +203,7 @@ func (pg *ProposalDetails) listenForSyncNotifications() { select { case notification := <-pg.ProposalNotifChan: if notification.ProposalStatus == wallet.Synced { - proposal, err := pg.WL.AssetsManager.Politeia.GetProposalRaw(pg.proposal.Token) + proposal, err := pg.AssetsManager.Politeia.GetProposalRaw(pg.proposal.Token) if err == nil { pg.proposal = &libwallet.Proposal{Proposal: *proposal} pg.ParentWindow().Reload() @@ -208,7 +211,7 @@ func (pg *ProposalDetails) listenForSyncNotifications() { } // is this really needed since listener has been set up on main.go case <-pg.ctx.Done(): - pg.WL.AssetsManager.Politeia.RemoveNotificationListener(ProposalDetailsPageID) + pg.AssetsManager.Politeia.RemoveNotificationListener(ProposalDetailsPageID) close(pg.ProposalNotifChan) pg.ProposalNotificationListener = nil @@ -362,7 +365,7 @@ func (pg *ProposalDetails) layoutNormalTitle(gtx C) D { layout.Rigid(func(gtx C) D { if proposal.Category == libwallet.ProposalCategoryActive { ic := pg.Theme.Icons.TimerIcon - if pg.WL.AssetsManager.IsDarkModeOn() { + if pg.AssetsManager.IsDarkModeOn() { ic = pg.Theme.Icons.TimerDarkMode } return layout.Inset{ @@ -385,7 +388,7 @@ func (pg *ProposalDetails) layoutNormalTitle(gtx C) D { return D{} } - if pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { + if pg.dcrWallet.IsWatchingOnlyWallet() { warning := pg.Theme.Label(values.TextSize16, values.String(values.StrWarningVote)) warning.Color = pg.Theme.Color.Danger return warning.Layout(gtx) @@ -536,7 +539,7 @@ func (pg *ProposalDetails) layoutDesktop(gtx layout.Context) layout.Dimensions { proposalDescription = proposal.IndexFile } else { var err error - proposalDescription, err = pg.WL.AssetsManager.Politeia.FetchProposalDescription(proposal.Token) + proposalDescription, err = pg.AssetsManager.Politeia.FetchProposalDescription(proposal.Token) if err != nil { log.Errorf("Error loading proposal description: %v", err) time.Sleep(7 * time.Second) @@ -603,7 +606,7 @@ func (pg *ProposalDetails) layoutMobile(gtx layout.Context) layout.Dimensions { proposalDescription = proposal.IndexFile } else { var err error - proposalDescription, err = pg.WL.AssetsManager.Politeia.FetchProposalDescription(proposal.Token) + proposalDescription, err = pg.AssetsManager.Politeia.FetchProposalDescription(proposal.Token) if err != nil { log.Errorf("Error loading proposal description: %v", err) time.Sleep(7 * time.Second) diff --git a/ui/page/governance/proposal_vote_modal.go b/ui/page/governance/proposal_vote_modal.go index d8dd7b227..c9f376912 100644 --- a/ui/page/governance/proposal_vote_modal.go +++ b/ui/page/governance/proposal_vote_modal.go @@ -53,7 +53,7 @@ func newVoteModal(l *load.Load, proposal *libwallet.Proposal) *voteModal { vm.noVote.activeBg = l.Theme.Color.Orange2 vm.noVote.dotColor = l.Theme.Color.Danger - vm.walletSelector = NewWalletSelector(l). + vm.walletSelector = NewDCRWalletSelector(l). Title(values.String(values.StrVotingWallet)). WalletSelected(func(w sharedW.Asset) { vm.detailsMu.Lock() @@ -75,7 +75,7 @@ func newVoteModal(l *load.Load, proposal *libwallet.Proposal) *voteModal { vm.ParentWindow().Reload() go func() { - voteDetails, err := vm.WL.AssetsManager.Politeia.ProposalVoteDetailsRaw(ctx, w.Internal().DCR, vm.proposal.Token) + voteDetails, err := vm.AssetsManager.Politeia.ProposalVoteDetailsRaw(ctx, w.Internal().DCR, vm.proposal.Token) vm.detailsMu.Lock() if !components.ContextDone(ctx) { if voteDetails != nil { @@ -146,7 +146,7 @@ func (vm *voteModal) sendVotes() { SetNegativeButtonCallback(func() { vm.isVoting = false }). SetPositiveButtonCallback(func(_, password string, pm *modal.CreatePasswordModal) bool { w := vm.walletSelector.selectedWallet.Internal().DCR - err := vm.WL.AssetsManager.Politeia.CastVotes(ctx, w, libwallet.ConvertVotes(votes), vm.proposal.Token, password) + err := vm.AssetsManager.Politeia.CastVotes(ctx, w, libwallet.ConvertVotes(votes), vm.proposal.Token, password) if err != nil { pm.SetError(err.Error()) pm.SetLoading(false) @@ -155,7 +155,7 @@ func (vm *voteModal) sendVotes() { vm.Dismiss() infoModal := modal.NewSuccessModal(vm.Load, values.String(values.StrVoteSent), modal.DefaultClickFunc()) vm.ParentWindow().ShowModal(infoModal) - go vm.WL.AssetsManager.Politeia.Sync(ctx) + go vm.AssetsManager.Politeia.Sync(ctx) pm.Dismiss() return true diff --git a/ui/page/governance/proposals_page.go b/ui/page/governance/proposals_page.go index 81409eebd..6ca31f36f 100644 --- a/ui/page/governance/proposals_page.go +++ b/ui/page/governance/proposals_page.go @@ -64,7 +64,7 @@ func NewProposalsPage(l *load.Load) *ProposalsPage { pg := &ProposalsPage{ Load: l, GenericPageModal: app.NewGenericPageModal(ProposalsPageID), - assetsManager: l.WL.AssetsManager, + assetsManager: l.AssetsManager, } pg.searchEditor = l.Theme.IconEditor(new(widget.Editor), values.String(values.StrSearch), l.Theme.Icons.SearchIcon, true) pg.searchEditor.Editor.SingleLine, pg.searchEditor.Editor.Submit, pg.searchEditor.Bordered = true, true, false @@ -107,7 +107,7 @@ func (pg *ProposalsPage) OnNavigatedTo() { } func (pg *ProposalsPage) syncAndUpdateProposals() { - go pg.WL.AssetsManager.Politeia.Sync(context.Background()) + go pg.AssetsManager.Politeia.Sync(context.Background()) // Only proceed if allowed make Proposals API call. pg.listenForSyncNotifications() go pg.scroll.FetchScrollData(false, pg.ParentWindow()) @@ -115,7 +115,7 @@ func (pg *ProposalsPage) syncAndUpdateProposals() { } func (pg *ProposalsPage) isGovernanceAPIAllowed() bool { - return pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) + return pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) } // fetchProposals is thread safe and on completing proposals fetch it triggers @@ -372,7 +372,7 @@ func (pg *ProposalsPage) listenForSyncNotifications() { return } pg.ProposalNotificationListener = listeners.NewProposalNotificationListener() - err := pg.WL.AssetsManager.Politeia.AddNotificationListener(pg.ProposalNotificationListener, ProposalsPageID) + err := pg.AssetsManager.Politeia.AddNotificationListener(pg.ProposalNotificationListener, ProposalsPageID) if err != nil { log.Errorf("Error adding politeia notification listener: %v", err) return @@ -390,7 +390,7 @@ func (pg *ProposalsPage) listenForSyncNotifications() { pg.ParentWindow().Reload() } case <-pg.ctx.Done(): - pg.WL.AssetsManager.Politeia.RemoveNotificationListener(ProposalsPageID) + pg.AssetsManager.Politeia.RemoveNotificationListener(ProposalsPageID) close(pg.ProposalNotifChan) pg.ProposalNotificationListener = nil diff --git a/ui/page/governance/treasury_page.go b/ui/page/governance/treasury_page.go index 5c706a5dc..68d1d4c55 100644 --- a/ui/page/governance/treasury_page.go +++ b/ui/page/governance/treasury_page.go @@ -60,7 +60,7 @@ func NewTreasuryPage(l *load.Load) *TreasuryPage { pg := &TreasuryPage{ Load: l, GenericPageModal: app.NewGenericPageModal(TreasuryPageID), - assetsManager: l.WL.AssetsManager, + assetsManager: l.AssetsManager, listContainer: &widget.List{ List: layout.List{Axis: layout.Vertical}, }, @@ -88,7 +88,7 @@ func (pg *TreasuryPage) OnNavigatedTo() { pg.ctx, pg.ctxCancel = context.WithCancel(context.TODO()) // Fetch (or re-fetch) treasury policies in background as this makes // a network call. Refresh the window once the call completes. - pg.PiKey = hex.EncodeToString(pg.WL.AssetsManager.PiKeys()[0]) + pg.PiKey = hex.EncodeToString(pg.AssetsManager.PiKeys()[0]) if pg.isTreasuryAPIAllowed() && pg.selectedWallet != nil { pg.FetchPolicies() @@ -102,7 +102,7 @@ func (pg *TreasuryPage) OnNavigatedFrom() { } func (pg *TreasuryPage) isTreasuryAPIAllowed() bool { - return pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) + return pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) } func (pg *TreasuryPage) HandleUserInteractions() { @@ -127,7 +127,7 @@ func (pg *TreasuryPage) HandleUserInteractions() { for pg.viewGovernanceKeys.Clicked() { host := "https://github.com/decred/dcrd/blob/master/chaincfg/mainnetparams.go#L477" - if pg.WL.AssetsManager.NetType() == libwallet.Testnet { + if pg.AssetsManager.NetType() == libwallet.Testnet { host = "https://github.com/decred/dcrd/blob/master/chaincfg/testnetparams.go#L390" } @@ -266,7 +266,7 @@ func (pg *TreasuryPage) layoutContent(gtx C) D { func (pg *TreasuryPage) layoutPiKey(gtx C) D { backgroundColor := pg.Theme.Color.LightBlue - if pg.WL.AssetsManager.IsDarkModeOn() { + if pg.AssetsManager.IsDarkModeOn() { backgroundColor = pg.Theme.Color.Background } @@ -326,11 +326,11 @@ func (pg *TreasuryPage) initWalletSelector() { pg.sourceWalletSelector = components.NewWalletAndAccountSelector(pg.Load, libutils.DCRWalletAsset). Title(values.String(values.StrSelectWallet)) if pg.sourceWalletSelector.SelectedWallet() != nil { - pg.selectedWallet = pg.sourceWalletSelector.SelectedWallet().Asset + pg.selectedWallet = pg.sourceWalletSelector.SelectedWallet() } - pg.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { - pg.selectedWallet = selectedWallet.Asset + pg.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { + pg.selectedWallet = selectedWallet pg.FetchPolicies() }) } diff --git a/ui/page/governance/wallet_selector.go b/ui/page/governance/wallet_selector.go index 92427d359..3613b88e0 100644 --- a/ui/page/governance/wallet_selector.go +++ b/ui/page/governance/wallet_selector.go @@ -11,6 +11,7 @@ import ( "github.com/crypto-power/cryptopower/app" "github.com/crypto-power/cryptopower/libwallet" sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" + "github.com/crypto-power/cryptopower/libwallet/utils" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/page/components" @@ -33,14 +34,14 @@ type WalletSelector struct { } // TODO: merge this into the account selector modal. -func NewWalletSelector(l *load.Load) *WalletSelector { +func NewDCRWalletSelector(l *load.Load) *WalletSelector { return &WalletSelector{ Load: l, - assetsManager: l.WL.AssetsManager, + assetsManager: l.AssetsManager, walletIsValid: func(sharedW.Asset) bool { return true }, openSelectorDialog: l.Theme.NewClickable(true), - wallets: l.WL.SortedWalletList(), + wallets: l.AssetsManager.AssetWallets(utils.DCRWalletAsset), } } @@ -92,13 +93,13 @@ func (as *WalletSelector) SelectFirstValidWallet() error { } func (as *WalletSelector) setupSelectedWallet(wallet sharedW.Asset) { - totalBalance, err := as.WL.TotalWalletBalance(wallet.GetWalletID()) + _, walletTotalBalance, err := sharedW.Balances(wallet) if err != nil { fmt.Println(err) return } - as.totalBalance = totalBalance.String() + as.totalBalance = walletTotalBalance.String() } func (as *WalletSelector) SelectedWallet() sharedW.Asset { @@ -164,13 +165,13 @@ type WalletSelectorModal struct { filteredWallets []sharedW.Asset } -func newWalletSelectorModal(l *load.Load, currentSelectedAccount sharedW.Asset) *WalletSelectorModal { +func newWalletSelectorModal(l *load.Load, currentSelectedWallet sharedW.Asset) *WalletSelectorModal { asm := &WalletSelectorModal{ Load: l, Modal: l.Theme.ModalFloatTitle("WalletSelectorModal"), walletsList: l.Theme.NewClickableList(layout.Vertical), - currentSelectedWallet: currentSelectedAccount, + currentSelectedWallet: currentSelectedWallet, isCancelable: true, } @@ -178,15 +179,16 @@ func newWalletSelectorModal(l *load.Load, currentSelectedAccount sharedW.Asset) } func (asm *WalletSelectorModal) OnResume() { - wallets := make([]sharedW.Asset, 0) + wallets := asm.AssetsManager.AssetWallets(asm.currentSelectedWallet.GetAssetType()) - for _, wal := range asm.WL.SortedWalletList() { + validWallets := make([]sharedW.Asset, 0) + for _, wal := range wallets { if asm.walletIsValid(wal) { - wallets = append(wallets, wal) + validWallets = append(validWallets, wal) } } - asm.filteredWallets = wallets + asm.filteredWallets = validWallets } func (asm *WalletSelectorModal) Handle() { @@ -255,8 +257,7 @@ func (asm *WalletSelectorModal) Layout(gtx layout.Context) layout.Dimensions { } func (asm *WalletSelectorModal) walletAccountLayout(gtx layout.Context, wallet sharedW.Asset) layout.Dimensions { - walletTotalBalance, _ := asm.WL.TotalWalletBalance(wallet.GetWalletID()) - walletSpendableBalance, _ := asm.WL.SpendableWalletBalance(wallet.GetWalletID()) + walletSpendableBalance, walletTotalBalance, _ := sharedW.Balances(wallet) return layout.Inset{ Bottom: values.MarginPadding20, diff --git a/ui/page/info/info_page.go b/ui/page/info/info_page.go index 3143a0970..4e51c11c9 100644 --- a/ui/page/info/info_page.go +++ b/ui/page/info/info_page.go @@ -34,6 +34,7 @@ type WalletInfo struct { // helper methods for accessing the PageNavigator that displayed this page // and the root WindowNavigator. *app.GenericPageModal + wallet sharedW.Asset *listeners.SyncProgressListener *listeners.BlocksRescanProgressListener @@ -68,11 +69,12 @@ type progressInfo struct { // status progress percentage. var syncProgressInfo = map[sharedW.Asset]progressInfo{} -func NewInfoPage(l *load.Load) *WalletInfo { +func NewInfoPage(l *load.Load, wallet sharedW.Asset) *WalletInfo { pg := &WalletInfo{ Load: l, GenericPageModal: app.NewGenericPageModal(InfoID), - assetsManager: l.WL.AssetsManager, + wallet: wallet, + assetsManager: l.AssetsManager, container: &widget.List{ List: layout.List{Axis: layout.Vertical}, }, @@ -98,7 +100,7 @@ func NewInfoPage(l *load.Load) *WalletInfo { func (pg *WalletInfo) OnNavigatedTo() { pg.ctx, pg.ctxCancel = context.WithCancel(context.TODO()) - autoSync := pg.WL.SelectedWallet.Wallet.ReadBoolConfigValueForKey(sharedW.AutoSyncConfigKey, false) + autoSync := pg.wallet.ReadBoolConfigValueForKey(sharedW.AutoSyncConfigKey, false) pg.syncSwitch.SetChecked(autoSync) pg.listenForNotifications() @@ -119,13 +121,13 @@ func (pg *WalletInfo) Layout(gtx layout.Context) layout.Dimensions { Right: values.MarginPadding10, Left: values.MarginPadding10, }.Layout(gtx, func(gtx C) D { - txt := pg.Theme.Body1(pg.WL.SelectedWallet.Wallet.GetWalletName()) + txt := pg.Theme.Body1(pg.wallet.GetWalletName()) txt.Font.Weight = font.SemiBold return txt.Layout(gtx) }) }), layout.Rigid(func(gtx C) D { - if len(pg.WL.SelectedWallet.Wallet.GetEncryptedSeed()) > 0 { + if len(pg.wallet.GetEncryptedSeed()) > 0 { return layout.Inset{ Top: values.MarginPadding16, }.Layout(gtx, func(gtx C) D { @@ -165,23 +167,24 @@ func (pg *WalletInfo) HandleUserInteractions() { }() } - isSyncShutting := pg.WL.SelectedWallet.Wallet.IsSyncShuttingDown() + isSyncShutting := pg.wallet.IsSyncShuttingDown() pg.syncSwitch.SetEnabled(!isSyncShutting) if pg.syncSwitch.Changed() { - if pg.WL.SelectedWallet.Wallet.IsRescanning() { - pg.WL.SelectedWallet.Wallet.CancelRescan() + if pg.wallet.IsRescanning() { + pg.wallet.CancelRescan() } + go func() { - pg.ToggleSync(func(b bool) { + pg.ToggleSync(pg.wallet, func(b bool) { pg.syncSwitch.SetChecked(b) - pg.WL.SelectedWallet.Wallet.SaveUserConfigValue(sharedW.AutoSyncConfigKey, b) + pg.wallet.SaveUserConfigValue(sharedW.AutoSyncConfigKey, b) }) }() } if pg.toBackup.Button.Clicked() { currentPage := pg.ParentWindow().CurrentPageID() - pg.ParentWindow().Display(seedbackup.NewBackupInstructionsPage(pg.Load, pg.WL.SelectedWallet.Wallet, func(load *load.Load, navigator app.WindowNavigator) { + pg.ParentWindow().Display(seedbackup.NewBackupInstructionsPage(pg.Load, pg.wallet, func(load *load.Load, navigator app.WindowNavigator) { navigator.ClosePagesAfter(currentPage) })) } @@ -203,7 +206,7 @@ func (pg *WalletInfo) listenForNotifications() { return } - selectedWallet := pg.WL.SelectedWallet.Wallet + selectedWallet := pg.wallet pg.SyncProgressListener = listeners.NewSyncProgress() err := selectedWallet.AddSyncProgressListener(pg.SyncProgressListener, InfoID) @@ -254,7 +257,7 @@ func (pg *WalletInfo) listenForNotifications() { // headers to fetch cannot be less than the previously fetched. // Page refresh only needed if there is new data to update the UI. if progress.headersToFetchOrScan >= previousProgress.headersToFetchOrScan { - currentAsset := pg.WL.SelectedWallet.Wallet + currentAsset := pg.wallet // set the new progress against the associated asset. syncProgressInfo[currentAsset] = progress diff --git a/ui/page/info/sync_status.go b/ui/page/info/sync_status.go index 69783f1da..fb06c46d1 100644 --- a/ui/page/info/sync_status.go +++ b/ui/page/info/sync_status.go @@ -19,14 +19,14 @@ func (pg *WalletInfo) initWalletStatusWidgets() { // syncStatusSection lays out content for displaying sync status. func (pg *WalletInfo) syncStatusSection(gtx C) D { - isBtcAsset := pg.WL.SelectedWallet.Wallet.GetAssetType() == libutils.BTCWalletAsset - isLtcAsset := pg.WL.SelectedWallet.Wallet.GetAssetType() == libutils.LTCWalletAsset - syncing := pg.WL.SelectedWallet.Wallet.IsSyncing() + isBtcAsset := pg.wallet.GetAssetType() == libutils.BTCWalletAsset + isLtcAsset := pg.wallet.GetAssetType() == libutils.LTCWalletAsset + syncing := pg.wallet.IsSyncing() // btcwallet does not export implementation to track address discovery. // During btc address discovery, show the normal synced info page with an // extra label showing the address discovery is in progress. - rescanning := pg.WL.SelectedWallet.Wallet.IsRescanning() && !isLtcAsset && !isBtcAsset && !syncing + rescanning := pg.wallet.IsRescanning() && !isLtcAsset && !isBtcAsset && !syncing uniform := layout.Inset{Top: values.MarginPadding5, Bottom: values.MarginPadding5} return pg.Theme.Card().Layout(gtx, func(gtx C) D { @@ -66,7 +66,7 @@ func (pg *WalletInfo) syncStatusSection(gtx C) D { func (pg *WalletInfo) syncBoxTitleRow(gtx C) D { statusLabel := pg.Theme.Label(values.TextSize14, values.String(values.StrOffline)) pg.walletStatusIcon.Color = pg.Theme.Color.Danger - if pg.WL.SelectedWallet.Wallet.IsConnectedToNetwork() { + if pg.wallet.IsConnectedToNetwork() { statusLabel.Text = values.String(values.StrOnline) pg.walletStatusIcon.Color = pg.Theme.Color.Success } @@ -75,7 +75,7 @@ func (pg *WalletInfo) syncBoxTitleRow(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(pg.Theme.Label(values.TextSize14, values.String(values.StrWalletStatus)).Layout), layout.Rigid(func(gtx layout.Context) layout.Dimensions { - if pg.WL.SelectedWallet.Wallet.IsSyncShuttingDown() { + if pg.wallet.IsSyncShuttingDown() { return layout.Inset{ Left: values.MarginPadding4, }.Layout(gtx, pg.Theme.Label(values.TextSize14, values.String(values.StrCanceling)).Layout) @@ -91,10 +91,10 @@ func (pg *WalletInfo) syncBoxTitleRow(gtx C) D { }), layout.Rigid(statusLabel.Layout), layout.Rigid(func(gtx C) D { - if pg.WL.SelectedWallet.Wallet.IsConnectedToNetwork() { + if pg.wallet.IsConnectedToNetwork() { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, layout.Rigid(func(gtx C) D { - connectedPeers := fmt.Sprintf("%d", pg.WL.SelectedWallet.Wallet.ConnectedPeers()) + connectedPeers := fmt.Sprintf("%d", pg.wallet.ConnectedPeers()) return pg.Theme.Label(values.TextSize14, values.StringF(values.StrConnectedTo, connectedPeers)).Layout(gtx) }), ) @@ -115,9 +115,9 @@ func (pg *WalletInfo) syncBoxTitleRow(gtx C) D { func (pg *WalletInfo) syncStatusIcon(gtx C) D { icon := pg.Theme.Icons.SyncingIcon - if pg.WL.SelectedWallet.Wallet.IsSynced() { + if pg.wallet.IsSynced() { icon = pg.Theme.Icons.SuccessIcon - } else if pg.WL.SelectedWallet.Wallet.IsSyncing() { + } else if pg.wallet.IsSyncing() { icon = pg.Theme.Icons.SyncingIcon } @@ -129,14 +129,14 @@ func (pg *WalletInfo) syncStatusIcon(gtx C) D { // syncContent lays out sync status content when the wallet is syncing, synced, not connected func (pg *WalletInfo) syncContent(gtx C, uniform layout.Inset) D { - isBtcAsset := pg.WL.SelectedWallet.Wallet.GetAssetType() == libutils.BTCWalletAsset - isLtcAsset := pg.WL.SelectedWallet.Wallet.GetAssetType() == libutils.LTCWalletAsset - isSyncing := pg.WL.SelectedWallet.Wallet.IsSyncing() + isBtcAsset := pg.wallet.GetAssetType() == libutils.BTCWalletAsset + isLtcAsset := pg.wallet.GetAssetType() == libutils.LTCWalletAsset + isSyncing := pg.wallet.IsSyncing() isBtcORLtcAsset := isBtcAsset || isLtcAsset // Rescanning should happen on a synced chain. - isRescanning := pg.WL.SelectedWallet.Wallet.IsRescanning() && !isSyncing + isRescanning := pg.wallet.IsRescanning() && !isSyncing isInprogress := isSyncing || isRescanning - bestBlock := pg.WL.SelectedWallet.Wallet.GetBestBlock() + bestBlock := pg.wallet.GetBestBlock() return uniform.Layout(gtx, func(gtx C) D { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -199,15 +199,15 @@ func (pg *WalletInfo) syncContent(gtx C, uniform layout.Inset) D { }), layout.Rigid(func(gtx C) D { currentSeconds := time.Now().Unix() - w := pg.WL.SelectedWallet.Wallet + w := pg.wallet daysBehind := components.TimeFormat(int(currentSeconds-w.GetBestBlockTimeStamp()), true) syncProgress := values.String(values.StrWalletNotSynced) - if pg.WL.SelectedWallet.Wallet.IsSyncing() { + if pg.wallet.IsSyncing() { syncProgress = values.StringF(values.StrSyncingProgressStat, daysBehind) - } else if pg.WL.SelectedWallet.Wallet.IsRescanning() { + } else if pg.wallet.IsRescanning() { syncProgress = values.String(values.StrRescanningBlocks) - } else if pg.WL.SelectedWallet.Wallet.IsSynced() { + } else if pg.wallet.IsSynced() { syncProgress = values.String(values.StrComplete) } @@ -269,7 +269,7 @@ func (pg *WalletInfo) progressStatusDetails() (int, string) { timeLeft = components.TimeFormat(int(rescanUpdate.ProgressReport.RescanTimeRemaining), true) } - if pg.WL.SelectedWallet.Wallet.IsSyncing() || pg.WL.SelectedWallet.Wallet.IsRescanning() { + if pg.wallet.IsSyncing() || pg.wallet.IsRescanning() { timeLeftLabel = values.StringF(values.StrTimeLeft, timeLeft) if progress == 0 { timeLeftLabel = values.String(values.StrLoading) @@ -284,7 +284,7 @@ func (pg *WalletInfo) rescanDetailsLayout(gtx C, inset layout.Inset) D { if rescanUpdate == nil { return D{} } - wal := pg.WL.AssetsManager.WalletWithID(rescanUpdate.WalletID) + wal := pg.AssetsManager.WalletWithID(rescanUpdate.WalletID) return layout.Inset{Top: values.MarginPadding10}.Layout(gtx, func(gtx C) D { gtx.Constraints.Min.X = gtx.Constraints.Max.X card := pg.Theme.Card() @@ -323,7 +323,7 @@ func (pg *WalletInfo) rescanDetailsLayout(gtx C, inset layout.Inset) D { } func (pg *WalletInfo) fetchSyncProgress() progressInfo { - pgrss, ok := syncProgressInfo[pg.WL.SelectedWallet.Wallet] + pgrss, ok := syncProgressInfo[pg.wallet] if !ok { pgrss = progressInfo{} } @@ -334,7 +334,7 @@ func (pg *WalletInfo) fetchSyncProgress() progressInfo { // deleteSyncProgress removes the map entry after the data persisted is no longer necessary. func (pg *WalletInfo) deleteSyncProgress() { - wal := pg.WL.SelectedWallet.Wallet + wal := pg.wallet if wal.IsSynced() { delete(syncProgressInfo, wal) } diff --git a/ui/page/privacy/account_mixer_page.go b/ui/page/privacy/account_mixer_page.go index ad5091c45..a56f3fbf4 100644 --- a/ui/page/privacy/account_mixer_page.go +++ b/ui/page/privacy/account_mixer_page.go @@ -36,7 +36,7 @@ type AccountMixerPage struct { ctxCancel context.CancelFunc pageContainer layout.List - wallet sharedW.Asset + dcrWallet *dcr.Asset settingsCollapsible *cryptomaterial.Collapsible unmixedAccount *cryptomaterial.Clickable @@ -52,20 +52,13 @@ type AccountMixerPage struct { MixerAccounts []preference.ItemPreference mixerCompleted bool - dcrImpl *dcr.Asset } -func NewAccountMixerPage(l *load.Load) *AccountMixerPage { - impl := l.WL.SelectedWallet.Wallet.(*dcr.Asset) - if impl == nil { - log.Warn(values.ErrDCRSupportedOnly) - return nil - } - - pg := &AccountMixerPage{ +func NewAccountMixerPage(l *load.Load, wallet *dcr.Asset) *AccountMixerPage { + return &AccountMixerPage{ Load: l, GenericPageModal: app.NewGenericPageModal(AccountMixerPageID), - wallet: l.WL.SelectedWallet.Wallet, + dcrWallet: wallet, toggleMixer: l.Theme.Switch(), mixerProgress: l.Theme.ProgressBar(0), settingsCollapsible: l.Theme.Collapsible(), @@ -73,11 +66,7 @@ func NewAccountMixerPage(l *load.Load) *AccountMixerPage { mixedAccount: l.Theme.NewClickable(false), coordinationServer: l.Theme.NewClickable(false), pageContainer: layout.List{Axis: layout.Vertical}, - - dcrImpl: impl, } - - return pg } // OnNavigatedTo is called when the page is about to be displayed and @@ -87,22 +76,22 @@ func NewAccountMixerPage(l *load.Load) *AccountMixerPage { func (pg *AccountMixerPage) OnNavigatedTo() { pg.ctx, pg.ctxCancel = context.WithCancel(context.TODO()) - if pg.WL.SelectedWallet.Wallet.IsSynced() { + if pg.dcrWallet.IsSynced() { // Listen for notifications only when the wallet is fully synced. pg.listenForMixerNotifications() } - pg.toggleMixer.SetChecked(pg.dcrImpl.IsAccountMixerActive()) + pg.toggleMixer.SetChecked(pg.dcrWallet.IsAccountMixerActive()) pg.mixerProgress.Height = values.MarginPadding18 pg.mixerProgress.Radius = cryptomaterial.Radius(2) - totalBalance, _ := components.CalculateTotalWalletsBalance(pg.Load) // TODO - handle error + totalBalance, _ := components.CalculateTotalWalletsBalance(pg.dcrWallet) // TODO - handle error pg.totalWalletBalance = totalBalance.Total // get balance information pg.getMixerBalance() } func (pg *AccountMixerPage) getMixerBalance() { - accounts, err := pg.wallet.GetAccountsRaw() + accounts, err := pg.dcrWallet.GetAccountsRaw() if err != nil { log.Error("could not load mixer account information. Please try again.") } @@ -114,9 +103,9 @@ func (pg *AccountMixerPage) getMixerBalance() { vm = append(vm, preference.ItemPreference{Key: acct.Name, Value: acct.Name}) } - if acct.Number == pg.dcrImpl.MixedAccountNumber() { + if acct.Number == pg.dcrWallet.MixedAccountNumber() { pg.mixedBalance = acct.Balance.Total - } else if acct.Number == pg.dcrImpl.UnmixedAccountNumber() { + } else if acct.Number == pg.dcrWallet.UnmixedAccountNumber() { pg.unmixedBalance = acct.Balance.Total } } @@ -223,7 +212,7 @@ func (pg *AccountMixerPage) mixerHeaderContent() layout.FlexChild { }.Layout(gtx, pg.Theme.Separator().Layout) }), layout.Rigid(func(gtx C) D { - if !pg.dcrImpl.IsAccountMixerActive() { + if !pg.dcrWallet.IsAccountMixerActive() { return layout.Inset{Top: values.MarginPadding16}.Layout(gtx, func(gtx C) D { return D{} }) @@ -382,7 +371,7 @@ func (pg *AccountMixerPage) HandleUserInteractions() { SetPositiveButtonText(values.String(values.StrYes)). SetPositiveButtonCallback(func(_ bool, _ *modal.InfoModal) bool { pg.toggleMixer.SetChecked(false) - go pg.dcrImpl.StopAccountMixer() + go pg.dcrWallet.StopAccountMixer() return true }) pg.ParentWindow().ShowModal(info) @@ -397,7 +386,7 @@ func (pg *AccountMixerPage) HandleUserInteractions() { // get account number for the selected wallet name acctNum := func(val string) int32 { - num, err := pg.wallet.AccountNumber(val) + num, err := pg.dcrWallet.AccountNumber(val) if err != nil { log.Error(err.Error()) return -1 @@ -406,7 +395,7 @@ func (pg *AccountMixerPage) HandleUserInteractions() { } for pg.mixedAccount.Clicked() { - name, err := pg.wallet.AccountName(pg.dcrImpl.MixedAccountNumber()) + name, err := pg.dcrWallet.AccountName(pg.dcrWallet.MixedAccountNumber()) if err != nil { log.Error(err.Error()) } @@ -426,7 +415,7 @@ func (pg *AccountMixerPage) HandleUserInteractions() { IsWallet(true). UpdateValues(func(val string) { if acctNum(val) != -1 { - pg.wallet.SetInt32ConfigValueForKey(sharedW.AccountMixerMixedAccount, acctNum(val)) + pg.dcrWallet.SetInt32ConfigValueForKey(sharedW.AccountMixerMixedAccount, acctNum(val)) pg.getMixerBalance() } }) @@ -434,7 +423,7 @@ func (pg *AccountMixerPage) HandleUserInteractions() { } for pg.unmixedAccount.Clicked() { - name, err := pg.wallet.AccountName(pg.dcrImpl.UnmixedAccountNumber()) + name, err := pg.dcrWallet.AccountName(pg.dcrWallet.UnmixedAccountNumber()) if err != nil { log.Error(err.Error()) } @@ -454,7 +443,7 @@ func (pg *AccountMixerPage) HandleUserInteractions() { IsWallet(true). UpdateValues(func(val string) { if acctNum(val) != -1 { - pg.wallet.SetInt32ConfigValueForKey(sharedW.AccountMixerUnmixedAccount, acctNum(val)) + pg.dcrWallet.SetInt32ConfigValueForKey(sharedW.AccountMixerUnmixedAccount, acctNum(val)) pg.getMixerBalance() } }) @@ -478,12 +467,12 @@ func (pg *AccountMixerPage) HandleUserInteractions() { } func (pg *AccountMixerPage) getMixerAccounts(isFilterMixed bool) []preference.ItemPreference { - filterAccountNumber := pg.dcrImpl.UnmixedAccountNumber() + filterAccountNumber := pg.dcrWallet.UnmixedAccountNumber() if isFilterMixed { - filterAccountNumber = pg.dcrImpl.MixedAccountNumber() + filterAccountNumber = pg.dcrWallet.MixedAccountNumber() } - accountFilter, err := pg.wallet.AccountName(filterAccountNumber) + accountFilter, err := pg.dcrWallet.AccountName(filterAccountNumber) if err != nil { log.Error(err.Error()) } @@ -505,7 +494,7 @@ func (pg *AccountMixerPage) showModalPasswordStartAccountMixer() { }). PositiveButton(values.String(values.StrConfirm), func(password string, pm *modal.PasswordModal) bool { go func() { - err := pg.dcrImpl.StartAccountMixer(password) + err := pg.dcrWallet.StartAccountMixer(password) if err != nil { pg.Toast.NotifyError(err.Error()) pm.SetLoading(false) @@ -529,14 +518,14 @@ func (pg *AccountMixerPage) listenForMixerNotifications() { } pg.AccountMixerNotificationListener = listeners.NewAccountMixerNotificationListener() - err := pg.dcrImpl.AddAccountMixerNotificationListener(pg, AccountMixerPageID) + err := pg.dcrWallet.AddAccountMixerNotificationListener(pg, AccountMixerPageID) if err != nil { log.Errorf("Error adding account mixer notification listener: %+v", err) return } pg.TxAndBlockNotificationListener = listeners.NewTxAndBlockNotificationListener() - err = pg.dcrImpl.AddTxAndBlockNotificationListener(pg.TxAndBlockNotificationListener, true, AccountMixerPageID) + err = pg.dcrWallet.AddTxAndBlockNotificationListener(pg.TxAndBlockNotificationListener, true, AccountMixerPageID) if err != nil { log.Errorf("Error adding tx and block notification listener: %v", err) return @@ -565,8 +554,8 @@ func (pg *AccountMixerPage) listenForMixerNotifications() { } case <-pg.ctx.Done(): - pg.dcrImpl.RemoveTxAndBlockNotificationListener(AccountMixerPageID) - pg.dcrImpl.RemoveAccountMixerNotificationListener(AccountMixerPageID) + pg.dcrWallet.RemoveTxAndBlockNotificationListener(AccountMixerPageID) + pg.dcrWallet.RemoveAccountMixerNotificationListener(AccountMixerPageID) close(pg.MixerChan) pg.CloseTxAndBlockChan() pg.AccountMixerNotificationListener = nil diff --git a/ui/page/privacy/manual_mixer_setup_page.go b/ui/page/privacy/manual_mixer_setup_page.go index 3207c5b25..f7f4ff72b 100644 --- a/ui/page/privacy/manual_mixer_setup_page.go +++ b/ui/page/privacy/manual_mixer_setup_page.go @@ -36,21 +36,15 @@ type ManualMixerSetupPage struct { infoButton cryptomaterial.IconButton toPrivacySetup cryptomaterial.Button - dcrImpl *dcr.Asset + dcrWallet *dcr.Asset } -func NewManualMixerSetupPage(l *load.Load) *ManualMixerSetupPage { - impl := l.WL.SelectedWallet.Wallet.(*dcr.Asset) - if impl == nil { - log.Warn(values.ErrDCRSupportedOnly) - return nil - } - +func NewManualMixerSetupPage(l *load.Load, dcrWallet *dcr.Asset) *ManualMixerSetupPage { pg := &ManualMixerSetupPage{ Load: l, GenericPageModal: app.NewGenericPageModal(ManualMixerSetupPageID), toPrivacySetup: l.Theme.Button(values.String(values.StrSetUp)), - dcrImpl: impl, + dcrWallet: dcrWallet, } // Mixed account picker @@ -58,7 +52,7 @@ func NewManualMixerSetupPage(l *load.Load) *ManualMixerSetupPage { Title(values.String(values.StrMixedAccount)). AccountSelected(func(selectedAccount *sharedW.Account) {}). AccountValidator(func(account *sharedW.Account) bool { - wal := pg.Load.WL.AssetsManager.WalletWithID(account.WalletID) + wal := pg.Load.AssetsManager.WalletWithID(account.WalletID) var unmixedAccNo int32 = -1 if unmixedAcc := pg.unmixedAccountSelector.SelectedAccount(); unmixedAcc != nil { @@ -74,14 +68,13 @@ func NewManualMixerSetupPage(l *load.Load) *ManualMixerSetupPage { return true }) - wl := load.NewWalletMapping(l.WL.SelectedWallet.Wallet) // Unmixed account picker pg.unmixedAccountSelector = components.NewWalletAndAccountSelector(l). Title(values.String(values.StrUnmixedAccount)). AccountSelected(func(selectedAccount *sharedW.Account) {}). AccountValidator(func(account *sharedW.Account) bool { - wal := pg.Load.WL.AssetsManager.WalletWithID(account.WalletID) + wal := pg.Load.AssetsManager.WalletWithID(account.WalletID) var mixedAccNo int32 = -1 if mixedAcc := pg.mixedAccountSelector.SelectedAccount(); mixedAcc != nil { @@ -98,8 +91,9 @@ func NewManualMixerSetupPage(l *load.Load) *ManualMixerSetupPage { return true }) - pg.mixedAccountSelector.SelectFirstValidAccount(wl) - pg.unmixedAccountSelector.SelectFirstValidAccount(wl) + + pg.mixedAccountSelector.SelectFirstValidAccount(dcrWallet) + pg.unmixedAccountSelector.SelectFirstValidAccount(dcrWallet) pg.backButton, pg.infoButton = components.SubpageHeaderButtons(l) @@ -113,9 +107,8 @@ func NewManualMixerSetupPage(l *load.Load) *ManualMixerSetupPage { func (pg *ManualMixerSetupPage) OnNavigatedTo() { pg.ctx, pg.ctxCancel = context.WithCancel(context.TODO()) - wl := load.NewWalletMapping(pg.WL.SelectedWallet.Wallet) - pg.mixedAccountSelector.SelectFirstValidAccount(wl) - pg.unmixedAccountSelector.SelectFirstValidAccount(wl) + pg.mixedAccountSelector.SelectFirstValidAccount(pg.dcrWallet) + pg.unmixedAccountSelector.SelectFirstValidAccount(pg.dcrWallet) } // Layout draws the page UI components into the provided layout context @@ -217,27 +210,27 @@ func (pg *ManualMixerSetupPage) showModalSetupMixerAcct() { } mixedAcctNumber := pg.mixedAccountSelector.SelectedAccount().Number unmixedAcctNumber := pg.unmixedAccountSelector.SelectedAccount().Number - err := pg.dcrImpl.SetAccountMixerConfig(mixedAcctNumber, unmixedAcctNumber, password) + err := pg.dcrWallet.SetAccountMixerConfig(mixedAcctNumber, unmixedAcctNumber, password) if err != nil { return errfunc(err) } - pg.WL.SelectedWallet.Wallet.SetBoolConfigValueForKey(sharedW.AccountMixerConfigSet, true) + pg.dcrWallet.SetBoolConfigValueForKey(sharedW.AccountMixerConfigSet, true) // rename mixed account - err = pg.WL.SelectedWallet.Wallet.RenameAccount(mixedAcctNumber, values.String(values.StrMixed)) + err = pg.dcrWallet.RenameAccount(mixedAcctNumber, values.String(values.StrMixed)) if err != nil { return errfunc(err) } // rename unmixed account - err = pg.WL.SelectedWallet.Wallet.RenameAccount(unmixedAcctNumber, values.String(values.StrUnmixed)) + err = pg.dcrWallet.RenameAccount(unmixedAcctNumber, values.String(values.StrUnmixed)) if err != nil { return errfunc(err) } pm.Dismiss() - pg.ParentNavigator().Display(NewAccountMixerPage(pg.Load)) + pg.ParentNavigator().Display(NewAccountMixerPage(pg.Load, pg.dcrWallet)) return true }) diff --git a/ui/page/privacy/setup_mixer_accounts_page.go b/ui/page/privacy/setup_mixer_accounts_page.go index 6fe4135d7..ebea3a587 100644 --- a/ui/page/privacy/setup_mixer_accounts_page.go +++ b/ui/page/privacy/setup_mixer_accounts_page.go @@ -8,6 +8,7 @@ import ( "gioui.org/widget" "github.com/crypto-power/cryptopower/app" + "github.com/crypto-power/cryptopower/libwallet/assets/dcr" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/page/components" @@ -24,6 +25,7 @@ type SetupMixerAccountsPage struct { // helper methods for accessing the PageNavigator that displayed this page // and the root WindowNavigator. *app.GenericPageModal + dcrWallet *dcr.Asset ctx context.Context // page context ctxCancel context.CancelFunc @@ -35,10 +37,11 @@ type SetupMixerAccountsPage struct { autoSetupIcon, nextIcon *cryptomaterial.Icon } -func NewSetupMixerAccountsPage(l *load.Load) *SetupMixerAccountsPage { +func NewSetupMixerAccountsPage(l *load.Load, dcrWallet *dcr.Asset) *SetupMixerAccountsPage { pg := &SetupMixerAccountsPage{ Load: l, GenericPageModal: app.NewGenericPageModal(SetupMixerAccountsPageID), + dcrWallet: dcrWallet, } pg.backButton, pg.infoButton = components.SubpageHeaderButtons(l) @@ -231,11 +234,11 @@ func (pg *SetupMixerAccountsPage) HandleUserInteractions() { window: pg.ParentWindow(), pageNavigator: pg.ParentNavigator(), checkBox: pg.Theme.CheckBox(new(widget.Bool), values.String(values.StrMoveFundsFrmDefaultToUnmixed)), - }) + }, pg.dcrWallet) } if pg.manualSetupClickable.Clicked() { - pg.ParentNavigator().Display(NewManualMixerSetupPage(pg.Load)) + pg.ParentNavigator().Display(NewManualMixerSetupPage(pg.Load, pg.dcrWallet)) } } diff --git a/ui/page/privacy/setup_privacy_page.go b/ui/page/privacy/setup_privacy_page.go index c3e2a2f3f..824df0085 100644 --- a/ui/page/privacy/setup_privacy_page.go +++ b/ui/page/privacy/setup_privacy_page.go @@ -29,6 +29,7 @@ type SetupPrivacyPage struct { // helper methods for accessing the PageNavigator that displayed this page // and the root WindowNavigator. *app.GenericPageModal + wallet *dcr.Asset ctx context.Context // page context ctxCancel context.CancelFunc @@ -40,10 +41,11 @@ type SetupPrivacyPage struct { infoButton cryptomaterial.IconButton } -func NewSetupPrivacyPage(l *load.Load) *SetupPrivacyPage { +func NewSetupPrivacyPage(l *load.Load, wallet *dcr.Asset) *SetupPrivacyPage { pg := &SetupPrivacyPage{ Load: l, GenericPageModal: app.NewGenericPageModal(SetupPrivacyPageID), + wallet: wallet, pageContainer: layout.List{Axis: layout.Vertical}, toPrivacySetup: l.Theme.Button(values.String(values.StrSetupStakeShuffle)), } @@ -133,7 +135,7 @@ func (pg *SetupPrivacyPage) privacyIntroLayout(gtx layout.Context) layout.Dimens // Part of the load.Page interface. func (pg *SetupPrivacyPage) HandleUserInteractions() { if pg.toPrivacySetup.Clicked() { - accounts, err := pg.WL.SelectedWallet.Wallet.GetAccountsRaw() + accounts, err := pg.wallet.GetAccountsRaw() if err != nil { log.Error(err) } @@ -152,9 +154,9 @@ func (pg *SetupPrivacyPage) HandleUserInteractions() { window: pg.ParentWindow(), pageNavigator: pg.ParentNavigator(), checkBox: pg.Theme.CheckBox(new(widget.Bool), values.String(values.StrMoveFundsFrmDefaultToUnmixed)), - }) + }, pg.wallet) } else { - pg.ParentNavigator().Display(NewSetupMixerAccountsPage(pg.Load)) + pg.ParentNavigator().Display(NewSetupMixerAccountsPage(pg.Load, pg.wallet)) } } } diff --git a/ui/page/privacy/shared_modals.go b/ui/page/privacy/shared_modals.go index 301b5ef5b..53ef98020 100644 --- a/ui/page/privacy/shared_modals.go +++ b/ui/page/privacy/shared_modals.go @@ -29,7 +29,7 @@ func showInfoModal(conf *sharedModalConfig, title, body, btnText string, isError conf.window.ShowModal(info) } -func showModalSetupMixerInfo(conf *sharedModalConfig) { +func showModalSetupMixerInfo(conf *sharedModalConfig, dcrWallet *dcr.Asset) { info := modal.NewCustomModal(conf.Load). Title(values.String(values.StrMultipleMixerAccNeeded)). SetupWithTemplate(modal.SetupMixerInfoTemplate). @@ -37,20 +37,20 @@ func showModalSetupMixerInfo(conf *sharedModalConfig) { SetNegativeButtonText(values.String(values.StrCancel)). SetPositiveButtonText(values.String(values.StrInitiateSetup)). SetPositiveButtonCallback(func(movefundsChecked bool, _ *modal.InfoModal) bool { - showModalSetupMixerAcct(conf, movefundsChecked) + showModalSetupMixerAcct(conf, dcrWallet, movefundsChecked) return true }) conf.window.ShowModal(info) } -func showModalSetupMixerAcct(conf *sharedModalConfig, movefundsChecked bool) { - if conf.WL.SelectedWallet.Wallet.GetAssetType() != utils.DCRWalletAsset { +func showModalSetupMixerAcct(conf *sharedModalConfig, dcrWallet *dcr.Asset, movefundsChecked bool) { + if dcrWallet.GetAssetType() != utils.DCRWalletAsset { log.Warnf("Mixer Account for (%v) not supported.", - conf.WL.SelectedWallet.Wallet.GetAssetType()) + dcrWallet.GetAssetType()) return } - accounts, _ := conf.WL.SelectedWallet.Wallet.GetAccountsRaw() + accounts, _ := dcrWallet.GetAccountsRaw() for _, acct := range accounts.Accounts { if acct.Name == values.String(values.StrMixed) || acct.Name == values.String(values.StrUnmixed) { info := modal.NewErrorModal(conf.Load, values.String(values.StrTakenAccount), modal.DefaultClickFunc()). @@ -70,17 +70,16 @@ func showModalSetupMixerAcct(conf *sharedModalConfig, movefundsChecked bool) { EnableConfirmPassword(false). Title(values.String(values.StrConfirmToCreateAccs)). SetPositiveButtonCallback(func(_, password string, pm *modal.CreatePasswordModal) bool { - dcrUniqueImpl := conf.WL.SelectedWallet.Wallet.(*dcr.Asset) - err := dcrUniqueImpl.CreateMixerAccounts(values.String(values.StrMixed), values.String(values.StrUnmixed), password) + err := dcrWallet.CreateMixerAccounts(values.String(values.StrMixed), values.String(values.StrUnmixed), password) if err != nil { pm.SetError(err.Error()) pm.SetLoading(false) return false } - conf.WL.SelectedWallet.Wallet.SetBoolConfigValueForKey(sharedW.AccountMixerConfigSet, true) + dcrWallet.SetBoolConfigValueForKey(sharedW.AccountMixerConfigSet, true) if movefundsChecked { - err := moveFundsFromDefaultToUnmixed(conf, password) + err := moveFundsFromDefaultToUnmixed(conf, dcrWallet, password) if err != nil { log.Error(err) txt := values.StringF(values.StrErrorMovingFunds, err.Error()) @@ -91,7 +90,7 @@ func showModalSetupMixerAcct(conf *sharedModalConfig, movefundsChecked bool) { pm.Dismiss() - conf.pageNavigator.Display(NewAccountMixerPage(conf.Load)) + conf.pageNavigator.Display(NewAccountMixerPage(conf.Load, dcrWallet)) return true }) @@ -100,42 +99,41 @@ func showModalSetupMixerAcct(conf *sharedModalConfig, movefundsChecked bool) { // moveFundsFromDefaultToUnmixed moves funds from the default wallet account to the // newly created unmixed account -func moveFundsFromDefaultToUnmixed(conf *sharedModalConfig, password string) error { - acc, err := conf.WL.SelectedWallet.Wallet.GetAccountsRaw() +func moveFundsFromDefaultToUnmixed(conf *sharedModalConfig, dcrWallet *dcr.Asset, password string) error { + acc, err := dcrWallet.GetAccountsRaw() if err != nil { return err } - dcrUniqueImpl := conf.WL.SelectedWallet.Wallet.(*dcr.Asset) // get the first account in the wallet as this is the default sourceAccount := acc.Accounts[0] - destinationAccount := dcrUniqueImpl.UnmixedAccountNumber() + destinationAccount := dcrWallet.UnmixedAccountNumber() - destinationAddress, err := conf.WL.SelectedWallet.Wallet.CurrentAddress(destinationAccount) + destinationAddress, err := dcrWallet.CurrentAddress(destinationAccount) if err != nil { return err } - err = dcrUniqueImpl.NewUnsignedTx(sourceAccount.Number, nil) + err = dcrWallet.NewUnsignedTx(sourceAccount.Number, nil) if err != nil { return err } // get tx fees - feeAndSize, err := dcrUniqueImpl.EstimateFeeAndSize() + feeAndSize, err := dcrWallet.EstimateFeeAndSize() if err != nil { return err } // calculate max amount to be sent amountAtom := sourceAccount.Balance.Spendable.ToInt() - feeAndSize.Fee.UnitValue - err = dcrUniqueImpl.AddSendDestination(destinationAddress, amountAtom, true) + err = dcrWallet.AddSendDestination(destinationAddress, amountAtom, true) if err != nil { return err } // send fund - _, err = dcrUniqueImpl.Broadcast(password, "") + _, err = dcrWallet.Broadcast(password, "") if err != nil { return err } diff --git a/ui/page/root/home_page.go b/ui/page/root/home_page.go index c8f9f7034..ab7e6230b 100644 --- a/ui/page/root/home_page.go +++ b/ui/page/root/home_page.go @@ -32,9 +32,9 @@ type HomePage struct { *load.Load - ctx context.Context - ctxCancel context.CancelFunc - drawerNav components.NavDrawer + ctx context.Context + ctxCancel context.CancelFunc + sendReceiveNavItems []components.NavBarItem navigationTab *cryptomaterial.Tab appLevelSettingsButton *cryptomaterial.Clickable @@ -81,22 +81,18 @@ func NewHomePage(l *load.Load) *HomePage { _, hp.infoButton = components.SubpageHeaderButtons(l) hp.infoButton.Size = values.MarginPadding15 - hp.drawerNav = components.NavDrawer{ - Load: hp.Load, - CurrentPage: hp.CurrentPageID(), - AppNavBarItems: []components.NavHandler{ - { - Clickable: hp.Theme.NewClickable(true), - Image: hp.Theme.Icons.SendIcon, - Title: values.String(values.StrSend), - PageID: send.SendPageID, - }, - { - Clickable: hp.Theme.NewClickable(true), - Image: hp.Theme.Icons.ReceiveIcon, - Title: values.String(values.StrReceive), - PageID: ReceivePageID, - }, + hp.sendReceiveNavItems = []components.NavBarItem{ + { + Clickable: hp.Theme.NewClickable(true), + Image: hp.Theme.Icons.SendIcon, + Title: values.String(values.StrSend), + PageID: send.SendPageID, + }, + { + Clickable: hp.Theme.NewClickable(true), + Image: hp.Theme.Icons.ReceiveIcon, + Title: values.String(values.StrReceive), + PageID: ReceivePageID, }, } @@ -105,12 +101,12 @@ func NewHomePage(l *load.Load) *HomePage { }() // init shared page functions - toggleSync := func(unlock load.NeedUnlockRestore) { - if hp.WL.SelectedWallet.Wallet.IsConnectedToNetwork() { - go hp.WL.SelectedWallet.Wallet.CancelSync() + toggleSync := func(wallet sharedW.Asset, unlock load.NeedUnlockRestore) { + if wallet.IsConnectedToNetwork() { + go wallet.CancelSync() unlock(false) } else { - hp.startSyncing(hp.WL.SelectedWallet.Wallet, unlock) + hp.startSyncing(wallet, unlock) } } l.ToggleSync = toggleSync @@ -148,28 +144,15 @@ func (hp *HomePage) OnNavigatedTo() { hp.Display(NewOverviewPage(hp.Load, hp.showNavigationFunc)) } - // Initiate the auto sync for all the DCR wallets with set autosync. - for _, wallet := range hp.WL.SortedWalletList(libutils.DCRWalletAsset) { - if wallet.ReadBoolConfigValueForKey(sharedW.AutoSyncConfigKey, false) { - hp.startSyncing(wallet, func(isUnlock bool) {}) - } - } - - // Initiate the auto sync for all the BTC wallets with set autosync. - for _, wallet := range hp.WL.SortedWalletList(libutils.BTCWalletAsset) { + // Initiate the auto sync for all wallets with autosync set. + allWallets := hp.AssetsManager.AllWallets() + for _, wallet := range allWallets { if wallet.ReadBoolConfigValueForKey(sharedW.AutoSyncConfigKey, false) { hp.startSyncing(wallet, func(isUnlock bool) {}) } } - // Initiate the auto sync for all the LTC wallets with set autosync. - for _, wallet := range hp.WL.SortedWalletList(libutils.LTCWalletAsset) { - if wallet.ReadBoolConfigValueForKey(sharedW.AutoSyncConfigKey, false) { - hp.startSyncing(wallet, func(isUnlock bool) {}) - } - } - - hp.isBalanceHidden = hp.WL.AssetsManager.IsTotalBalanceVisible() + hp.isBalanceHidden = hp.AssetsManager.IsTotalBalanceVisible() } // OnDarkModeChanged is triggered whenever the dark mode setting is changed @@ -219,13 +202,14 @@ func (hp *HomePage) HandleUserInteractions() { hp.navigationTab.SetSelectedTab(values.String(values.StrTrade)) } - for _, item := range hp.drawerNav.AppNavBarItems { + for _, item := range hp.sendReceiveNavItems { for item.Clickable.Clicked() { switch strings.ToLower(item.PageID) { case values.StrReceive: hp.ParentWindow().ShowModal(components.NewReceiveModal(hp.Load)) + case values.StrSend: - allWallets := hp.WL.AssetsManager.AllWallets() + allWallets := hp.AssetsManager.AllWallets() isSendAvailable := false for _, wallet := range allWallets { if !wallet.IsWatchingOnlyWallet() { @@ -236,7 +220,7 @@ func (hp *HomePage) HandleUserInteractions() { hp.showWarningNoWallet() return } - hp.ParentWindow().ShowModal(send.NewSendPage(hp.Load, true)) + hp.ParentWindow().ShowModal(send.NewSendPage(hp.Load, nil)) } } } @@ -262,7 +246,7 @@ func (hp *HomePage) HandleUserInteractions() { for hp.hideBalanceButton.Clicked() { hp.isBalanceHidden = !hp.isBalanceHidden - hp.WL.AssetsManager.SetTotalBalanceVisibility(hp.isBalanceHidden) + hp.AssetsManager.SetTotalBalanceVisibility(hp.isBalanceHidden) } hp.bottomNavigationBar.CurrentPage = hp.CurrentPageID() @@ -608,7 +592,7 @@ func (hp *HomePage) totalBalanceLayout(gtx C) D { } func (hp *HomePage) balanceLayout(gtx C) D { - if components.IsFetchExchangeRateAPIAllowed(hp.WL) && hp.totalBalanceUSD != "" { + if hp.AssetsManager.ExchangeRateFetchingEnabled() && hp.totalBalanceUSD != "" { return layout.Flex{}.Layout(gtx, layout.Rigid(hp.LayoutUSDBalance), layout.Rigid(func(gtx C) D { @@ -672,7 +656,7 @@ func (hp *HomePage) notificationSettingsLayout(gtx C) D { if hp.Load.GetCurrentAppWidth() <= gtx.Dp(values.StartMobileView) { return D{} } - return hp.drawerNav.LayoutTopBar(gtx) + return components.LayoutNavigationBar(gtx, hp.Theme, hp.sendReceiveNavItems) }), layout.Rigid(func(gtx C) D { return layout.Inset{ @@ -733,8 +717,8 @@ func (hp *HomePage) startSyncing(wallet sharedW.Asset, unlock load.NeedUnlockRes log.Debugf("Error starting sync: %v", err) } - if hp.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.ExchangeHTTPAPI) { - err := hp.WL.AssetsManager.InstantSwap.Sync(hp.ctx) + if hp.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.ExchangeHTTPAPI) { + err := hp.AssetsManager.InstantSwap.Sync(hp.ctx) if err != nil { log.Errorf("Error syncing instant swap: %v", err) } @@ -788,7 +772,7 @@ func (hp *HomePage) unlockWalletForSyncing(wal sharedW.Asset, unlock load.NeedUn } func (hp *HomePage) CalculateAssetsUSDBalance() { - if components.IsFetchExchangeRateAPIAllowed(hp.WL) { + if hp.AssetsManager.ExchangeRateFetchingEnabled() { assetsBalance, err := components.CalculateTotalAssetsBalance(hp.Load) if err != nil { log.Error(err) diff --git a/ui/page/root/main_page.go b/ui/page/root/main_page.go index a20d3c5fc..c1c4b9d31 100644 --- a/ui/page/root/main_page.go +++ b/ui/page/root/main_page.go @@ -36,9 +36,20 @@ const ( MainPageID = "Main" ) -type MainPage struct { +// SingleWalletMasterPage is a master page for interacting with a single wallet. +// It has sub pages for viewing a wallet's info, sending and receiving funds for +// a wallet, viewing a wallet's transactions, etc. +// TODO: Rename this file in a separate commit, for easier review. +type SingleWalletMasterPage struct { *app.MasterPage + selectedWallet sharedW.Asset + // walletBalance is cached here to avoid repeatedly fetching the balance + // from the wallet on each layout. TODO: Ensure this is updated on new + // blocks and txs, or read realtime balance directly from wallet and don't + // cache. + walletBalance sharedW.AssetAmount + *load.Load *listeners.SyncProgressListener *listeners.TxAndBlockNotificationListener @@ -53,11 +64,6 @@ type MainPage struct { openWalletSelector *cryptomaterial.Clickable checkBox cryptomaterial.CheckBoxStyle - // page state variables - totalBalance sharedW.AssetAmount - selectedWallet sharedW.Asset - assetType libutils.AssetType - usdExchangeRate float64 usdExchangeSet bool isFetchingExchangeRate bool @@ -69,29 +75,28 @@ type MainPage struct { showNavigationFunc func() } -func NewMainPage(l *load.Load, showNavigationFunc func()) *MainPage { - mp := &MainPage{ +func NewSingleWalletMasterPage(l *load.Load, wallet sharedW.Asset, showNavigationFunc func()) *SingleWalletMasterPage { + swmp := &SingleWalletMasterPage{ Load: l, MasterPage: app.NewMasterPage(MainPageID), + selectedWallet: wallet, checkBox: l.Theme.CheckBox(new(widget.Bool), values.String(values.StrAwareOfRisk)), showNavigationFunc: showNavigationFunc, } - mp.selectedWallet = mp.WL.SelectedWallet.Wallet + swmp.initTabOptions() - mp.initTabOptions() + swmp.hideBalanceButton = swmp.Theme.NewClickable(false) + swmp.openWalletSelector = swmp.Theme.NewClickable(false) + swmp.refreshExchangeRateBtn = swmp.Theme.NewClickable(true) - mp.hideBalanceButton = mp.Theme.NewClickable(false) - mp.openWalletSelector = mp.Theme.NewClickable(false) - mp.refreshExchangeRateBtn = mp.Theme.NewClickable(true) - - return mp + return swmp } // ID is a unique string that identifies the page and may be used // to differentiate this page from other pages. // Part of the load.Page interface. -func (mp *MainPage) ID() string { +func (swmp *SingleWalletMasterPage) ID() string { return MainPageID } @@ -99,48 +104,47 @@ func (mp *MainPage) ID() string { // may be used to initialize page features that are only relevant when // the page is displayed. // Part of the load.Page interface. -func (mp *MainPage) OnNavigatedTo() { - mp.ctx, mp.ctxCancel = context.WithCancel(context.TODO()) +func (swmp *SingleWalletMasterPage) OnNavigatedTo() { + swmp.ctx, swmp.ctxCancel = context.WithCancel(context.TODO()) - mp.assetType = mp.selectedWallet.GetAssetType() // load wallet account balance first before rendering page contents. // It loads balance for the current selected wallet. - mp.updateBalance() + swmp.updateBalance() // updateExchangeSetting also calls updateBalance() but because of the API // call it may take a while before the balance and USD conversion is updated. // updateBalance() is called above first to prevent crash when balance value // is required before updateExchangeSetting() returns. - mp.updateExchangeSetting() + swmp.updateExchangeSetting() - backupLater := mp.selectedWallet.ReadBoolConfigValueForKey(sharedW.SeedBackupNotificationConfigKey, false) + backupLater := swmp.selectedWallet.ReadBoolConfigValueForKey(sharedW.SeedBackupNotificationConfigKey, false) // reset the checkbox - mp.checkBox.CheckBox.Value = false + swmp.checkBox.CheckBox.Value = false - needBackup := mp.selectedWallet.GetEncryptedSeed() != "" + needBackup := swmp.selectedWallet.GetEncryptedSeed() != "" if needBackup && !backupLater { - mp.showBackupInfo() + swmp.showBackupInfo() } - if mp.CurrentPage() == nil { - mp.Display(info.NewInfoPage(mp.Load)) // TODO: Should pagestack have a start page? + if swmp.CurrentPage() == nil { + swmp.Display(info.NewInfoPage(swmp.Load, swmp.selectedWallet)) // TODO: Should pagestack have a start page? YES! } - mp.listenForNotifications() // start sync notifications listening. + swmp.listenForNotifications() // start sync notifications listening. - if mp.assetType == libutils.DCRWalletAsset { - if mp.selectedWallet.ReadBoolConfigValueForKey(sharedW.FetchProposalConfigKey, false) && mp.isGovernanceAPIAllowed() { - if mp.WL.AssetsManager.Politeia.IsSyncing() { + if swmp.selectedWallet.GetAssetType() == libutils.DCRWalletAsset { + if swmp.selectedWallet.ReadBoolConfigValueForKey(sharedW.FetchProposalConfigKey, false) && swmp.isGovernanceAPIAllowed() { + if swmp.AssetsManager.Politeia.IsSyncing() { return } - go mp.WL.AssetsManager.Politeia.Sync(mp.ctx) + go swmp.AssetsManager.Politeia.Sync(swmp.ctx) } } - mp.CurrentPage().OnNavigatedTo() + swmp.CurrentPage().OnNavigatedTo() } // initTabOptions initializes the page navigation tabs -func (mp *MainPage) initTabOptions() { +func (swmp *SingleWalletMasterPage) initTabOptions() { commonTabs := []string{ values.String(values.StrInfo), values.String(values.StrSend), @@ -149,7 +153,7 @@ func (mp *MainPage) initTabOptions() { values.String(values.StrSettings), } - if mp.selectedWallet.GetAssetType() == libutils.DCRWalletAsset { + if swmp.selectedWallet.GetAssetType() == libutils.DCRWalletAsset { dcrSpecificTabs := []string{ values.String(values.StrStakeShuffle), values.String(values.StrStaking), @@ -159,28 +163,28 @@ func (mp *MainPage) initTabOptions() { commonTabs = append(commonTabs[:4], append(dcrSpecificTabs, commonTabs[4:]...)...) } - mp.pageNavigationTab = mp.Theme.SegmentedControl(commonTabs) + swmp.pageNavigationTab = swmp.Theme.SegmentedControl(commonTabs) } -func (mp *MainPage) isGovernanceAPIAllowed() bool { - return mp.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) +func (swmp *SingleWalletMasterPage) isGovernanceAPIAllowed() bool { + return swmp.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI) } -func (mp *MainPage) updateExchangeSetting() { - mp.usdExchangeSet = false - if components.IsFetchExchangeRateAPIAllowed(mp.WL) { - go mp.fetchExchangeRate() +func (swmp *SingleWalletMasterPage) updateExchangeSetting() { + swmp.usdExchangeSet = false + if swmp.AssetsManager.ExchangeRateFetchingEnabled() { + go swmp.fetchExchangeRate() } } -func (mp *MainPage) fetchExchangeRate() { - if mp.isFetchingExchangeRate { +func (swmp *SingleWalletMasterPage) fetchExchangeRate() { + if swmp.isFetchingExchangeRate { return } - mp.isFetchingExchangeRate = true + swmp.isFetchingExchangeRate = true var market string - switch mp.assetType { + switch swmp.selectedWallet.GetAssetType() { case libutils.DCRWalletAsset: market = values.DCRUSDTMarket case libutils.BTCWalletAsset: @@ -188,50 +192,50 @@ func (mp *MainPage) fetchExchangeRate() { case libutils.LTCWalletAsset: market = values.LTCUSDTMarket default: - log.Errorf("Unsupported asset type: %s", mp.assetType) - mp.isFetchingExchangeRate = false + log.Errorf("Asset type %q is not supported for exchange rate fetching", swmp.selectedWallet.GetAssetType()) + swmp.isFetchingExchangeRate = false return } - rate := mp.WL.AssetsManager.RateSource.GetTicker(market) + rate := swmp.AssetsManager.RateSource.GetTicker(market) if rate == nil || rate.LastTradePrice <= 0 { - mp.isFetchingExchangeRate = false + swmp.isFetchingExchangeRate = false return } - mp.usdExchangeRate = rate.LastTradePrice - mp.updateBalance() - mp.usdExchangeSet = true - mp.ParentWindow().Reload() - mp.isFetchingExchangeRate = false + swmp.usdExchangeRate = rate.LastTradePrice + swmp.updateBalance() + swmp.usdExchangeSet = true + swmp.ParentWindow().Reload() + swmp.isFetchingExchangeRate = false } -func (mp *MainPage) updateBalance() { - totalBalance, err := components.CalculateTotalWalletsBalance(mp.Load) +func (swmp *SingleWalletMasterPage) updateBalance() { + totalBalance, err := components.CalculateTotalWalletsBalance(swmp.selectedWallet) if err != nil { log.Error(err) return } - mp.totalBalance = totalBalance.Total - balanceInUSD := totalBalance.Total.MulF64(mp.usdExchangeRate).ToCoin() - mp.totalBalanceUSD = utils.FormatAsUSDString(mp.Printer, balanceInUSD) + swmp.walletBalance = totalBalance.Total + balanceInUSD := totalBalance.Total.MulF64(swmp.usdExchangeRate).ToCoin() + swmp.totalBalanceUSD = utils.FormatAsUSDString(swmp.Printer, balanceInUSD) } // OnDarkModeChanged is triggered whenever the dark mode setting is changed // to enable restyling UI elements where necessary. // Satisfies the load.AppSettingsChangeHandler interface. -func (mp *MainPage) OnDarkModeChanged(isDarkModeOn bool) { +func (swmp *SingleWalletMasterPage) OnDarkModeChanged(isDarkModeOn bool) { // TODO: currentPage will likely be the Settings page when this method // is called. If that page implements the AppSettingsChangeHandler interface, // the following code will trigger the OnDarkModeChanged method of that // page. - if currentPage, ok := mp.CurrentPage().(load.AppSettingsChangeHandler); ok { + if currentPage, ok := swmp.CurrentPage().(load.AppSettingsChangeHandler); ok { currentPage.OnDarkModeChanged(isDarkModeOn) } } -func (mp *MainPage) OnCurrencyChanged() { - mp.updateExchangeSetting() +func (swmp *SingleWalletMasterPage) OnCurrencyChanged() { + swmp.updateExchangeSetting() } // HandleUserInteractions is called just before Layout() to determine @@ -239,57 +243,67 @@ func (mp *MainPage) OnCurrencyChanged() { // used to update the page's UI components shortly before they are // displayed. // Part of the load.Page interface. -func (mp *MainPage) HandleUserInteractions() { - if mp.CurrentPage() != nil { - mp.CurrentPage().HandleUserInteractions() +func (swmp *SingleWalletMasterPage) HandleUserInteractions() { + if swmp.CurrentPage() != nil { + swmp.CurrentPage().HandleUserInteractions() } - if mp.refreshExchangeRateBtn.Clicked() { - go mp.fetchExchangeRate() + if swmp.refreshExchangeRateBtn.Clicked() { + go swmp.fetchExchangeRate() } - for mp.openWalletSelector.Clicked() { - mp.showNavigationFunc() + for swmp.openWalletSelector.Clicked() { + swmp.showNavigationFunc() } displayPage := func(pg app.Page) { // Load the current wallet balance on page reload. - mp.updateBalance() - mp.Display(pg) + swmp.updateBalance() + swmp.Display(pg) } - if mp.pageNavigationTab.Changed() { + if swmp.pageNavigationTab.Changed() { var pg app.Page - switch mp.pageNavigationTab.SelectedSegment() { + switch swmp.pageNavigationTab.SelectedSegment() { case values.String(values.StrSend): - pg = send.NewSendPage(mp.Load, false) + pg = send.NewSendPage(swmp.Load, swmp.selectedWallet) case values.String(values.StrReceive): - pg = NewReceivePage(mp.Load) + pg = NewReceivePage(swmp.Load, swmp.selectedWallet) case values.String(values.StrInfo): - pg = info.NewInfoPage(mp.Load) + pg = info.NewInfoPage(swmp.Load, swmp.selectedWallet) case values.String(values.StrTransactions): - pg = transaction.NewTransactionsPage(mp.Load) + pg = transaction.NewTransactionsPage(swmp.Load, swmp.selectedWallet) case values.String(values.StrStakeShuffle): - dcrUniqueImpl := mp.selectedWallet.(*dcr.Asset) - if dcrUniqueImpl != nil { - if !dcrUniqueImpl.AccountMixerConfigIsSet() { - pg = privacy.NewSetupPrivacyPage(mp.Load) + dcrW := swmp.selectedWallet.(*dcr.Asset) + if dcrW != nil { + if !dcrW.AccountMixerConfigIsSet() { + pg = privacy.NewSetupPrivacyPage(swmp.Load, dcrW) } else { - pg = privacy.NewAccountMixerPage(mp.Load) + pg = privacy.NewAccountMixerPage(swmp.Load, dcrW) } } case values.String(values.StrStaking): - pg = staking.NewStakingPage(mp.Load) + dcrW := swmp.selectedWallet.(*dcr.Asset) + if dcrW == nil { + log.Error(values.ErrDCRSupportedOnly) + } else { + pg = staking.NewStakingPage(swmp.Load, dcrW) + } case values.String(values.StrSettings): - pg = NewWalletSettingsPage(mp.Load, mp.showNavigationFunc) + pg = NewWalletSettingsPage(swmp.Load, swmp.selectedWallet, swmp.showNavigationFunc) } - displayPage(pg) + if pg != nil { + // Should never be nil, but play safe. Could theoretically be nil if + // an attempt was made to access stake shuffle features or open the + // staking page with a non-dcr wallet. + displayPage(pg) + } } - for mp.hideBalanceButton.Clicked() { - mp.isBalanceHidden = !mp.isBalanceHidden - mp.selectedWallet.SetBoolConfigValueForKey(sharedW.HideBalanceConfigKey, mp.isBalanceHidden) + for swmp.hideBalanceButton.Clicked() { + swmp.isBalanceHidden = !swmp.isBalanceHidden + swmp.selectedWallet.SetBoolConfigValueForKey(sharedW.HideBalanceConfigKey, swmp.isBalanceHidden) } } @@ -297,8 +311,8 @@ func (mp *MainPage) HandleUserInteractions() { // that this page wishes to capture. The HandleKeyPress() method will only be // called when any of these key combinations is pressed. // Satisfies the load.KeyEventHandler interface for receiving key events. -func (mp *MainPage) KeysToHandle() key.Set { - if currentPage := mp.CurrentPage(); currentPage != nil { +func (swmp *SingleWalletMasterPage) KeysToHandle() key.Set { + if currentPage := swmp.CurrentPage(); currentPage != nil { if keyEvtHandler, ok := currentPage.(load.KeyEventHandler); ok { return keyEvtHandler.KeysToHandle() } @@ -309,8 +323,8 @@ func (mp *MainPage) KeysToHandle() key.Set { // HandleKeyPress is called when one or more keys are pressed on the current // window that match any of the key combinations returned by KeysToHandle(). // Satisfies the load.KeyEventHandler interface for receiving key events. -func (mp *MainPage) HandleKeyPress(evt *key.Event) { - if currentPage := mp.CurrentPage(); currentPage != nil { +func (swmp *SingleWalletMasterPage) HandleKeyPress(evt *key.Event) { + if currentPage := swmp.CurrentPage(); currentPage != nil { if keyEvtHandler, ok := currentPage.(load.KeyEventHandler); ok { keyEvtHandler.HandleKeyPress(evt) } @@ -324,35 +338,35 @@ func (mp *MainPage) HandleKeyPress(evt *key.Event) { // OnNavigatedTo() will be called again. This method should not destroy UI // components unless they'll be recreated in the OnNavigatedTo() method. // Part of the load.Page interface. -func (mp *MainPage) OnNavigatedFrom() { +func (swmp *SingleWalletMasterPage) OnNavigatedFrom() { // Also disappear all child pages. - if mp.CurrentPage() != nil { - mp.CurrentPage().OnNavigatedFrom() + if swmp.CurrentPage() != nil { + swmp.CurrentPage().OnNavigatedFrom() } // The encrypted seed exists by default and is cleared after wallet is backed up. // Activate the modal requesting the user to backup their current wallet on // every wallet open request until the encrypted seed is cleared (backup happens). - if mp.selectedWallet.GetEncryptedSeed() != "" { - mp.selectedWallet.SaveUserConfigValue(sharedW.SeedBackupNotificationConfigKey, false) + if swmp.selectedWallet.GetEncryptedSeed() != "" { + swmp.selectedWallet.SaveUserConfigValue(sharedW.SeedBackupNotificationConfigKey, false) } - mp.ctxCancel() + swmp.ctxCancel() } // Layout draws the page UI components into the provided layout context // to be eventually drawn on screen. // Part of the load.Page interface. -func (mp *MainPage) Layout(gtx C) D { - mp.Load.SetCurrentAppWidth(gtx.Constraints.Max.X) +func (swmp *SingleWalletMasterPage) Layout(gtx C) D { + swmp.Load.SetCurrentAppWidth(gtx.Constraints.Max.X) // TODO: mobile layout - // if mp.Load.GetCurrentAppWidth() <= gtx.Dp(values.StartMobileView) { - // return mp.layoutMobile(gtx) + // if swmp.Load.GetCurrentAppWidth() <= gtx.Dp(values.StartMobileView) { + // return swmp.layoutMobile(gtx) // } - return mp.layoutDesktop(gtx) + return swmp.layoutDesktop(gtx) } -func (mp *MainPage) layoutDesktop(gtx C) D { +func (swmp *SingleWalletMasterPage) layoutDesktop(gtx C) D { return layout.Stack{}.Layout(gtx, layout.Expanded(func(gtx C) D { return cryptomaterial.LinearLayout{ @@ -361,7 +375,7 @@ func (mp *MainPage) layoutDesktop(gtx C) D { Orientation: layout.Vertical, Alignment: layout.Middle, }.Layout(gtx, - layout.Rigid(mp.LayoutTopBar), + layout.Rigid(swmp.LayoutTopBar), layout.Rigid(func(gtx C) D { return cryptomaterial.LinearLayout{ Width: gtx.Dp(values.MarginPadding550), @@ -370,22 +384,22 @@ func (mp *MainPage) layoutDesktop(gtx C) D { Alignment: layout.Middle, Margin: layout.Inset{Top: values.MarginPadding28}, }.Layout(gtx, - layout.Rigid(mp.pageTabLayout), + layout.Rigid(swmp.pageTabLayout), layout.Rigid(func(gtx C) D { - if mp.CurrentPage() == nil { + if swmp.CurrentPage() == nil { return D{} } - switch mp.CurrentPage().ID() { + switch swmp.CurrentPage().ID() { case ReceivePageID, send.SendPageID, staking.OverviewPageID, transaction.TransactionsPageID, privacy.AccountMixerPageID: // Disable page functionality if a page is not synced or rescanning is in progress. - if !mp.selectedWallet.IsSynced() || mp.selectedWallet.IsRescanning() { - return components.DisablePageWithOverlay(mp.Load, mp.CurrentPage(), gtx, + if !swmp.selectedWallet.IsSynced() || swmp.selectedWallet.IsRescanning() { + return components.DisablePageWithOverlay(swmp.Load, swmp.CurrentPage(), gtx, values.String(values.StrFunctionUnavailable), nil) } fallthrough default: - return mp.CurrentPage().Layout(gtx) + return swmp.CurrentPage().Layout(gtx) } }), ) @@ -395,8 +409,8 @@ func (mp *MainPage) layoutDesktop(gtx C) D { ) } -func (mp *MainPage) LayoutTopBar(gtx C) D { - assetType := mp.assetType +func (swmp *SingleWalletMasterPage) LayoutTopBar(gtx C) D { + assetType := swmp.selectedWallet.GetAssetType() return cryptomaterial.LinearLayout{ Width: cryptomaterial.MatchParent, Height: cryptomaterial.WrapContent, @@ -418,31 +432,31 @@ func (mp *MainPage) LayoutTopBar(gtx C) D { }, }.GradientLayout(gtx, assetType, layout.Rigid(func(gtx C) D { - isWatchOnlyWallet := mp.selectedWallet.IsWatchingOnlyWallet() + isWatchOnlyWallet := swmp.selectedWallet.IsWatchingOnlyWallet() return layout.W.Layout(gtx, func(gtx C) D { return cryptomaterial.LinearLayout{ Width: cryptomaterial.WrapContent, Height: cryptomaterial.WrapContent, Orientation: layout.Horizontal, Alignment: layout.Middle, - Clickable: mp.openWalletSelector, + Clickable: swmp.openWalletSelector, }.Layout(gtx, layout.Rigid(func(gtx C) D { return layout.Inset{ Left: values.MarginPadding12, Right: values.MarginPadding12, - }.Layout(gtx, mp.Theme.Icons.ChevronLeft.Layout24dp) + }.Layout(gtx, swmp.Theme.Icons.ChevronLeft.Layout24dp) }), layout.Rigid(func(gtx C) D { - image := components.CoinImageBySymbol(mp.Load, assetType, isWatchOnlyWallet) + image := components.CoinImageBySymbol(swmp.Load, assetType, isWatchOnlyWallet) if image != nil { return image.Layout24dp(gtx) } return D{} }), layout.Rigid(func(gtx C) D { - lbl := mp.Theme.H6(mp.selectedWallet.GetWalletName()) - lbl.Color = mp.Theme.Color.PageNavText + lbl := swmp.Theme.H6(swmp.selectedWallet.GetWalletName()) + lbl.Color = swmp.Theme.Color.PageNavText return layout.Inset{ Left: values.MarginPadding10, }.Layout(gtx, lbl.Layout) @@ -452,7 +466,7 @@ func (mp *MainPage) LayoutTopBar(gtx C) D { return layout.Inset{ Left: values.MarginPadding10, }.Layout(gtx, func(gtx C) D { - return components.WalletHightlighLabel(mp.Theme, gtx, values.TextSize16, values.String(values.StrWatchOnly)) + return components.WalletHightlighLabel(swmp.Theme, gtx, values.TextSize16, values.String(values.StrWatchOnly)) }) } return D{} @@ -465,21 +479,21 @@ func (mp *MainPage) LayoutTopBar(gtx C) D { return layout.E.Layout(gtx, func(gtx C) D { return layout.Flex{}.Layout(gtx, layout.Rigid(func(gtx C) D { - icon := mp.Theme.Icons.RevealIcon - if mp.isBalanceHidden { - icon = mp.Theme.Icons.ConcealIcon + icon := swmp.Theme.Icons.RevealIcon + if swmp.isBalanceHidden { + icon = swmp.Theme.Icons.ConcealIcon } return layout.Inset{ Top: values.MarginPadding5, Right: values.MarginPadding9, }.Layout(gtx, func(gtx C) D { - return mp.hideBalanceButton.Layout(gtx, icon.Layout16dp) + return swmp.hideBalanceButton.Layout(gtx, icon.Layout16dp) }) }), - layout.Rigid(mp.totalAssetBalance), + layout.Rigid(swmp.totalAssetBalance), layout.Rigid(func(gtx C) D { - if !mp.isBalanceHidden { - return mp.LayoutUSDBalance(gtx) + if !swmp.isBalanceHidden { + return swmp.LayoutUSDBalance(gtx) } return D{} }), @@ -490,42 +504,42 @@ func (mp *MainPage) LayoutTopBar(gtx C) D { }), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = gtx.Constraints.Max.X - return mp.Theme.Separator().Layout(gtx) + return swmp.Theme.Separator().Layout(gtx) }), ) } -func (mp *MainPage) pageTabLayout(gtx C) D { - return layout.Inset{Bottom: values.MarginPadding16}.Layout(gtx, mp.pageNavigationTab.TransparentLayout) +func (swmp *SingleWalletMasterPage) pageTabLayout(gtx C) D { + return layout.Inset{Bottom: values.MarginPadding16}.Layout(gtx, swmp.pageNavigationTab.TransparentLayout) } -func (mp *MainPage) LayoutUSDBalance(gtx C) D { - if !mp.usdExchangeSet { +func (swmp *SingleWalletMasterPage) LayoutUSDBalance(gtx C) D { + if !swmp.usdExchangeSet { return D{} } switch { - case mp.isFetchingExchangeRate && mp.usdExchangeRate == 0: + case swmp.isFetchingExchangeRate && swmp.usdExchangeRate == 0: gtx.Constraints.Max.Y = gtx.Dp(values.MarginPadding18) gtx.Constraints.Max.X = gtx.Constraints.Max.Y return layout.Inset{ Top: values.MarginPadding8, Left: values.MarginPadding5, }.Layout(gtx, func(gtx C) D { - loader := material.Loader(mp.Theme.Base) + loader := material.Loader(swmp.Theme.Base) return loader.Layout(gtx) }) - case !mp.isFetchingExchangeRate && mp.usdExchangeRate == 0: + case !swmp.isFetchingExchangeRate && swmp.usdExchangeRate == 0: return layout.Inset{ Top: values.MarginPadding7, Left: values.MarginPadding5, }.Layout(gtx, func(gtx C) D { - return mp.refreshExchangeRateBtn.Layout(gtx, func(gtx C) D { - return mp.Theme.Icons.Restore.Layout16dp(gtx) + return swmp.refreshExchangeRateBtn.Layout(gtx, func(gtx C) D { + return swmp.Theme.Icons.Restore.Layout16dp(gtx) }) }) - case len(mp.totalBalanceUSD) > 0: - lbl := mp.Theme.Label(values.TextSize20, fmt.Sprintf("/ %s", mp.totalBalanceUSD)) - lbl.Color = mp.Theme.Color.PageNavText + case len(swmp.totalBalanceUSD) > 0: + lbl := swmp.Theme.Label(values.TextSize20, fmt.Sprintf("/ %s", swmp.totalBalanceUSD)) + lbl.Color = swmp.Theme.Color.PageNavText inset := layout.Inset{Left: values.MarginPadding8} return inset.Layout(gtx, lbl.Layout) default: @@ -533,23 +547,23 @@ func (mp *MainPage) LayoutUSDBalance(gtx C) D { } } -func (mp *MainPage) totalAssetBalance(gtx C) D { - if mp.isBalanceHidden || mp.totalBalance == nil { - hiddenBalanceText := mp.Theme.Label(values.TextSize18*0.8, "*******************") +func (swmp *SingleWalletMasterPage) totalAssetBalance(gtx C) D { + if swmp.isBalanceHidden || swmp.walletBalance == nil { + hiddenBalanceText := swmp.Theme.Label(values.TextSize18*0.8, "*******************") return layout.Inset{Bottom: values.MarginPadding0, Top: values.MarginPadding5}.Layout(gtx, func(gtx C) D { - hiddenBalanceText.Color = mp.Theme.Color.PageNavText + hiddenBalanceText.Color = swmp.Theme.Color.PageNavText return hiddenBalanceText.Layout(gtx) }) } - return components.LayoutBalanceWithUnit(gtx, mp.Load, mp.totalBalance.String()) + return components.LayoutBalanceWithUnit(gtx, swmp.Load, swmp.walletBalance.String()) } // postDesktopNotification posts notifications to the desktop. -func (mp *MainPage) postDesktopNotification(notifier interface{}) { +func (swmp *SingleWalletMasterPage) postDesktopNotification(notifier interface{}) { var notification string switch t := notifier.(type) { case wallet.NewTransaction: - wal := mp.selectedWallet + wal := swmp.selectedWallet switch t.Transaction.Type { case dcr.TxTypeRegular: if t.Transaction.Direction != dcr.TxDirectionReceived { @@ -567,14 +581,14 @@ func (mp *MainPage) postDesktopNotification(notifier interface{}) { return } - if mp.WL.AssetsManager.OpenedWalletsCount() > 1 { + if swmp.AssetsManager.OpenedWalletsCount() > 1 { notification = fmt.Sprintf("[%s] %s", wal.GetWalletName(), notification) } initializeBeepNotification(notification) case wallet.Proposal: - proposalNotification := mp.selectedWallet.ReadBoolConfigValueForKey(sharedW.ProposalNotificationConfigKey, false) || - !mp.WL.AssetsManager.IsPrivacyModeOn() + proposalNotification := swmp.selectedWallet.ReadBoolConfigValueForKey(sharedW.ProposalNotificationConfigKey, false) || + !swmp.AssetsManager.IsPrivacyModeOn() if !proposalNotification { return } @@ -607,44 +621,44 @@ func initializeBeepNotification(n string) { // listenForNotifications starts a goroutine to watch for notifications // and update the UI accordingly. -func (mp *MainPage) listenForNotifications() { +func (swmp *SingleWalletMasterPage) listenForNotifications() { // Return if any of the listener is not nil. switch { - case mp.SyncProgressListener != nil: + case swmp.SyncProgressListener != nil: return - case mp.TxAndBlockNotificationListener != nil: + case swmp.TxAndBlockNotificationListener != nil: return - case mp.ProposalNotificationListener != nil: + case swmp.ProposalNotificationListener != nil: return - case mp.OrderNotificationListener != nil: + case swmp.OrderNotificationListener != nil: return } - mp.SyncProgressListener = listeners.NewSyncProgress() - err := mp.selectedWallet.AddSyncProgressListener(mp.SyncProgressListener, MainPageID) + swmp.SyncProgressListener = listeners.NewSyncProgress() + err := swmp.selectedWallet.AddSyncProgressListener(swmp.SyncProgressListener, MainPageID) if err != nil { log.Errorf("Error adding sync progress listener: %v", err) return } - mp.TxAndBlockNotificationListener = listeners.NewTxAndBlockNotificationListener() - err = mp.selectedWallet.AddTxAndBlockNotificationListener(mp.TxAndBlockNotificationListener, true, MainPageID) + swmp.TxAndBlockNotificationListener = listeners.NewTxAndBlockNotificationListener() + err = swmp.selectedWallet.AddTxAndBlockNotificationListener(swmp.TxAndBlockNotificationListener, true, MainPageID) if err != nil { log.Errorf("Error adding tx and block notification listener: %v", err) return } - mp.ProposalNotificationListener = listeners.NewProposalNotificationListener() - if mp.isGovernanceAPIAllowed() { - err = mp.WL.AssetsManager.Politeia.AddNotificationListener(mp.ProposalNotificationListener, MainPageID) + swmp.ProposalNotificationListener = listeners.NewProposalNotificationListener() + if swmp.isGovernanceAPIAllowed() { + err = swmp.AssetsManager.Politeia.AddNotificationListener(swmp.ProposalNotificationListener, MainPageID) if err != nil { log.Errorf("Error adding politeia notification listener: %v", err) return } } - mp.OrderNotificationListener = listeners.NewOrderNotificationListener() - err = mp.WL.AssetsManager.InstantSwap.AddNotificationListener(mp.OrderNotificationListener, MainPageID) + swmp.OrderNotificationListener = listeners.NewOrderNotificationListener() + err = swmp.AssetsManager.InstantSwap.AddNotificationListener(swmp.OrderNotificationListener, MainPageID) if err != nil { log.Errorf("Error adding instantswap notification listener: %v", err) return @@ -653,19 +667,19 @@ func (mp *MainPage) listenForNotifications() { go func() { for { select { - case n := <-mp.TxAndBlockNotifChan(): + case n := <-swmp.TxAndBlockNotifChan(): switch n.Type { case listeners.NewTransaction: - mp.updateBalance() - if mp.WL.AssetsManager.IsTransactionNotificationsOn() { + swmp.updateBalance() + if swmp.AssetsManager.IsTransactionNotificationsOn() { update := wallet.NewTransaction{ Transaction: n.Transaction, } - mp.postDesktopNotification(update) + swmp.postDesktopNotification(update) } - mp.ParentWindow().Reload() + swmp.ParentWindow().Reload() case listeners.BlockAttached: - beep := mp.selectedWallet.ReadBoolConfigValueForKey(sharedW.BeepNewBlocksConfigKey, false) + beep := swmp.selectedWallet.ReadBoolConfigValueForKey(sharedW.BeepNewBlocksConfigKey, false) if beep { err := beeep.Beep(5, 1) if err != nil { @@ -673,46 +687,46 @@ func (mp *MainPage) listenForNotifications() { } } - mp.updateBalance() - mp.ParentWindow().Reload() + swmp.updateBalance() + swmp.ParentWindow().Reload() case listeners.TxConfirmed: - mp.updateBalance() - mp.ParentWindow().Reload() + swmp.updateBalance() + swmp.ParentWindow().Reload() } - case notification := <-mp.ProposalNotifChan: + case notification := <-swmp.ProposalNotifChan: // Post desktop notification for all events except the synced event. if notification.ProposalStatus != wallet.Synced { - mp.postDesktopNotification(notification) + swmp.postDesktopNotification(notification) } - case notification := <-mp.OrderNotifChan: + case notification := <-swmp.OrderNotifChan: // Post desktop notification for all events except the synced // event. if notification.OrderStatus != wallet.OrderStatusSynced { - // TODO: mp.postDesktopNotification does not do anything + // TODO: swmp.postDesktopNotification does not do anything // with wallet.Order types. - mp.postDesktopNotification(notification) + swmp.postDesktopNotification(notification) } - case n := <-mp.SyncStatusChan: + case n := <-swmp.SyncStatusChan: if n.Stage == wallet.SyncCompleted { - mp.updateBalance() - mp.ParentWindow().Reload() + swmp.updateBalance() + swmp.ParentWindow().Reload() } - case <-mp.ctx.Done(): - mp.selectedWallet.RemoveSyncProgressListener(MainPageID) - mp.selectedWallet.RemoveTxAndBlockNotificationListener(MainPageID) - mp.WL.AssetsManager.Politeia.RemoveNotificationListener(MainPageID) - mp.WL.AssetsManager.InstantSwap.RemoveNotificationListener(MainPageID) - - close(mp.SyncStatusChan) - mp.CloseTxAndBlockChan() - close(mp.ProposalNotifChan) - close(mp.OrderNotifChan) - - mp.SyncProgressListener = nil - mp.TxAndBlockNotificationListener = nil - mp.ProposalNotificationListener = nil - mp.OrderNotificationListener = nil + case <-swmp.ctx.Done(): + swmp.selectedWallet.RemoveSyncProgressListener(MainPageID) + swmp.selectedWallet.RemoveTxAndBlockNotificationListener(MainPageID) + swmp.AssetsManager.Politeia.RemoveNotificationListener(MainPageID) + swmp.AssetsManager.InstantSwap.RemoveNotificationListener(MainPageID) + + close(swmp.SyncStatusChan) + swmp.CloseTxAndBlockChan() + close(swmp.ProposalNotifChan) + close(swmp.OrderNotifChan) + + swmp.SyncProgressListener = nil + swmp.TxAndBlockNotificationListener = nil + swmp.ProposalNotificationListener = nil + swmp.OrderNotificationListener = nil return } @@ -720,24 +734,24 @@ func (mp *MainPage) listenForNotifications() { }() } -func (mp *MainPage) showBackupInfo() { - backupNowOrLaterModal := modal.NewCustomModal(mp.Load). +func (swmp *SingleWalletMasterPage) showBackupInfo() { + backupNowOrLaterModal := modal.NewCustomModal(swmp.Load). SetupWithTemplate(modal.WalletBackupInfoTemplate). SetCancelable(false). SetContentAlignment(layout.W, layout.W, layout.Center). - CheckBox(mp.checkBox, true). + CheckBox(swmp.checkBox, true). SetNegativeButtonText(values.String(values.StrBackupLater)). SetNegativeButtonCallback(func() { - mp.selectedWallet.SaveUserConfigValue(sharedW.SeedBackupNotificationConfigKey, true) + swmp.selectedWallet.SaveUserConfigValue(sharedW.SeedBackupNotificationConfigKey, true) }). - PositiveButtonStyle(mp.Load.Theme.Color.Primary, mp.Load.Theme.Color.InvText). + PositiveButtonStyle(swmp.Load.Theme.Color.Primary, swmp.Load.Theme.Color.InvText). SetPositiveButtonText(values.String(values.StrBackupNow)). SetPositiveButtonCallback(func(_ bool, _ *modal.InfoModal) bool { - mp.selectedWallet.SaveUserConfigValue(sharedW.SeedBackupNotificationConfigKey, true) - mp.ParentNavigator().Display(seedbackup.NewBackupInstructionsPage(mp.Load, mp.selectedWallet, func(load *load.Load, navigator app.WindowNavigator) { - navigator.ClosePagesAfter(mp.ParentWindow().CurrentPageID()) + swmp.selectedWallet.SaveUserConfigValue(sharedW.SeedBackupNotificationConfigKey, true) + swmp.ParentNavigator().Display(seedbackup.NewBackupInstructionsPage(swmp.Load, swmp.selectedWallet, func(load *load.Load, navigator app.WindowNavigator) { + navigator.ClosePagesAfter(swmp.ParentWindow().CurrentPageID()) })) return true }) - mp.ParentWindow().ShowModal(backupNowOrLaterModal) + swmp.ParentWindow().ShowModal(backupNowOrLaterModal) } diff --git a/ui/page/root/overview_page.go b/ui/page/root/overview_page.go index 9307f4747..8b5afa325 100644 --- a/ui/page/root/overview_page.go +++ b/ui/page/root/overview_page.go @@ -218,8 +218,8 @@ func (pg *OverviewPage) OnNavigatedTo() { pg.proposalItems = components.LoadProposals(pg.Load, libwallet.ProposalCategoryAll, 0, 3, true) pg.orders = components.LoadOrders(pg.Load, 0, 3, true) - if components.IsFetchExchangeRateAPIAllowed(pg.WL) { - go pg.WL.AssetsManager.RateSource.Refresh(false) + if pg.AssetsManager.ExchangeRateFetchingEnabled() { + go pg.AssetsManager.RateSource.Refresh(false) } pg.listenForMixerNotifications() @@ -239,25 +239,23 @@ func (pg *OverviewPage) HandleUserInteractions() { } if pg.forceRefreshRates.Clicked() { - go pg.WL.AssetsManager.RateSource.Refresh(true) + go pg.AssetsManager.RateSource.Refresh(true) } // Navigate to mixer page when wallet mixer slider forward button is clicked. if pg.forwardButton.Button.Clicked() { curSliderIndex := pg.mixerSlider.GetSelectedIndex() mixerData := pg.mixerSliderData[pg.sortedMixerSlideKeys[curSliderIndex]] - pg.WL.SelectedWallet = &load.WalletItem{ - Wallet: mixerData.Asset, - } + selectedWallet := mixerData.Asset pg.showNavigationFunc(true) walletCallbackFunc := func() { pg.showNavigationFunc(false) } - mp := NewMainPage(pg.Load, walletCallbackFunc) - pg.ParentNavigator().Display(mp) - mp.Display(privacy.NewAccountMixerPage(pg.Load)) // Display mixer page on the main page. - mp.pageNavigationTab.SetSelectedSegment(values.String(values.StrStakeShuffle)) + swmp := NewSingleWalletMasterPage(pg.Load, selectedWallet, walletCallbackFunc) + pg.ParentNavigator().Display(swmp) + swmp.Display(privacy.NewAccountMixerPage(pg.Load, selectedWallet)) // Display mixer page on the main page. + swmp.pageNavigationTab.SetSelectedSegment(values.String(values.StrStakeShuffle)) } } @@ -805,13 +803,13 @@ func (pg *OverviewPage) mobileMarketOverview(gtx C) D { func (pg *OverviewPage) marketRates() map[string]*ext.Ticker { marketRates := make(map[string]*ext.Ticker) - if !components.IsFetchExchangeRateAPIAllowed(pg.WL) { + if !pg.AssetsManager.ExchangeRateFetchingEnabled() { return marketRates } for i := range pg.mktValues { asset := pg.mktValues[i] - rate := pg.WL.AssetsManager.RateSource.GetTicker(asset.market) + rate := pg.AssetsManager.RateSource.GetTicker(asset.market) if rate == nil || rate.LastTradePrice <= 0 { continue } @@ -906,7 +904,7 @@ func (pg *OverviewPage) txStakingSection(gtx C) D { } txAndWallet := func(mtx *multiWalletTx) (*sharedW.Transaction, sharedW.Asset) { - return mtx.Transaction, pg.WL.AssetsManager.WalletWithID(mtx.walletID) + return mtx.Transaction, pg.AssetsManager.WalletWithID(mtx.walletID) } return cryptomaterial.LinearLayout{ @@ -1072,7 +1070,7 @@ func (pg *OverviewPage) recentProposal(gtx C) D { } func (pg *OverviewPage) updateAssetsUSDBalance() { - if components.IsFetchExchangeRateAPIAllowed(pg.WL) { + if pg.AssetsManager.ExchangeRateFetchingEnabled() { assetsTotalUSDBalance, err := components.CalculateAssetsUSDBalance(pg.Load, pg.assetsTotalBalance) if err != nil { log.Error(err) @@ -1182,7 +1180,7 @@ func (pg *OverviewPage) listenForMixerNotifications() { // Get all DCR wallets, and subscribe to the individual wallet's mixer channel. // We are only interested in DCR wallets since mixing support // is limited to DCR at this point. - dcrWallets := pg.WL.AssetsManager.AllDCRWallets() + dcrWallets := pg.AssetsManager.AllDCRWallets() if pg.AccountMixerNotificationListener == nil { pg.AccountMixerNotificationListener = listeners.NewAccountMixerNotificationListener() @@ -1208,7 +1206,7 @@ func (pg *OverviewPage) listenForMixerNotifications() { } pg.RateListener = ext.NewRateListener() - err := pg.WL.AssetsManager.RateSource.AddRateListener(pg.RateListener, OverviewPageID) + err := pg.AssetsManager.RateSource.AddRateListener(pg.RateListener, OverviewPageID) if err != nil { log.Error("RateSource.AddRateListener error: %v", err) } @@ -1268,7 +1266,7 @@ func (pg *OverviewPage) listenForMixerNotifications() { w.RemoveAccountMixerNotificationListener(OverviewPageID) w.RemoveTxAndBlockNotificationListener(OverviewPageID) } - pg.WL.AssetsManager.RateSource.RemoveRateListener(OverviewPageID) + pg.AssetsManager.RateSource.RemoveRateListener(OverviewPageID) close(pg.MixerChan) pg.CloseTxAndBlockChan() close(pg.RateUpdateChan) @@ -1320,14 +1318,14 @@ func (pg *OverviewPage) reloadBalances() { func (pg *OverviewPage) ratesRefreshComponent() func(gtx C) D { return func(gtx layout.Context) layout.Dimensions { - refreshing := pg.WL.AssetsManager.RateSource.Refreshing() + refreshing := pg.AssetsManager.RateSource.Refreshing() return layout.Flex{Axis: layout.Horizontal, Alignment: layout.End}.Layout(gtx, layout.Rigid(func(gtx layout.Context) layout.Dimensions { var text string if refreshing { text = values.String(values.StrRefreshState) } else { - lastUpdatedTimestamp := pg.WL.AssetsManager.RateSource.LastUpdate().Unix() + lastUpdatedTimestamp := pg.AssetsManager.RateSource.LastUpdate().Unix() text = values.String(values.StrUpdated) + " " + components.TimeAgo(lastUpdatedTimestamp) } lastUpdatedInfo := pg.Theme.Label(values.TextSize12, text) @@ -1359,7 +1357,7 @@ func (pg *OverviewPage) ratesRefreshComponent() func(gtx C) D { func (pg *OverviewPage) loadTransactions() { pg.transactions = make([]*multiWalletTx, 0) - wal := pg.WL.AllSortedWalletList() + wal := pg.AssetsManager.AllWallets() for _, w := range wal { txs, err := w.GetTransactionsRaw(0, 3, libutils.TxFilterAllTx, true) if err != nil { @@ -1385,7 +1383,7 @@ func (pg *OverviewPage) loadTransactions() { func (pg *OverviewPage) loadStakes() { pg.stakes = make([]*multiWalletTx, 0) - wal := pg.WL.AssetsManager.AllDCRWallets() + wal := pg.AssetsManager.AllDCRWallets() for _, w := range wal { txs, err := w.GetTransactionsRaw(0, 6, libutils.TxFilterStaking, true) if err != nil { diff --git a/ui/page/root/receive_page.go b/ui/page/root/receive_page.go index ceab9ddd2..1f033e7a5 100644 --- a/ui/page/root/receive_page.go +++ b/ui/page/root/receive_page.go @@ -56,14 +56,14 @@ type ReceivePage struct { isCopying bool backdrop *widget.Clickable infoButton cryptomaterial.IconButton - selectedWallet *load.WalletMapping + selectedWallet sharedW.Asset } -func NewReceivePage(l *load.Load) *ReceivePage { +func NewReceivePage(l *load.Load, wallet sharedW.Asset) *ReceivePage { pg := &ReceivePage{ Load: l, GenericPageModal: app.NewGenericPageModal(ReceivePageID), - assetsManager: l.WL.AssetsManager, + assetsManager: l.AssetsManager, pageContainer: layout.List{ Axis: layout.Vertical, }, @@ -77,9 +77,7 @@ func NewReceivePage(l *load.Load) *ReceivePage { receiveAddress: l.Theme.Label(values.TextSize20, ""), card: l.Theme.Card(), backdrop: new(widget.Clickable), - } - pg.selectedWallet = &load.WalletMapping{ - Asset: l.WL.SelectedWallet.Wallet, + selectedWallet: wallet, } pg.info.Inset, pg.info.Size = layout.UniformInset(values.MarginPadding5), values.MarginPadding20 @@ -120,7 +118,7 @@ func NewReceivePage(l *load.Load) *ReceivePage { if account.Number == load.MaxInt32 { return false } - if account.Number != pg.selectedWallet.MixedAccountNumber() { + if account.Number != load.MixedAccountNumber(pg.selectedWallet) { return true } return false @@ -136,7 +134,7 @@ func NewReceivePage(l *load.Load) *ReceivePage { // Part of the load.Page interface. func (pg *ReceivePage) OnNavigatedTo() { pg.ctx, pg.ctxCancel = context.WithCancel(context.TODO()) - if !pg.WL.SelectedWallet.Wallet.IsSynced() { + if !pg.selectedWallet.IsSynced() { // Events are disabled until the wallet is fully synced. return } @@ -144,7 +142,7 @@ func (pg *ReceivePage) OnNavigatedTo() { pg.selector.ListenForTxNotifications(pg.ctx, pg.ParentWindow()) pg.selector.SelectFirstValidAccount(pg.selectedWallet) // Want to reset the user's selection everytime this page appears? // might be better to track the last selection in a variable and reselect it. - currentAddress, err := pg.WL.SelectedWallet.Wallet.CurrentAddress(pg.selector.SelectedAccount().Number) + currentAddress, err := pg.selectedWallet.CurrentAddress(pg.selector.SelectedAccount().Number) if err != nil { errStr := fmt.Sprintf("Error getting current address: %v", err) errModal := modal.NewErrorModal(pg.Load, errStr, modal.DefaultClickFunc()) @@ -208,7 +206,7 @@ func (pg *ReceivePage) layoutDesktop(gtx layout.Context) layout.Dimensions { return pg.titleLayout(gtx) }), layout.Rigid(func(gtx C) D { - if pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { + if pg.selectedWallet.IsWatchingOnlyWallet() { warning := pg.Theme.Label(values.TextSize16, values.String(values.StrWarningWatchWallet)) warning.Color = pg.Theme.Color.Danger return layout.Center.Layout(gtx, warning.Layout) @@ -222,14 +220,14 @@ func (pg *ReceivePage) layoutDesktop(gtx layout.Context) layout.Dimensions { Alignment: layout.Middle, }.Layout(gtx, layout.Rigid(func(gtx C) D { - if pg.currentAddress != "" && pg.WL.SelectedWallet.Wallet.IsSynced() { + if pg.currentAddress != "" && pg.selectedWallet.IsSynced() { // Display generated address only on a synced wallet return pg.addressLayout(gtx) } return D{} }), layout.Rigid(func(gtx C) D { - if pg.qrImage == nil || !pg.WL.SelectedWallet.Wallet.IsSynced() { + if pg.qrImage == nil || !pg.selectedWallet.IsSynced() { // Display generated address only on a synced wallet return D{} } @@ -363,7 +361,7 @@ func (pg *ReceivePage) topNav(gtx C) D { // m := values.MarginPadding0 return layout.Flex{}.Layout(gtx, layout.Rigid(func(gtx C) D { - textWithUnit := values.String(values.StrReceive) + " " + string(pg.WL.SelectedWallet.Wallet.GetAssetType()) + textWithUnit := values.String(values.StrReceive) + " " + string(pg.selectedWallet.GetAssetType()) return /*layout.Inset{Left: m}.Layout(gtx, */ pg.Theme.H6(textWithUnit).Layout(gtx) }), layout.Flexed(1, func(gtx C) D { @@ -459,7 +457,7 @@ func (pg *ReceivePage) HandleUserInteractions() { } if pg.infoButton.Button.Clicked() { - textWithUnit := values.String(values.StrReceive) + " " + string(pg.WL.SelectedWallet.Wallet.GetAssetType()) + textWithUnit := values.String(values.StrReceive) + " " + string(pg.selectedWallet.GetAssetType()) info := modal.NewCustomModal(pg.Load). Title(textWithUnit). Body(values.String(values.StrReceiveInfo)). diff --git a/ui/page/root/wallet_list.go b/ui/page/root/wallet_list.go index 7f16c02de..345ea542b 100644 --- a/ui/page/root/wallet_list.go +++ b/ui/page/root/wallet_list.go @@ -8,7 +8,6 @@ import ( libutils "github.com/crypto-power/cryptopower/libwallet/utils" "github.com/crypto-power/cryptopower/listeners" "github.com/crypto-power/cryptopower/ui/cryptomaterial" - "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/modal" "github.com/crypto-power/cryptopower/ui/page/components" "github.com/crypto-power/cryptopower/ui/utils" @@ -22,8 +21,8 @@ func (pg *WalletSelectorPage) initWalletSelectorOptions() { func (pg *WalletSelectorPage) loadWallets() { - wallets := pg.WL.AllSortedWalletList() - walletsList := make(map[libutils.AssetType][]*load.WalletItem) + wallets := pg.AssetsManager.AllWallets() + walletsList := make(map[libutils.AssetType][]*walletWithBalance) for _, wal := range wallets { balance, err := wal.GetWalletBalance() @@ -31,9 +30,9 @@ func (pg *WalletSelectorPage) loadWallets() { log.Errorf("wallet (%v) balance was ignored : %v", wal.GetWalletName(), err) } - listItem := &load.WalletItem{ - Wallet: wal, - TotalBalance: balance.Total, + listItem := &walletWithBalance{ + wallet: wal, + totalBalance: balance.Total, } walletsList[wal.GetAssetType()] = append(walletsList[wal.GetAssetType()], listItem) @@ -49,9 +48,9 @@ func (pg *WalletSelectorPage) loadWallets() { func (pg *WalletSelectorPage) loadBadWallets() { pg.badWalletsList = make(map[libutils.AssetType][]*badWalletListItem) - dcrBadWallets := pg.WL.AssetsManager.DCRBadWallets() - btcBadWallets := pg.WL.AssetsManager.BTCBadWallets() - ltcBadWallets := pg.WL.AssetsManager.LTCBadWallets() + dcrBadWallets := pg.AssetsManager.DCRBadWallets() + btcBadWallets := pg.AssetsManager.BTCBadWallets() + ltcBadWallets := pg.AssetsManager.LTCBadWallets() populateBadWallets := func(assetType libutils.AssetType, badWallets map[int]*sharedW.Wallet) { for _, badWallet := range badWallets { @@ -78,7 +77,7 @@ func (pg *WalletSelectorPage) deleteBadWallet(badWalletID int) { PositiveButtonStyle(pg.Load.Theme.Color.Surface, pg.Load.Theme.Color.Danger). SetPositiveButtonText(values.String(values.StrRemove)). SetPositiveButtonCallback(func(_ bool, im *modal.InfoModal) bool { - err := pg.WL.AssetsManager.DeleteBadWallet(badWalletID) + err := pg.AssetsManager.DeleteBadWallet(badWalletID) if err != nil { errorModal := modal.NewErrorModal(pg.Load, err.Error(), modal.DefaultClickFunc()) pg.ParentWindow().ShowModal(errorModal) @@ -143,7 +142,7 @@ func (pg *WalletSelectorPage) walletListLayout(gtx C, assetType libutils.AssetTy }) } -func (pg *WalletSelectorPage) walletSection(gtx C, mainWalletList []*load.WalletItem) D { +func (pg *WalletSelectorPage) walletSection(gtx C, mainWalletList []*walletWithBalance) D { pg.listLock.RLock() defer pg.listLock.RUnlock() @@ -151,13 +150,13 @@ func (pg *WalletSelectorPage) walletSection(gtx C, mainWalletList []*load.Wallet for i, wallet := range mainWalletList { globalIndex := len(itemIDs) itemIDs = append(itemIDs, walletIndexTuple{ - AssetType: wallet.Wallet.GetAssetType(), + AssetType: wallet.wallet.GetAssetType(), Index: globalIndex, }) // Populate the mapping here pg.indexMapping[globalIndex] = walletIndexTuple{ - AssetType: wallet.Wallet.GetAssetType(), + AssetType: wallet.wallet.GetAssetType(), Index: i, } } @@ -242,7 +241,7 @@ func (pg *WalletSelectorPage) badWalletsWrapper(gtx C, badWalletsList []*badWall ) } -func (pg *WalletSelectorPage) walletWrapper(gtx C, item *load.WalletItem) D { +func (pg *WalletSelectorPage) walletWrapper(gtx C, item *walletWithBalance) D { return cryptomaterial.LinearLayout{ Width: cryptomaterial.WrapContent, Height: cryptomaterial.WrapContent, @@ -268,13 +267,13 @@ func (pg *WalletSelectorPage) walletWrapper(gtx C, item *load.WalletItem) D { Alignment: layout.Middle, }.Layout(gtx, layout.Rigid(func(gtx C) D { - txt := pg.Theme.Label(values.TextSize16, item.Wallet.GetWalletName()) + txt := pg.Theme.Label(values.TextSize16, item.wallet.GetWalletName()) txt.Color = pg.Theme.Color.Text txt.Font.Weight = font.SemiBold return txt.Layout(gtx) }), layout.Rigid(func(gtx C) D { - if item.Wallet.IsWatchingOnlyWallet() { + if item.wallet.IsWatchingOnlyWallet() { return layout.Inset{ Left: values.MarginPadding8, }.Layout(gtx, func(gtx C) D { @@ -291,10 +290,10 @@ func (pg *WalletSelectorPage) walletWrapper(gtx C, item *load.WalletItem) D { Alignment: layout.Middle, }.Layout(gtx, layout.Rigid(func(gtx C) D { - return pg.syncStatusIcon(gtx, item.Wallet) + return pg.syncStatusIcon(gtx, item.wallet) }), layout.Rigid(func(gtx C) D { - if len(item.Wallet.GetEncryptedSeed()) > 0 { + if len(item.wallet.GetEncryptedSeed()) > 0 { return layout.Flex{ Axis: layout.Horizontal, Alignment: layout.Middle, @@ -326,12 +325,12 @@ func (pg *WalletSelectorPage) walletWrapper(gtx C, item *load.WalletItem) D { Alignment: layout.End, }.Layout(gtx, layout.Rigid(func(gtx C) D { - return components.LayoutBalanceWithStateSemiBold(gtx, pg.Load, item.TotalBalance.String()) + return components.LayoutBalanceWithStateSemiBold(gtx, pg.Load, item.totalBalance.String()) }), layout.Rigid(func(gtx C) D { usdBalance := "" - if components.IsFetchExchangeRateAPIAllowed(pg.WL) { - usdBalance = utils.FormatAsUSDString(pg.Printer, item.TotalBalance.MulF64(pg.assetRate[item.Wallet.GetAssetType()]).ToCoin()) + if pg.AssetsManager.ExchangeRateFetchingEnabled() { + usdBalance = utils.FormatAsUSDString(pg.Printer, item.totalBalance.MulF64(pg.assetRate[item.wallet.GetAssetType()]).ToCoin()) } return components.LayoutBalanceWithStateUSD(gtx, pg.Load, usdBalance) }), @@ -349,7 +348,7 @@ func (pg *WalletSelectorPage) listenForNotifications() { pg.isListenerAdded = true - allWallets := pg.WL.AllSortedWalletList() + allWallets := pg.AssetsManager.AllWallets() for _, w := range allWallets { syncListener := listeners.NewSyncProgress() err := w.AddSyncProgressListener(syncListener, WalletSelectorPageID) @@ -358,13 +357,21 @@ func (pg *WalletSelectorPage) listenForNotifications() { return } + // TODO: Probably also need to register a tx and block listener to + // update wallet balances when the wallet receives new txs. + go func(wal sharedW.Asset) { for { select { case n := <-syncListener.SyncStatusChan: if n.Stage == wallet.SyncCompleted { + // TODO: Does this update the wallet balances?? + // pg.loadWallets() is only called when the page is + // about to be displayed, not when it the window is + // reloaded. pg.ParentWindow().Reload() } + case <-pg.ctx.Done(): wal.RemoveSyncProgressListener(WalletSelectorPageID) close(syncListener.SyncStatusChan) diff --git a/ui/page/root/wallet_selector_page.go b/ui/page/root/wallet_selector_page.go index 35f3a1828..75bc76fa7 100644 --- a/ui/page/root/wallet_selector_page.go +++ b/ui/page/root/wallet_selector_page.go @@ -37,6 +37,11 @@ type walletIndexTuple struct { type showNavigationFunc func(showNavigation bool) +type walletWithBalance struct { + wallet sharedW.Asset + totalBalance sharedW.AssetAmount +} + type WalletSelectorPage struct { *load.Load // GenericPageModal defines methods such as ID() and OnAttachedToNavigator() @@ -57,7 +62,7 @@ type WalletSelectorPage struct { // wallet selector options listLock sync.RWMutex - walletsList map[libutils.AssetType][]*load.WalletItem + walletsList map[libutils.AssetType][]*walletWithBalance indexMapping map[int]walletIndexTuple badWalletsList map[libutils.AssetType][]*badWalletListItem @@ -93,7 +98,7 @@ func NewWalletSelectorPage(l *load.Load) *WalletSelectorPage { pg.assetsBalance = make(map[libutils.AssetType]sharedW.AssetAmount) pg.assetsTotalUSDBalance = make(map[libutils.AssetType]float64) pg.assetRate = make(map[libutils.AssetType]float64) - pg.walletsList = make(map[libutils.AssetType][]*load.WalletItem) + pg.walletsList = make(map[libutils.AssetType][]*walletWithBalance) pg.indexMapping = make(map[int]walletIndexTuple) pg.addWalClickable = make(map[libutils.AssetType]*cryptomaterial.Clickable) @@ -111,7 +116,7 @@ func (pg *WalletSelectorPage) OnNavigatedTo() { pg.showNavigationFunc(false) - for _, asset := range pg.WL.AssetsManager.AllAssetTypes() { + for _, asset := range pg.AssetsManager.AllAssetTypes() { pg.assetCollapsibles[asset] = pg.Load.Theme.Collapsible() pg.addWalClickable[asset] = pg.Load.Theme.NewClickable(false) pg.addWalClickable[asset].Radius = cryptomaterial.Radius(14) @@ -140,7 +145,7 @@ func (pg *WalletSelectorPage) OnNavigatedTo() { break } - rate := pg.WL.AssetsManager.RateSource.GetTicker(marketValue) + rate := pg.AssetsManager.RateSource.GetTicker(marketValue) if err != nil { log.Error(err) break @@ -178,13 +183,13 @@ func (pg *WalletSelectorPage) HandleUserInteractions() { return } - pg.WL.SelectedWallet = wallets[tuple.Index] + selectedWallet := wallets[tuple.Index].wallet pg.showNavigationFunc(true) callback := func() { pg.ParentNavigator().CloseCurrentPage() } - pg.ParentNavigator().Display(NewMainPage(pg.Load, callback)) + pg.ParentNavigator().Display(NewSingleWalletMasterPage(pg.Load, selectedWallet, callback)) } for _, walletsOfType := range pg.badWalletsList { @@ -237,7 +242,7 @@ func (pg *WalletSelectorPage) layoutMobile(gtx C) D { func (pg *WalletSelectorPage) pageContentLayout(gtx C) D { assetDropdown := func(gtx C) D { - supportedAssets := pg.WL.AssetsManager.AllAssetTypes() + supportedAssets := pg.AssetsManager.AllAssetTypes() return pg.Theme.List(pg.assetDropdownContainer).Layout(gtx, len(supportedAssets), func(gtx C, i int) D { return layout.Inset{Top: values.MarginPadding15}.Layout(gtx, pg.assetDropdown(supportedAssets[i])) }) @@ -356,7 +361,7 @@ func (pg *WalletSelectorPage) dropdownTitleLayout(gtx C, asset libutils.AssetTyp }), layout.Rigid(func(gtx C) D { usdBalance := "" - if components.IsFetchExchangeRateAPIAllowed(pg.WL) { + if pg.AssetsManager.ExchangeRateFetchingEnabled() { usdBalance = utils.FormatAsUSDString(pg.Printer, pg.assetsTotalUSDBalance[asset]) } return components.LayoutBalanceWithStateUSD(gtx, pg.Load, usdBalance) diff --git a/ui/page/root/wallet_settings_page.go b/ui/page/root/wallet_settings_page.go index 12d7262ab..c4f8928bd 100644 --- a/ui/page/root/wallet_settings_page.go +++ b/ui/page/root/wallet_settings_page.go @@ -66,11 +66,11 @@ type WalletSettingsPage struct { peerAddr string } -func NewWalletSettingsPage(l *load.Load, walletCallbackFunc func()) *WalletSettingsPage { +func NewWalletSettingsPage(l *load.Load, wallet sharedW.Asset, walletCallbackFunc func()) *WalletSettingsPage { pg := &WalletSettingsPage{ Load: l, GenericPageModal: app.NewGenericPageModal(WalletSettingsPageID), - wallet: l.WL.SelectedWallet.Wallet, + wallet: wallet, changePass: l.Theme.NewClickable(false), rescan: l.Theme.NewClickable(false), setGapLimit: l.Theme.NewClickable(false), @@ -115,16 +115,16 @@ func (pg *WalletSettingsPage) OnNavigatedTo() { } func (pg *WalletSettingsPage) readBool(key string) bool { - return pg.WL.SelectedWallet.Wallet.ReadBoolConfigValueForKey(key, false) + return pg.wallet.ReadBoolConfigValueForKey(key, false) } func (pg *WalletSettingsPage) isPrivacyModeOn() bool { - return pg.WL.AssetsManager.IsPrivacyModeOn() + return pg.AssetsManager.IsPrivacyModeOn() } func (pg *WalletSettingsPage) loadPeerAddress() { if !pg.isPrivacyModeOn() { - pg.peerAddr = pg.WL.SelectedWallet.Wallet.ReadStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") + pg.peerAddr = pg.wallet.ReadStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") pg.connectToPeer.SetChecked(false) if pg.peerAddr != "" { pg.connectToPeer.SetChecked(true) @@ -194,7 +194,7 @@ func (pg *WalletSettingsPage) generalSection() layout.Widget { dim := func(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - if pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { + if pg.wallet.IsWatchingOnlyWallet() { return D{} } return layout.Inset{}.Layout(gtx, pg.sectionContent(pg.changePass, values.String(values.StrSpendingPassword))) @@ -216,7 +216,7 @@ func (pg *WalletSettingsPage) generalSection() layout.Widget { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(pg.subSectionSwitch(values.String(values.StrConnectToSpecificPeer), pg.connectToPeer)), layout.Rigid(func(gtx C) D { - if pg.WL.SelectedWallet.Wallet.ReadStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") == "" && pg.isPrivacyModeOn() { + if pg.wallet.ReadStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") == "" && pg.isPrivacyModeOn() { return D{} } @@ -309,7 +309,7 @@ func (pg *WalletSettingsPage) pageSections(gtx C, title string, body layout.Widg } if title == values.String(values.StrAccount) { return layout.E.Layout(gtx, func(gtx C) D { - if pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { + if pg.wallet.IsWatchingOnlyWallet() { return D{} } return pg.addAccount.Layout(gtx, pg.Theme.Icons.AddIcon.Layout24dp) @@ -430,10 +430,10 @@ func (pg *WalletSettingsPage) changeSpendingPasswordModal() { func (pg *WalletSettingsPage) deleteWalletModal() { textModal := modal.NewTextInputModal(pg.Load). Hint(values.String(values.StrWalletName)). - SetTextWithTemplate(modal.RemoveWalletInfoTemplate, pg.WL.SelectedWallet.Wallet.GetWalletName()). + SetTextWithTemplate(modal.RemoveWalletInfoTemplate, pg.wallet.GetWalletName()). PositiveButtonStyle(pg.Load.Theme.Color.Surface, pg.Load.Theme.Color.Danger). SetPositiveButtonCallback(func(walletName string, m *modal.TextInputModal) bool { - if walletName != pg.WL.SelectedWallet.Wallet.GetWalletName() { + if walletName != pg.wallet.GetWalletName() { m.SetError(values.String(values.StrWalletNameMismatch)) m.SetLoading(false) return false @@ -441,7 +441,7 @@ func (pg *WalletSettingsPage) deleteWalletModal() { walletDeleted := func() { m.Dismiss() - if pg.WL.AssetsManager.LoadedWalletsCount() > 0 { + if pg.AssetsManager.LoadedWalletsCount() > 0 { pg.walletCallbackFunc() } else { pg.ParentWindow().CloseAllPages() @@ -450,7 +450,7 @@ func (pg *WalletSettingsPage) deleteWalletModal() { if pg.wallet.IsWatchingOnlyWallet() { // no password is required for watching only wallets. - err := pg.WL.AssetsManager.DeleteWallet(pg.WL.SelectedWallet.Wallet.GetWalletID(), "") + err := pg.AssetsManager.DeleteWallet(pg.wallet.GetWalletID(), "") if err != nil { m.SetError(err.Error()) m.SetLoading(false) @@ -468,7 +468,7 @@ func (pg *WalletSettingsPage) deleteWalletModal() { m.SetLoading(false) }). SetPositiveButtonCallback(func(_, password string, pm *modal.CreatePasswordModal) bool { - err := pg.WL.AssetsManager.DeleteWallet(pg.WL.SelectedWallet.Wallet.GetWalletID(), password) + err := pg.AssetsManager.DeleteWallet(pg.wallet.GetWalletID(), password) if err != nil { pm.SetError(err.Error()) pm.SetLoading(false) @@ -499,7 +499,7 @@ func (pg *WalletSettingsPage) renameWalletModal() { return false } - err := pg.WL.SelectedWallet.Wallet.RenameWallet(name) + err := pg.wallet.RenameWallet(name) if err != nil { tm.SetError(err.Error()) tm.SetLoading(false) @@ -525,7 +525,7 @@ func (pg *WalletSettingsPage) showSPVPeerDialog() { return false } if ipAddress != "" { - pg.WL.SelectedWallet.Wallet.SetSpecificPeer(ipAddress) + pg.wallet.SetSpecificPeer(ipAddress) pg.loadPeerAddress() } return true @@ -534,7 +534,7 @@ func (pg *WalletSettingsPage) showSPVPeerDialog() { SetPositiveButtonText(values.String(values.StrConfirm)). SetNegativeButtonText(values.String(values.StrCancel)). SetNegativeButtonCallback(func() { - pg.peerAddr = pg.WL.SelectedWallet.Wallet.ReadStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") + pg.peerAddr = pg.wallet.ReadStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") pg.connectToPeer.SetChecked(pg.peerAddr != "") }) pg.ParentWindow().ShowModal(textModal) @@ -570,7 +570,7 @@ func (pg *WalletSettingsPage) showWarningModalDialog(title, msg string) { // TODO: Check if deletion happened successfully // Since only one peer is available at time, the single peer key can // be set to empty string to delete its entry.. - pg.WL.SelectedWallet.Wallet.RemovePeers() + pg.wallet.RemovePeers() pg.peerAddr = "" return true }) @@ -597,7 +597,7 @@ func (pg *WalletSettingsPage) HandleUserInteractions() { PositiveButtonStyle(pg.Theme.Color.Primary, pg.Theme.Color.Surface). SetPositiveButtonText(values.String(values.StrRescan)). SetPositiveButtonCallback(func(_ bool, im *modal.InfoModal) bool { - err := pg.WL.SelectedWallet.Wallet.RescanBlocks() + err := pg.wallet.RescanBlocks() if err != nil { errorModal := modal.NewErrorModal(pg.Load, err.Error(), modal.DefaultClickFunc()) pg.ParentWindow().ShowModal(errorModal) @@ -638,7 +638,7 @@ func (pg *WalletSettingsPage) HandleUserInteractions() { } if pg.spendUnconfirmed.Changed() { - pg.WL.SelectedWallet.Wallet.SaveUserConfigValue(sharedW.SpendUnconfirmedConfigKey, pg.spendUnconfirmed.IsChecked()) + pg.wallet.SaveUserConfigValue(sharedW.SpendUnconfirmedConfigKey, pg.spendUnconfirmed.IsChecked()) } if pg.spendUnmixedFunds.Changed() { @@ -652,7 +652,7 @@ func (pg *WalletSettingsPage) HandleUserInteractions() { tim.SetError(values.String(values.StrConfirmPending)) tim.SetLoading(false) } else { - pg.WL.SelectedWallet.Wallet.SetBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, true) + pg.wallet.SetBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, true) tim.Dismiss() } return false @@ -665,7 +665,7 @@ func (pg *WalletSettingsPage) HandleUserInteractions() { pg.ParentWindow().ShowModal(textModal) } else { - pg.WL.SelectedWallet.Wallet.SetBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, false) + pg.wallet.SetBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, false) } } @@ -685,15 +685,15 @@ func (pg *WalletSettingsPage) HandleUserInteractions() { } if pg.verifyMessage.Clicked() { - pg.ParentNavigator().Display(security.NewVerifyMessagePage(pg.Load)) + pg.ParentNavigator().Display(security.NewVerifyMessagePage(pg.Load, pg.wallet)) } if pg.validateAddr.Clicked() { - pg.ParentNavigator().Display(security.NewValidateAddressPage(pg.Load)) + pg.ParentNavigator().Display(security.NewValidateAddressPage(pg.Load, pg.wallet)) } if pg.signMessage.Clicked() { - pg.ParentNavigator().Display(security.NewSignMessagePage(pg.Load)) + pg.ParentNavigator().Display(security.NewSignMessagePage(pg.Load, pg.wallet)) } if pg.checklog.Clicked() { @@ -701,7 +701,7 @@ func (pg *WalletSettingsPage) HandleUserInteractions() { } if pg.checkStats.Clicked() { - pg.ParentNavigator().Display(s.NewStatPage(pg.Load)) + pg.ParentNavigator().Display(s.NewStatPage(pg.Load, pg.wallet)) } for pg.addAccount.Clicked() { @@ -733,17 +733,17 @@ func (pg *WalletSettingsPage) HandleUserInteractions() { if clicked, selectedItem := pg.accountsList.ItemClicked(); clicked { switch pg.wallet.GetAssetType() { case libutils.BTCWalletAsset: - pg.ParentNavigator().Display(s.NewAcctBTCDetailsPage(pg.Load, pg.accounts[selectedItem].Account)) + pg.ParentNavigator().Display(s.NewAcctBTCDetailsPage(pg.Load, pg.wallet, pg.accounts[selectedItem].Account)) case libutils.DCRWalletAsset: - pg.ParentNavigator().Display(s.NewAcctDetailsPage(pg.Load, pg.accounts[selectedItem].Account)) + pg.ParentNavigator().Display(s.NewAcctDetailsPage(pg.Load, pg.wallet, pg.accounts[selectedItem].Account)) case libutils.LTCWalletAsset: - pg.ParentNavigator().Display(s.NewAcctLTCDetailsPage(pg.Load, pg.accounts[selectedItem].Account)) + pg.ParentNavigator().Display(s.NewAcctLTCDetailsPage(pg.Load, pg.wallet, pg.accounts[selectedItem].Account)) } } } func (pg *WalletSettingsPage) gapLimitModal() { - walGapLim := pg.WL.SelectedWallet.Wallet.ReadStringConfigValueForKey(load.GapLimitConfigKey, "20") + walGapLim := pg.wallet.ReadStringConfigValueForKey(load.GapLimitConfigKey, "20") textModal := modal.NewTextInputModal(pg.Load). Hint(values.String(values.StrGapLimit)). SetTextWithTemplate(modal.SetGapLimitTemplate). @@ -765,7 +765,7 @@ func (pg *WalletSettingsPage) gapLimitModal() { gLimit := uint32(val) tm.SetLoading(true) - err = pg.WL.SelectedWallet.Wallet.(*dcr.Asset).DiscoverUsage(gLimit) + err = pg.wallet.(*dcr.Asset).DiscoverUsage(gLimit) if err != nil { tm.SetError(err.Error()) tm.SetLoading(false) @@ -775,7 +775,7 @@ func (pg *WalletSettingsPage) gapLimitModal() { info := modal.NewSuccessModal(pg.Load, values.String(values.StrAddressDiscoveryStarted), modal.DefaultClickFunc()). Body(values.String(values.StrAddressDiscoveryStartedBody)) pg.ParentWindow().ShowModal(info) - pg.WL.SelectedWallet.Wallet.SetStringConfigValueForKey(load.GapLimitConfigKey, gapLimit) + pg.wallet.SetStringConfigValueForKey(load.GapLimitConfigKey, gapLimit) return true }) textModal.Title(values.String(values.StrDiscoverAddressUsage)). diff --git a/ui/page/security/sign_message_page.go b/ui/page/security/sign_message_page.go index c943adef7..b28864464 100644 --- a/ui/page/security/sign_message_page.go +++ b/ui/page/security/sign_message_page.go @@ -51,7 +51,7 @@ type SignMessagePage struct { infoButton cryptomaterial.IconButton } -func NewSignMessagePage(l *load.Load) *SignMessagePage { +func NewSignMessagePage(l *load.Load, wallet sharedW.Asset) *SignMessagePage { addressEditor := l.Theme.Editor(new(widget.Editor), values.String(values.StrAddress)) addressEditor.Editor.SingleLine, addressEditor.Editor.Submit = true, true messageEditor := l.Theme.Editor(new(widget.Editor), values.String(values.StrMessage)) @@ -70,7 +70,7 @@ func NewSignMessagePage(l *load.Load) *SignMessagePage { pg := &SignMessagePage{ Load: l, GenericPageModal: app.NewGenericPageModal(SignMessagePageID), - wallet: l.WL.SelectedWallet.Wallet, + wallet: wallet, container: layout.List{ Axis: layout.Vertical, }, @@ -333,7 +333,7 @@ func (pg *SignMessagePage) validateAddress() bool { switch { case !uiUtils.StringNotEmpty(address): errorMessage = values.String(values.StrEnterValidAddress) - case !pg.WL.SelectedWallet.Wallet.IsAddressValid(address): + case !pg.wallet.IsAddressValid(address): errorMessage = values.String(values.StrInvalidAddress) case !pg.wallet.HaveAddress(address): errorMessage = values.String(values.StrAddrNotOwned) diff --git a/ui/page/security/validate_address.go b/ui/page/security/validate_address.go index 588e5230c..2d8ccc527 100644 --- a/ui/page/security/validate_address.go +++ b/ui/page/security/validate_address.go @@ -6,6 +6,7 @@ import ( "gioui.org/widget" "github.com/crypto-power/cryptopower/app" + sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/modal" @@ -30,6 +31,7 @@ type ValidateAddressPage struct { // helper methods for accessing the PageNavigator that displayed this page // and the root WindowNavigator. *app.GenericPageModal + wallet sharedW.Asset addressEditor cryptomaterial.Editor clearBtn, validateBtn cryptomaterial.Button @@ -37,10 +39,11 @@ type ValidateAddressPage struct { backButton cryptomaterial.IconButton } -func NewValidateAddressPage(l *load.Load) *ValidateAddressPage { +func NewValidateAddressPage(l *load.Load, wallet sharedW.Asset) *ValidateAddressPage { pg := &ValidateAddressPage{ Load: l, GenericPageModal: app.NewGenericPageModal(ValidateAddressPageID), + wallet: wallet, } pg.backButton, _ = components.SubpageHeaderButtons(l) @@ -197,11 +200,11 @@ func (pg *ValidateAddressPage) validateAddress() { var verifyMsgAddr string var info *modal.InfoModal - if !pg.WL.SelectedWallet.Wallet.IsAddressValid(address) { + if !pg.wallet.IsAddressValid(address) { verifyMsgAddr = values.String(values.StrInvalidAddress) info = modal.NewErrorModal(pg.Load, verifyMsgAddr, modal.DefaultClickFunc()) } else { - if !pg.WL.SelectedWallet.Wallet.HaveAddress(address) { + if !pg.wallet.HaveAddress(address) { verifyMsgAddr = values.String(values.StrNotOwned) } else { verifyMsgAddr = values.String(values.StrOwned) diff --git a/ui/page/security/verify_message_page.go b/ui/page/security/verify_message_page.go index 381a7638f..fe578d9be 100644 --- a/ui/page/security/verify_message_page.go +++ b/ui/page/security/verify_message_page.go @@ -7,6 +7,7 @@ import ( "gioui.org/widget" "github.com/crypto-power/cryptopower/app" + sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/modal" @@ -24,6 +25,7 @@ type VerifyMessagePage struct { // helper methods for accessing the PageNavigator that displayed this page // and the root WindowNavigator. *app.GenericPageModal + wallet sharedW.Asset addressEditor cryptomaterial.Editor messageEditor cryptomaterial.Editor @@ -32,15 +34,14 @@ type VerifyMessagePage struct { backButton cryptomaterial.IconButton infoButton cryptomaterial.IconButton - addressIsValid bool - EnableEditorSwitch bool + addressIsValid bool } -func NewVerifyMessagePage(l *load.Load) *VerifyMessagePage { +func NewVerifyMessagePage(l *load.Load, wallet sharedW.Asset) *VerifyMessagePage { pg := &VerifyMessagePage{ - Load: l, - GenericPageModal: app.NewGenericPageModal(VerifyMessagePageID), - EnableEditorSwitch: false, + Load: l, + GenericPageModal: app.NewGenericPageModal(VerifyMessagePageID), + wallet: wallet, } pg.addressEditor = l.Theme.Editor(new(widget.Editor), values.String(values.StrAddress)) @@ -170,7 +171,7 @@ func (pg *VerifyMessagePage) HandleUserInteractions() { var verifyMessageText string var info *modal.InfoModal - valid, err := pg.WL.SelectedWallet.Wallet.VerifyMessage(pg.addressEditor.Editor.Text(), pg.messageEditor.Editor.Text(), pg.signatureEditor.Editor.Text()) + valid, err := pg.wallet.VerifyMessage(pg.addressEditor.Editor.Text(), pg.messageEditor.Editor.Text(), pg.signatureEditor.Editor.Text()) if err != nil || !valid { verifyMessageText = values.String(values.StrInvalidAddress) if !valid { @@ -246,7 +247,7 @@ func (pg *VerifyMessagePage) validateAddress() bool { switch { case !utils.StringNotEmpty(address): errorMessage = values.String(values.StrEnterValidAddress) - case !pg.WL.SelectedWallet.Wallet.IsAddressValid(address): + case !pg.wallet.IsAddressValid(address): errorMessage = values.String(values.StrInvalidAddress) default: valid = true diff --git a/ui/page/seedbackup/verify_seed.go b/ui/page/seedbackup/verify_seed.go index 2ddd94a63..c6d1185d2 100644 --- a/ui/page/seedbackup/verify_seed.go +++ b/ui/page/seedbackup/verify_seed.go @@ -184,7 +184,7 @@ func (pg *VerifySeedPage) verifySeed() { if !pg.toggleSeedInput.IsChecked() { seed = pg.selectedSeedPhrase() } - _, err := pg.WL.SelectedWallet.Wallet.VerifySeedForWallet(seed, password) + _, err := pg.wallet.VerifySeedForWallet(seed, password) if err != nil { if err.Error() == utils.ErrInvalid { msg := values.String(values.StrSeedValidationFailed) diff --git a/ui/page/send/layout.go b/ui/page/send/layout.go index 5ef6ab7b3..63dc066ec 100644 --- a/ui/page/send/layout.go +++ b/ui/page/send/layout.go @@ -80,7 +80,7 @@ func (pg *Page) Layout(gtx layout.Context) layout.Dimensions { return pg.layoutMobile(gtx) } - if pg.isModalLayout { + if pg.modalLayout != nil { modalContent := []layout.Widget{pg.layoutDesktop} return pg.modalLayout.Layout(gtx, modalContent, 450) } @@ -93,7 +93,7 @@ func (pg *Page) layoutDesktop(gtx layout.Context) D { return pg.pageSections(gtx, values.String(values.StrFrom), false, func(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - if pg.isModalLayout { + if pg.modalLayout != nil { return layout.Inset{ Bottom: values.MarginPadding16, }.Layout(gtx, func(gtx C) D { @@ -120,13 +120,14 @@ func (pg *Page) layoutDesktop(gtx layout.Context) D { func(gtx C) D { // disable this section if the layout is a modal layout // and the selected wallet is not synced. - if pg.isModalLayout && !pg.selectedWallet.IsSynced() { + if pg.modalLayout != nil && !pg.selectedWallet.IsSynced() { gtx = gtx.Disabled() } return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(pg.toSection), layout.Rigid(func(gtx C) D { - if pg.isModalLayout { + if pg.modalLayout != nil { + // coin selection not allowed on the send modal return D{} } return pg.coinSelectionSection(gtx) diff --git a/ui/page/send/manual_coin_selection.go b/ui/page/send/manual_coin_selection.go index e88331bc6..fd588145b 100644 --- a/ui/page/send/manual_coin_selection.go +++ b/ui/page/send/manual_coin_selection.go @@ -145,7 +145,7 @@ func NewManualCoinSelectionPage(l *load.Load, sendPage *Page) *ManualCoinSelecti pg.confirmationsClickable = pg.Theme.NewClickable(true) pg.dateClickable = pg.Theme.NewClickable(false) - pg.strAssetType = pg.WL.SelectedWallet.Wallet.GetAssetType().String() + pg.strAssetType = sendPage.selectedWallet.GetAssetType().String() name := fmt.Sprintf("%v(%v)", values.String(values.StrAmount), pg.strAssetType) // UTXO table view titles. @@ -212,7 +212,7 @@ func (pg *ManualCoinSelectionPage) OnNavigatedTo() { func (pg *ManualCoinSelectionPage) fetchAccountsInfo() error { account := pg.sendPage.sourceAccountSelector.SelectedAccount() - info, err := pg.WL.SelectedWallet.Wallet.UnspentOutputs(int32(account.AccountNumber)) + info, err := pg.sendPage.selectedWallet.UnspentOutputs(int32(account.AccountNumber)) if err != nil { return fmt.Errorf("querying the account (%v) info failed: %v", account.AccountNumber, err) } @@ -334,7 +334,7 @@ func (pg *ManualCoinSelectionPage) updateSummaryInfo() { } func (pg *ManualCoinSelectionPage) computeUTXOsSize() string { - wallet := pg.WL.SelectedWallet.Wallet + wallet := pg.sendPage.selectedWallet // Access to coin selection page is restricted unless destination address is selected. destination, _ := pg.sendPage.sendDestination.destinationAddress() diff --git a/ui/page/send/page.go b/ui/page/send/page.go index 04b0fcde1..6f8d8af16 100644 --- a/ui/page/send/page.go +++ b/ui/page/send/page.go @@ -40,9 +40,10 @@ type Page struct { // helper methods for accessing the PageNavigator that displayed this page // and the root WindowNavigator. *app.GenericPageModal - - modalLayout *cryptomaterial.Modal - isModalLayout bool + // modalLayout is initialized if this page will be displayed as a modal + // rather than a full page. A modal display is used and a wallet selector is + // displayed if this send page is opened from the home page. + modalLayout *cryptomaterial.Modal ctx context.Context // page context ctxCancel context.CancelFunc @@ -71,7 +72,7 @@ type Page struct { txLabelInputEditor cryptomaterial.Editor *authoredTxData - selectedWallet *load.WalletMapping + selectedWallet sharedW.Asset feeRateSelector *components.FeeRateSelector toCoinSelection *cryptomaterial.Clickable @@ -99,26 +100,26 @@ type selectedUTXOsInfo struct { totalUTXOsAmount int64 } -func NewSendPage(l *load.Load, isModalLayout bool) *Page { +func NewSendPage(l *load.Load, wallet sharedW.Asset) *Page { pg := &Page{ Load: l, authoredTxData: &authoredTxData{}, shadowBox: l.Theme.Shadow(), backdrop: new(widget.Clickable), - isModalLayout: isModalLayout, exchangeRate: -1, } - if isModalLayout { + if wallet == nil { + // When this page is opened from the home page, the wallet to use is not + // specified. This page will be opened as a modal and a wallet selector + // will be displayed. pg.modalLayout = l.Theme.ModalFloatTitle(values.String(values.StrSend)) pg.GenericPageModal = pg.modalLayout.GenericPageModal - pg.initWalletSelector() + pg.initWalletSelector() // will auto select the first wallet in the dropdown as pg.selectedWallet } else { pg.GenericPageModal = app.NewGenericPageModal(SendPageID) - pg.selectedWallet = &load.WalletMapping{ - Asset: l.WL.SelectedWallet.Wallet, - } + pg.selectedWallet = wallet } pg.amount = newSendAmount(l.Theme, pg.selectedWallet.GetAssetType()) @@ -155,7 +156,7 @@ func (pg *Page) initWalletSelector() { pg.selectedWallet = pg.sourceWalletSelector.SelectedWallet() // Source wallet picker - pg.sourceWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + pg.sourceWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { pg.selectedWallet = selectedWallet pg.amount.setAssetType(selectedWallet.GetAssetType()) pg.sendDestination.initDestinationWalletSelector(selectedWallet.GetAssetType()) @@ -192,11 +193,11 @@ func (pg *Page) initializeAccountSelectors() { // only mixed accounts can send to address/wallets for wallet with privacy setup switch pg.sendDestination.accountSwitch.SelectedIndex() { case sendToAddress: - accountIsValid = account.Number == pg.selectedWallet.MixedAccountNumber() + accountIsValid = account.Number == load.MixedAccountNumber(pg.selectedWallet) case SendToWallet: destinationWalletID := pg.sendDestination.destinationWalletSelector.SelectedWallet().GetWalletID() if destinationWalletID != pg.selectedWallet.GetWalletID() { - accountIsValid = account.Number == pg.selectedWallet.MixedAccountNumber() + accountIsValid = account.Number == load.MixedAccountNumber(pg.selectedWallet) } } } @@ -213,7 +214,7 @@ func (pg *Page) initializeAccountSelectors() { accountIsValid := account.Number != load.MaxInt32 // Filter mixed wallet destinationWallet := pg.sendDestination.destinationAccountSelector.SelectedWallet() - isMixedAccount := destinationWallet.MixedAccountNumber() == account.Number + isMixedAccount := load.MixedAccountNumber(destinationWallet) == account.Number // Filter the sending account. sourceWalletID := pg.sourceAccountSelector.SelectedAccount().WalletID isSameAccount := sourceWalletID == account.WalletID && account.Number == pg.sourceAccountSelector.SelectedAccount().Number @@ -227,7 +228,7 @@ func (pg *Page) initializeAccountSelectors() { pg.validateAndConstructTx() }) - pg.sendDestination.destinationWalletSelector.WalletSelected(func(selectedWallet *load.WalletMapping) { + pg.sendDestination.destinationWalletSelector.WalletSelected(func(selectedWallet sharedW.Asset) { pg.sendDestination.destinationAccountSelector.SelectFirstValidAccount(selectedWallet) if pg.selectedWallet.GetAssetType() == libUtil.DCRWalletAsset { pg.sourceAccountSelector.SelectFirstValidAccount(pg.selectedWallet) @@ -274,8 +275,8 @@ func (pg *Page) OnNavigatedTo() { pg.sendDestination.destinationAddressEditor.Editor.Focus() pg.usdExchangeSet = false - if components.IsFetchExchangeRateAPIAllowed(pg.WL) { - pg.usdExchangeSet = pg.WL.AssetsManager.RateSource.Ready() + if pg.AssetsManager.ExchangeRateFetchingEnabled() { + pg.usdExchangeSet = pg.AssetsManager.RateSource.Ready() go pg.fetchExchangeRate() } else { // If exchange rate is not supported, validate and construct the TX. @@ -285,7 +286,7 @@ func (pg *Page) OnNavigatedTo() { if pg.selectedWallet.GetAssetType() == libUtil.BTCWalletAsset && pg.isFeerateAPIApproved() { // This API call may take sometime to return. Call this before and cache // results. - go pg.selectedWallet.GetAPIFeeRate() + go load.GetAPIFeeRate(pg.selectedWallet) } } @@ -315,7 +316,7 @@ func (pg *Page) fetchExchangeRate() { return } - rate := pg.WL.AssetsManager.RateSource.GetTicker(market) + rate := pg.AssetsManager.RateSource.GetTicker(market) if rate == nil || rate.LastTradePrice <= 0 { pg.isFetchingExchangeRate = false return @@ -535,14 +536,14 @@ func (pg *Page) HandleUserInteractions() { if pg.nextButton.Clicked() { if pg.selectedWallet.IsUnsignedTxExist() { - pg.confirmTxModal = newSendConfirmModal(pg.Load, pg.authoredTxData, *pg.selectedWallet) + pg.confirmTxModal = newSendConfirmModal(pg.Load, pg.authoredTxData, pg.selectedWallet) pg.confirmTxModal.exchangeRateSet = pg.exchangeRate != -1 && pg.usdExchangeSet pg.confirmTxModal.txLabel = pg.txLabelInputEditor.Editor.Text() pg.confirmTxModal.txSent = func() { pg.resetFields() pg.clearEstimates() - if pg.isModalLayout { + if pg.modalLayout != nil { pg.modalLayout.Dismiss() } } @@ -554,7 +555,7 @@ func (pg *Page) HandleUserInteractions() { // if destination switch is equal to Address if pg.sendDestination.sendToAddress { if pg.sendDestination.validate() { - if !components.IsFetchExchangeRateAPIAllowed(pg.WL) { + if !pg.AssetsManager.ExchangeRateFetchingEnabled() { if len(pg.amount.amountEditor.Editor.Text()) == 0 { pg.amount.SendMax = false } @@ -566,7 +567,7 @@ func (pg *Page) HandleUserInteractions() { } } } else { - if !components.IsFetchExchangeRateAPIAllowed(pg.WL) { + if !pg.AssetsManager.ExchangeRateFetchingEnabled() { if len(pg.amount.amountEditor.Editor.Text()) == 0 { pg.amount.SendMax = false } @@ -653,5 +654,5 @@ func (pg *Page) OnNavigatedFrom() { } func (pg *Page) isFeerateAPIApproved() bool { - return pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libUtil.FeeRateHTTPAPI) + return pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libUtil.FeeRateHTTPAPI) } diff --git a/ui/page/send/send_confirm_modal.go b/ui/page/send/send_confirm_modal.go index f6765f67e..dc7b60f83 100644 --- a/ui/page/send/send_confirm_modal.go +++ b/ui/page/send/send_confirm_modal.go @@ -12,6 +12,7 @@ import ( "gioui.org/widget" "gioui.org/widget/material" + sharedW "github.com/crypto-power/cryptopower/libwallet/assets/wallet" "github.com/crypto-power/cryptopower/ui/cryptomaterial" "github.com/crypto-power/cryptopower/ui/load" "github.com/crypto-power/cryptopower/ui/modal" @@ -32,12 +33,12 @@ type sendConfirmModal struct { isSending bool *authoredTxData - asset load.WalletMapping + asset sharedW.Asset exchangeRateSet bool txLabel string } -func newSendConfirmModal(l *load.Load, data *authoredTxData, asset load.WalletMapping) *sendConfirmModal { +func newSendConfirmModal(l *load.Load, data *authoredTxData, asset sharedW.Asset) *sendConfirmModal { scm := &sendConfirmModal{ Load: l, Modal: l.Theme.ModalFloatTitle("send_confirm_modal"), @@ -183,7 +184,7 @@ func (scm *sendConfirmModal) Layout(gtx layout.Context) D { }.Layout(gtx, func(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - sendWallet := scm.WL.AssetsManager.WalletWithID(scm.sourceAccount.WalletID) + sendWallet := scm.AssetsManager.WalletWithID(scm.sourceAccount.WalletID) return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(func(gtx C) D { txt := scm.Theme.Body2(values.String(values.StrFrom)) @@ -237,7 +238,7 @@ func (scm *sendConfirmModal) Layout(gtx layout.Context) D { layout.Rigid(scm.setWalletLogo), layout.Rigid(func(gtx C) D { return layout.Inset{}.Layout(gtx, func(gtx C) D { - destinationWallet := scm.WL.AssetsManager.WalletWithID(scm.destinationAccount.WalletID) + destinationWallet := scm.AssetsManager.WalletWithID(scm.destinationAccount.WalletID) txt := scm.Theme.Label(unit.Sp(16), destinationWallet.GetWalletName()) txt.Color = scm.Theme.Color.Text txt.Font.Weight = font.Medium diff --git a/ui/page/send/send_destination.go b/ui/page/send/send_destination.go index 165d6b8eb..38dd8c6a8 100644 --- a/ui/page/send/send_destination.go +++ b/ui/page/send/send_destination.go @@ -76,7 +76,7 @@ func (dst *destination) destinationAddress() (string, error) { return "", fmt.Errorf(values.String(values.StrInvalidAddress)) } - wal := dst.WL.AssetsManager.WalletWithID(destinationAccount.WalletID) + wal := dst.AssetsManager.WalletWithID(destinationAccount.WalletID) return wal.CurrentAddress(destinationAccount.Number) } diff --git a/ui/page/settings/about_page.go b/ui/page/settings/about_page.go index 56130a5e2..26acea31c 100644 --- a/ui/page/settings/about_page.go +++ b/ui/page/settings/about_page.go @@ -42,9 +42,9 @@ func NewAboutPage(l *load.Load) *AboutPage { card: l.Theme.Card(), container: &layout.List{Axis: layout.Vertical}, version: l.Theme.Body1(values.String(values.StrVersion)), - versionValue: l.Theme.Body1(l.Version()), + versionValue: l.Theme.Body1(l.AppInfo.Version()), buildDate: l.Theme.Body1(values.String(values.StrBuildDate)), - buildDateValue: l.Theme.Body1(l.BuildDate().Format("2006-01-02 15:04:05")), + buildDateValue: l.Theme.Body1(l.AppInfo.BuildDate().Format("2006-01-02 15:04:05")), network: l.Theme.Body1(values.String(values.StrNetwork)), license: l.Theme.Body1(values.String(values.StrLicense)), licenseRow: l.Theme.NewClickable(true), @@ -58,7 +58,7 @@ func NewAboutPage(l *load.Load) *AboutPage { pg.versionValue.Color = col pg.buildDateValue.Color = col - netType := pg.WL.AssetsManager.NetType().Display() + netType := pg.AssetsManager.NetType().Display() pg.networkValue = l.Theme.Body1(netType) pg.networkValue.Color = col diff --git a/ui/page/settings/account_details_page.go b/ui/page/settings/account_details_page.go index 3e3c22669..3f00ceb4b 100644 --- a/ui/page/settings/account_details_page.go +++ b/ui/page/settings/account_details_page.go @@ -54,11 +54,11 @@ type AcctDetailsPage struct { isHiddenExtendedxPubkey bool } -func NewAcctDetailsPage(l *load.Load, account *sharedW.Account) *AcctDetailsPage { +func NewAcctDetailsPage(l *load.Load, wallet sharedW.Asset, account *sharedW.Account) *AcctDetailsPage { pg := &AcctDetailsPage{ Load: l, GenericPageModal: app.NewGenericPageModal(AccountDetailsPageID), - wallet: l.WL.SelectedWallet.Wallet, + wallet: wallet, account: account, theme: l.Theme, @@ -98,7 +98,7 @@ func (pg *AcctDetailsPage) OnNavigatedTo() { pg.votingAuthority = balance.VotingAuthority.String() pg.immatureStakeGen = balance.ImmatureStakeGeneration.String() - pg.hdPath = pg.WL.DCRHDPrefix() + strconv.Itoa(int(pg.account.Number)) + "'" + pg.hdPath = pg.AssetsManager.DCRHDPrefix() + strconv.Itoa(int(pg.account.Number)) + "'" ext := pg.account.ExternalKeyCount internal := pg.account.InternalKeyCount @@ -438,7 +438,7 @@ func (pg *AcctDetailsPage) HandleUserInteractions() { } func (pg *AcctDetailsPage) loadExtendedPubKey() { - xpub, err := pg.WL.SelectedWallet.Wallet.GetExtendedPubKey(pg.account.Number) + xpub, err := pg.wallet.GetExtendedPubKey(pg.account.Number) if err != nil { pg.Toast.NotifyError(err.Error()) } diff --git a/ui/page/settings/btc_account_details_page.go b/ui/page/settings/btc_account_details_page.go index fb1b73c22..4b163ad14 100644 --- a/ui/page/settings/btc_account_details_page.go +++ b/ui/page/settings/btc_account_details_page.go @@ -47,11 +47,11 @@ type BTCAcctDetailsPage struct { infoButton cryptomaterial.IconButton } -func NewAcctBTCDetailsPage(l *load.Load, account *sharedW.Account) *BTCAcctDetailsPage { +func NewAcctBTCDetailsPage(l *load.Load, wallet sharedW.Asset, account *sharedW.Account) *BTCAcctDetailsPage { pg := &BTCAcctDetailsPage{ Load: l, GenericPageModal: app.NewGenericPageModal(AccountDetailsPageID), - wallet: l.WL.SelectedWallet.Wallet, + wallet: wallet, account: account, theme: l.Theme, @@ -78,7 +78,7 @@ func NewAcctBTCDetailsPage(l *load.Load, account *sharedW.Account) *BTCAcctDetai func (pg *BTCAcctDetailsPage) OnNavigatedTo() { pg.totalBalance = pg.account.Balance.Total.String() - pg.hdPath = pg.WL.BTCHDPrefix() + strconv.Itoa(int(pg.account.AccountNumber)) + "'" + pg.hdPath = pg.AssetsManager.BTCHDPrefix() + strconv.Itoa(int(pg.account.AccountNumber)) + "'" ext := pg.account.ExternalKeyCount internal := pg.account.InternalKeyCount @@ -400,7 +400,7 @@ func (pg *BTCAcctDetailsPage) HandleUserInteractions() { } func (pg *BTCAcctDetailsPage) loadExtendedPubKey() { - xpub, err := pg.WL.SelectedWallet.Wallet.GetExtendedPubKey(pg.account.Number) + xpub, err := pg.wallet.GetExtendedPubKey(pg.account.Number) if err != nil { pg.Toast.NotifyError(err.Error()) } diff --git a/ui/page/settings/ltc_account_details_page.go b/ui/page/settings/ltc_account_details_page.go index eb67cff59..825d9232e 100644 --- a/ui/page/settings/ltc_account_details_page.go +++ b/ui/page/settings/ltc_account_details_page.go @@ -47,11 +47,11 @@ type LTCAcctDetailsPage struct { infoButton cryptomaterial.IconButton } -func NewAcctLTCDetailsPage(l *load.Load, account *sharedW.Account) *LTCAcctDetailsPage { +func NewAcctLTCDetailsPage(l *load.Load, wallet sharedW.Asset, account *sharedW.Account) *LTCAcctDetailsPage { pg := <CAcctDetailsPage{ Load: l, GenericPageModal: app.NewGenericPageModal(AccountDetailsPageID), - wallet: l.WL.SelectedWallet.Wallet, + wallet: wallet, account: account, theme: l.Theme, @@ -78,7 +78,7 @@ func NewAcctLTCDetailsPage(l *load.Load, account *sharedW.Account) *LTCAcctDetai func (pg *LTCAcctDetailsPage) OnNavigatedTo() { pg.totalBalance = pg.account.Balance.Total.String() - pg.hdPath = pg.WL.LTCHDPrefix() + strconv.Itoa(int(pg.account.AccountNumber)) + "'" + pg.hdPath = pg.AssetsManager.LTCHDPrefix() + strconv.Itoa(int(pg.account.AccountNumber)) + "'" ext := pg.account.ExternalKeyCount internal := pg.account.InternalKeyCount @@ -397,7 +397,7 @@ func (pg *LTCAcctDetailsPage) HandleUserInteractions() { } func (pg *LTCAcctDetailsPage) loadExtendedPubKey() { - xpub, err := pg.WL.SelectedWallet.Wallet.GetExtendedPubKey(pg.account.Number) + xpub, err := pg.wallet.GetExtendedPubKey(pg.account.Number) if err != nil { pg.Toast.NotifyError(err.Error()) } diff --git a/ui/page/settings/settings_page.go b/ui/page/settings/settings_page.go index 63211fe3c..574c7e6a4 100644 --- a/ui/page/settings/settings_page.go +++ b/ui/page/settings/settings_page.go @@ -92,7 +92,7 @@ func NewSettingsPage(l *load.Load) *SettingPage { _, pg.networkInfoButton = components.SubpageHeaderButtons(l) pg.backButton, pg.infoButton = components.SubpageHeaderButtons(l) - pg.isDarkModeOn = pg.WL.AssetsManager.IsDarkModeOn() + pg.isDarkModeOn = pg.AssetsManager.IsDarkModeOn() return pg } @@ -247,7 +247,7 @@ func (pg *SettingPage) general() layout.Widget { languageRow := row{ title: values.String(values.StrLanguage), clickable: pg.language, - label: pg.Theme.Body2(pg.WL.AssetsManager.GetLanguagePreference()), + label: pg.Theme.Body2(pg.AssetsManager.GetLanguagePreference()), } return pg.clickableRow(gtx, languageRow) }), @@ -262,12 +262,12 @@ func (pg *SettingPage) general() layout.Widget { func (pg *SettingPage) networkSettings() layout.Widget { return func(gtx C) D { return pg.wrapSection(gtx, values.String(values.StrPrivacySettings), func(gtx C) D { - if pg.WL.AssetsManager.IsPrivacyModeOn() { + if pg.AssetsManager.IsPrivacyModeOn() { return D{} } return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - lKey := pg.WL.AssetsManager.GetCurrencyConversionExchange() + lKey := pg.AssetsManager.GetCurrencyConversionExchange() l := preference.GetKeyValue(lKey, preference.ExchOptions) exchangeRate := row{ title: values.String(values.StrExchangeRate), @@ -349,7 +349,7 @@ func (pg *SettingPage) debug() layout.Widget { logLevel := row{ title: values.String(values.StrLogLevel), clickable: pg.logLevel, - label: pg.Theme.Body2(pg.WL.AssetsManager.GetLogLevels()), + label: pg.Theme.Body2(pg.AssetsManager.GetLogLevels()), } return pg.clickableRow(gtx, logLevel) }), @@ -411,7 +411,7 @@ func (pg *SettingPage) HandleUserInteractions() { sharedW.LanguagePreferenceKey, values.DefaultLangauge, preference.LangOptions). Title(values.StrLanguage). UpdateValues(func(_ string) { - values.SetUserLanguage(pg.WL.AssetsManager.GetLanguagePreference()) + values.SetUserLanguage(pg.AssetsManager.GetLanguagePreference()) }) pg.ParentWindow().ShowModal(langSelectorModal) break @@ -433,28 +433,28 @@ func (pg *SettingPage) HandleUserInteractions() { for pg.appearanceMode.Clicked() { pg.isDarkModeOn = !pg.isDarkModeOn - pg.WL.AssetsManager.SetDarkMode(pg.isDarkModeOn) + pg.AssetsManager.SetDarkMode(pg.isDarkModeOn) pg.RefreshTheme(pg.ParentWindow()) } if pg.transactionNotification.Changed() { - pg.WL.AssetsManager.SetTransactionsNotifications(pg.transactionNotification.IsChecked()) + pg.AssetsManager.SetTransactionsNotifications(pg.transactionNotification.IsChecked()) } if pg.governanceAPI.Changed() { - pg.WL.AssetsManager.SetHTTPAPIPrivacyMode(libutils.GovernanceHTTPAPI, pg.governanceAPI.IsChecked()) + pg.AssetsManager.SetHTTPAPIPrivacyMode(libutils.GovernanceHTTPAPI, pg.governanceAPI.IsChecked()) } if pg.exchangeAPI.Changed() { - pg.WL.AssetsManager.SetHTTPAPIPrivacyMode(libutils.ExchangeHTTPAPI, pg.exchangeAPI.IsChecked()) + pg.AssetsManager.SetHTTPAPIPrivacyMode(libutils.ExchangeHTTPAPI, pg.exchangeAPI.IsChecked()) } if pg.feeRateAPI.Changed() { - pg.WL.AssetsManager.SetHTTPAPIPrivacyMode(libutils.FeeRateHTTPAPI, pg.feeRateAPI.IsChecked()) + pg.AssetsManager.SetHTTPAPIPrivacyMode(libutils.FeeRateHTTPAPI, pg.feeRateAPI.IsChecked()) } if pg.vspAPI.Changed() { - pg.WL.AssetsManager.SetHTTPAPIPrivacyMode(libutils.VspAPI, pg.vspAPI.IsChecked()) + pg.AssetsManager.SetHTTPAPIPrivacyMode(libutils.VspAPI, pg.vspAPI.IsChecked()) } if pg.privacyActive.Changed() { - pg.WL.AssetsManager.SetPrivacyMode(pg.privacyActive.IsChecked()) + pg.AssetsManager.SetPrivacyMode(pg.privacyActive.IsChecked()) pg.updatePrivacySettings() } @@ -495,7 +495,7 @@ func (pg *SettingPage) HandleUserInteractions() { } if pg.viewLog.Clicked() { - pg.ParentNavigator().Display(NewLogPage(pg.Load, pg.WL.AssetsManager.LogFile(), values.String(values.StrAppLog))) + pg.ParentNavigator().Display(NewLogPage(pg.Load, pg.AssetsManager.LogFile(), values.String(values.StrAppLog))) } for pg.changeStartupPass.Clicked() { @@ -510,7 +510,7 @@ func (pg *SettingPage) HandleUserInteractions() { pm.SetLoading(false) return false } - err := pg.WL.AssetsManager.VerifyStartupPassphrase(password) + err := pg.AssetsManager.VerifyStartupPassphrase(password) if err != nil { pm.SetError(err.Error()) pm.SetLoading(false) @@ -530,7 +530,7 @@ func (pg *SettingPage) HandleUserInteractions() { m.SetLoading(false) return false } - err := pg.WL.AssetsManager.ChangeStartupPassphrase(password, newPassword, sharedW.PassphraseTypePass) + err := pg.AssetsManager.ChangeStartupPassphrase(password, newPassword, sharedW.PassphraseTypePass) if err != nil { m.SetError(err.Error()) m.SetLoading(false) @@ -561,7 +561,7 @@ func (pg *SettingPage) HandleUserInteractions() { m.SetLoading(false) return false } - err := pg.WL.AssetsManager.SetStartupPassphrase(password, sharedW.PassphraseTypePass) + err := pg.AssetsManager.SetStartupPassphrase(password, sharedW.PassphraseTypePass) if err != nil { m.SetError(err.Error()) m.SetLoading(false) @@ -584,7 +584,7 @@ func (pg *SettingPage) HandleUserInteractions() { Title(values.String(values.StrConfirmRemoveStartupPass)). PasswordHint(values.String(values.StrStartupPassword)). SetPositiveButtonCallback(func(_, password string, pm *modal.CreatePasswordModal) bool { - err := pg.WL.AssetsManager.RemoveStartupPassphrase(password) + err := pg.AssetsManager.RemoveStartupPassphrase(password) if err != nil { pm.SetError(err.Error()) pm.SetLoading(false) @@ -609,7 +609,7 @@ func (pg *SettingPage) showNoticeSuccess(title string) { } func (pg *SettingPage) updateSettingOptions() { - isPassword := pg.WL.AssetsManager.IsStartupSecuritySet() + isPassword := pg.AssetsManager.IsStartupSecuritySet() pg.startupPassword.SetChecked(false) pg.isStartupPassword = false if isPassword { @@ -621,21 +621,25 @@ func (pg *SettingPage) updateSettingOptions() { } func (pg *SettingPage) updatePrivacySettings() { - pg.setInitialSwitchStatus(pg.privacyActive, pg.WL.AssetsManager.IsPrivacyModeOn()) - if !pg.WL.AssetsManager.IsPrivacyModeOn() { - pg.setInitialSwitchStatus(pg.transactionNotification, pg.WL.AssetsManager.IsTransactionNotificationsOn()) - pg.setInitialSwitchStatus(pg.governanceAPI, pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI)) - pg.setInitialSwitchStatus(pg.exchangeAPI, pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.ExchangeHTTPAPI)) - pg.setInitialSwitchStatus(pg.feeRateAPI, pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.FeeRateHTTPAPI)) - pg.setInitialSwitchStatus(pg.vspAPI, pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.VspAPI)) - } else { + pg.setInitialSwitchStatus(pg.privacyActive, pg.AssetsManager.IsPrivacyModeOn()) + if !pg.AssetsManager.IsPrivacyModeOn() { + pg.setInitialSwitchStatus(pg.transactionNotification, pg.AssetsManager.IsTransactionNotificationsOn()) + pg.setInitialSwitchStatus(pg.governanceAPI, pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.GovernanceHTTPAPI)) + pg.setInitialSwitchStatus(pg.exchangeAPI, pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.ExchangeHTTPAPI)) + pg.setInitialSwitchStatus(pg.feeRateAPI, pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.FeeRateHTTPAPI)) + pg.setInitialSwitchStatus(pg.vspAPI, pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.VspAPI)) + } /*else { + // TODO: Re "Clear all the peers saved if the privacy mode is on". Does + // this mean clear all peers for all wallets? The privacy mode isn't on + // for just the selected wallet afterall. + if pg.WL.SelectedWallet != nil { go func() { // Clear all the peers saved if the privacy mode is on. pg.WL.SelectedWallet.Wallet.SetStringConfigValueForKey(sharedW.SpvPersistentPeerAddressesConfigKey, "") }() } - } + }*/ } // OnNavigatedFrom is called when the page is about to be removed from diff --git a/ui/page/settings/statistics_page.go b/ui/page/settings/statistics_page.go index 6c7416dc9..73632efab 100644 --- a/ui/page/settings/statistics_page.go +++ b/ui/page/settings/statistics_page.go @@ -30,26 +30,26 @@ type StatPage struct { // and the root WindowNavigator. *app.GenericPageModal + wallet sharedW.Asset txs []*sharedW.Transaction accounts *sharedW.Accounts l layout.List scrollbarList *widget.List startupTime string - netType string backButton cryptomaterial.IconButton } -func NewStatPage(l *load.Load) *StatPage { +func NewStatPage(l *load.Load, wallet sharedW.Asset) *StatPage { pg := &StatPage{ Load: l, GenericPageModal: app.NewGenericPageModal(StatisticsPageID), + wallet: wallet, l: layout.List{Axis: layout.Vertical}, scrollbarList: &widget.List{ List: layout.List{Axis: layout.Vertical}, }, - netType: l.WL.AssetsManager.NetType().Display(), } pg.backButton, _ = components.SubpageHeaderButtons(l) @@ -62,25 +62,25 @@ func NewStatPage(l *load.Load) *StatPage { // the page is displayed. // Part of the load.Page interface. func (pg *StatPage) OnNavigatedTo() { - txs, err := pg.WL.SelectedWallet.Wallet.GetTransactionsRaw(0, 0, dcr.TxFilterAll, true) + txs, err := pg.wallet.GetTransactionsRaw(0, 0, dcr.TxFilterAll, true) if err != nil { log.Errorf("Error getting txs: %s", err.Error()) } else { pg.txs = txs } - acc, err := pg.WL.SelectedWallet.Wallet.GetAccountsRaw() + acc, err := pg.wallet.GetAccountsRaw() if err != nil { log.Errorf("Error getting wallet accounts: %s", err.Error()) } else { // Filter imported account. accounts := make([]*sharedW.Account, 0) for _, v := range acc.Accounts { - if pg.WL.SelectedWallet.Wallet.GetAssetType() == libutils.BTCWalletAsset && v.AccountNumber != btc.ImportedAccountNumber { + if pg.wallet.GetAssetType() == libutils.BTCWalletAsset && v.AccountNumber != btc.ImportedAccountNumber { accounts = append(accounts, v) } - if pg.WL.SelectedWallet.Wallet.GetAssetType() == libutils.DCRWalletAsset && v.Number != dcr.ImportedAccountNumber { + if pg.wallet.GetAssetType() == libutils.DCRWalletAsset && v.Number != dcr.ImportedAccountNumber { accounts = append(accounts, v) } @@ -113,21 +113,28 @@ func (pg *StatPage) layoutStats(gtx C) D { } } - bestBlock := pg.WL.SelectedWallet.Wallet.GetBestBlockHeight() - bestBlockTime := time.Unix(pg.WL.SelectedWallet.Wallet.GetBestBlockTimeStamp(), 0) + bestBlock := pg.wallet.GetBestBlockHeight() + bestBlockTime := time.Unix(pg.wallet.GetBestBlockTimeStamp(), 0) secondsSinceBestBlock := int64(time.Since(bestBlockTime).Seconds()) + walletDataSize := "Unknown" + v, err := pg.AssetsManager.RootDirFileSizeInBytes(pg.wallet.DataDir()) + if err != nil { + walletDataSize = fmt.Sprintf("%f GB", float64(v)*1e-9) + } + line := pg.Theme.Separator() line.Color = pg.Theme.Color.Gray2 + netType := pg.AssetsManager.NetType().Display() items := []layout.Widget{ - item(values.String(values.StrBuild), pg.netType+", "+time.Now().Format("2006-01-02")), + item(values.String(values.StrBuild), netType+", "+time.Now().Format("2006-01-02")), line.Layout, - item(values.String(values.StrPeersConnected), strconv.Itoa(int(pg.WL.SelectedWallet.Wallet.ConnectedPeers()))), + item(values.String(values.StrPeersConnected), strconv.Itoa(int(pg.wallet.ConnectedPeers()))), line.Layout, item(values.String(values.StrUptime), pg.startupTime), line.Layout, - item(values.String(values.StrNetwork), pg.netType), + item(values.String(values.StrNetwork), netType), line.Layout, item(values.String(values.StrBestBlocks), fmt.Sprintf("%d", bestBlock)), line.Layout, @@ -135,9 +142,9 @@ func (pg *StatPage) layoutStats(gtx C) D { line.Layout, item(values.String(values.StrBestBlockAge), components.SecondsToDays(secondsSinceBestBlock)), line.Layout, - item(values.String(values.StrWalletDirectory), pg.WL.WalletDirectory()), + item(values.String(values.StrWalletDirectory), pg.wallet.DataDir()), line.Layout, - item(values.String(values.StrDateSize), pg.WL.DataSize()), + item(values.String(values.StrDateSize), walletDataSize), line.Layout, item(values.String(values.StrTransactions), fmt.Sprintf("%d", len(pg.txs))), line.Layout, @@ -212,7 +219,7 @@ func (pg *StatPage) appStartTime() { m := (v - h*3600) / 60 s := v - h*3600 - m*60 return fmt.Sprintf("%02d:%02d:%02d", h, m, s) - }(pg.Load.StartupTime()) + }(pg.AppInfo.StartupTime()) } // HandleUserInteractions is called just before Layout() to determine diff --git a/ui/page/staking/stake_info.go b/ui/page/staking/stake_info.go index 9087b073d..7863019ea 100644 --- a/ui/page/staking/stake_info.go +++ b/ui/page/staking/stake_info.go @@ -38,7 +38,7 @@ func (pg *Page) stakePriceSection(gtx C) D { }), layout.Rigid(func(gtx C) D { return layout.Center.Layout(gtx, func(gtx C) D { - if pg.WL.SelectedWallet.Wallet.IsSyncing() || pg.WL.SelectedWallet.Wallet.IsRescanning() || !pg.isTicketsPurchaseAllowed() { + if pg.dcrWallet.IsSyncing() || pg.dcrWallet.IsRescanning() || !pg.isTicketsPurchaseAllowed() { title := pg.Theme.Label(values.TextSize16, values.String(values.StrLoadingPrice)) title.Color = col return title.Layout(gtx) @@ -54,11 +54,11 @@ func (pg *Page) stakePriceSection(gtx C) D { }.Layout(gtx, pg.Theme.Icons.TimerIcon.Layout12dp) }), layout.Rigid(func(gtx C) D { - secs, _ := pg.dcrImpl.NextTicketPriceRemaining() + secs, _ := pg.dcrWallet.NextTicketPriceRemaining() txt := pg.Theme.Label(values.TextSize16, nextTicketRemaining(int(secs))) txt.Color = col - if pg.WL.SelectedWallet.Wallet.IsSyncing() { + if pg.dcrWallet.IsSyncing() { txt.Text = values.String(values.StrSyncingState) } return txt.Layout(gtx) @@ -75,13 +75,13 @@ func (pg *Page) stakePriceSection(gtx C) D { layout.Rigid(func(gtx C) D { title := pg.Theme.Label(values.TextSize16, values.String(values.StrStake)) title.Color = col - if !pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { + if !pg.dcrWallet.IsWatchingOnlyWallet() { return title.Layout(gtx) } return D{} }), layout.Rigid(func(gtx C) D { - if !pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { + if !pg.dcrWallet.IsWatchingOnlyWallet() { return layout.Inset{ Right: values.MarginPadding40, Left: values.MarginPadding4, @@ -95,7 +95,7 @@ func (pg *Page) stakePriceSection(gtx C) D { // if pg.ticketBuyerWallet.IsAutoTicketsPurchaseActive() { // icon = pg.Theme.Icons.SettingsInactiveIcon // } - if !pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { + if !pg.dcrWallet.IsWatchingOnlyWallet() { return pg.stakeSettings.Layout(gtx, icon.Layout24dp) } return D{} @@ -141,17 +141,17 @@ func (pg *Page) dataRows(title string, count int) layout.FlexChild { } func (pg *Page) CalculateTotalTicketsCanBuy() int { - if !pg.dcrImpl.Synced() { + if !pg.dcrWallet.Synced() { return 0 } - totalBalance, err := components.CalculateMixedAccountBalance(pg.dcrImpl) + totalBalance, err := components.CalculateMixedAccountBalance(pg.dcrWallet) if err != nil { log.Debugf("missing set mixed account error: %v", err) return 0 } - ticketPrice, err := pg.dcrImpl.TicketPrice() + ticketPrice, err := pg.dcrWallet.TicketPrice() if err != nil { log.Errorf("ticketPrice error: %v", err) return 0 @@ -165,7 +165,7 @@ func (pg *Page) CalculateTotalTicketsCanBuy() int { } func (pg *Page) balanceProgressBarLayout(gtx C) D { - totalBalance, err := components.CalculateMixedAccountBalance(pg.dcrImpl) + totalBalance, err := components.CalculateMixedAccountBalance(pg.dcrWallet) if err != nil { return D{} } @@ -194,7 +194,7 @@ func (pg *Page) balanceProgressBarLayout(gtx C) D { }) } total := totalBalance.Spendable.ToInt() + totalBalance.LockedByTickets.ToInt() - pb := pg.Theme.MultiLayerProgressBar(pg.WL.SelectedWallet.Wallet.ToAmount(total).ToCoin(), items) + pb := pg.Theme.MultiLayerProgressBar(pg.dcrWallet.ToAmount(total).ToCoin(), items) pb.Height = values.MarginPadding16 pb.ShowLedger = true return pb.Layout(gtx, labelWdg) diff --git a/ui/page/staking/stake_list.go b/ui/page/staking/stake_list.go index 77bebed71..f5356b903 100644 --- a/ui/page/staking/stake_list.go +++ b/ui/page/staking/stake_list.go @@ -19,7 +19,7 @@ func (pg *Page) listenForTxNotifications() { } pg.TxAndBlockNotificationListener = listeners.NewTxAndBlockNotificationListener() - err := pg.dcrImpl.AddTxAndBlockNotificationListener(pg.TxAndBlockNotificationListener, true, OverviewPageID) + err := pg.dcrWallet.AddTxAndBlockNotificationListener(pg.TxAndBlockNotificationListener, true, OverviewPageID) if err != nil { log.Errorf("Error adding tx and block notification listener: %v", err) return @@ -33,7 +33,7 @@ func (pg *Page) listenForTxNotifications() { pg.ParentWindow().Reload() } case <-pg.ctx.Done(): - pg.dcrImpl.RemoveTxAndBlockNotificationListener(OverviewPageID) + pg.dcrWallet.RemoveTxAndBlockNotificationListener(OverviewPageID) pg.CloseTxAndBlockChan() pg.TxAndBlockNotificationListener = nil @@ -44,12 +44,12 @@ func (pg *Page) listenForTxNotifications() { } func (pg *Page) fetchTickets(offset, pageSize int32) ([]*transactionItem, int, bool, error) { - txs, err := pg.WL.SelectedWallet.Wallet.GetTransactionsRaw(offset, pageSize, dcr.TxFilterTickets, true) + txs, err := pg.dcrWallet.GetTransactionsRaw(offset, pageSize, dcr.TxFilterTickets, true) if err != nil { return nil, -1, false, err } - tickets, err := stakeToTransactionItems(pg.Load, txs, true, func(filter int32) bool { + tickets, err := pg.stakeToTransactionItems(txs, true, func(filter int32) bool { return filter == dcr.TxFilterTickets }) return tickets, len(tickets), false, err @@ -106,7 +106,7 @@ func (pg *Page) ticketListLayout(gtx C) D { return layout.Inset{ Bottom: values.MarginPadding5, }.Layout(gtx, func(gtx C) D { - return ticketListLayout(gtx, pg.Load, ticket) + return ticketListLayout(gtx, pg.Load, pg.dcrWallet, ticket) }) }), ) diff --git a/ui/page/staking/stake_modal.go b/ui/page/staking/stake_modal.go index c3a1b0425..be5800882 100644 --- a/ui/page/staking/stake_modal.go +++ b/ui/page/staking/stake_modal.go @@ -38,21 +38,15 @@ type ticketBuyerModal struct { dcrImpl *dcr.Asset } -func newTicketBuyerModal(l *load.Load) *ticketBuyerModal { - impl := l.WL.SelectedWallet.Wallet.(*dcr.Asset) - if impl == nil { - log.Warn(values.ErrDCRSupportedOnly) - return nil - } - +func newTicketBuyerModal(l *load.Load, wallet *dcr.Asset) *ticketBuyerModal { tb := &ticketBuyerModal{ Load: l, Modal: l.Theme.ModalFloatTitle("staking_modal"), cancel: l.Theme.OutlineButton(values.String(values.StrCancel)), saveSettingsBtn: l.Theme.Button(values.String(values.StrSave)), - vspSelector: components.NewVSPSelector(l).Title(values.String(values.StrSelectVSP)), - dcrImpl: impl, + vspSelector: components.NewVSPSelector(l, wallet).Title(values.String(values.StrSelectVSP)), + dcrImpl: wallet, } tb.balToMaintainEditor = l.Theme.Editor(new(widget.Editor), values.String(values.StrBalToMaintain)) @@ -92,8 +86,6 @@ func (tb *ticketBuyerModal) OnResume() { go tb.dcrImpl.ReloadVSPList(context.TODO()) } - wl := load.NewWalletMapping(tb.WL.SelectedWallet.Wallet) - // loop through all available wallets and select the one with ticket buyer config. // if non, set the selected wallet to the first. // temporary work around for only one wallet. @@ -110,19 +102,19 @@ func (tb *ticketBuyerModal) OnResume() { tb.accountSelector.SetSelectedAccount(account) } else { // If a valid account is not set, choose one from available the valid accounts. - if err := tb.accountSelector.SelectFirstValidAccount(wl); err != nil { + if err := tb.accountSelector.SelectFirstValidAccount(tb.dcrImpl); err != nil { errModal := modal.NewErrorModal(tb.Load, err.Error(), modal.DefaultClickFunc()) tb.ParentWindow().ShowModal(errModal) } } tb.vspSelector.SelectVSP(tbConfig.VspHost) - w := tb.WL.SelectedWallet.Wallet + w := tb.dcrImpl tb.balToMaintainEditor.Editor.SetText(strconv.FormatFloat(w.ToAmount(tbConfig.BalanceToMaintain).ToCoin(), 'f', 0, 64)) } if tb.accountSelector.SelectedAccount() == nil { - err := tb.accountSelector.SelectFirstValidAccount(wl) + err := tb.accountSelector.SelectFirstValidAccount(tb.dcrImpl) if err != nil { errModal := modal.NewErrorModal(tb.Load, err.Error(), modal.DefaultClickFunc()) tb.ParentWindow().ShowModal(errModal) @@ -197,19 +189,17 @@ func (tb *ticketBuyerModal) initializeAccountSelector() { AccountSelected(func(selectedAccount *sharedW.Account) {}). AccountValidator(func(account *sharedW.Account) bool { // Imported and watch only wallet accounts are invalid for sending - accountIsValid := account.Number != dcr.ImportedAccountNumber && !tb.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() + accountIsValid := account.Number != dcr.ImportedAccountNumber && !tb.dcrImpl.IsWatchingOnlyWallet() - if tb.WL.SelectedWallet.Wallet.ReadBoolConfigValueForKey(sharedW.AccountMixerConfigSet, false) && - !tb.WL.SelectedWallet.Wallet.ReadBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, false) { + if tb.dcrImpl.ReadBoolConfigValueForKey(sharedW.AccountMixerConfigSet, false) && + !tb.dcrImpl.ReadBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, false) { // Spending from unmixed accounts is disabled for the selected wallet - dcrImpl := tb.WL.SelectedWallet.Wallet.(*dcr.Asset) - accountIsValid = account.Number == dcrImpl.MixedAccountNumber() + accountIsValid = account.Number == tb.dcrImpl.MixedAccountNumber() } return accountIsValid }) - wl := load.NewWalletMapping(tb.WL.SelectedWallet.Wallet) - tb.accountSelector.SelectFirstValidAccount(wl) + tb.accountSelector.SelectFirstValidAccount(tb.dcrImpl) } func (tb *ticketBuyerModal) OnDismiss() { diff --git a/ui/page/staking/stake_overview.go b/ui/page/staking/stake_overview.go index 535bca80a..bdafb7aeb 100644 --- a/ui/page/staking/stake_overview.go +++ b/ui/page/staking/stake_overview.go @@ -66,20 +66,14 @@ type Page struct { navToSettingsBtn cryptomaterial.Button processingTicket uint32 - dcrImpl *dcr.Asset + dcrWallet *dcr.Asset } -func NewStakingPage(l *load.Load) *Page { - impl := l.WL.SelectedWallet.Wallet.(*dcr.Asset) - if impl == nil { - log.Error(values.ErrDCRSupportedOnly) - return nil - } - +func NewStakingPage(l *load.Load, dcrWallet *dcr.Asset) *Page { pg := &Page{ Load: l, GenericPageModal: app.NewGenericPageModal(OverviewPageID), - dcrImpl: impl, + dcrWallet: dcrWallet, } pg.scroll = components.NewScroll(l, pageSize, pg.fetchTickets) @@ -104,7 +98,7 @@ func (pg *Page) OnNavigatedTo() { // If staking is disabled no startup func should be called // Layout will draw an overlay to show that stacking is disabled. - isSyncingOrRescanning := !pg.WL.SelectedWallet.Wallet.IsSynced() || pg.WL.SelectedWallet.Wallet.IsRescanning() + isSyncingOrRescanning := !pg.dcrWallet.IsSynced() || pg.dcrWallet.IsRescanning() if pg.isTicketsPurchaseAllowed() && !isSyncingOrRescanning { pg.ctx, pg.ctxCancel = context.WithCancel(context.TODO()) @@ -112,7 +106,7 @@ func (pg *Page) OnNavigatedTo() { pg.loadPageData() // starts go routines to refresh the display which is just about to be displayed, ok? - pg.stake.SetChecked(pg.dcrImpl.IsAutoTicketsPurchaseActive()) + pg.stake.SetChecked(pg.dcrWallet.IsAutoTicketsPurchaseActive()) pg.setStakingButtonsState() @@ -127,8 +121,8 @@ func (pg *Page) OnNavigatedTo() { // fetch ticket price only when the wallet is synced func (pg *Page) fetchTicketPrice() { - ticketPrice, err := pg.dcrImpl.TicketPrice() - if err != nil && !pg.WL.SelectedWallet.Wallet.IsSynced() { + ticketPrice, err := pg.dcrWallet.TicketPrice() + if err != nil && !pg.dcrWallet.IsSynced() { log.Error(err) pg.ticketPrice = dcrutil.Amount(0).String() errModal := modal.NewErrorModal(pg.Load, values.String(values.StrWalletNotSynced), modal.DefaultClickFunc()) @@ -140,19 +134,19 @@ func (pg *Page) fetchTicketPrice() { func (pg *Page) setStakingButtonsState() { // disable auto ticket purchase if wallet is not synced - pg.stake.SetEnabled(pg.WL.SelectedWallet.Wallet.IsSynced() || !pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet()) + pg.stake.SetEnabled(pg.dcrWallet.IsSynced() || !pg.dcrWallet.IsWatchingOnlyWallet()) } func (pg *Page) loadPageData() { go func() { - if len(pg.dcrImpl.KnownVSPs()) == 0 { + if len(pg.dcrWallet.KnownVSPs()) == 0 { // TODO: Does this page need this list? if pg.ctx != nil { - pg.dcrImpl.ReloadVSPList(pg.ctx) + pg.dcrWallet.ReloadVSPList(pg.ctx) } } - totalRewards, err := pg.dcrImpl.TotalStakingRewards() + totalRewards, err := pg.dcrWallet.TotalStakingRewards() if err != nil { errModal := modal.NewErrorModal(pg.Load, err.Error(), modal.DefaultClickFunc()) pg.ParentWindow().ShowModal(errModal) @@ -160,7 +154,7 @@ func (pg *Page) loadPageData() { pg.totalRewards = dcrutil.Amount(totalRewards).String() } - overview, err := pg.dcrImpl.StakingOverview() + overview, err := pg.dcrWallet.StakingOverview() if err != nil { errModal := modal.NewErrorModal(pg.Load, err.Error(), modal.DefaultClickFunc()) pg.ParentWindow().ShowModal(errModal) @@ -173,7 +167,7 @@ func (pg *Page) loadPageData() { } func (pg *Page) isTicketsPurchaseAllowed() bool { - return pg.WL.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.VspAPI) + return pg.AssetsManager.IsHTTPAPIPrivacyModeOff(libutils.VspAPI) } // Layout draws the page UI components into the provided layout context @@ -181,7 +175,7 @@ func (pg *Page) isTicketsPurchaseAllowed() bool { // Part of the load.Page interface. func (pg *Page) Layout(gtx C) D { // If Tickets Purcahse API is not allowed, display the overlay with the message. - isSyncingOrRescanning := !pg.WL.SelectedWallet.Wallet.IsSynced() || pg.WL.SelectedWallet.Wallet.IsRescanning() + isSyncingOrRescanning := !pg.dcrWallet.IsSynced() || pg.dcrWallet.IsRescanning() overlay := layout.Stacked(func(gtx C) D { return D{} }) if !pg.isTicketsPurchaseAllowed() && !isSyncingOrRescanning { gtxCopy := gtx @@ -262,15 +256,15 @@ func (pg *Page) HandleUserInteractions() { if pg.stake.Changed() { if pg.stake.IsChecked() { - if pg.dcrImpl.TicketBuyerConfigIsSet() { + if pg.dcrWallet.TicketBuyerConfigIsSet() { // get ticket buyer config to check if the saved wallet account is mixed // check if mixer is set, if yes check if allow spend from unmixed account // if not set, check if the saved account is mixed before opening modal // if it is not, open stake config modal - tbConfig := pg.dcrImpl.AutoTicketsBuyerConfig() - if pg.WL.SelectedWallet.Wallet.ReadBoolConfigValueForKey(sharedW.AccountMixerConfigSet, false) && - !pg.WL.SelectedWallet.Wallet.ReadBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, false) && - (tbConfig.PurchaseAccount == pg.dcrImpl.MixedAccountNumber()) { + tbConfig := pg.dcrWallet.AutoTicketsBuyerConfig() + if pg.dcrWallet.ReadBoolConfigValueForKey(sharedW.AccountMixerConfigSet, false) && + !pg.dcrWallet.ReadBoolConfigValueForKey(sharedW.SpendUnmixedFundsKey, false) && + (tbConfig.PurchaseAccount == pg.dcrWallet.MixedAccountNumber()) { pg.startTicketBuyerPasswordModal() } else { pg.ticketBuyerSettingsModal() @@ -279,18 +273,18 @@ func (pg *Page) HandleUserInteractions() { pg.ticketBuyerSettingsModal() } } else { - pg.dcrImpl.StopAutoTicketsPurchase() + pg.dcrWallet.StopAutoTicketsPurchase() } } - if pg.stakeSettings.Clicked() && !pg.WL.SelectedWallet.Wallet.IsWatchingOnlyWallet() { - if pg.dcrImpl.IsAutoTicketsPurchaseActive() { + if pg.stakeSettings.Clicked() && !pg.dcrWallet.IsWatchingOnlyWallet() { + if pg.dcrWallet.IsAutoTicketsPurchaseActive() { errModal := modal.NewErrorModal(pg.Load, values.String(values.StrAutoTicketWarn), modal.DefaultClickFunc()) pg.ParentWindow().ShowModal(errModal) return } - ticketBuyerModal := newTicketBuyerModal(pg.Load). + ticketBuyerModal := newTicketBuyerModal(pg.Load, pg.dcrWallet). OnSettingsSaved(func() { infoModal := modal.NewSuccessModal(pg.Load, values.String(values.StrTicketSettingSaved), modal.DefaultClickFunc()) pg.ParentWindow().ShowModal(infoModal) @@ -301,19 +295,19 @@ func (pg *Page) HandleUserInteractions() { pg.ParentWindow().ShowModal(ticketBuyerModal) } - secs, _ := pg.dcrImpl.NextTicketPriceRemaining() + secs, _ := pg.dcrWallet.NextTicketPriceRemaining() if secs <= 0 { pg.fetchTicketPrice() } - if pg.WL.SelectedWallet.Wallet.IsSynced() { + if pg.dcrWallet.IsSynced() { pg.fetchTicketPrice() } if clicked, selectedItem := pg.ticketsList.ItemClicked(); clicked { tickets := pg.scroll.FetchedData() ticketTx := tickets[selectedItem].transaction - pg.ParentNavigator().Display(tpage.NewTransactionDetailsPage(pg.Load, ticketTx, true)) + pg.ParentNavigator().Display(tpage.NewTransactionDetailsPage(pg.Load, ticketTx, pg.dcrWallet)) // Check if this ticket is fully registered with a VSP // and log any discrepancies. @@ -323,7 +317,7 @@ func (pg *Page) HandleUserInteractions() { // but where it is necessary to display vsp-stored info, the // wallet passphrase should be requested and used to unlock // the wallet before calling this method. - ticketInfo, err := pg.dcrImpl.VSPTicketInfo(ticketTx.Hash) + ticketInfo, err := pg.dcrWallet.VSPTicketInfo(ticketTx.Hash) if err != nil { log.Errorf("VSPTicketInfo error: %v", err) } else { @@ -346,7 +340,7 @@ func (pg *Page) HandleUserInteractions() { } account := ticketTx.Inputs[0].AccountNumber - err = ticketInfo.Client.ProcessTicket(pg.ctx, txHash, pg.dcrImpl.GetvspPolicy(account)) + err = ticketInfo.Client.ProcessTicket(pg.ctx, txHash, pg.dcrWallet.GetvspPolicy(account)) if err != nil { log.Errorf("processing the unconfirmed tx fee failed: %v", err) } @@ -370,7 +364,7 @@ func (pg *Page) HandleUserInteractions() { } func (pg *Page) ticketBuyerSettingsModal() { - ticketBuyerModal := newTicketBuyerModal(pg.Load). + ticketBuyerModal := newTicketBuyerModal(pg.Load, pg.dcrWallet). OnCancel(func() { pg.stake.SetChecked(false) }). @@ -383,9 +377,9 @@ func (pg *Page) ticketBuyerSettingsModal() { } func (pg *Page) startTicketBuyerPasswordModal() { - tbConfig := pg.dcrImpl.AutoTicketsBuyerConfig() - balToMaintain := pg.WL.SelectedWallet.Wallet.ToAmount(tbConfig.BalanceToMaintain).ToCoin() - name, err := pg.WL.SelectedWallet.Wallet.AccountNameRaw(uint32(tbConfig.PurchaseAccount)) + tbConfig := pg.dcrWallet.AutoTicketsBuyerConfig() + balToMaintain := pg.dcrWallet.ToAmount(tbConfig.BalanceToMaintain).ToCoin() + name, err := pg.dcrWallet.AccountNameRaw(uint32(tbConfig.PurchaseAccount)) if err != nil { errModal := modal.NewErrorModal(pg.Load, values.StringF(values.StrTicketError, err), modal.DefaultClickFunc()) pg.ParentWindow().ShowModal(errModal) @@ -399,7 +393,7 @@ func (pg *Page) startTicketBuyerPasswordModal() { SetCancelable(false). UseCustomWidget(func(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(pg.Theme.Label(values.TextSize14, values.StringF(values.StrWalletToPurchaseFrom, pg.WL.SelectedWallet.Wallet.GetWalletName())).Layout), + layout.Rigid(pg.Theme.Label(values.TextSize14, values.StringF(values.StrWalletToPurchaseFrom, pg.dcrWallet.GetWalletName())).Layout), layout.Rigid(pg.Theme.Label(values.TextSize14, values.StringF(values.StrSelectedAccount, name)).Layout), layout.Rigid(pg.Theme.Label(values.TextSize14, values.StringF(values.StrBalToMaintainValue, balToMaintain)).Layout), layout.Rigid(func(gtx C) D { label := pg.Theme.Label(values.TextSize14, fmt.Sprintf("VSP: %s", tbConfig.VspHost)) @@ -423,7 +417,7 @@ func (pg *Page) startTicketBuyerPasswordModal() { txt := pg.Theme.Label(values.TextSize14, msg) txt.Alignment = text.Middle txt.Color = pg.Theme.Color.GrayText3 - if pg.WL.AssetsManager.IsDarkModeOn() { + if pg.AssetsManager.IsDarkModeOn() { txt.Color = pg.Theme.Color.Gray3 } return txt.Layout(gtx) @@ -434,21 +428,21 @@ func (pg *Page) startTicketBuyerPasswordModal() { }). SetNegativeButtonCallback(func() { pg.stake.SetChecked(false) }). SetPositiveButtonCallback(func(_, password string, pm *modal.CreatePasswordModal) bool { - if !pg.WL.SelectedWallet.Wallet.IsConnectedToNetwork() { + if !pg.dcrWallet.IsConnectedToNetwork() { pm.SetError(values.String(values.StrNotConnected)) pm.SetLoading(false) pg.stake.SetChecked(false) return false } - err := pg.dcrImpl.StartTicketBuyer(password) + err := pg.dcrWallet.StartTicketBuyer(password) if err != nil { pm.SetError(err.Error()) pm.SetLoading(false) return false } - pg.stake.SetChecked(pg.dcrImpl.IsAutoTicketsPurchaseActive()) + pg.stake.SetChecked(pg.dcrWallet.IsAutoTicketsPurchaseActive()) pg.ParentWindow().Reload() pm.Dismiss() diff --git a/ui/page/staking/utils.go b/ui/page/staking/utils.go index 8b2cd6311..07a5aa9a0 100644 --- a/ui/page/staking/utils.go +++ b/ui/page/staking/utils.go @@ -32,22 +32,14 @@ type transactionItem struct { dateTooltip *cryptomaterial.Tooltip daysBehindTooltip *cryptomaterial.Tooltip durationTooltip *cryptomaterial.Tooltip - - dcrImpl *dcr.Asset } -func stakeToTransactionItems(l *load.Load, txs []*sharedW.Transaction, newestFirst bool, hasFilter func(int32) bool) ([]*transactionItem, error) { - impl := l.WL.SelectedWallet.Wallet.(*dcr.Asset) - if impl == nil { - log.Warn(values.ErrDCRSupportedOnly) - return nil, values.ErrDCRSupportedOnly - } - +func (pg *Page) stakeToTransactionItems(txs []*sharedW.Transaction, newestFirst bool, hasFilter func(int32) bool) ([]*transactionItem, error) { tickets := make([]*transactionItem, 0) for _, tx := range txs { - bestBlockHeight := impl.GetBestBlockHeight() + bestBlockHeight := pg.dcrWallet.GetBestBlockHeight() - ticketSpender, err := impl.TicketSpender(tx.Hash) + ticketSpender, err := pg.dcrWallet.TicketSpender(tx.Hash) if err != nil { return nil, err } @@ -72,13 +64,13 @@ func stakeToTransactionItems(l *load.Load, txs []*sharedW.Transaction, newestFir } ticketCopy := tx - txStatus := components.TransactionTitleIcon(l, impl, tx) + txStatus := components.TransactionTitleIcon(pg.Load, pg.dcrWallet, tx) confirmations := dcr.Confirmations(bestBlockHeight, tx) var ticketAge string showProgress := txStatus.TicketStatus == dcr.TicketStatusImmature || txStatus.TicketStatus == dcr.TicketStatusLive if ticketSpender != nil { /// voted or revoked - showProgress = dcr.Confirmations(bestBlockHeight, ticketSpender) <= impl.TicketMaturity() + showProgress = dcr.Confirmations(bestBlockHeight, ticketSpender) <= pg.dcrWallet.TicketMaturity() ticketAge = fmt.Sprintf("%d days", ticketSpender.DaysToVoteOrRevoke) } else if txStatus.TicketStatus == dcr.TicketStatusImmature || txStatus.TicketStatus == dcr.TicketStatusLive { @@ -91,9 +83,9 @@ func stakeToTransactionItems(l *load.Load, txs []*sharedW.Transaction, newestFir var progress float32 if showProgress { - progressMax := impl.TicketMaturity() + progressMax := pg.dcrWallet.TicketMaturity() if txStatus.TicketStatus == dcr.TicketStatusLive { - progressMax = impl.TicketExpiry() + progressMax = pg.dcrWallet.TicketExpiry() } confs := confirmations @@ -115,13 +107,11 @@ func stakeToTransactionItems(l *load.Load, txs []*sharedW.Transaction, newestFir purchaseTime: time.Unix(tx.Timestamp, 0).Format("Jan 2, 2006 15:04:05 PM"), ticketAge: ticketAge, - statusTooltip: l.Theme.Tooltip(), - walletNameTooltip: l.Theme.Tooltip(), - dateTooltip: l.Theme.Tooltip(), - daysBehindTooltip: l.Theme.Tooltip(), - durationTooltip: l.Theme.Tooltip(), - - dcrImpl: impl, + statusTooltip: pg.Theme.Tooltip(), + walletNameTooltip: pg.Theme.Tooltip(), + dateTooltip: pg.Theme.Tooltip(), + daysBehindTooltip: pg.Theme.Tooltip(), + durationTooltip: pg.Theme.Tooltip(), }) } @@ -147,11 +137,11 @@ func stakeToTransactionItems(l *load.Load, txs []*sharedW.Transaction, newestFir return tickets, nil } -func TicketStatusDetails(gtx C, l *load.Load, tx *transactionItem) D { +func TicketStatusDetails(gtx C, l *load.Load, dcrWallet *dcr.Asset, tx *transactionItem) D { date := time.Unix(tx.transaction.Timestamp, 0).Format("Jan 2, 2006") timeSplit := time.Unix(tx.transaction.Timestamp, 0).Format("03:04:05 PM") dateTime := fmt.Sprintf("%v at %v", date, timeSplit) - bestBlock := l.WL.SelectedWallet.Wallet.GetBestBlock() + bestBlock := dcrWallet.GetBestBlock() col := l.Theme.Color.GrayText3 switch tx.status.TicketStatus { @@ -160,8 +150,8 @@ func TicketStatusDetails(gtx C, l *load.Load, tx *transactionItem) D { lbl.Color = col return lbl.Layout(gtx) case dcr.TicketStatusImmature: - maturity := tx.dcrImpl.TicketMaturity() - blockTime := l.WL.SelectedWallet.Wallet.TargetTimePerBlockMinutes() + maturity := dcrWallet.TicketMaturity() + blockTime := dcrWallet.TargetTimePerBlockMinutes() maturityDuration := time.Duration(maturity*int32(blockTime)) * time.Minute blockRemaining := (bestBlock.Height - tx.transaction.BlockHeight) @@ -184,8 +174,8 @@ func TicketStatusDetails(gtx C, l *load.Load, tx *transactionItem) D { }), ) case dcr.TicketStatusLive: - expiry := tx.dcrImpl.TicketExpiry() - lbl := l.Theme.Label(values.TextSize16, values.StringF(values.StrLiveInfoDisc, expiry, getTimeToMatureOrExpire(l, tx), expiry)) + expiry := dcrWallet.TicketExpiry() + lbl := l.Theme.Label(values.TextSize16, values.StringF(values.StrLiveInfoDisc, expiry, getTimeToMatureOrExpire(dcrWallet, tx), expiry)) lbl.Color = col return lbl.Layout(gtx) case dcr.TicketStatusVotedOrRevoked: @@ -228,7 +218,7 @@ func multiContent(gtx C, l *load.Load, leftText, rightText string) D { ) } -func ticketListLayout(gtx C, l *load.Load, ticket *transactionItem) layout.Dimensions { +func ticketListLayout(gtx C, l *load.Load, wallet *dcr.Asset, ticket *transactionItem) layout.Dimensions { return layout.Inset{ Right: values.MarginPadding26, }.Layout(gtx, func(gtx C) D { @@ -253,7 +243,7 @@ func ticketListLayout(gtx C, l *load.Load, ticket *transactionItem) layout.Dimen ) }, func(gtx C) D { - return TicketStatusDetails(gtx, l, ticket) + return TicketStatusDetails(gtx, l, wallet, ticket) }) }) } @@ -289,15 +279,16 @@ func nextTicketRemaining(allsecs int) string { return str } -func getTimeToMatureOrExpire(l *load.Load, tx *transactionItem) int { - progressMax := tx.dcrImpl.TicketMaturity() +func getTimeToMatureOrExpire(dcrWallet *dcr.Asset, tx *transactionItem) int { + progressMax := dcrWallet.TicketMaturity() if tx.status.TicketStatus == dcr.TicketStatusLive { - progressMax = tx.dcrImpl.TicketExpiry() + progressMax = dcrWallet.TicketExpiry() } - confs := dcr.Confirmations(l.WL.SelectedWallet.Wallet.GetBestBlockHeight(), tx.transaction) + bestBlockHeight := dcrWallet.GetBestBlockHeight() + confs := dcr.Confirmations(bestBlockHeight, tx.transaction) if tx.ticketSpender != nil { - confs = dcr.Confirmations(l.WL.SelectedWallet.Wallet.GetBestBlockHeight(), tx.ticketSpender) + confs = dcr.Confirmations(bestBlockHeight, tx.ticketSpender) } progress := (float32(confs) / float32(progressMax)) * 100 diff --git a/ui/page/start_page.go b/ui/page/start_page.go index ea679fece..6cf3651cf 100644 --- a/ui/page/start_page.go +++ b/ui/page/start_page.go @@ -86,12 +86,12 @@ func (sp *startPage) OnNavigatedTo() { return } - if sp.WL.AssetsManager.LoadedWalletsCount() > 0 { + if sp.AssetsManager.LoadedWalletsCount() > 0 { sp.currentPage = -1 sp.setLanguageSetting() // Set the log levels. - sp.WL.AssetsManager.GetLogLevels() - if sp.WL.AssetsManager.IsStartupSecuritySet() { + sp.AssetsManager.GetLogLevels() + if sp.AssetsManager.IsStartupSecuritySet() { sp.unlock() } else { go sp.openWallets("") @@ -132,7 +132,7 @@ func (sp *startPage) unlock() { PasswordHint(values.String(values.StrStartupPassword)). SetNegativeButtonText(values.String(values.StrExit)). SetNegativeButtonCallback(func() { - sp.WL.AssetsManager.Shutdown() + sp.AssetsManager.Shutdown() os.Exit(0) }). SetCancelable(false). @@ -152,7 +152,7 @@ func (sp *startPage) unlock() { } func (sp *startPage) openWallets(password string) error { - err := sp.WL.AssetsManager.OpenWallets(password) + err := sp.AssetsManager.OpenWallets(password) if err != nil { log.Errorf("Error opening wallet: %v", err) // show err dialog @@ -170,9 +170,10 @@ func (sp *startPage) openWallets(password string) error { // Part of the load.Page interface. func (sp *startPage) HandleUserInteractions() { if sp.addWalletButton.Clicked() { - sp.ParentNavigator().Display(components.NewCreateWallet(sp.Load, func() { + createWalletPage := components.NewCreateWallet(sp.Load, func() { sp.ParentNavigator().Display(root.NewHomePage(sp.Load)) - })) + }) + sp.ParentNavigator().Display(createWalletPage) } if sp.skipButton.Clicked() { @@ -261,7 +262,7 @@ func (sp *startPage) loadingSection(gtx C) D { }) }), layout.Rigid(func(gtx C) D { - netType := sp.WL.AssetsManager.NetType().Display() + netType := sp.AssetsManager.NetType().Display() nType := sp.Theme.Label(values.TextSize20, netType) nType.Font.Weight = font.Medium return layout.Inset{Top: values.MarginPadding14}.Layout(gtx, nType.Layout) @@ -269,7 +270,7 @@ func (sp *startPage) loadingSection(gtx C) D { layout.Rigid(func(gtx C) D { if sp.loading { loadStatus := sp.Theme.Label(values.TextSize20, values.String(values.StrLoading)) - if sp.WL.AssetsManager.LoadedWalletsCount() > 0 { + if sp.AssetsManager.LoadedWalletsCount() > 0 { switch { case sp.isQuitting: loadStatus.Text = values.String(values.StrClosingWallet) @@ -408,9 +409,9 @@ func (sp *startPage) currentPageIndicatorLayout(gtx C) D { } func (sp *startPage) setLanguageSetting() { - langPre := sp.WL.AssetsManager.GetLanguagePreference() + langPre := sp.AssetsManager.GetLanguagePreference() if langPre == "" { - sp.WL.AssetsManager.SetLanguagePreference(values.DefaultLangauge) + sp.AssetsManager.SetLanguagePreference(values.DefaultLangauge) } values.SetUserLanguage(langPre) } diff --git a/ui/page/transaction/transaction_details_page.go b/ui/page/transaction/transaction_details_page.go index c1119729d..fa93d5bd2 100644 --- a/ui/page/transaction/transaction_details_page.go +++ b/ui/page/transaction/transaction_details_page.go @@ -90,7 +90,7 @@ type TxDetailsPage struct { moreOptionIsOpen bool } -func NewTransactionDetailsPage(l *load.Load, transaction *sharedW.Transaction, _ /*isTicket*/ bool) *TxDetailsPage { +func NewTransactionDetailsPage(l *load.Load, transaction *sharedW.Transaction, wallet sharedW.Asset) *TxDetailsPage { rebroadcast := l.Theme.Label(values.TextSize14, values.String(values.StrRebroadcast)) rebroadcast.TextSize = values.TextSize14 rebroadcast.Color = l.Theme.Color.Text @@ -118,7 +118,7 @@ func NewTransactionDetailsPage(l *load.Load, transaction *sharedW.Transaction, _ shadowBox: l.Theme.Shadow(), transaction: transaction, - wallet: l.WL.SelectedWallet.Wallet, + wallet: wallet, rebroadcast: rebroadcast, rebroadcastClickable: l.Theme.NewClickable(true), rebroadcastIcon: l.Theme.Icons.Rebroadcast, @@ -249,7 +249,7 @@ func (pg *TxDetailsPage) OnNavigatedTo() { } pg.getTXSourceAccountAndDirection() - pg.txnWidgets = initTxnWidgets(pg.Load, pg.transaction) + pg.initTxnWidgets() } func (pg *TxDetailsPage) getMoreItem() []moreItem { @@ -292,7 +292,7 @@ func (pg *TxDetailsPage) Layout(gtx C) D { } pg.transaction = pg.txBackStack pg.getTXSourceAccountAndDirection() - pg.txnWidgets = initTxnWidgets(pg.Load, pg.transaction) + pg.initTxnWidgets() pg.txBackStack = nil pg.ParentWindow().Reload() }, @@ -692,17 +692,17 @@ func (pg *TxDetailsPage) txnTypeAndID(gtx C) D { if pg.txConfirmations() == 0 { txt.Text = caser.String(values.String(values.StrUnconfirmedTx)) txt.Color = pg.Theme.Color.GrayText2 - } else if pg.txConfirmations() >= pg.WL.SelectedWallet.Wallet.RequiredConfirmations() { + } else if pg.txConfirmations() >= pg.wallet.RequiredConfirmations() { txt.Text = caser.String(values.String(values.StrConfirmed)) txt.Color = pg.Theme.Color.Success } else { - txt.Text = caser.String(values.StringF(values.StrTxStatusPending, pg.txConfirmations(), pg.WL.SelectedWallet.Wallet.RequiredConfirmations())) + txt.Text = caser.String(values.StringF(values.StrTxStatusPending, pg.txConfirmations(), pg.wallet.RequiredConfirmations())) txt.Color = pg.Theme.Color.GrayText2 } return txt.Layout(gtx) }), layout.Rigid(func(gtx C) D { - if pg.txConfirmations() >= pg.WL.SelectedWallet.Wallet.RequiredConfirmations() { + if pg.txConfirmations() >= pg.wallet.RequiredConfirmations() { m := values.MarginPadding10 return layout.Inset{ Left: m, @@ -714,7 +714,7 @@ func (pg *TxDetailsPage) txnTypeAndID(gtx C) D { return D{} }), layout.Rigid(func(gtx C) D { - if pg.txConfirmations() >= pg.WL.SelectedWallet.Wallet.RequiredConfirmations() { + if pg.txConfirmations() >= pg.wallet.RequiredConfirmations() { txt := pg.Theme.Body2(values.StringF(values.StrNConfirmations, pg.txConfirmations())) txt.Color = pg.Theme.Color.GrayText2 return txt.Layout(gtx) @@ -864,7 +864,7 @@ func (pg *TxDetailsPage) txnIORow(gtx C, amount int64, acctNum int32, address st } func (pg *TxDetailsPage) showbrowserURLModal(copyredirect *cryptomaterial.Clickable) { - redirectURL := pg.WL.AssetsManager.BlockExplorerURLForTx(pg.wallet.GetAssetType(), pg.transaction.Hash) + redirectURL := pg.AssetsManager.BlockExplorerURLForTx(pg.wallet.GetAssetType(), pg.transaction.Hash) info := modal.NewCustomModal(pg.Load). Title(values.String(values.StrViewOnExplorer)). Body(values.String(values.StrCopyLink)). @@ -940,7 +940,7 @@ func (pg *TxDetailsPage) HandleUserInteractions() { pg.txBackStack = pg.transaction pg.transaction = pg.ticketSpent pg.getTXSourceAccountAndDirection() - pg.txnWidgets = initTxnWidgets(pg.Load, pg.transaction) + pg.initTxnWidgets() pg.ParentWindow().Reload() } } @@ -984,34 +984,33 @@ func (pg *TxDetailsPage) HandleUserInteractions() { // Part of the load.Page interface. func (pg *TxDetailsPage) OnNavigatedFrom() {} -func initTxnWidgets(l *load.Load, transaction *sharedW.Transaction) transactionWdg { +func (pg *TxDetailsPage) initTxnWidgets() { var txn transactionWdg - wal := l.WL.SelectedWallet.Wallet - t := time.Unix(transaction.Timestamp, 0).UTC() - txn.time = l.Theme.Body2(t.Format(time.UnixDate)) - txn.status = l.Theme.Body1("") - txn.wallet = l.Theme.Body2(wal.GetWalletName()) + t := time.Unix(pg.transaction.Timestamp, 0).UTC() + txn.time = pg.Theme.Body2(t.Format(time.UnixDate)) + txn.status = pg.Theme.Body1("") + txn.wallet = pg.Theme.Body2(pg.wallet.GetWalletName()) - if components.TxConfirmations(wal, transaction) >= l.WL.SelectedWallet.Wallet.RequiredConfirmations() { - txn.status.Text = components.FormatDateOrTime(transaction.Timestamp) - txn.confirmationIcons = l.Theme.Icons.ConfirmIcon + if components.TxConfirmations(pg.wallet, pg.transaction) >= pg.wallet.RequiredConfirmations() { + txn.status.Text = components.FormatDateOrTime(pg.transaction.Timestamp) + txn.confirmationIcons = pg.Theme.Icons.ConfirmIcon } else { txn.status.Text = values.String(values.StrPending) - txn.status.Color = l.Theme.Color.GrayText2 - txn.confirmationIcons = l.Theme.Icons.PendingIcon + txn.status.Color = pg.Theme.Color.GrayText2 + txn.confirmationIcons = pg.Theme.Icons.PendingIcon } - txStatus := components.TransactionTitleIcon(l, wal, transaction) + txStatus := components.TransactionTitleIcon(pg.Load, pg.wallet, pg.transaction) txn.txStatus = txStatus - x := len(transaction.Inputs) + len(transaction.Outputs) + x := len(pg.transaction.Inputs) + len(pg.transaction.Outputs) txn.copyTextButtons = make([]*cryptomaterial.Clickable, x) for i := 0; i < x; i++ { - txn.copyTextButtons[i] = l.Theme.NewClickable(false) + txn.copyTextButtons[i] = pg.Theme.NewClickable(false) } - return txn + pg.txnWidgets = txn } func timeString(timestamp int64) string { diff --git a/ui/page/transaction/transactions_page.go b/ui/page/transaction/transactions_page.go index cf296b8a9..2b5130c94 100644 --- a/ui/page/transaction/transactions_page.go +++ b/ui/page/transaction/transactions_page.go @@ -39,6 +39,8 @@ var txTabs = []string{ values.String(values.StrStakingActivity), } +// TransactionsPage shows transactions for a specific wallet or for all wallets. +// TODO: Add support for showing all wallet txs. type TransactionsPage struct { *load.Load // GenericPageModal defines methods such as ID() and OnAttachedToNavigator() @@ -47,6 +49,8 @@ type TransactionsPage struct { // and the root WindowNavigator. *app.GenericPageModal + selectedWallet sharedW.Asset + *listeners.TxAndBlockNotificationListener ctx context.Context // page context ctxCancel context.CancelFunc @@ -64,10 +68,11 @@ type TransactionsPage struct { materialLoader material.LoaderStyle } -func NewTransactionsPage(l *load.Load) *TransactionsPage { +func NewTransactionsPage(l *load.Load, wallet sharedW.Asset) *TransactionsPage { pg := &TransactionsPage{ Load: l, GenericPageModal: app.NewGenericPageModal(TransactionsPageID), + selectedWallet: wallet, separator: l.Theme.Separator(), transactionList: l.Theme.NewClickableList(layout.Vertical), } @@ -92,7 +97,7 @@ func (pg *TransactionsPage) OnNavigatedTo() { pg.ctx, pg.ctxCancel = context.WithCancel(context.TODO()) pg.refreshAvailableTxType() - if !pg.WL.SelectedWallet.Wallet.IsSynced() { + if !pg.selectedWallet.IsSynced() { // Events are disabled until the wallet is fully synced. return } @@ -155,7 +160,7 @@ func (pg *TransactionsPage) pageTitle(gtx C) D { } func (pg *TransactionsPage) refreshAvailableTxType() { - wal := pg.WL.SelectedWallet.Wallet + wal := pg.selectedWallet items := []cryptomaterial.DropDownItem{} _, keysinfo := components.TxPageDropDownFields(wal.GetAssetType(), pg.selectedTabIndex) for _, name := range keysinfo { @@ -190,7 +195,7 @@ func (pg *TransactionsPage) refreshAvailableTxType() { } func (pg *TransactionsPage) loadTransactions(offset, pageSize int32) ([]*sharedW.Transaction, int, bool, error) { - wal := pg.WL.SelectedWallet.Wallet + wal := pg.selectedWallet mapinfo, _ := components.TxPageDropDownFields(wal.GetAssetType(), pg.selectedTabIndex) if len(mapinfo) < 1 { err := fmt.Errorf("asset type(%v) and tab index(%d) found", wal.GetAssetType(), pg.selectedTabIndex) @@ -231,7 +236,7 @@ func (pg *TransactionsPage) Layout(gtx layout.Context) layout.Dimensions { func (pg *TransactionsPage) layoutDesktop(gtx layout.Context) layout.Dimensions { pg.scroll.OnScrollChangeListener(pg.ParentWindow()) - wal := pg.WL.SelectedWallet.Wallet + wal := pg.selectedWallet txlisingView := layout.Flexed(1, func(gtx C) D { return layout.Inset{Top: values.MarginPadding0}.Layout(gtx, func(gtx C) D { @@ -296,7 +301,7 @@ func (pg *TransactionsPage) layoutDesktop(gtx layout.Context) layout.Dimensions }) items := []layout.FlexChild{layout.Rigid(pg.pageTitle)} - if pg.WL.SelectedWallet.Wallet.GetAssetType() == utils.DCRWalletAsset { + if pg.selectedWallet.GetAssetType() == utils.DCRWalletAsset { // Layouts only supportted by DCR line := pg.Theme.Separator() line.Color = pg.Theme.Color.Gray3 @@ -308,7 +313,7 @@ func (pg *TransactionsPage) layoutDesktop(gtx layout.Context) layout.Dimensions } func (pg *TransactionsPage) layoutMobile(gtx layout.Context) layout.Dimensions { - wal := pg.WL.SelectedWallet.Wallet + wal := pg.selectedWallet container := func(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -380,7 +385,7 @@ func (pg *TransactionsPage) HandleUserInteractions() { if clicked, selectedItem := pg.transactionList.ItemClicked(); clicked { transactions := pg.scroll.FetchedData() - pg.ParentNavigator().Display(NewTransactionDetailsPage(pg.Load, transactions[selectedItem], false)) + pg.ParentNavigator().Display(NewTransactionDetailsPage(pg.Load, transactions[selectedItem], pg.selectedWallet)) } cryptomaterial.DisplayOneDropdown(pg.txTypeDropDown) @@ -396,7 +401,7 @@ func (pg *TransactionsPage) listenForTxNotifications() { return } pg.TxAndBlockNotificationListener = listeners.NewTxAndBlockNotificationListener() - err := pg.WL.SelectedWallet.Wallet.AddTxAndBlockNotificationListener(pg.TxAndBlockNotificationListener, true, TransactionsPageID) + err := pg.selectedWallet.AddTxAndBlockNotificationListener(pg.TxAndBlockNotificationListener, true, TransactionsPageID) if err != nil { log.Errorf("Error adding tx and block notification listener: %v", err) return @@ -411,7 +416,7 @@ func (pg *TransactionsPage) listenForTxNotifications() { pg.ParentWindow().Reload() } case <-pg.ctx.Done(): - pg.WL.SelectedWallet.Wallet.RemoveTxAndBlockNotificationListener(TransactionsPageID) + pg.selectedWallet.RemoveTxAndBlockNotificationListener(TransactionsPageID) pg.CloseTxAndBlockChan() pg.TxAndBlockNotificationListener = nil diff --git a/ui/preference/list_preference.go b/ui/preference/list_preference.go index efaecdbce..4b063cd60 100644 --- a/ui/preference/list_preference.go +++ b/ui/preference/list_preference.go @@ -95,11 +95,11 @@ func NewListPreference(l *load.Load, preferenceKey, defaultValue string, items [ func (lp *ListPreferenceModal) ReadPreferenceKeyedValue() string { switch lp.preferenceKey { case sharedW.CurrencyConversionConfigKey: - return lp.WL.AssetsManager.GetCurrencyConversionExchange() + return lp.AssetsManager.GetCurrencyConversionExchange() case sharedW.LanguagePreferenceKey: - return lp.WL.AssetsManager.GetLanguagePreference() + return lp.AssetsManager.GetLanguagePreference() case sharedW.LogLevelConfigKey: - return lp.WL.AssetsManager.GetLogLevels() + return lp.AssetsManager.GetLogLevels() default: return "" } @@ -109,11 +109,11 @@ func (lp *ListPreferenceModal) SavePreferenceKeyedValue() { val := lp.optionsRadioGroup.Value switch lp.preferenceKey { case sharedW.CurrencyConversionConfigKey: - lp.WL.AssetsManager.SetCurrencyConversionExchange(val) + lp.AssetsManager.SetCurrencyConversionExchange(val) case sharedW.LanguagePreferenceKey: - lp.WL.AssetsManager.SetLanguagePreference(val) + lp.AssetsManager.SetLanguagePreference(val) case sharedW.LogLevelConfigKey: - lp.WL.AssetsManager.SetLogLevels(val) + lp.AssetsManager.SetLogLevels(val) } } diff --git a/ui/window.go b/ui/window.go index c895410ce..39fa100aa 100644 --- a/ui/window.go +++ b/ui/window.go @@ -111,15 +111,10 @@ func (win *Window) NewLoad(mw *libwallet.AssetsManager, version string, buildDat th.SwitchDarkMode(isDarkModeOn, assets.DecredIcons) l := &load.Load{ - AppInfo: load.StartApp(version, buildDate), + AppInfo: load.StartApp(version, buildDate, mw), Theme: th, - WL: &load.WalletLoad{ - AssetsManager: mw, - TxAuthor: win.txAuthor, - }, - // NB: Toasts implementation is maintained here for the cases where its // very essential to have a toast UI component implementation otherwise // restraints should be exercised when planning to reuse it else where.