diff --git a/android/java/org/chromium/chrome/browser/app/domain/NetworkSelectorModel.java b/android/java/org/chromium/chrome/browser/app/domain/NetworkSelectorModel.java index 7ca17d67bf1f..58da2f4d3f5e 100644 --- a/android/java/org/chromium/chrome/browser/app/domain/NetworkSelectorModel.java +++ b/android/java/org/chromium/chrome/browser/app/domain/NetworkSelectorModel.java @@ -83,7 +83,8 @@ public void init() { // Selected local network can be "All networks" allNetworkList.add(0, allNetwork); } - updateLocalNetwork(allNetworkList, mSelectedChainId); + updateLocalNetwork(allNetworkList, mSelectedChainId, + mNetworkModel.getNetwork(mSelectedChainId).coin); return networkListsCopy; }); } @@ -146,8 +147,8 @@ public Mode getMode() { public SelectionMode getSelectionType() { return mSelectionMode; } - private void updateLocalNetwork(List networkInfos, String chainId) { - NetworkInfo networkInfo = NetworkUtils.findNetwork(networkInfos, chainId); + private void updateLocalNetwork(List networkInfos, String chainId, int coin) { + NetworkInfo networkInfo = NetworkUtils.findNetwork(networkInfos, chainId, coin); if (networkInfo != null) { _mSelectedNetwork.postValue(networkInfo); } diff --git a/android/java/org/chromium/chrome/browser/app/domain/PortfolioModel.java b/android/java/org/chromium/chrome/browser/app/domain/PortfolioModel.java index ad83bfc3fcdd..71b57d9b835a 100644 --- a/android/java/org/chromium/chrome/browser/app/domain/PortfolioModel.java +++ b/android/java/org/chromium/chrome/browser/app/domain/PortfolioModel.java @@ -126,14 +126,17 @@ private void fetchNftMetadata(List nftList, List a } else { // Other NFTs. nftDataModels.add(new NftDataModel(userAsset, - NetworkUtils.findNetwork(allNetworkList, userAsset.chainId), null)); + NetworkUtils.findNetwork( + allNetworkList, userAsset.chainId, userAsset.coin), + null)); } } } nftMetaDataHandler.setWhenAllCompletedAction(() -> { for (AsyncUtils.BaseGetNftMetadataContext metadata : nftMetadataList) { nftDataModels.add(new NftDataModel(metadata.asset, - NetworkUtils.findNetwork(allNetworkList, metadata.asset.chainId), + NetworkUtils.findNetwork( + allNetworkList, metadata.asset.chainId, metadata.asset.coin), new NftMetadata(metadata.tokenMetadata, metadata.errorCode, metadata.errorMessage))); } diff --git a/android/java/org/chromium/chrome/browser/app/domain/TransactionsModel.java b/android/java/org/chromium/chrome/browser/app/domain/TransactionsModel.java index 0023863afc6e..dc7845d41cc9 100644 --- a/android/java/org/chromium/chrome/browser/app/domain/TransactionsModel.java +++ b/android/java/org/chromium/chrome/browser/app/domain/TransactionsModel.java @@ -153,7 +153,7 @@ public void update(WeakReference activityRef) { == txNetworks.size()) { parseTransactions(mActivityRef, assetAccountsNetworkBalances, - filteredTransactions); + filteredTransactions, networkInfo.coin); } }); } @@ -165,7 +165,7 @@ public void update(WeakReference activityRef) { private void parseTransactions(WeakReference activityRef, List assetAccountsNetworkBalances, - TransactionInfo[] transactionInfoArr) { + TransactionInfo[] transactionInfoArr, int coin) { // Received balances of all network, can now fetch transaction var allAccountsArray = mAllAccountInfoList.toArray(new AccountInfo[0]); SolanaTransactionsGasHelper solanaTransactionsGasHelper = @@ -183,7 +183,7 @@ private void parseTransactions(WeakReference activityRe if (perTxSolanaFee.get(txInfo.id) != null) { solanaEstimatedTxFee = perTxSolanaFee.get(txInfo.id); } - var txNetwork = NetworkUtils.findNetwork(mAllNetworkInfoList, txInfo.chainId); + var txNetwork = NetworkUtils.findNetwork(mAllNetworkInfoList, txInfo.chainId, coin); var txExtraData = assetAccountsNetworkBalances.stream() .filter(data -> data.networkInfo.chainId.equals(txInfo.chainId)) diff --git a/android/java/org/chromium/chrome/browser/app/domain/UserAssetModel.java b/android/java/org/chromium/chrome/browser/app/domain/UserAssetModel.java index 9086d6a91eca..b5da3a0a0897 100644 --- a/android/java/org/chromium/chrome/browser/app/domain/UserAssetModel.java +++ b/android/java/org/chromium/chrome/browser/app/domain/UserAssetModel.java @@ -23,21 +23,20 @@ import org.chromium.chrome.browser.crypto_wallet.util.WalletConstants; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.stream.Stream; public class UserAssetModel { private final Object mLock = new Object(); - private BraveWalletService mBraveWalletService; - private JsonRpcService mJsonRpcService; - private BlockchainRegistry mBlockchainRegistry; + private final BraveWalletService mBraveWalletService; + private final JsonRpcService mJsonRpcService; + private final BlockchainRegistry mBlockchainRegistry; private final WalletCoinAdapter.AdapterType mType; private NetworkInfo mSelectedNetwork; private List mCryptoNetworks; - private CryptoSharedData mSharedData; - private MutableLiveData _mAssetsResult; + private final CryptoSharedData mSharedData; + private final MutableLiveData _mAssetsResult; public LiveData mAssetsResult; public UserAssetModel(BraveWalletService braveWalletService, JsonRpcService jsonRpcService, @@ -63,34 +62,20 @@ public void fetchAssets(boolean nftsOnly, NetworkInfo selectedNetwork) { if (NetworkUtils.isAllNetwork(mSelectedNetwork)) { fetchAllNetworksAssets(nftsOnly); } else { - TokenUtils.getUserAssetsFiltered(mBraveWalletService, + TokenUtils.getVisibleUserAssetsFiltered(mBraveWalletService, mSelectedNetwork, mSelectedNetwork.coin, - TokenUtils.TokenType.ALL, userAssets -> { - TokenUtils.getAllTokensFiltered(mBraveWalletService, - mBlockchainRegistry, mSelectedNetwork, - mSelectedNetwork.coin, - nftsOnly ? TokenUtils.TokenType.NFTS - : TokenUtils.TokenType.NON_NFTS, - tokens -> { - _mAssetsResult.postValue(new AssetsResult( - Arrays.asList(tokens), - Arrays.asList(userAssets))); - }); - }); + TokenUtils.TokenType.ALL, + userAssets + -> TokenUtils.getAllTokensFiltered(mBraveWalletService, + mBlockchainRegistry, mSelectedNetwork, + nftsOnly ? TokenUtils.TokenType.NFTS + : TokenUtils.TokenType.NON_NFTS, + tokens -> { + _mAssetsResult.postValue( + new AssetsResult(Arrays.asList(tokens), + Arrays.asList(userAssets))); + })); } - } else if (mType == WalletCoinAdapter.AdapterType.SEND_ASSETS_LIST) { - assert mSelectedNetwork != null; - TokenUtils.getUserAssetsFiltered(mBraveWalletService, mSelectedNetwork, - mSelectedNetwork.coin, TokenUtils.TokenType.ALL, tokens -> { - _mAssetsResult.postValue(new AssetsResult( - Arrays.asList(tokens), Collections.emptyList())); - }); - } else if (mType == WalletCoinAdapter.AdapterType.BUY_ASSETS_LIST) { - TokenUtils.getBuyTokensFiltered(mBlockchainRegistry, mSelectedNetwork, - TokenUtils.TokenType.ALL, tokens -> { - _mAssetsResult.postValue(new AssetsResult( - Arrays.asList(tokens), Collections.emptyList())); - }); } }); } diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/WalletCoinAdapter.java b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/WalletCoinAdapter.java index 361cb1d044f2..38c743a7ed58 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/WalletCoinAdapter.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/WalletCoinAdapter.java @@ -45,20 +45,18 @@ public enum AdapterType { VISIBLE_ASSETS_LIST, EDIT_VISIBLE_ASSETS_LIST, ACCOUNTS_LIST, - SELECT_ACCOUNTS_LIST, - BUY_ASSETS_LIST, - SEND_ASSETS_LIST; + SELECT_ACCOUNTS_LIST } private Context context; private List walletListItemModelList = new ArrayList<>(); - private List walletListItemModelListCopy = new ArrayList<>(); - private List mCheckedPositions = new ArrayList<>(); + private final List walletListItemModelListCopy = new ArrayList<>(); + private final List mCheckedPositions = new ArrayList<>(); private OnWalletListItemClick onWalletListItemClick; private int walletListItemType; private AdapterType mType; - private ExecutorService mExecutor; - private Handler mHandler; + private final ExecutorService mExecutor; + private final Handler mHandler; private int previousSelectedPos; public WalletCoinAdapter(AdapterType type) { @@ -78,8 +76,8 @@ public WalletCoinAdapter(AdapterType type) { @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { WalletListItemModel walletListItemModel = walletListItemModelList.get(position); - // When ViewHolder is re-used, it has the obeservers which are fired when - // we modifying checkbox. This may cause unwanted modifying of the model + // When ViewHolder is re-used, it has the observers which are fired when + // we modifying checkbox. This may cause unwanted modifying of the model. holder.resetObservers(); holder.titleText.setText(walletListItemModel.getTitle()); @@ -101,16 +99,6 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) { if (walletListItemType == Utils.TRANSACTION_ITEM) { onWalletListItemClick.onTransactionClick(walletListItemModel.getTransactionInfo()); } else if (walletListItemType == Utils.ASSET_ITEM) { - if (mType == AdapterType.BUY_ASSETS_LIST || mType == AdapterType.SEND_ASSETS_LIST) { - for (int i = 0; i < walletListItemModelListCopy.size(); i++) { - WalletListItemModel item = walletListItemModelListCopy.get(i); - if (item.getTitle().equals(holder.titleText.getText()) - || item.getSubTitle().equals(holder.subTitleText.getText())) { - mCheckedPositions.add((Integer) i); - break; - } - } - } if (mType != AdapterType.EDIT_VISIBLE_ASSETS_LIST) { onWalletListItemClick.onAssetClick(walletListItemModel.getBlockchainToken()); } @@ -161,7 +149,7 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) { holder.text2Text.setVisibility(View.GONE); if (mType == AdapterType.EDIT_VISIBLE_ASSETS_LIST) { holder.assetCheck.setVisibility(View.VISIBLE); - holder.assetCheck.setChecked(walletListItemModel.getIsUserSelected()); + holder.assetCheck.setChecked(walletListItemModel.isVisible()); holder.assetCheck.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { @Override @@ -218,11 +206,10 @@ public void onCheckedChanged( onWalletListItemClick.onMaybeShowTrashButton( walletListItemModel, holder.iconTrash); holder.iconTrash.setOnClickListener( - v -> { onWalletListItemClick.onTrashIconClick(walletListItemModel); }); + v -> onWalletListItemClick.onTrashIconClick(walletListItemModel)); } } - } else if (mType == AdapterType.ACCOUNTS_LIST - || mType == AdapterType.SELECT_ACCOUNTS_LIST) { + } else { holder.iconImg.setImageResource(android.R.color.transparent); if (walletListItemModel.getAccountInfo() != null) { Utils.setBlockiesBitmapResourceFromAccount(mExecutor, mHandler, holder.iconImg, @@ -236,14 +223,13 @@ public void onCheckedChanged( }); if (mType == AdapterType.SELECT_ACCOUNTS_LIST) { holder.ivSelected.setVisibility( - walletListItemModel.getIsUserSelected() ? View.VISIBLE : View.INVISIBLE); + walletListItemModel.isVisible() ? View.VISIBLE : View.INVISIBLE); } } } private boolean isAssetSelectionType() { - return mType == AdapterType.EDIT_VISIBLE_ASSETS_LIST || mType == AdapterType.BUY_ASSETS_LIST - || mType == AdapterType.SEND_ASSETS_LIST; + return mType == AdapterType.EDIT_VISIBLE_ASSETS_LIST; } @Override @@ -263,7 +249,7 @@ public void setWalletListItemModelList(List walletListItemM mCheckedPositions.clear(); } for (int i = 0; i < walletListItemModelListCopy.size(); i++) { - if (walletListItemModelListCopy.get(i).getIsUserSelected()) { + if (walletListItemModelListCopy.get(i).isVisible()) { mCheckedPositions.add((Integer) i); } } @@ -320,10 +306,10 @@ public void updateSelectedNetwork(String title, String subTitle) { } private void updateSelectedNetwork(int selectedAccountPosition) { - walletListItemModelList.get(previousSelectedPos).setIsUserSelected(false); + walletListItemModelList.get(previousSelectedPos).isVisible(false); notifyItemChanged(previousSelectedPos); - walletListItemModelList.get(selectedAccountPosition).setIsUserSelected(true); + walletListItemModelList.get(selectedAccountPosition).isVisible(true); previousSelectedPos = selectedAccountPosition; notifyItemChanged(selectedAccountPosition); } diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/ApproveTxBottomSheetDialogFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/ApproveTxBottomSheetDialogFragment.java index 0f90736820af..885f8ff1ab99 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/ApproveTxBottomSheetDialogFragment.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/ApproveTxBottomSheetDialogFragment.java @@ -286,8 +286,8 @@ public void setupDialog(@NonNull Dialog dialog, int style) { // First fill in data that does not require remote queries TokenUtils.getAllTokensFiltered(getBraveWalletService(), - getBlockchainRegistry(), mTxNetwork, mTxNetwork.coin, - TokenUtils.TokenType.ALL, tokenList -> { + getBlockchainRegistry(), mTxNetwork, TokenUtils.TokenType.ALL, + tokenList -> { SolanaTransactionsGasHelper solanaTransactionsGasHelper = new SolanaTransactionsGasHelper( (BraveWalletBaseActivity) getActivity(), diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/EditVisibleAssetsBottomSheetDialogFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/EditVisibleAssetsBottomSheetDialogFragment.java index 5267c0ba7154..97984bfe563b 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/EditVisibleAssetsBottomSheetDialogFragment.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/EditVisibleAssetsBottomSheetDialogFragment.java @@ -5,7 +5,8 @@ package org.chromium.chrome.browser.crypto_wallet.fragments; -import android.annotation.SuppressLint; +import static java.lang.Boolean.compare; + import android.app.Activity; import android.app.Dialog; import android.content.Context; @@ -228,15 +229,17 @@ public void onDismiss(@NonNull DialogInterface dialog) { private void setupFullHeight(BottomSheetDialog bottomSheetDialog) { FrameLayout bottomSheet = bottomSheetDialog.findViewById(R.id.design_bottom_sheet); - BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); - ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams(); + if (bottomSheet != null) { + BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); + ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams(); - int windowHeight = getWindowHeight(); - if (layoutParams != null) { - layoutParams.height = windowHeight; + int windowHeight = getWindowHeight(); + if (layoutParams != null) { + layoutParams.height = windowHeight; + } + bottomSheet.setLayoutParams(layoutParams); + behavior.setState(BottomSheetBehavior.STATE_EXPANDED); } - bottomSheet.setLayoutParams(layoutParams); - behavior.setState(BottomSheetBehavior.STATE_EXPANDED); } private int getWindowHeight() { @@ -250,9 +253,8 @@ private int getWindowHeight() { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - @SuppressLint("InflateParams") - final View view = LayoutInflater.from(getContext()) - .inflate(R.layout.edit_visible_assets_bottom_sheet, null); + final View view = + inflater.inflate(R.layout.edit_visible_assets_bottom_sheet, container, false); Button saveAssets = view.findViewById(R.id.saveAssets); TextView addCustomAsset = view.findViewById(R.id.add_custom_asset); @@ -347,7 +349,7 @@ public void onAttach(@NonNull Context context) { itemModel.setIconPath(token.logo); itemModel.setAssetNetwork(networkInfo); - itemModel.setIsUserSelected(true); + itemModel.isVisible(true); mWalletCoinAdapter.addItem(itemModel); mIsAssetsListChanged = true; } @@ -363,8 +365,10 @@ private void showAddAssetActivity() { private void setUpAssetsList( View view, List tokens, List userSelectedTokens) { HashSet selectedTokensSymbols = new HashSet<>(); - for (BlockchainToken userSelectedToken : userSelectedTokens) { - selectedTokensSymbols.add(Utils.tokenToString(userSelectedToken)); + if (!mNftsOnly) { + for (BlockchainToken userSelectedToken : userSelectedTokens) { + selectedTokensSymbols.add(Utils.tokenToString(userSelectedToken)); + } } RecyclerView rvAssets = view.findViewById(R.id.rvAssets); mWalletCoinAdapter = new WalletCoinAdapter(mType); @@ -373,8 +377,15 @@ private void setUpAssetsList( for (int i = 0; i < tokens.size(); i++) { BlockchainToken token = tokens.get(i); - NetworkInfo assetNetwork = NetworkUtils.findNetwork(mCryptoNetworks, token.chainId); - String subtitle = !isEditVisibleAssetType || assetNetwork == null + NetworkInfo assetNetwork = + NetworkUtils.findNetwork(mCryptoNetworks, token.chainId, token.coin); + if (assetNetwork == null) { + Log.e(TAG, + String.format("Asset network for token with chain Id %s was null.", + token.chainId)); + continue; + } + String subtitle = !isEditVisibleAssetType ? token.symbol : getString(R.string.brave_wallet_portfolio_asset_network_description, token.symbol, assetNetwork.chainName); @@ -385,12 +396,16 @@ private void setUpAssetsList( itemModel.setAssetNetwork(assetNetwork); itemModel.setBrowserResourcePath(tokensPath); itemModel.setIconPath("file://" + tokensPath + "/" + token.logo); - itemModel.setIsUserSelected(selectedTokensSymbols.contains(Utils.tokenToString(token))); + if (mNftsOnly) { + itemModel.isVisible(token.visible); + } else { + itemModel.isVisible(selectedTokensSymbols.contains(Utils.tokenToString(token))); + } + walletListItemModelList.add(itemModel); } walletListItemModelList.sort( - (item1, item2) - -> Boolean.compare(item2.getIsUserSelected(), item1.getIsUserSelected())); + (item1, item2) -> compare(item2.isVisible(), item1.isVisible())); mWalletCoinAdapter.setWalletListItemModelList(walletListItemModelList); mWalletCoinAdapter.setOnWalletListItemClick(this); mWalletCoinAdapter.setWalletListItemType(Utils.ASSET_ITEM); @@ -489,7 +504,19 @@ public void onAssetCheckedChanged( } BlockchainToken thisToken = walletListItemModel.getBlockchainToken(); - TokenUtils.isCustomToken(getBlockchainRegistry(), walletListItemModel.getAssetNetwork(), + final BraveWalletService braveWalletService = getBraveWalletService(); + if (braveWalletService == null) { + Log.e(TAG, "BraveWalletService was null."); + return; + } + + final BlockchainRegistry blockchainRegistry = getBlockchainRegistry(); + if (blockchainRegistry == null) { + Log.e(TAG, "BlockchainRegistry was null."); + return; + } + + TokenUtils.isCustomToken(blockchainRegistry, walletListItemModel.getAssetNetwork(), walletListItemModel.getBlockchainToken().coin, thisToken, isCustom -> { // Only show add asset dialog on click when: // 1. It is an ERC721 token @@ -498,26 +525,22 @@ public void onAssetCheckedChanged( if (thisToken.isErc721 && !isCustom && (thisToken.tokenId == null || thisToken.tokenId.trim().isEmpty())) { showAddAssetActivity(); - walletListItemModel.setIsUserSelected( + walletListItemModel.isVisible( false); // The added token is different from the listed one itemCheckboxConsistency(walletListItemModel, assetCheck, isChecked); } else { - BraveWalletService braveWalletService = getBraveWalletService(); - // TODO: all the asserts need to be removed. Shall do proper - // error handling instead. - assert braveWalletService != null; if (!isCustom) { if (isChecked) { braveWalletService.addUserAsset(thisToken, (success) -> { if (success) { - walletListItemModel.setIsUserSelected(true); + walletListItemModel.isVisible(true); } itemCheckboxConsistency(walletListItemModel, assetCheck, true); }); } else { braveWalletService.removeUserAsset(thisToken, (success) -> { if (success) { - walletListItemModel.setIsUserSelected(false); + walletListItemModel.isVisible(false); } itemCheckboxConsistency(walletListItemModel, assetCheck, false); }); @@ -526,7 +549,7 @@ public void onAssetCheckedChanged( braveWalletService.setUserAssetVisible( thisToken, isChecked, success -> { if (success) { - walletListItemModel.setIsUserSelected(isChecked); + walletListItemModel.isVisible(isChecked); } itemCheckboxConsistency( walletListItemModel, assetCheck, isChecked); @@ -539,9 +562,9 @@ public void onAssetCheckedChanged( private void itemCheckboxConsistency( WalletListItemModel walletListItemModel, CheckBox assetCheck, boolean isChecked) { - if (isChecked != walletListItemModel.getIsUserSelected()) { + if (isChecked != walletListItemModel.isVisible()) { assetCheck.setTag("noOnClickListener"); - assetCheck.setChecked(walletListItemModel.getIsUserSelected()); + assetCheck.setChecked(walletListItemModel.isVisible()); } } diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/model/WalletListItemModel.java b/android/java/org/chromium/chrome/browser/crypto_wallet/model/WalletListItemModel.java index 3e15216a7e9b..af674afd8104 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/model/WalletListItemModel.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/model/WalletListItemModel.java @@ -27,7 +27,7 @@ public class WalletListItemModel { private String mText2; private BlockchainToken mBlockchainToken; private AccountInfo mAccountInfo; - private boolean mIsUserSelected; + private boolean mVisible; private double mTotalGas; private double mTotalGasFiat; private String[] mAddressesForBitmap; @@ -193,12 +193,12 @@ public String getText2() { return mText2; } - public boolean getIsUserSelected() { - return mIsUserSelected; + public boolean isVisible() { + return mVisible; } - public void setIsUserSelected(boolean isUserSelected) { - mIsUserSelected = isUserSelected; + public void isVisible(final boolean visible) { + mVisible = visible; } public boolean isErc721() { diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/BalanceHelper.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/BalanceHelper.java index 40ff2ca527ae..501dddea973e 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/BalanceHelper.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/BalanceHelper.java @@ -256,7 +256,7 @@ private static void processP3ACoinNetworks(@CoinType.EnumType int coinType, AccountInfo[] accountInfoArray = AssetUtils.filterAccountsByNetwork( allAccounts.accounts, network.coin, network.chainId); - TokenUtils.getUserAssetsFiltered( + TokenUtils.getVisibleUserAssetsFiltered( braveWalletService, network, coinType, TokenUtils.TokenType.ALL, tokens -> { // Assets balances. GetNativeAssetsBalancesResponseContext getNativeAssetsBalancesContext = diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/NetworkUtils.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/NetworkUtils.java index 53cd85c86d53..6163e85d6577 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/NetworkUtils.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/NetworkUtils.java @@ -8,6 +8,9 @@ import android.content.Context; import android.text.TextUtils; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.chromium.brave_wallet.mojom.BraveWalletConstants; import org.chromium.brave_wallet.mojom.CoinType; import org.chromium.brave_wallet.mojom.NetworkInfo; @@ -76,7 +79,7 @@ public static NetworkInfo getAllNetworkOption(Context context) { return sAllNetworksOption; } - public static boolean isAllNetwork(NetworkInfo networkInfo) { + public static boolean isAllNetwork(@Nullable final NetworkInfo networkInfo) { if (networkInfo == null) return false; return networkInfo.chainId.equals("all"); } @@ -89,14 +92,20 @@ public static List nonTestNetwork(List networkInfos) { } /** - * Get the NetworkInfo object of given chainId - * @param networkInfos all networks - * @param chainId of network to be found - * @return found network or null + * Gets the network info object of given chainId and symbol. + * @param networks All networks available. + * @param chainId Chain Id of the network to be found. + * @param coin Coin type of the network to be found. + * @return Network info or {@code null} if the network was not found. */ - public static NetworkInfo findNetwork(List networkInfos, String chainId) { - if (networkInfos.isEmpty() || TextUtils.isEmpty(chainId)) return null; - return JavaUtils.find(networkInfos, networkInfo -> networkInfo.chainId.equals(chainId)); + @Nullable + public static NetworkInfo findNetwork( + @NonNull List networks, @Nullable String chainId, int coin) { + if (networks.isEmpty() || TextUtils.isEmpty(chainId)) { + return null; + } + return JavaUtils.find(networks, + networkInfo -> networkInfo.chainId.equals(chainId) && networkInfo.coin == coin); } public static boolean isTestNetwork(String chainId) { diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/TokenUtils.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/TokenUtils.java index 5d627b6dd9d4..b212f8107d06 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/TokenUtils.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/TokenUtils.java @@ -5,6 +5,10 @@ package org.chromium.chrome.browser.crypto_wallet.util; +import android.text.TextUtils; + +import androidx.annotation.NonNull; + import org.chromium.base.Callback; import org.chromium.brave_wallet.mojom.BlockchainRegistry; import org.chromium.brave_wallet.mojom.BlockchainToken; @@ -20,7 +24,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Locale; +import java.util.stream.Stream; public class TokenUtils { /** @@ -68,43 +72,43 @@ public enum TokenType { private static BlockchainToken[] filterTokens(NetworkInfo selectedNetwork, BlockchainToken[] tokens, TokenType tokenType, boolean keepVisibleOnly) { BlockchainToken nativeAsset = Utils.makeNetworkAsset(selectedNetwork); - ArrayList arrayTokens = new ArrayList<>(Arrays.asList(tokens)); - Utils.removeIf(arrayTokens, t -> { - boolean typeFilter; + Stream tokenStream = Arrays.stream(tokens).filter(token -> { + final boolean typeFilter; switch (tokenType) { case NFTS: - typeFilter = !t.isNft; + typeFilter = token.isNft; break; case ERC20: - typeFilter = !t.isErc20; + typeFilter = token.isErc20; break; case ERC721: - typeFilter = !t.isErc721; + typeFilter = token.isErc721; break; case SOL: - typeFilter = t.coin != CoinType.SOL; + typeFilter = token.coin == CoinType.SOL; break; case NON_NFTS: - typeFilter = t.isNft; + typeFilter = !token.isNft; break; case ALL: - typeFilter = false; + typeFilter = true; break; default: throw new UnsupportedOperationException("Token type not supported."); } - return typeFilter || isSameToken(t, nativeAsset) || (keepVisibleOnly && !t.visible); + return typeFilter && !isSameToken(token, nativeAsset) + && (!keepVisibleOnly || token.visible); }); - // The native assets are not added - // when filtering only NFTs. + // When token type is NFTS the native assets should not be added. + // For all the other cases we add them. if (tokenType != TokenType.NFTS) { - arrayTokens.add(0, nativeAsset); + tokenStream = Stream.concat(Stream.of(nativeAsset), tokenStream); } - return arrayTokens.toArray(new BlockchainToken[0]); + return tokenStream.toArray(BlockchainToken[] ::new); } - public static void getUserAssetsFiltered(BraveWalletService braveWalletService, + public static void getVisibleUserAssetsFiltered(BraveWalletService braveWalletService, NetworkInfo selectedNetwork, int coinType, TokenType tokenType, Callbacks.Callback1 callback) { braveWalletService.getUserAssets( @@ -115,56 +119,72 @@ public static void getUserAssetsFiltered(BraveWalletService braveWalletService, }); } + /* + * Wrapper for {@link BlockchainRegistry#getAllTokens} with Goerli contract address + * modifications. + * + * Note:: all calls to {@link BlockchainRegistry#getAllTokens} should be intercepted by + * this method. + */ + public static void getAllTokens(@NonNull BlockchainRegistry blockchainRegistry, String chainId, + int coinType, Callbacks.Callback1 callback) { + blockchainRegistry.getAllTokens(chainId, coinType, + tokens -> callback.call(Utils.fixupTokensRegistry(tokens, chainId))); + } + /** - * Get tokens of all networks from networkInfos list. - * @param blockchainRegistry to get tokens from core - * @param callback to get array of tokens + * Gets all tokens from each network and filters out tokens different from a given type. + * @param blockchainRegistry BraveChainRegistry to retrieve all tokens from core. + * @param networks Network list whose tokens will get retrieved and filtered. + * @param tokenType Token type used for filtering. + * @param callback Callback containing a filtered array of tokens for each network. + * Note:: It does not add user assets. */ public static void getAllTokensFiltered(BlockchainRegistry blockchainRegistry, - List networkInfos, TokenType tokenType, + List networks, TokenType tokenType, Callbacks.Callback1 callback) { AsyncUtils.MultiResponseHandler allNetworkTokenCollector = - new AsyncUtils.MultiResponseHandler(networkInfos.size()); + new AsyncUtils.MultiResponseHandler(networks.size()); ArrayList allTokenContexts = new ArrayList<>(); - for (NetworkInfo networkInfo : networkInfos) { + for (NetworkInfo networkInfo : networks) { AsyncUtils.GetNetworkAllTokensContext context = new AsyncUtils.GetNetworkAllTokensContext( allNetworkTokenCollector.singleResponseComplete, networkInfo); - blockchainRegistry.getAllTokens(networkInfo.chainId, networkInfo.coin, context); + getAllTokens(blockchainRegistry, networkInfo.chainId, networkInfo.coin, context); allTokenContexts.add(context); } - allNetworkTokenCollector.setWhenAllCompletedAction(() -> { - callback.call(allTokenContexts.stream() - .map(context - -> filterTokens(context.networkInfo, context.tokens, - tokenType, false)) - .flatMap(tokens -> Arrays.stream(tokens)) - .toArray(BlockchainToken[] ::new)); - }); + allNetworkTokenCollector.setWhenAllCompletedAction( + () + -> callback.call(allTokenContexts.stream() + .map(context + -> filterTokens(context.networkInfo, + context.tokens, tokenType, false)) + .flatMap(Arrays::stream) + .toArray(BlockchainToken[] ::new))); } - /* - * Wrapper for BlockchainRegistry.getAllTokens with Goerli contract address modifications. + /** + * Gets all tokens from a given single network, includes user assets and filters out tokens + * different from a given type. + * @param braveWalletService BraveWalletService to retrieve user asset from core. + * @param blockchainRegistry BraveChainRegistry to retrieve all tokens from core. + * @param selectedNetwork Selected network whose tokens will be retrieved. + * @param tokenType Token type used for filtering. + * @param callback Callback containing a filtered array of tokens for the given network. */ - public static void getAllTokens(BlockchainRegistry blockchainRegistry, String chainId, - int coinType, Callbacks.Callback1 callback) { - blockchainRegistry.getAllTokens(chainId, coinType, tokens -> { - tokens = Utils.fixupTokensRegistry(tokens, chainId); - callback.call(tokens); - }); - } - public static void getAllTokensFiltered(BraveWalletService braveWalletService, - BlockchainRegistry blockchainRegistry, NetworkInfo selectedNetwork, int coinType, - TokenType tokenType, Callbacks.Callback1 callback) { - getAllTokens(blockchainRegistry, selectedNetwork.chainId, coinType, tokens -> { - braveWalletService.getUserAssets(selectedNetwork.chainId, coinType, userTokens -> { - BlockchainToken[] filteredTokens = filterTokens(selectedNetwork, - distinctiveConcatenatedArrays(tokens, userTokens), tokenType, false); - callback.call(filteredTokens); - }); - }); + BlockchainRegistry blockchainRegistry, NetworkInfo selectedNetwork, TokenType tokenType, + Callbacks.Callback1 callback) { + getAllTokens(blockchainRegistry, selectedNetwork.chainId, selectedNetwork.coin, + tokens + -> braveWalletService.getUserAssets( + selectedNetwork.chainId, selectedNetwork.coin, userTokens -> { + BlockchainToken[] filteredTokens = filterTokens(selectedNetwork, + distinctiveConcatenatedArrays(tokens, userTokens), tokenType, + false); + callback.call(filteredTokens); + })); } /** @@ -201,19 +221,18 @@ public static void getUserOrAllTokensFiltered(BraveWalletService braveWalletServ Callbacks.Callback1 callback) { if (JavaUtils.anyNull(braveWalletService, blockchainRegistry)) return; if (userAssetsOnly) - getUserAssetsFiltered( + getVisibleUserAssetsFiltered( braveWalletService, selectedNetwork, coinType, tokenType, callback); else - getAllTokensFiltered(braveWalletService, blockchainRegistry, selectedNetwork, coinType, - tokenType, callback); + getAllTokensFiltered( + braveWalletService, blockchainRegistry, selectedNetwork, tokenType, callback); } private static final int[] SUPPORTED_RAMP_PROVIDERS = { OnRampProvider.RAMP, OnRampProvider.SARDINE, OnRampProvider.TRANSAK}; public static void getBuyTokensFiltered(BlockchainRegistry blockchainRegistry, - NetworkInfo selectedNetwork, TokenType tokenType, - Callbacks.Callback1 callback) { + NetworkInfo selectedNetwork, Callbacks.Callback1 callback) { int[] rampProviders = SUPPORTED_RAMP_PROVIDERS; blockchainRegistry.getProvidersBuyTokens(rampProviders, selectedNetwork.chainId, tokens -> { // blockchainRegistry.getProvidersBuyTokens returns a full list of tokens that are @@ -234,7 +253,7 @@ public static void isBuySupported(BlockchainRegistry blockchainRegistry, NetworkInfo selectedNetwork, String assetSymbol, String contractAddress, String chainId, Callback1 callback) { getBuyTokensFiltered( - blockchainRegistry, selectedNetwork, TokenUtils.TokenType.ALL, tokens -> { + blockchainRegistry, selectedNetwork, tokens -> { callback.call(JavaUtils.includes(tokens, iToken -> AssetUtils.Filters.isSameToken( @@ -242,11 +261,21 @@ public static void isBuySupported(BlockchainRegistry blockchainRegistry, }); } - public static void isCustomToken(BlockchainRegistry blockchainRegistry, - NetworkInfo selectedNetwork, int coinType, BlockchainToken token, + public static void isCustomToken(@NonNull BlockchainRegistry blockchainRegistry, + @NonNull NetworkInfo selectedNetwork, int coinType, @NonNull BlockchainToken token, Callbacks.Callback1 callback) { assert !JavaUtils.anyNull(token, selectedNetwork) : "Token or network should not be null"; if (JavaUtils.anyNull(token, selectedNetwork)) return; + + if (TextUtils.isEmpty(token.contractAddress)) { + callback.call(false); + return; + } + // Any token with a token ID should be considered a custom token + if (!TextUtils.isEmpty(token.tokenId)) { + callback.call(true); + return; + } getAllTokens(blockchainRegistry, selectedNetwork.chainId, coinType, tokens -> { boolean isCustom = true; tokens = filterTokens(selectedNetwork, tokens, TokenType.ALL, false); @@ -261,7 +290,7 @@ public static void isCustomToken(BlockchainRegistry blockchainRegistry, } /** - * Concatenate arrays, add only elements of arraySecond that are not present in the arrayFirst + * Concatenates arrays, add only elements of arraySecond that are not present in the arrayFirst * @param arrayFirst first array to be added in the result * @param arraySecond second array, only distinctive elements are added in result by comparing * with the items of arrayFirst @@ -285,26 +314,32 @@ public static BlockchainToken[] distinctiveConcatenatedArrays( } } - return both.toArray(new BlockchainToken[both.size()]); + return both.toArray(new BlockchainToken[0]); } - public static boolean isSameToken(BlockchainToken token1, BlockchainToken token2) { - if (token1.chainId.equals(token2.chainId) && token1.symbol.equals(token2.symbol) - && ((token1.tokenId.isEmpty() && token2.tokenId.isEmpty()) - || token1.tokenId.equals(token2.tokenId)) - && token1.contractAddress.toLowerCase(Locale.getDefault()) - .equals(token2.contractAddress.toLowerCase(Locale.getDefault()))) { - return true; - } - - return false; + /** + * Checks if two tokens are equal. Two tokens are equal if: + * - Chain ID matches. + * - Symbol matches. + * - Token ID matches. + * - Contract address (ignore case) matches. + * + * @param token1 First token to compare. + * @param token2 Second token to compare. + * @return {@code true} if two tokens are equal, {@code false} otherwise. + */ + public static boolean isSameToken( + @NonNull BlockchainToken token1, @NonNull BlockchainToken token2) { + return token1.chainId.equals(token2.chainId) && token1.symbol.equals(token2.symbol) + && token1.tokenId.equals(token2.tokenId) + && token1.contractAddress.equalsIgnoreCase(token2.contractAddress); } public static void getExactUserAsset(BraveWalletService braveWalletService, NetworkInfo selectedNetwork, int coinType, String assetSymbol, String assetName, String assetId, String contractAddress, int assetDecimals, Callback callback) { - getUserAssetsFiltered( + getVisibleUserAssetsFiltered( braveWalletService, selectedNetwork, coinType, TokenType.ALL, userAssets -> { BlockchainToken resultToken = null; for (BlockchainToken userAsset : userAssets) { @@ -322,7 +357,7 @@ public static void getExactUserAsset(BraveWalletService braveWalletService, }); } - private static Comparator blockchainTokenComparatorPerGasOrBatType = + private static final Comparator blockchainTokenComparatorPerGasOrBatType = (token1, token2) -> { boolean isNativeToken1 = AssetUtils.isNativeToken(token1); boolean isNativeToken2 = AssetUtils.isNativeToken(token2); diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java index 8be947d5fc03..aeaa34002c40 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java @@ -14,7 +14,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -327,23 +326,6 @@ public static void isCustomNetwork(JsonRpcService jsonRpcService, int coinType, }); } - public static String[] makeNetworksAbbrevList(Activity activity, NetworkInfo[] allNetworks) { - List categories = new ArrayList(); - - for (NetworkInfo network : allNetworks) { - // Disables localhost on Release builds - if ((network.chainId.equals(BraveWalletConstants.LOCALHOST_CHAIN_ID) - && 0 - != (activity.getApplicationInfo().flags - & ApplicationInfo.FLAG_DEBUGGABLE)) - || !network.chainId.equals(BraveWalletConstants.LOCALHOST_CHAIN_ID)) { - categories.add(getNetworkShortText(network)); - } - } - - return categories.toArray(new String[0]); - } - public static NetworkInfo getNetworkInfoByChainId( String chainId, List allNetworks) { for (NetworkInfo network : allNetworks) { @@ -1016,10 +998,6 @@ public static String getTimeframeString(int assetPriceTimeframe) { * Java port of the same function in components/brave_wallet_ui/options/asset-options.ts. */ public static BlockchainToken makeNetworkAsset(NetworkInfo network) { - String logo; - - logo = getNetworkIconName(network); - BlockchainToken asset = new BlockchainToken(); asset.name = network.symbolName; asset.symbol = network.symbol; @@ -1027,7 +1005,7 @@ public static BlockchainToken makeNetworkAsset(NetworkInfo network) { asset.isErc20 = false; asset.isErc721 = false; asset.isNft = false; - asset.logo = logo; + asset.logo = getNetworkIconName(network); asset.decimals = network.decimals; asset.visible = true; asset.chainId = network.chainId; @@ -1138,7 +1116,7 @@ public static AccountInfo findAccount(AccountInfo[] accounts, AccountId accountI public static List filterAccountsByCoin( AccountInfo[] accounts, @CoinType.EnumType int coinType) { return Arrays.stream(accounts) - .filter(account -> { return account.accountId.coin == coinType; }) + .filter(account -> account.accountId.coin == coinType) .collect(Collectors.toList()); } @@ -1256,7 +1234,8 @@ private static void workWithTransactions(BraveWalletBaseActivity activity, } var txNetwork = JavaUtils.safeVal( - NetworkUtils.findNetwork(allNetworks, txInfo.chainId), selectedNetwork); + NetworkUtils.findNetwork(allNetworks, txInfo.chainId, selectedNetwork.coin), + selectedNetwork); ParsedTransaction parsedTx = ParsedTransaction.parseTransaction(txInfo, txNetwork, accounts, assetPrices, solanaEstimatedTxFee, fullTokenList, nativeAssetsBalances, blockchainTokensBalances); @@ -1548,7 +1527,8 @@ private static WalletListItemModel mapToWalletListItemModel( Double fiatBalance = Utils.getOrDefault(perTokenFiatSum, currentAssetKey, 0.0d); String fiatBalanceString = String.format(Locale.getDefault(), "$%,.2f", fiatBalance); Double cryptoBalance = Utils.getOrDefault(perTokenCryptoSum, currentAssetKey, 0.0d); - NetworkInfo assetNetwork = NetworkUtils.findNetwork(allNetworkInfos, userAsset.chainId); + NetworkInfo assetNetwork = + NetworkUtils.findNetwork(allNetworkInfos, userAsset.chainId, userAsset.coin); String subtitle = assetNetwork == null ? userAsset.symbol : resources.getString(R.string.brave_wallet_portfolio_asset_network_description, @@ -1703,8 +1683,7 @@ public static void getP3ANetworks( } public static boolean isNativeToken(NetworkInfo selectedNetwork, BlockchainToken token) { - if (token.symbol.equals(selectedNetwork.symbol)) return true; - return false; + return token.symbol.equals(selectedNetwork.symbol); } public static int getCoinIcon(int coinType) { diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/Validations.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/Validations.java index 1872340079f8..b070ed03b7e2 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/Validations.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/Validations.java @@ -93,8 +93,7 @@ public void validate(NetworkInfo selectedNetwork, KeyringService keyringService, assert selectedNetwork != null; TokenUtils.getAllTokensFiltered(braveWalletService, blockchainRegistry, - selectedNetwork, selectedNetwork.coin, TokenUtils.TokenType.ALL, - (tokens) -> { + selectedNetwork, TokenUtils.TokenType.ALL, (tokens) -> { fillKnowContracts(tokens); checkForKnowContracts( receiverAccountAddressLower, callback, resources);