Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Fix #8160: User asset duplication caused by a new iOS17 memory leaks #8174

Merged
merged 10 commits into from
Oct 5, 2023
159 changes: 53 additions & 106 deletions Sources/BraveWallet/Crypto/Stores/AccountActivityStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import Foundation
import BraveCore

class AccountActivityStore: ObservableObject {
class AccountActivityStore: ObservableObject, WalletSubStore {
/// If we want to observe selected account changes (ex. in `WalletPanelView`).
/// In some cases, we do not want to update the account displayed when the
/// selected account changes (ex. when removing an account).
Expand Down Expand Up @@ -37,7 +37,12 @@ class AccountActivityStore: ObservableObject {
/// Cache for storing `BlockchainToken`s that are not in user assets or our token registry.
/// This could occur with a dapp creating a transaction.
private var tokenInfoCache: [String: BraveWallet.BlockchainToken] = [:]


private var keyringServiceObserver: KeyringServiceObserver?
private var rpcServiceObserver: JsonRpcServiceObserver?
private var txServiceObserver: TxServiceObserver?
private var walletServiceObserver: WalletServiceObserver?

init(
account: BraveWallet.AccountInfo,
observeAccountUpdates: Bool,
Expand All @@ -63,15 +68,57 @@ class AccountActivityStore: ObservableObject {
self.ipfsApi = ipfsApi
self.assetManager = userAssetManager

self.keyringService.add(self)
self.rpcService.add(self)
self.txService.add(self)
self.walletService.add(self)
self.keyringServiceObserver = KeyringServiceObserver(
keyringService: keyringService,
_selectedWalletAccountChanged: { [weak self] account in
guard let self else { return }
guard self.observeAccountUpdates else { return }
StephenHeaps marked this conversation as resolved.
Show resolved Hide resolved
self.account = account
self.update()
},
_selectedDappAccountChanged: { [weak self] _, account in
guard let self else { return }
guard self.observeAccountUpdates, let account else { return }
self.account = account
self.update()
}
)
self.rpcServiceObserver = JsonRpcServiceObserver(
rpcService: rpcService,
_chainChangedEvent: { [weak self] _, _, _ in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// Handle small gap between chain changing and txController having the correct chain Id
self?.update()
}
}
)
self.txServiceObserver = TxServiceObserver(
txService: txService,
_onNewUnapprovedTx: { [weak self] _ in
self?.update()
},
_onTransactionStatusChanged: { [weak self] _ in
self?.update()
}
)
self.walletServiceObserver = WalletServiceObserver(
walletService: walletService,
_onDefaultBaseCurrencyChanged: { [weak self] currency in
self?.currencyCode = currency
}
)

walletService.defaultBaseCurrency { [self] currencyCode in
self.currencyCode = currencyCode
}
}

func tearDown() {
keyringServiceObserver = nil
rpcServiceObserver = nil
txServiceObserver = nil
walletServiceObserver = nil
}

func update() {
Task { @MainActor in
Expand Down Expand Up @@ -273,103 +320,3 @@ class AccountActivityStore: ObservableObject {
}
#endif
}

extension AccountActivityStore: BraveWalletKeyringServiceObserver {
func keyringCreated(_ keyringId: BraveWallet.KeyringId) {
}

func keyringRestored(_ keyringId: BraveWallet.KeyringId) {
}

func keyringReset() {
}

func locked() {
}

func unlocked() {
}

func backedUp() {
}

func accountsChanged() {
}

func autoLockMinutesChanged() {
}

func selectedWalletAccountChanged(_ account: BraveWallet.AccountInfo) {
guard observeAccountUpdates else { return }
self.account = account
update()
}

func selectedDappAccountChanged(_ coin: BraveWallet.CoinType, account: BraveWallet.AccountInfo?) {
guard observeAccountUpdates, let account else { return }
self.account = account
update()
}

func accountsAdded(_ addedAccounts: [BraveWallet.AccountInfo]) {
}
}

extension AccountActivityStore: BraveWalletJsonRpcServiceObserver {
func chainChangedEvent(_ chainId: String, coin: BraveWallet.CoinType, origin: URLOrigin?) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// Handle small gap between chain changing and txController having the correct chain Id
self.update()
}
}
func onAddEthereumChainRequestCompleted(_ chainId: String, error: String) {
}
func onIsEip1559Changed(_ chainId: String, isEip1559: Bool) {
}
}

extension AccountActivityStore: BraveWalletTxServiceObserver {
func onNewUnapprovedTx(_ txInfo: BraveWallet.TransactionInfo) {
update()
}
func onTransactionStatusChanged(_ txInfo: BraveWallet.TransactionInfo) {
update()
}
func onUnapprovedTxUpdated(_ txInfo: BraveWallet.TransactionInfo) {
}
func onTxServiceReset() {
}
}

extension AccountActivityStore: BraveWalletBraveWalletServiceObserver {
public func onActiveOriginChanged(_ originInfo: BraveWallet.OriginInfo) {
}

public func onDefaultWalletChanged(_ wallet: BraveWallet.DefaultWallet) {
}

public func onDefaultBaseCurrencyChanged(_ currency: String) {
currencyCode = currency
}

public func onDefaultBaseCryptocurrencyChanged(_ cryptocurrency: String) {
}

public func onNetworkListChanged() {
}

func onDefaultEthereumWalletChanged(_ wallet: BraveWallet.DefaultWallet) {
}

func onDefaultSolanaWalletChanged(_ wallet: BraveWallet.DefaultWallet) {
}

public func onDiscoverAssetsStarted() {
}

func onDiscoverAssetsCompleted(_ discoveredAssets: [BraveWallet.BlockchainToken]) {
}

func onResetWallet() {
}
}
113 changes: 28 additions & 85 deletions Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ enum AssetDetailType: Identifiable {
}
}

class AssetDetailStore: ObservableObject {
class AssetDetailStore: ObservableObject, WalletSubStore {
@Published private(set) var isInitialState: Bool = true
@Published private(set) var isLoadingPrice: Bool = false
@Published private(set) var isLoadingChart: Bool = false
Expand Down Expand Up @@ -81,6 +81,9 @@ class AssetDetailStore: ObservableObject {
/// A list of tokens that are supported with the current selected network for all supported
/// on-ramp providers.
private var allBuyTokensAllOptions: [BraveWallet.OnRampProvider: [BraveWallet.BlockchainToken]] = [:]
private var keyringServiceObserver: KeyringServiceObserver?
private var txServiceObserver: TxServiceObserver?
private var walletServiceObserver: WalletServiceObserver?
let assetDetailType: AssetDetailType
var assetDetailToken: BraveWallet.BlockchainToken {
switch assetDetailType {
Expand Down Expand Up @@ -127,14 +130,35 @@ class AssetDetailStore: ObservableObject {
self.assetManager = userAssetManager
self.assetDetailType = assetDetailType

self.keyringService.add(self)
self.txService.add(self)
self.walletService.add(self)
self.keyringServiceObserver = KeyringServiceObserver(
keyringService: keyringService,
_accountsChanged: { [weak self] in
self?.update()
}
)
self.txServiceObserver = TxServiceObserver(
txService: txService,
_onTransactionStatusChanged: { [weak self] _ in
self?.update()
}
)
self.walletServiceObserver = WalletServiceObserver(
walletService: walletService,
_onDefaultBaseCurrencyChanged: { [weak self] currency in
self?.currencyCode = currency
}
)

walletService.defaultBaseCurrency { [self] currencyCode in
self.currencyCode = currencyCode
}
}

func tearDown() {
keyringServiceObserver = nil
txServiceObserver = nil
walletServiceObserver = nil
}

private let percentFormatter = NumberFormatter().then {
$0.numberStyle = .percent
Expand Down Expand Up @@ -370,84 +394,3 @@ class AssetDetailStore: ObservableObject {
}
}
}

extension AssetDetailStore: BraveWalletKeyringServiceObserver {
func keyringReset() {
}

func accountsChanged() {
update()
}

func keyringCreated(_ keyringId: BraveWallet.KeyringId) {
}

func keyringRestored(_ keyringId: BraveWallet.KeyringId) {
}

func locked() {
}

func unlocked() {
}

func backedUp() {
}

func autoLockMinutesChanged() {
}

func selectedWalletAccountChanged(_ account: BraveWallet.AccountInfo) {
}

func selectedDappAccountChanged(_ coin: BraveWallet.CoinType, account: BraveWallet.AccountInfo?) {
}

func accountsAdded(_ addedAccounts: [BraveWallet.AccountInfo]) {
}
}

extension AssetDetailStore: BraveWalletTxServiceObserver {
func onNewUnapprovedTx(_ txInfo: BraveWallet.TransactionInfo) {
}
func onUnapprovedTxUpdated(_ txInfo: BraveWallet.TransactionInfo) {
}
func onTransactionStatusChanged(_ txInfo: BraveWallet.TransactionInfo) {
update()
}
func onTxServiceReset() {
}
}

extension AssetDetailStore: BraveWalletBraveWalletServiceObserver {
public func onActiveOriginChanged(_ originInfo: BraveWallet.OriginInfo) {
}

public func onDefaultWalletChanged(_ wallet: BraveWallet.DefaultWallet) {
}

public func onDefaultBaseCurrencyChanged(_ currency: String) {
currencyCode = currency
}

public func onDefaultBaseCryptocurrencyChanged(_ cryptocurrency: String) {
}

public func onNetworkListChanged() {
}

func onDefaultEthereumWalletChanged(_ wallet: BraveWallet.DefaultWallet) {
}

func onDefaultSolanaWalletChanged(_ wallet: BraveWallet.DefaultWallet) {
}

func onDiscoverAssetsStarted() {
}

func onDiscoverAssetsCompleted(_ discoveredAssets: [BraveWallet.BlockchainToken]) {
}

func onResetWallet() {
}
}
Loading