diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni
index 25eee42375629..bfb91486639ba 100644
--- a/android/brave_java_sources.gni
+++ b/android/brave_java_sources.gni
@@ -107,6 +107,7 @@ brave_java_sources = [
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/CreateAccountBottomSheetFragment.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/EditVisibleAssetsBottomSheetDialogFragment.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java",
+ "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/SolanaTxDetailsFragment.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/SwapBottomSheetDialogFragment.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TwoLineItemFragment.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxDetailsFragment.java",
@@ -135,7 +136,6 @@ brave_java_sources = [
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/modal/DAppsDialog.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/model/CryptoAccountTypeInfo.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/model/OnboardingViewModel.java",
- "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/model/SolanaInstructionPresenter.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/model/TxNonSwipeableViewPager.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/model/WalletListItemModel.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/observers/ApprovedTxObserver.java",
@@ -143,6 +143,8 @@ brave_java_sources = [
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/observers/TxServiceObserverImpl.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/permission/BraveDappPermissionPromptDialog.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/permission/BravePermissionAccountsListAdapter.java",
+ "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/presenters/Amount.java",
+ "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/presenters/SolanaInstructionPresenter.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/util/AccountsPermissionsHelper.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/util/AddressUtils.java",
"../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/util/AndroidUtils.java",
diff --git a/android/java/AndroidManifest.xml b/android/java/AndroidManifest.xml
index 77f19cf32e16c..cd3bb3ef80859 100644
--- a/android/java/AndroidManifest.xml
+++ b/android/java/AndroidManifest.xml
@@ -97,7 +97,7 @@
tools:ignore="LockedOrientationActivity"/>
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletDAppsActivity.java b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletDAppsActivity.java
index cee111cebe77d..e62f0223731d7 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletDAppsActivity.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletDAppsActivity.java
@@ -9,6 +9,8 @@
import android.content.Intent;
import android.util.Log;
+import android.view.Window;
+import android.view.WindowManager;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
@@ -84,6 +86,9 @@ public int getValue() {
@Override
protected void triggerLayoutInflation() {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_brave_wallet_dapps);
Intent intent = getIntent();
mActivityType = ActivityType.valueOf(
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/ApproveTxFragmentPageAdapter.java b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/ApproveTxFragmentPageAdapter.java
index 9eff88cff9cf2..33532a8a6acdf 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/ApproveTxFragmentPageAdapter.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/ApproveTxFragmentPageAdapter.java
@@ -6,6 +6,7 @@
package org.chromium.chrome.browser.crypto_wallet.adapters;
import android.app.Activity;
+import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -18,8 +19,10 @@
import org.chromium.brave_wallet.mojom.NetworkInfo;
import org.chromium.brave_wallet.mojom.TransactionInfo;
import org.chromium.chrome.R;
+import org.chromium.chrome.browser.crypto_wallet.fragments.SolanaTxDetailsFragment;
import org.chromium.chrome.browser.crypto_wallet.fragments.TxDetailsFragment;
import org.chromium.chrome.browser.crypto_wallet.fragments.TxFragment;
+import org.chromium.chrome.browser.crypto_wallet.util.TransactionUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -37,6 +40,8 @@ public class ApproveTxFragmentPageAdapter extends FragmentStatePagerAdapter {
private HashMap> mBlockchainTokensBalances;
private boolean mUpdateTxObjectManually;
private long mSolanaEstimatedTxFee;
+ private Context mContext;
+ private Fragment mDetailsFragment;
public ApproveTxFragmentPageAdapter(FragmentManager fm, TransactionInfo txInfo,
NetworkInfo selectedNetwork, AccountInfo[] accounts,
@@ -52,6 +57,7 @@ public ApproveTxFragmentPageAdapter(FragmentManager fm, TransactionInfo txInfo,
mFullTokenList = fullTokenList;
mNativeAssetsBalances = nativeAssetsBalances;
mBlockchainTokensBalances = blockchainTokensBalances;
+ mContext = activity;
mTitles = new ArrayList<>(Arrays.asList(activity.getText(R.string.transaction).toString(),
activity.getText(R.string.transaction_details).toString()));
mUpdateTxObjectManually = updateTxObjectManually;
@@ -66,10 +72,23 @@ public Fragment getItem(int position) {
mFullTokenList, mNativeAssetsBalances, mBlockchainTokensBalances,
mUpdateTxObjectManually, mSolanaEstimatedTxFee);
} else {
- return TxDetailsFragment.newInstance(mTxInfo);
+ if (mDetailsFragment == null) {
+ if (TransactionUtils.isSolanaTx(mTxInfo)) {
+ mDetailsFragment = SolanaTxDetailsFragment.newInstance(mTxInfo, mContext);
+ } else {
+ mDetailsFragment = TxDetailsFragment.newInstance(mTxInfo);
+ }
+ }
+ return mDetailsFragment;
}
}
+ @Override
+ public void notifyDataSetChanged() {
+ mDetailsFragment = null;
+ super.notifyDataSetChanged();
+ }
+
@Override
public int getCount() {
return mTitles.size();
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/TwoLineItemRecyclerViewAdapter.java b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/TwoLineItemRecyclerViewAdapter.java
index 98faa84eda1b4..d20634071212d 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/TwoLineItemRecyclerViewAdapter.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/TwoLineItemRecyclerViewAdapter.java
@@ -107,6 +107,10 @@ public TwoLineItemText(String title, String subTitle) {
this.subTitle = subTitle;
}
+ public TwoLineItemText(String title) {
+ this.title = title;
+ }
+
public String getTitle() {
return title;
}
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 3a02582898f7c..3fa268034da83 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
@@ -48,6 +48,7 @@
import org.chromium.chrome.browser.crypto_wallet.adapters.ApproveTxFragmentPageAdapter;
import org.chromium.chrome.browser.crypto_wallet.listeners.TransactionConfirmationListener;
import org.chromium.chrome.browser.crypto_wallet.observers.ApprovedTxObserver;
+import org.chromium.chrome.browser.crypto_wallet.util.AndroidUtils;
import org.chromium.chrome.browser.crypto_wallet.util.ParsedTransaction;
import org.chromium.chrome.browser.crypto_wallet.util.SolanaTransactionsGasHelper;
import org.chromium.chrome.browser.crypto_wallet.util.TokenUtils;
@@ -356,27 +357,40 @@ private ParsedTransaction fillAssetDependentControls(View view, NetworkInfo sele
getResources().getString(R.string.activate_erc20), parsedTx.getSymbol()));
} else if (parsedTx.getIsSwap()) {
txType.setText(getResources().getString(R.string.swap));
+ } else if (parsedTx.isSolanaDappTransaction) {
+ txType.setText(R.string.brave_wallet_approve_transaction);
} else {
txType.setText(getResources().getString(R.string.send));
}
- String amountText =
- String.format(getResources().getString(R.string.crypto_wallet_amount_asset),
- parsedTx.formatValueToDisplay(), parsedTx.getSymbol());
- TextView fromTo = view.findViewById(R.id.from_to);
- fromTo.setText(String.format(getResources().getString(R.string.crypto_wallet_from_to),
- mAccountName, parsedTx.getSender(), parsedTx.getRecipient()));
- TextView amountAsset = view.findViewById(R.id.amount_asset);
TextView amountFiat = view.findViewById(R.id.amount_fiat);
- amountFiat.setText(
- String.format(getResources().getString(R.string.crypto_wallet_amount_fiat),
- String.format(Locale.getDefault(), "%.2f", parsedTx.getFiatTotal())));
- if (mTxInfo.txType == TransactionType.ERC721_TRANSFER_FROM
- || mTxInfo.txType == TransactionType.ERC721_SAFE_TRANSFER_FROM) {
- amountText = Utils.tokenToString(parsedTx.getErc721BlockchainToken());
- amountFiat.setVisibility(View.GONE); // Display NFT values in the future
+ TextView amountAsset = view.findViewById(R.id.amount_asset);
+ if (parsedTx.isSolanaDappTransaction) {
+ AndroidUtils.gone(amountFiat, amountAsset);
+ } else {
+ amountFiat.setText(
+ String.format(getResources().getString(R.string.crypto_wallet_amount_fiat),
+ String.format(Locale.getDefault(), "%.2f", parsedTx.getFiatTotal())));
+ String amountText =
+ String.format(getResources().getString(R.string.crypto_wallet_amount_asset),
+ parsedTx.formatValueToDisplay(), parsedTx.getSymbol());
+
+ if (mTxInfo.txType == TransactionType.ERC721_TRANSFER_FROM
+ || mTxInfo.txType == TransactionType.ERC721_SAFE_TRANSFER_FROM) {
+ amountText = Utils.tokenToString(parsedTx.getErc721BlockchainToken());
+ amountFiat.setVisibility(View.GONE); // Display NFT values in the future
+ }
+ amountAsset.setText(amountText);
+ }
+
+ TextView fromTo = view.findViewById(R.id.from_to);
+ if (parsedTx.getSender() != null && !parsedTx.getSender().equals(parsedTx.getRecipient())) {
+ fromTo.setText(String.format(getResources().getString(R.string.crypto_wallet_from_to),
+ mAccountName, parsedTx.getSender(), "->", parsedTx.getRecipient()));
+ } else {
+ fromTo.setText(String.format(getResources().getString(R.string.crypto_wallet_from_to),
+ mAccountName, parsedTx.getSender(), "", ""));
}
- amountAsset.setText(amountText);
setupPager(view, selectedNetwork, accounts, assetPrices, fullTokenList,
nativeAssetsBalances, blockchainTokensBalances);
return parsedTx;
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/SolanaTxDetailsFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/SolanaTxDetailsFragment.java
new file mode 100644
index 0000000000000..821466f01f1df
--- /dev/null
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/SolanaTxDetailsFragment.java
@@ -0,0 +1,39 @@
+/* Copyright (c) 2022 The Brave Authors. All rights reserved.
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.chromium.chrome.browser.crypto_wallet.fragments;
+
+import android.content.Context;
+
+import androidx.fragment.app.Fragment;
+
+import org.chromium.brave_wallet.mojom.SolanaInstruction;
+import org.chromium.brave_wallet.mojom.TransactionInfo;
+import org.chromium.chrome.browser.crypto_wallet.adapters.TwoLineItemRecyclerViewAdapter;
+import org.chromium.chrome.browser.crypto_wallet.presenters.SolanaInstructionPresenter;
+import org.chromium.chrome.browser.crypto_wallet.util.TransactionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SolanaTxDetailsFragment {
+ public static Fragment newInstance(TransactionInfo txInfo, Context context) {
+ List details = new ArrayList<>();
+ SolanaInstruction[] instructions =
+ TransactionUtils.safeSolData(txInfo.txDataUnion).instructions;
+ details.add(new TwoLineItemRecyclerViewAdapter.TwoLineItemText(
+ context.getString(TransactionUtils.getTxType(txInfo))));
+
+ for (SolanaInstruction solanaInstruction : instructions) {
+ SolanaInstructionPresenter solanaInstructionPresenter =
+ new SolanaInstructionPresenter(solanaInstruction);
+ details.addAll(solanaInstructionPresenter.toTwoLineList(context));
+ if (instructions.length > 1) {
+ details.add(new TwoLineItemRecyclerViewAdapter.TwoLineItemDivider());
+ }
+ }
+ return new TwoLineItemFragment(details);
+ }
+}
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TwoLineItemFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TwoLineItemFragment.java
index 9340353a138de..a306c7a3c7742 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TwoLineItemFragment.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TwoLineItemFragment.java
@@ -8,6 +8,7 @@
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -37,6 +38,7 @@ public static TwoLineItemFragment newInstance(List items) {
return fragment;
}
+ @SuppressLint("ClickableViewAccessibility")
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -44,6 +46,24 @@ public View onCreateView(
RecyclerView recyclerView = (RecyclerView) view;
adapter = new TwoLineItemRecyclerViewAdapter(items);
recyclerView.setAdapter(adapter);
+ recyclerView.setOnTouchListener((v, event) -> {
+ int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ // Disallow NestedScrollView to intercept touch events.
+ v.getParent().requestDisallowInterceptTouchEvent(true);
+ break;
+
+ case MotionEvent.ACTION_UP:
+ // Allow NestedScrollView to intercept touch events.
+ v.getParent().requestDisallowInterceptTouchEvent(false);
+ break;
+ }
+
+ // Handle RecyclerView touch events.
+ v.onTouchEvent(event);
+ return true;
+ });
return view;
}
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxDetailsFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxDetailsFragment.java
index 95273e18f6965..c409475a9b6e2 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxDetailsFragment.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxDetailsFragment.java
@@ -24,6 +24,7 @@
import org.chromium.brave_wallet.mojom.TxData1559;
import org.chromium.brave_wallet.mojom.TxDataUnion;
import org.chromium.chrome.R;
+import org.chromium.chrome.browser.crypto_wallet.util.TransactionUtils;
import org.chromium.chrome.browser.crypto_wallet.util.Utils;
public class TxDetailsFragment extends Fragment {
@@ -59,35 +60,7 @@ public void setupView(View view) {
return;
}
assert mTxInfo.txParams.length == mTxInfo.txArgs.length;
- String functionType = getResources().getString(R.string.wallet_details_function_type_other);
- switch (mTxInfo.txType) {
- case TransactionType.ERC20_TRANSFER:
- functionType = getResources().getString(
- R.string.wallet_details_function_type_erc20transfer);
- break;
- case TransactionType.ERC20_APPROVE:
- functionType = getResources().getString(
- R.string.wallet_details_function_type_erc20approve);
- break;
- case TransactionType.ERC721_TRANSFER_FROM:
- functionType = getResources().getString(
- R.string.wallet_details_function_type_erc721transfer);
- break;
- case TransactionType.SOLANA_SYSTEM_TRANSFER:
- functionType = getResources().getString(
- R.string.wallet_details_function_type_solana_system_transfer);
- break;
- case TransactionType.SOLANA_SPL_TOKEN_TRANSFER:
- functionType = getResources().getString(
- R.string.wallet_details_function_type_spl_token_transfer);
- break;
- case TransactionType.SOLANA_SPL_TOKEN_TRANSFER_WITH_ASSOCIATED_TOKEN_ACCOUNT_CREATION:
- functionType = getResources().getString(
- R.string.wallet_details_function_type_solana_spl_token_transfer_with_associated_token_account_creation);
- break;
- default:
- break;
- }
+ String functionType = getString(TransactionUtils.getTxType(mTxInfo));
TextView functionTypeWidget = view.findViewById(R.id.function_type);
functionTypeWidget.setText(String.format(
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxFragment.java
index d4500b925edc4..071167be6c989 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxFragment.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/TxFragment.java
@@ -25,20 +25,21 @@
import androidx.fragment.app.Fragment;
import org.chromium.brave_wallet.mojom.AccountInfo;
-import org.chromium.brave_wallet.mojom.AssetPriceTimeframe;
import org.chromium.brave_wallet.mojom.BlockchainToken;
import org.chromium.brave_wallet.mojom.CoinType;
import org.chromium.brave_wallet.mojom.EthTxManagerProxy;
import org.chromium.brave_wallet.mojom.NetworkInfo;
+import org.chromium.brave_wallet.mojom.SolanaSendTransactionOptions;
+import org.chromium.brave_wallet.mojom.SolanaTxData;
import org.chromium.brave_wallet.mojom.TransactionInfo;
-import org.chromium.brave_wallet.mojom.TransactionType;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.crypto_wallet.activities.AdvanceTxSettingActivity;
-import org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletActivity;
import org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletBaseActivity;
-import org.chromium.chrome.browser.crypto_wallet.activities.BuySendSwapActivity;
+import org.chromium.chrome.browser.crypto_wallet.presenters.Amount;
+import org.chromium.chrome.browser.crypto_wallet.util.AndroidUtils;
import org.chromium.chrome.browser.crypto_wallet.util.ParsedTransaction;
import org.chromium.chrome.browser.crypto_wallet.util.ParsedTransactionFees;
+import org.chromium.chrome.browser.crypto_wallet.util.TransactionUtils;
import org.chromium.chrome.browser.crypto_wallet.util.Utils;
import org.chromium.chrome.browser.crypto_wallet.util.WalletConstants;
@@ -64,6 +65,7 @@ public class TxFragment extends Fragment {
// don't use them. It would be good to eventually migrate to observers everywhere.
private boolean mUpdateTxObjectManually;
public static final int START_ADVANCE_SETTING_ACTIVITY_CODE = 0;
+ private boolean mIsSolanaInstruction;
public static TxFragment newInstance(TransactionInfo txInfo, NetworkInfo selectedNetwork,
AccountInfo[] accounts, HashMap assetPrices,
@@ -99,6 +101,7 @@ private TxFragment(TransactionInfo txInfo, NetworkInfo selectedNetwork, AccountI
mPreviousCheckedPriorityId = -1;
mUpdateTxObjectManually = updateTxObjectManually;
mSolanaEstimatedTxFee = solanaEstimatedTxFee;
+ mIsSolanaInstruction = TransactionUtils.isSolanaTx(txInfo);
}
@Override
@@ -116,7 +119,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
View advanceSettingContainer = view.findViewById(R.id.fragment_tx_tv_advance_setting);
advanceSettingContainer.setVisibility(
- isAdvanceSettingEnabled(mSelectedNetwork) ? View.VISIBLE : View.INVISIBLE);
+ isAdvanceSettingEnabled(mSelectedNetwork) ? View.VISIBLE : View.GONE);
advanceSettingContainer.setOnClickListener(v -> {
Intent toAdvanceTxSetting =
@@ -407,27 +410,66 @@ private void setupView(View view) {
mAssetPrices, mSolanaEstimatedTxFee, mFullTokenList, mNativeAssetsBalances,
mBlockchainTokensBalances);
+ if (mIsSolanaInstruction) {
+ TextView gasTxTv = view.findViewById(R.id.frag_tx_tv_gas);
+ TextView totalHeading = view.findViewById(R.id.frag_tx_tv_total_heading);
+
+ gasTxTv.setText(R.string.brave_wallet_allow_spend_transaction_fee);
+ totalHeading.setText(R.string.brave_wallet_confirm_transaction_amount_fee);
+ SolanaTxData solanaTxData = TransactionUtils.safeSolData(mTxInfo.txDataUnion);
+ if (solanaTxData != null && solanaTxData.sendOptions != null) {
+ SolanaSendTransactionOptions sendTxOptions = solanaTxData.sendOptions;
+ LinearLayout sendOptionsLinearLayout =
+ view.findViewById(R.id.frag_tx_ll_send_options);
+ if (sendTxOptions.maxRetries != null) {
+ TextView tvLabel = AndroidUtils.makeHeaderTv(requireContext());
+ TextView tvVal = AndroidUtils.makeSubHeaderTv(requireContext());
+ tvLabel.setText(R.string.brave_wallet_solana_max_retries);
+ tvVal.setText(String.valueOf(sendTxOptions.maxRetries.maxRetries));
+ sendOptionsLinearLayout.addView(tvLabel);
+ sendOptionsLinearLayout.addView(tvVal);
+ }
+ if (sendTxOptions.preflightCommitment != null) {
+ TextView tvLabel = AndroidUtils.makeHeaderTv(requireContext());
+ TextView tvVal = AndroidUtils.makeSubHeaderTv(requireContext());
+ tvLabel.setText(R.string.brave_wallet_solana_preflight_commitment);
+ tvVal.setText(sendTxOptions.preflightCommitment);
+ sendOptionsLinearLayout.addView(tvLabel);
+ sendOptionsLinearLayout.addView(tvVal);
+ }
+ if (sendTxOptions.skipPreflight != null) {
+ TextView tvLabel = AndroidUtils.makeHeaderTv(requireContext());
+ TextView tvVal = AndroidUtils.makeSubHeaderTv(requireContext());
+ tvLabel.setText(R.string.brave_wallet_solana_skip_preflight);
+ tvVal.setText(String.valueOf(sendTxOptions.skipPreflight.skipPreflight));
+ sendOptionsLinearLayout.addView(tvLabel);
+ sendOptionsLinearLayout.addView(tvVal);
+ }
+ }
+ }
TextView gasFeeAmount = view.findViewById(R.id.gas_fee_amount);
final double totalGas = mParsedTx.getGasFee();
- gasFeeAmount.setText(String.format(
- getResources().getString(R.string.crypto_wallet_gas_fee_amount),
- String.format(Locale.getDefault(), "%.8f", totalGas), mSelectedNetwork.symbol));
+ String symbol =
+ mParsedTx.getSymbol() == null ? mParsedTx.getSymbol() : mSelectedNetwork.symbol;
+ gasFeeAmount.setText(
+ String.format(getResources().getString(R.string.crypto_wallet_gas_fee_amount),
+ String.format(Locale.getDefault(), "%.8f", totalGas), symbol));
String valueAssetText = mParsedTx.formatValueToDisplay();
TextView totalAmount = view.findViewById(R.id.total_amount);
- totalAmount.setText(String.format(
- getResources().getString(R.string.crypto_wallet_total_amount), valueAssetText,
- mParsedTx.getSymbol(), String.format(Locale.getDefault(), "%.8f", totalGas),
- mSelectedNetwork.symbol));
+ totalAmount.setText(
+ String.format(getResources().getString(R.string.crypto_wallet_total_amount),
+ valueAssetText, mParsedTx.getSymbol(),
+ String.format(Locale.getDefault(), "%.8f", totalGas), symbol));
TextView gasFeeAmountFiat = view.findViewById(R.id.gas_fee_amount_fiat);
gasFeeAmountFiat.setText(
String.format(getResources().getString(R.string.crypto_wallet_amount_fiat),
- String.format(Locale.getDefault(), "%.2f", mParsedTx.getGasFeeFiat())));
+ new Amount(mParsedTx.getFiatTotal()).toStringFormat()));
TextView totalAmountFiat = view.findViewById(R.id.total_amount_fiat);
totalAmountFiat.setText(
String.format(getResources().getString(R.string.crypto_wallet_amount_fiat),
- String.format(Locale.getDefault(), "%.2f", mParsedTx.getFiatTotal())));
+ new Amount(mParsedTx.getFiatTotal()).toStringFormat()));
}
@Override
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/dapps/SignTransactionFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/dapps/SignTransactionFragment.java
index d9911cfc3f55e..b820f63199e8b 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/dapps/SignTransactionFragment.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/dapps/SignTransactionFragment.java
@@ -38,7 +38,7 @@
import org.chromium.chrome.browser.crypto_wallet.adapters.TwoLineItemRecyclerViewAdapter;
import org.chromium.chrome.browser.crypto_wallet.adapters.TwoLineItemRecyclerViewAdapter.TwoLineItem;
import org.chromium.chrome.browser.crypto_wallet.fragments.TwoLineItemFragment;
-import org.chromium.chrome.browser.crypto_wallet.model.SolanaInstructionPresenter;
+import org.chromium.chrome.browser.crypto_wallet.presenters.SolanaInstructionPresenter;
import org.chromium.chrome.browser.crypto_wallet.util.NavigationItem;
import org.chromium.chrome.browser.crypto_wallet.util.TransactionUtils;
import org.chromium.chrome.browser.crypto_wallet.util.Utils;
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/modal/BraveWalletPanel.java b/android/java/org/chromium/chrome/browser/crypto_wallet/modal/BraveWalletPanel.java
index ae8c676d3b5fb..810da66f4baff 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/modal/BraveWalletPanel.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/modal/BraveWalletPanel.java
@@ -87,7 +87,7 @@ public class BraveWalletPanel implements DialogInterface {
private WalletModel mWalletModel;
private AccountInfo mSelectedAccount;
private NetworkInfo mSelectedNetwork;
- private Observer mAccountInfoObserver = accountInfo -> {
+ private final Observer mAccountInfoObserver = accountInfo -> {
if (accountInfo == null) return;
mSelectedAccount = accountInfo;
mBraveWalletPanelServices.getKeyringService().getKeyringInfo(
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/presenters/Amount.java b/android/java/org/chromium/chrome/browser/crypto_wallet/presenters/Amount.java
new file mode 100644
index 0000000000000..8a6280c2a68a0
--- /dev/null
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/presenters/Amount.java
@@ -0,0 +1,79 @@
+/* Copyright (c) 2022 The Brave Authors. All rights reserved.
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.chromium.chrome.browser.crypto_wallet.presenters;
+
+import android.text.TextUtils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+public class Amount {
+ private BigDecimal mValue;
+
+ public Amount(BigDecimal value) {
+ if (value == null) {
+ this.mValue = BigDecimal.ZERO;
+ return;
+ }
+ this.mValue = value;
+ }
+
+ public Amount(String value) {
+ if (TextUtils.isEmpty(value)) {
+ this.mValue = BigDecimal.ZERO;
+ return;
+ }
+ this.mValue = new BigDecimal(value);
+ }
+
+ public Amount(double value) {
+ this.mValue = new BigDecimal(value);
+ }
+
+ public Amount add(BigDecimal value) {
+ BigDecimal safeVal = safeVal(value);
+ mValue = mValue.add(safeVal);
+ return this;
+ }
+
+ public Amount add(Amount value) {
+ BigDecimal safeVal = safeVal(value);
+ mValue = mValue.add(safeVal);
+ return this;
+ }
+
+ // Default max decimal precision is 8
+ public String toStringFormat() {
+ return toStringFormat(8);
+ }
+
+ public String toStringFormat(int decimalLength) {
+ return mValue.setScale(decimalLength, RoundingMode.HALF_UP)
+ .stripTrailingZeros()
+ .toPlainString();
+ }
+
+ public String toHex() {
+ if (mValue.signum() == 0) return "0x0";
+ return "0x" + mValue.toBigInteger().toString(16);
+ }
+
+ private static BigDecimal safeVal(BigDecimal value) {
+ return (value == null) ? BigDecimal.ZERO : value;
+ }
+
+ private static BigDecimal safeVal(Amount value) {
+ return (value != null && value.mValue != null) ? value.mValue : BigDecimal.ZERO;
+ }
+
+ private void safeInit() {
+ if (mValue == null) mValue = BigDecimal.ZERO;
+ }
+
+ public BigDecimal getValue() {
+ return BigDecimal.valueOf(mValue.doubleValue());
+ }
+}
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/model/SolanaInstructionPresenter.java b/android/java/org/chromium/chrome/browser/crypto_wallet/presenters/SolanaInstructionPresenter.java
similarity index 70%
rename from android/java/org/chromium/chrome/browser/crypto_wallet/model/SolanaInstructionPresenter.java
rename to android/java/org/chromium/chrome/browser/crypto_wallet/presenters/SolanaInstructionPresenter.java
index fb5e9a74b04d4..cf0ac7cbaeec1 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/model/SolanaInstructionPresenter.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/presenters/SolanaInstructionPresenter.java
@@ -1,6 +1,12 @@
-package org.chromium.chrome.browser.crypto_wallet.model;
+/* Copyright (c) 2022 The Brave Authors. All rights reserved.
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.chromium.chrome.browser.crypto_wallet.presenters;
import android.content.Context;
+import android.text.TextUtils;
import org.chromium.brave_wallet.mojom.CoinType;
import org.chromium.brave_wallet.mojom.SolanaAccountMeta;
@@ -9,7 +15,6 @@
import org.chromium.brave_wallet.mojom.SolanaInstructionParam;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.crypto_wallet.adapters.TwoLineItemRecyclerViewAdapter.TwoLineItem;
-import org.chromium.chrome.browser.crypto_wallet.adapters.TwoLineItemRecyclerViewAdapter.TwoLineItemDivider;
import org.chromium.chrome.browser.crypto_wallet.adapters.TwoLineItemRecyclerViewAdapter.TwoLineItemHeader;
import org.chromium.chrome.browser.crypto_wallet.adapters.TwoLineItemRecyclerViewAdapter.TwoLineItemText;
import org.chromium.chrome.browser.crypto_wallet.util.TransactionUtils;
@@ -26,6 +31,9 @@ public class SolanaInstructionPresenter {
public boolean mIsUnknown;
private boolean isDecodedDataPresent;
private SolanaInstruction mSolanaInstruction;
+ private Integer mInstructionType;
+ private String mFromPubKey;
+ private String mToPubKey;
public SolanaInstructionPresenter(SolanaInstruction solanaInstruction) {
assert solanaInstruction != null : "solanaInstruction is null";
@@ -74,7 +82,7 @@ public List toTwoLineList(Context context) {
TransactionUtils.getSolanaProgramIdName(mSolanaInstruction.programId, context)
+ " - "
+ context.getString(
- TransactionUtils.getSolType(mSolanaInstruction.programId,
+ TransactionUtils.getSolTxSubType(mSolanaInstruction.programId,
mSolanaInstruction.decodedData != null
? mSolanaInstruction.decodedData.instructionType
: -1)),
@@ -87,10 +95,14 @@ public List toTwoLineList(Context context) {
twoLineItems.addAll(solanaInstructionPresenter.accountDataToList());
if (shouldShowRawData()) {
- // add data field also
+ // Add data and program id field also
twoLineItems.add(
new TwoLineItemHeader(context.getString(R.string.brave_wallet_data_text)));
twoLineItems.addAll(solanaInstructionPresenter.dataToList());
+
+ twoLineItems.add(
+ new TwoLineItemHeader(context.getString(R.string.brave_wallet_tx_progam_id)));
+ twoLineItems.addAll(solanaInstructionPresenter.programIdToList());
}
twoLineItems.addAll(solanaInstructionPresenter.accountParamDataToList());
return twoLineItems;
@@ -128,18 +140,84 @@ public List accountParamDataToList() {
return twoLineItemDataSources;
}
+ public List programIdToList() {
+ return Arrays.asList(new TwoLineItemText(null, mSolanaInstruction.programId));
+ }
+
public List dataToList() {
return Arrays.asList(new TwoLineItemText(null, Arrays.toString(mSolanaInstruction.data)));
}
+ // Get lamport from decoded data params
+ public String getLamportAmount() {
+ if (isDecodedDataPresent && mSolanaInstruction.decodedData.params != null) {
+ for (SolanaInstructionParam instructionParam : mSolanaInstruction.decodedData.params) {
+ if (instructionParam.name.equalsIgnoreCase(WalletConstants.SOL_LAMPORTS)) {
+ return instructionParam.value;
+ }
+ }
+ }
+ return "0";
+ }
+
+ public Integer getInstructionType() {
+ if (mInstructionType != null) return mInstructionType;
+ if (isDecodedDataPresent) {
+ mInstructionType = mSolanaInstruction.decodedData.instructionType;
+ return mInstructionType;
+ }
+ return null;
+ }
+
+ public String fromPubKey() {
+ if (mFromPubKey != null) return mFromPubKey;
+ mFromPubKey = getPubKeyPerParamKey(WalletConstants.SOL_DAPP_FROM_ACCOUNT);
+ return mFromPubKey;
+ }
+
+ public String toPubKey() {
+ if (mToPubKey != null) return mToPubKey;
+ mToPubKey = getPubKeyPerParamKey(WalletConstants.SOL_DAPP_TO_ACCOUNT);
+ return mToPubKey;
+ }
+
+ // Returns the first found account pub key from accounts meta, corresponding to input "key" from
+ // accountParams
+ public String getPubKeyPerParamKey(String key) {
+ if (TextUtils.isEmpty(key)) return null;
+ String pubKey = null;
+ if (isAccountMetaPresent()) {
+ SolanaInstructionAccountParam[] accountParams =
+ mSolanaInstruction.decodedData.accountParams;
+ for (int i = 0; i < accountParams.length; i++) {
+ if (accountParams[i].name.equalsIgnoreCase(key)) {
+ if (mSolanaInstruction.accountMetas.length > i) {
+ pubKey = mSolanaInstruction.accountMetas[i].pubkey;
+ }
+ return pubKey;
+ }
+ }
+ }
+ return pubKey;
+ }
+
public SolanaInstruction getSolanaInstruction() {
return mSolanaInstruction;
}
+ public boolean isTokenInstruction() {
+ return mSolanaInstruction.programId.equals(WalletConstants.SOL_INS_TOKEN);
+ }
+
public boolean shouldShowRawData() {
return mIsUnknown || mSolanaInstruction.decodedData == null;
}
+ private boolean isAccountMetaPresent() {
+ return isDecodedDataPresent && mSolanaInstruction.decodedData.accountParams != null
+ && mSolanaInstruction.accountMetas != null;
+ }
+
public static class SolanaInstructionAccountPresenter {
public String mPubKey;
public String mLocalizeAccountHeader;
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/AndroidUtils.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/AndroidUtils.java
index add666f4ab533..295270aa4403b 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/AndroidUtils.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/AndroidUtils.java
@@ -1,14 +1,18 @@
package org.chromium.chrome.browser.crypto_wallet.util;
import android.content.Context;
+import android.graphics.Typeface;
import android.os.Build;
import android.text.Html;
import android.text.Spanned;
import android.util.TypedValue;
import android.view.View;
+import android.widget.TextView;
import androidx.annotation.IdRes;
+import org.chromium.chrome.R;
+
public class AndroidUtils {
public static int getToolBarHeight(Context context) {
TypedValue tv = new TypedValue();
@@ -43,4 +47,35 @@ public static Spanned formatHTML(String html) {
return Html.fromHtml(html);
}
}
+
+ // Views
+ public static TextView makeHeaderTv(Context context) {
+ TextView textView = new TextView(context);
+ textView.setTextAppearance(R.style.BraveWalletTextViewTitle);
+ textView.setTypeface(null, Typeface.BOLD);
+ textView.setId(View.generateViewId());
+ return textView;
+ }
+
+ public static TextView makeSubHeaderTv(Context context) {
+ TextView textView = new TextView(context);
+ textView.setTextAppearance(R.style.BraveWalletTextViewSubTitle);
+ textView.setId(View.generateViewId());
+ return textView;
+ }
+
+ public static void gone(View... views) {
+ setViewVisibility(false, views);
+ }
+
+ public static void show(View... views) {
+ setViewVisibility(true, views);
+ }
+
+ private static void setViewVisibility(boolean isVisible, View... views) {
+ int visibility = isVisible ? View.VISIBLE : View.GONE;
+ for (View view : views) {
+ view.setVisibility(visibility);
+ }
+ }
}
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransaction.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransaction.java
index 35184c92c488e..6f59a68161863 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransaction.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransaction.java
@@ -5,26 +5,30 @@
package org.chromium.chrome.browser.crypto_wallet.util;
+import static org.chromium.chrome.browser.crypto_wallet.util.WalletConstants.SOLANA_TRANSACTION_TYPES;
+
import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
import android.util.Pair;
-import org.chromium.base.Log;
import org.chromium.brave_wallet.mojom.AccountInfo;
import org.chromium.brave_wallet.mojom.BlockchainToken;
-import org.chromium.brave_wallet.mojom.CoinType;
import org.chromium.brave_wallet.mojom.FilTxData;
import org.chromium.brave_wallet.mojom.NetworkInfo;
+import org.chromium.brave_wallet.mojom.SolanaInstruction;
+import org.chromium.brave_wallet.mojom.SolanaSystemInstruction;
+import org.chromium.brave_wallet.mojom.SolanaTokenInstruction;
import org.chromium.brave_wallet.mojom.SolanaTxData;
import org.chromium.brave_wallet.mojom.TransactionInfo;
-import org.chromium.brave_wallet.mojom.TransactionStatus;
import org.chromium.brave_wallet.mojom.TransactionType;
-import org.chromium.brave_wallet.mojom.TxData;
import org.chromium.brave_wallet.mojom.TxData1559;
import org.chromium.brave_wallet.mojom.TxDataUnion;
import org.chromium.chrome.R;
-import org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletBaseActivity;
+import org.chromium.chrome.browser.crypto_wallet.presenters.SolanaInstructionPresenter;
import org.chromium.mojo_base.mojom.TimeDelta;
+import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -33,6 +37,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -78,6 +83,9 @@ public class ParsedTransaction extends ParsedTransactionFees {
private BlockchainToken buyToken;
private double minBuyAmount;
+ // Solana
+ public boolean isSolanaDappTransaction;
+
// There are too many fields to init here
private ParsedTransaction(ParsedTransactionFees parsedTransactionFees) {
super(parsedTransactionFees.getGasLimit(), parsedTransactionFees.getGasPrice(),
@@ -89,126 +97,6 @@ private ParsedTransaction(ParsedTransactionFees parsedTransactionFees) {
parsedTransactionFees.getGasPremium(), parsedTransactionFees.getGasFeeCap());
}
- public String getHash() {
- return this.hash;
- }
-
- public String getNonce() {
- return this.nonce;
- }
-
- public TimeDelta getCreatedTime() {
- return this.createdTime;
- }
-
- public int getStatus() {
- return this.status;
- }
-
- public int getType() {
- return this.type;
- }
-
- public String getSender() {
- return this.sender;
- }
-
- public String getSenderLabel() {
- return this.senderLabel;
- }
-
- public String getRecipient() {
- return this.recipient;
- }
-
- public String getRecipientLabel() {
- return this.recipientLabel;
- }
-
- public double getFiatValue() {
- return this.fiatValue;
- }
-
- public double getFiatTotal() {
- return this.fiatTotal;
- }
-
- public double getNativeCurrencyTotal() {
- return this.nativeCurrencyTotal;
- }
-
- public double getValue() {
- return this.value;
- }
-
- public String getSymbol() {
- return this.symbol;
- }
-
- public BlockchainToken getToken() {
- return this.token;
- }
-
- public int getDecimals() {
- return this.decimals;
- }
-
- public boolean getInsufficientFundsForGasError() {
- return this.insufficientFundsForGasError;
- }
-
- public boolean getInsufficientFundsError() {
- return this.insufficientFundsError;
- }
-
- public String getContractAddressError() {
- return this.contractAddressError;
- }
-
- public String getSameAddressError() {
- return this.sameAddressError;
- }
-
- public BlockchainToken getErc721BlockchainToken() {
- return this.erc721BlockchainToken;
- }
-
- public String getErc721TokenId() {
- return this.erc721TokenId;
- }
-
- public boolean getIsSwap() {
- return this.isSwap;
- }
-
- public String getApprovalTarget() {
- return this.approvalTarget;
- }
-
- public String getApprovalTargetLabel() {
- return this.approvalTargetLabel;
- }
-
- public boolean getIsApprovalUnlimited() {
- return this.isApprovalUnlimited;
- }
-
- public BlockchainToken getSellToken() {
- return this.sellToken;
- }
-
- public double getSellAmount() {
- return this.sellAmount;
- }
-
- public BlockchainToken getBuyToken() {
- return this.buyToken;
- }
-
- public double getMinBuyAmount() {
- return this.minBuyAmount;
- }
-
private static BlockchainToken findToken(
BlockchainToken[] fullTokenList, String contractAddress) {
if (contractAddress == null) return null;
@@ -252,25 +140,22 @@ public static ParsedTransaction parseTransaction(TransactionInfo txInfo,
final ParsedTransactionFees feeDetails = ParsedTransactionFees.parseTransactionFees(
txInfo, selectedNetwork, networkSpotPrice, solFeeEstimatesFee);
TxDataUnion txDataUnion = txInfo.txDataUnion;
- TxData1559 txData = txInfo.txDataUnion.which() == TxDataUnion.Tag.EthTxData1559
- ? txInfo.txDataUnion.getEthTxData1559()
+ TxData1559 txData = txDataUnion.which() == TxDataUnion.Tag.EthTxData1559
+ ? txDataUnion.getEthTxData1559()
: null;
- SolanaTxData solTxData = txInfo.txDataUnion.which() == TxDataUnion.Tag.SolanaTxData
- ? txInfo.txDataUnion.getSolanaTxData()
+ SolanaTxData solTxData = txDataUnion.which() == TxDataUnion.Tag.SolanaTxData
+ ? txDataUnion.getSolanaTxData()
: null;
- ;
- FilTxData filTxData = txInfo.txDataUnion.which() == TxDataUnion.Tag.FilTxData
- ? txInfo.txDataUnion.getFilTxData()
+ FilTxData filTxData = txDataUnion.which() == TxDataUnion.Tag.FilTxData
+ ? txDataUnion.getFilTxData()
: null;
- ;
final boolean isFilTransaction = filTxData != null;
final boolean isSPLTransaction = txInfo.txType == TransactionType.SOLANA_SPL_TOKEN_TRANSFER
|| txInfo.txType
== TransactionType
.SOLANA_SPL_TOKEN_TRANSFER_WITH_ASSOCIATED_TOKEN_ACCOUNT_CREATION;
- final boolean isSolTransaction =
- txInfo.txType == TransactionType.SOLANA_SYSTEM_TRANSFER || isSPLTransaction;
+ final boolean isSolTransaction = SOLANA_TRANSACTION_TYPES.contains(txInfo.txType);
final String value = isSPLTransaction
? solTxData != null ? String.valueOf(solTxData.amount) : ""
@@ -279,9 +164,9 @@ public static ParsedTransaction parseTransaction(TransactionInfo txInfo,
: txData != null ? txData.baseData.value
: "";
- final String to = isSolTransaction ? solTxData != null ? solTxData.toWalletAddress : ""
- : isFilTransaction ? filTxData.to
- : txData.baseData.to;
+ String to = isSolTransaction ? solTxData != null ? solTxData.toWalletAddress : ""
+ : isFilTransaction ? filTxData.to
+ : txData.baseData.to;
final String nonce = txData != null ? txData.baseData.nonce : "";
AccountInfo account = Utils.findAccount(accounts, txInfo.fromAddress);
@@ -310,8 +195,116 @@ public static ParsedTransaction parseTransaction(TransactionInfo txInfo,
parsedTransaction.status = txInfo.txStatus;
parsedTransaction.sender = txInfo.fromAddress;
parsedTransaction.senderLabel = getAddressLabel(accounts, txInfo.fromAddress);
+ parsedTransaction.isSolanaDappTransaction =
+ WalletConstants.SOLANA_DAPPS_TRANSACTION_TYPES.contains(txInfo.txType);
+
+ int txType = txInfo.txType;
+ if (txType == TransactionType.SOLANA_DAPP_SIGN_TRANSACTION
+ || txType == TransactionType.SOLANA_DAPP_SIGN_AND_SEND_TRANSACTION
+ || txType == TransactionType.SOLANA_SWAP
+ || txType == TransactionType.OTHER && solTxData != null) {
+ if (solTxData == null) {
+ parsedTransaction.recipient = "";
+ parsedTransaction.recipientLabel = "";
+ parsedTransaction.fiatTotal = 0;
+ parsedTransaction.fiatValue = 0;
+ parsedTransaction.decimals = 0;
+ parsedTransaction.symbol = "";
+ return parsedTransaction;
+ }
+ BigDecimal lamportTransferredAmount = new BigDecimal(value);
+ for (SolanaInstruction solanaInstruction : solTxData.instructions) {
+ SolanaInstructionPresenter presenter =
+ new SolanaInstructionPresenter(solanaInstruction);
+ String lamport = presenter.getLamportAmount();
+ Integer instructionType = presenter.getInstructionType();
+ boolean isInsExists = instructionType != null;
+ if (isInsExists
+ && (instructionType == SolanaSystemInstruction.TRANSFER
+ || instructionType == SolanaSystemInstruction.TRANSFER_WITH_SEED
+ || (presenter.isTokenInstruction()
+ && instructionType == SolanaTokenInstruction.TRANSFER))) {
+ String fromPubKey = presenter.fromPubKey();
+ String toPubKey = presenter.toPubKey();
+ if (TextUtils.isEmpty(to)) {
+ to = toPubKey;
+ }
+
+ // only show lamports as transferred if the amount is going to a different
+ // pubKey
+ if (!toPubKey.equals(fromPubKey)) {
+ lamportTransferredAmount =
+ lamportTransferredAmount.add(new BigDecimal(lamport));
+ }
+ } else if (isInsExists
+ && (instructionType == SolanaSystemInstruction.WITHDRAW_NONCE_ACCOUNT)) {
+ String noncePubKey =
+ presenter.getPubKeyPerParamKey(WalletConstants.SOL_DAPP_NONCE_ACCOUNT);
+ String toPubKey = presenter.toPubKey();
+ if (TextUtils.isEmpty(to)) {
+ to = toPubKey;
+ }
+ if (noncePubKey != null && noncePubKey.equals(txInfo.fromAddress)) {
+ lamportTransferredAmount =
+ lamportTransferredAmount.add(new BigDecimal(lamport));
+ } else if (!TextUtils.isEmpty(toPubKey)
+ && toPubKey.equals(txInfo.fromAddress)) {
+ lamportTransferredAmount =
+ lamportTransferredAmount.subtract(new BigDecimal(lamport));
+ }
+ } else if (isInsExists
+ && (instructionType == SolanaSystemInstruction.CREATE_ACCOUNT
+ || instructionType
+ == SolanaSystemInstruction.CREATE_ACCOUNT_WITH_SEED)) {
+ String fromPubKey = presenter.fromPubKey();
+ String newAccountPubKey =
+ presenter.getPubKeyPerParamKey(WalletConstants.SOL_DAPP_NEW_ACCOUNT);
+ if (TextUtils.isEmpty(to)) {
+ to = newAccountPubKey;
+ }
+ if (!TextUtils.isEmpty(fromPubKey) && fromPubKey.equals(txInfo.fromAddress)) {
+ lamportTransferredAmount =
+ lamportTransferredAmount.add(new BigDecimal(lamport));
+ }
+ } else {
+ if (presenter.mIsUnknown) {
+ if (TextUtils.isEmpty(to)) {
+ try {
+ to = solanaInstruction.accountMetas[0].pubkey;
+ } catch (Exception ignored) {
+ }
+ }
+ } else {
+ lamportTransferredAmount =
+ lamportTransferredAmount.add(new BigDecimal(lamport));
+ }
+ }
+ }
+ final int decimals = token != null ? token.decimals : Utils.SOL_DEFAULT_DECIMALS;
+ final double price = Utils.getOrDefault(assetPrices, tokenSymbolLower, 0.0d);
+ final double sendAmount = Utils.getBalanceForCoinType(
+ TransactionUtils.getCoinFromTxDataUnion(txDataUnion), decimals,
+ lamportTransferredAmount.toPlainString());
+ final double sendAmountFiat = sendAmount * price;
+ final double totalAmountFiat = parsedTransaction.getGasFeeFiat() + sendAmountFiat;
+ final boolean insufficientNativeFunds =
+ parsedTransaction.getGasFee() > accountNativeBalance;
+ final boolean insufficientTokenFunds = sendAmount > accountTokenBalance;
- if (txInfo.txType == TransactionType.ERC20_TRANSFER && txInfo.txArgs.length > 1) {
+ parsedTransaction.recipient = to;
+ parsedTransaction.recipientLabel = getAddressLabel(accounts, to);
+ parsedTransaction.fiatValue = sendAmountFiat;
+ parsedTransaction.fiatTotal = totalAmountFiat;
+ parsedTransaction.nativeCurrencyTotal = sendAmountFiat / networkSpotPrice;
+ parsedTransaction.value = sendAmount;
+ parsedTransaction.symbol = token != null ? token.symbol : "";
+ parsedTransaction.decimals = Utils.SOL_DEFAULT_DECIMALS;
+ parsedTransaction.insufficientFundsError = insufficientTokenFunds;
+ parsedTransaction.insufficientFundsForGasError = insufficientNativeFunds;
+ parsedTransaction.isSwap = txType == TransactionType.SOLANA_SWAP;
+ parsedTransaction.contractAddressError = checkForContractAddressError(fullTokenList,
+ solTxData.toWalletAddress != null ? solTxData.toWalletAddress : to);
+ } else if (txInfo.txType == TransactionType.ERC20_TRANSFER && txInfo.txArgs.length > 1) {
final String address = txInfo.txArgs[0];
final String amount = txInfo.txArgs[1];
final int decimals = token != null ? token.decimals : Utils.ETH_DEFAULT_DECIMALS;
@@ -531,7 +524,9 @@ public String formatValueToDisplay() {
} else if (this.isSwap) {
return String.format(Locale.getDefault(), "%.4f", this.value);
} else {
- return String.format(Locale.getDefault(), "%.4f", this.value);
+ String sVal = String.format(Locale.getDefault(), "%.9f", value);
+ // Show amount without trailing zeros
+ return !sVal.contains(".") ? sVal : sVal.replaceAll("0*$", "").replaceAll("\\.$", "");
}
}
@@ -575,4 +570,124 @@ public Pair makeTxListItemTitles(Context context) {
return new Pair(action, detailInfo);
}
+
+ public String getHash() {
+ return this.hash;
+ }
+
+ public String getNonce() {
+ return this.nonce;
+ }
+
+ public TimeDelta getCreatedTime() {
+ return this.createdTime;
+ }
+
+ public int getStatus() {
+ return this.status;
+ }
+
+ public int getType() {
+ return this.type;
+ }
+
+ public String getSender() {
+ return this.sender;
+ }
+
+ public String getSenderLabel() {
+ return this.senderLabel;
+ }
+
+ public String getRecipient() {
+ return this.recipient;
+ }
+
+ public String getRecipientLabel() {
+ return this.recipientLabel;
+ }
+
+ public double getFiatValue() {
+ return this.fiatValue;
+ }
+
+ public double getFiatTotal() {
+ return this.fiatTotal;
+ }
+
+ public double getNativeCurrencyTotal() {
+ return this.nativeCurrencyTotal;
+ }
+
+ public double getValue() {
+ return this.value;
+ }
+
+ public String getSymbol() {
+ return this.symbol;
+ }
+
+ public BlockchainToken getToken() {
+ return this.token;
+ }
+
+ public int getDecimals() {
+ return this.decimals;
+ }
+
+ public boolean getInsufficientFundsForGasError() {
+ return this.insufficientFundsForGasError;
+ }
+
+ public boolean getInsufficientFundsError() {
+ return this.insufficientFundsError;
+ }
+
+ public String getContractAddressError() {
+ return this.contractAddressError;
+ }
+
+ public String getSameAddressError() {
+ return this.sameAddressError;
+ }
+
+ public BlockchainToken getErc721BlockchainToken() {
+ return this.erc721BlockchainToken;
+ }
+
+ public String getErc721TokenId() {
+ return this.erc721TokenId;
+ }
+
+ public boolean getIsSwap() {
+ return this.isSwap;
+ }
+
+ public String getApprovalTarget() {
+ return this.approvalTarget;
+ }
+
+ public String getApprovalTargetLabel() {
+ return this.approvalTargetLabel;
+ }
+
+ public boolean getIsApprovalUnlimited() {
+ return this.isApprovalUnlimited;
+ }
+
+ public BlockchainToken getSellToken() {
+ return this.sellToken;
+ }
+
+ public double getSellAmount() {
+ return this.sellAmount;
+ }
+
+ public BlockchainToken getBuyToken() {
+ return this.buyToken;
+ }
+
+ public double getMinBuyAmount() {
+ return this.minBuyAmount;
+ }
}
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransactionFees.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransactionFees.java
index 441b393be4e27..e85606e284e5c 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransactionFees.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/ParsedTransactionFees.java
@@ -5,6 +5,8 @@
package org.chromium.chrome.browser.crypto_wallet.util;
+import static org.chromium.chrome.browser.crypto_wallet.util.WalletConstants.SOLANA_TRANSACTION_TYPES;
+
import org.chromium.base.Log;
import org.chromium.brave_wallet.mojom.FilTxData;
import org.chromium.brave_wallet.mojom.NetworkInfo;
@@ -104,11 +106,7 @@ public static ParsedTransactionFees parseTransactionFees(TransactionInfo txInfo,
: null;
FilTxData filTxData = null; // TODO: add with FIL
final int networkDecimals = selectedNetwork.decimals;
- final boolean isSolTransaction = txInfo.txType == TransactionType.SOLANA_SYSTEM_TRANSFER
- || txInfo.txType == TransactionType.SOLANA_SPL_TOKEN_TRANSFER
- || txInfo.txType
- == TransactionType
- .SOLANA_SPL_TOKEN_TRANSFER_WITH_ASSOCIATED_TOKEN_ACCOUNT_CREATION;
+ final boolean isSolTransaction = SOLANA_TRANSACTION_TYPES.contains(txInfo.txType);
final boolean isFilTransaction = filTxData != null;
final String gasLimit = isFilTransaction ? filTxData.gasLimit
: (txData != null ? txData.baseData.gasLimit : "");
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/SolanaTransactionsGasHelper.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/SolanaTransactionsGasHelper.java
index a4b492a1df823..4c7828709f995 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/SolanaTransactionsGasHelper.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/SolanaTransactionsGasHelper.java
@@ -59,7 +59,7 @@ public void maybeGetSolanaGasEstimations(Runnable runWhenDone) {
estimatesContext.txMetaId = txInfo.id;
estimatesContexts.add(estimatesContext);
- if (mActivity != null)
+ if (mActivity.get() != null)
mActivity.get().getSolanaTxManagerProxy().getEstimatedTxFee(
txInfo.id, estimatesContext);
}
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/TransactionUtils.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/TransactionUtils.java
index e9affba53f419..499fca3080d79 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/TransactionUtils.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/TransactionUtils.java
@@ -16,6 +16,8 @@
import org.chromium.brave_wallet.mojom.SolanaSystemInstruction;
import org.chromium.brave_wallet.mojom.SolanaTokenInstruction;
import org.chromium.brave_wallet.mojom.SolanaTxData;
+import org.chromium.brave_wallet.mojom.TransactionInfo;
+import org.chromium.brave_wallet.mojom.TransactionType;
import org.chromium.brave_wallet.mojom.TxDataUnion;
import org.chromium.chrome.R;
@@ -33,7 +35,39 @@ else if (txDataUnion.which() == TxDataUnion.Tag.SolanaTxData)
return CoinType.ETH;
}
+ public static @StringRes int getTxType(TransactionInfo info) {
+ if (info == null) return R.string.wallet_details_function_type_other;
+ switch (info.txType) {
+ case TransactionType.ERC20_TRANSFER:
+ return R.string.wallet_details_function_type_erc20transfer;
+ case TransactionType.ERC20_APPROVE:
+ return R.string.wallet_details_function_type_erc20approve;
+ case TransactionType.ERC721_TRANSFER_FROM:
+ return R.string.wallet_details_function_type_erc721transfer;
+ case TransactionType.SOLANA_SYSTEM_TRANSFER:
+ return R.string.wallet_details_function_type_solana_system_transfer;
+ case TransactionType.SOLANA_SPL_TOKEN_TRANSFER:
+ return R.string.wallet_details_function_type_spl_token_transfer;
+ case TransactionType.SOLANA_SPL_TOKEN_TRANSFER_WITH_ASSOCIATED_TOKEN_ACCOUNT_CREATION:
+ return R.string
+ .wallet_details_function_type_solana_spl_token_transfer_with_associated_token_account_creation;
+ case TransactionType.SOLANA_DAPP_SIGN_AND_SEND_TRANSACTION:
+ return R.string.wallet_details_function_type_solana_dapp_sign_and_send;
+ case TransactionType.SOLANA_DAPP_SIGN_TRANSACTION:
+ return R.string.wallet_details_function_type_solana_dapp_sign;
+ default:
+ return R.string.wallet_details_function_type_other;
+ }
+ }
+
// ---------- Solana ----------
+ public static boolean isSolanaTx(TransactionInfo transactionInfo) {
+ if (transactionInfo == null || transactionInfo.txDataUnion == null) return false;
+ return WalletConstants.SOLANA_TRANSACTION_TYPES.contains(transactionInfo.txType)
+ || transactionInfo.txType == TransactionType.OTHER
+ && safeSolData(transactionInfo.txDataUnion) != null;
+ }
+
public static String getSolanaProgramIdName(String programId, Context context) {
if (TextUtils.isEmpty(programId)) return "";
switch (programId) {
@@ -58,7 +92,7 @@ public static String getSolanaProgramIdName(String programId, Context context) {
}
}
- public static int getSolType(String programId, int instructionType) {
+ public static int getSolTxSubType(String programId, int instructionType) {
if (TextUtils.isEmpty(programId)) return R.string.brave_wallet_unknown;
switch (programId) {
@@ -75,7 +109,8 @@ public static boolean isSolTxUnknown(String programId) {
if (TextUtils.isEmpty(programId)) return true;
switch (programId) {
case WalletConstants.SOL_INS_SYSTEM:
- case WalletConstants.SOL_INS_TOKEN:
+ case WalletConstants.SOL_INS_VOTE:
+ case WalletConstants.SOL_INS_STAKE:
return false;
default:
return true;
diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/WalletConstants.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/WalletConstants.java
index 653ce7a8b29e0..5730b45c6c05a 100644
--- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/WalletConstants.java
+++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/WalletConstants.java
@@ -1,7 +1,7 @@
package org.chromium.chrome.browser.crypto_wallet.util;
import org.chromium.brave_wallet.mojom.BraveWalletConstants;
-import org.chromium.chrome.R;
+import org.chromium.brave_wallet.mojom.TransactionType;
import java.util.Arrays;
import java.util.List;
@@ -68,8 +68,22 @@ public final class WalletConstants {
BraveWalletConstants.MAINNET_CHAIN_ID, BraveWalletConstants.GOERLI_CHAIN_ID);
// Solana
- public static final String SOL_LAMPORTS = "lamports";
public static final String SOL = "SOL";
+ public static final String SOL_LAMPORTS = "lamports";
+ public static final String SOL_DAPP_FROM_ACCOUNT = "from_account";
+ public static final String SOL_DAPP_TO_ACCOUNT = "to_account";
+ public static final String SOL_DAPP_NONCE_ACCOUNT = "nonce_account";
+ public static final String SOL_DAPP_NEW_ACCOUNT = "new_account";
+
+ public static List SOLANA_TRANSACTION_TYPES = Arrays.asList(
+ TransactionType.SOLANA_SYSTEM_TRANSFER, TransactionType.SOLANA_SPL_TOKEN_TRANSFER,
+ TransactionType.SOLANA_SPL_TOKEN_TRANSFER_WITH_ASSOCIATED_TOKEN_ACCOUNT_CREATION,
+ TransactionType.SOLANA_DAPP_SIGN_TRANSACTION,
+ TransactionType.SOLANA_DAPP_SIGN_AND_SEND_TRANSACTION);
+
+ public static List SOLANA_DAPPS_TRANSACTION_TYPES =
+ Arrays.asList(TransactionType.SOLANA_DAPP_SIGN_TRANSACTION,
+ TransactionType.SOLANA_DAPP_SIGN_AND_SEND_TRANSACTION);
// Solana instruction types
public static final String SOL_INS_SYSTEM = BraveWalletConstants.SOLANA_SYSTEM_PROGRAM_ID;
diff --git a/android/java/res/layout/approve_tx_bottom_sheet.xml b/android/java/res/layout/approve_tx_bottom_sheet.xml
index 3f3804e341d96..283cd82008f4e 100644
--- a/android/java/res/layout/approve_tx_bottom_sheet.xml
+++ b/android/java/res/layout/approve_tx_bottom_sheet.xml
@@ -159,26 +159,32 @@
app:tabIndicatorColor="@null"
app:tabSelectedTextColor="@color/tab_color"
app:tabTextAppearance="@style/BraveWalletTabsTextAppearance"
- app:tabTextColor="@color/wallet_text_color" />
+ app:tabTextColor="@color/wallet_text_color"
+ app:layout_constraintBottom_toTopOf="@id/navigation_view_pager"/>
+
+
-
-
+ app:layout_constraintTop_toBottomOf="@id/navigation_view_pager">
diff --git a/android/java/res/values-night/brave_colors.xml b/android/java/res/values-night/brave_colors.xml
index 75812d11d6d12..afcdaef0bddd6 100644
--- a/android/java/res/values-night/brave_colors.xml
+++ b/android/java/res/values-night/brave_colors.xml
@@ -44,6 +44,7 @@
#453e2d
+ #C2C4CF
#84889C
diff --git a/android/java/res/values/brave_colors.xml b/android/java/res/values/brave_colors.xml
index 9a31c30b98712..b113d9bf507f9 100644
--- a/android/java/res/values/brave_colors.xml
+++ b/android/java/res/values/brave_colors.xml
@@ -32,6 +32,7 @@
#F0F2FF
+ #868E96
#868E96
#cc0000
#51cf66
diff --git a/android/java/res/values/brave_styles.xml b/android/java/res/values/brave_styles.xml
index a454fa4f75ab9..434716f33d54c 100644
--- a/android/java/res/values/brave_styles.xml
+++ b/android/java/res/values/brave_styles.xml
@@ -63,6 +63,23 @@
- 14sp
+
+
+
+
+
+