Merge pull request #15593 from brave/feat-solana-dapps-tx

feat(wallet): implement solana dapps send tx
This commit is contained in:
Pavneet Singh
2022-10-28 22:00:41 +05:30
committed by GitHub
28 changed files with 783 additions and 238 deletions
+3 -1
View File
@@ -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",
+1 -1
View File
@@ -97,7 +97,7 @@
tools:ignore="LockedOrientationActivity"/>
<activity android:name="org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletDAppsActivity"
android:theme="@style/Theme.Chromium.Activity"
android:theme="@style/BraveTranslucentMaterial"
android:screenOrientation="sensorPortrait"
tools:ignore="LockedOrientationActivity"/>
@@ -9,6 +9,8 @@ import static org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletDA
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 class BraveWalletDAppsActivity extends BraveWalletBaseActivity
@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(
@@ -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.BlockchainToken;
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<String, HashMap<String, Double>> 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 class ApproveTxFragmentPageAdapter extends FragmentStatePagerAdapter {
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 class ApproveTxFragmentPageAdapter extends FragmentStatePagerAdapter {
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();
@@ -107,6 +107,10 @@ public class TwoLineItemRecyclerViewAdapter extends RecyclerView.Adapter<Recycle
this.subTitle = subTitle;
}
public TwoLineItemText(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
@@ -48,6 +48,7 @@ import org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletBaseActiv
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 @@ public class ApproveTxBottomSheetDialogFragment extends BottomSheetDialogFragmen
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;
@@ -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<TwoLineItemRecyclerViewAdapter.TwoLineItem> 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);
}
}
@@ -8,6 +8,7 @@ package org.chromium.chrome.browser.crypto_wallet.fragments;
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 class TwoLineItemFragment extends Fragment {
return fragment;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -44,6 +46,24 @@ public class TwoLineItemFragment extends Fragment {
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;
}
@@ -24,6 +24,7 @@ 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.util.TransactionUtils;
import org.chromium.chrome.browser.crypto_wallet.util.Utils;
public class TxDetailsFragment extends Fragment {
@@ -59,35 +60,7 @@ public class TxDetailsFragment extends Fragment {
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(
@@ -25,20 +25,21 @@ import androidx.annotation.Nullable;
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<String, Double> assetPrices,
@@ -99,6 +101,7 @@ public class TxFragment extends Fragment {
mPreviousCheckedPriorityId = -1;
mUpdateTxObjectManually = updateTxObjectManually;
mSolanaEstimatedTxFee = solanaEstimatedTxFee;
mIsSolanaInstruction = TransactionUtils.isSolanaTx(txInfo);
}
@Override
@@ -116,7 +119,7 @@ public class TxFragment extends Fragment {
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 @@ public class TxFragment extends Fragment {
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
@@ -38,7 +38,7 @@ import org.chromium.chrome.browser.crypto_wallet.adapters.FragmentNavigationItem
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;
@@ -87,7 +87,7 @@ public class BraveWalletPanel implements DialogInterface {
private WalletModel mWalletModel;
private AccountInfo mSelectedAccount;
private NetworkInfo mSelectedNetwork;
private Observer<AccountInfo> mAccountInfoObserver = accountInfo -> {
private final Observer<AccountInfo> mAccountInfoObserver = accountInfo -> {
if (accountInfo == null) return;
mSelectedAccount = accountInfo;
mBraveWalletPanelServices.getKeyringService().getKeyringInfo(
@@ -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());
}
}
@@ -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.SolanaInstructionAccountParam;
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 class SolanaInstructionPresenter {
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 class SolanaInstructionPresenter {
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 class SolanaInstructionPresenter {
return twoLineItemDataSources;
}
public List<TwoLineItemText> programIdToList() {
return Arrays.asList(new TwoLineItemText(null, mSolanaInstruction.programId));
}
public List<TwoLineItemText> 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;
@@ -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 class AndroidUtils {
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);
}
}
}
@@ -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.Date;
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 @@ public class ParsedTransaction extends 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 class ParsedTransaction extends ParsedTransactionFees {
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 class ParsedTransaction extends ParsedTransactionFees {
: 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 class ParsedTransaction extends ParsedTransactionFees {
parsedTransaction.status = txInfo.txStatus;
parsedTransaction.sender = txInfo.fromAddress;
parsedTransaction.senderLabel = getAddressLabel(accounts, txInfo.fromAddress);
parsedTransaction.isSolanaDappTransaction =
WalletConstants.SOLANA_DAPPS_TRANSACTION_TYPES.contains(txInfo.txType);
if (txInfo.txType == TransactionType.ERC20_TRANSFER && txInfo.txArgs.length > 1) {
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;
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 class ParsedTransaction extends ParsedTransactionFees {
} 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 class ParsedTransaction extends ParsedTransactionFees {
return new Pair<String, String>(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;
}
}
@@ -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 class ParsedTransactionFees {
: 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 : "");
@@ -59,7 +59,7 @@ public class SolanaTransactionsGasHelper {
estimatesContext.txMetaId = txInfo.id;
estimatesContexts.add(estimatesContext);
if (mActivity != null)
if (mActivity.get() != null)
mActivity.get().getSolanaTxManagerProxy().getEstimatedTxFee(
txInfo.id, estimatesContext);
}
@@ -16,6 +16,8 @@ import org.chromium.brave_wallet.mojom.SignTransactionRequest;
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 @@ public class TransactionUtils {
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 class TransactionUtils {
}
}
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 class TransactionUtils {
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;
@@ -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<Integer> 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<Integer> 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;
@@ -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"/>
<org.chromium.chrome.browser.crypto_wallet.model.TxNonSwipeableViewPager
android:id="@+id/navigation_view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintHeight_default="spread"
app:layout_constraintTop_toBottomOf="@id/tabs"
app:layout_constraintHeight_min="240dp"
app:layout_constraintBottom_toTopOf="@id/actions_container"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<LinearLayout
android:id="@+id/actions_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tabs">
<org.chromium.chrome.browser.crypto_wallet.model.TxNonSwipeableViewPager
android:id="@+id/navigation_view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
app:layout_constraintTop_toBottomOf="@id/navigation_view_pager">
<Button
android:id="@+id/btn_reject_transactions"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAllCaps="false"
@@ -189,7 +195,7 @@
android:id="@+id/approve_tx_bottom_sheet_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:layout_marginVertical="6dp"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatButton
@@ -16,11 +16,12 @@
android:orientation="horizontal">
<TextView
android:id="@+id/frag_tx_tv_gas"
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_marginTop="37dp"
android:layout_marginBottom="4dp"
android:paddingStart="24dp"
android:layout_marginStart="24dp"
android:text="@string/gas_fee"
android:textColor="@color/wallet_text_color"
android:textSize="14sp" />
@@ -82,9 +83,9 @@
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_marginTop="37dp"
android:layout_marginBottom="4dp"
android:paddingStart="24dp"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/total"
android:textColor="@color/wallet_text_color"
android:textSize="14sp" />
@@ -96,6 +97,7 @@
android:orientation="vertical">
<TextView
android:id="@+id/frag_tx_tv_total_heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
@@ -133,6 +135,14 @@
android:layout_marginEnd="30dp"
android:background="@color/wallet_text_color" />
<LinearLayout
android:id="@+id/frag_tx_ll_send_options"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="24dp"/>
<TextView
android:id="@+id/fragment_tx_tv_advance_setting"
android:layout_width="match_parent"
@@ -12,6 +12,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="@color/brave_wallet_day_night_text_color"
android:textStyle="bold"
tools:text="Demo" />
@@ -20,6 +21,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="@color/brave_theme_hint_text"
android:textColor="@color/brave_theme_subtitle_text"
tools:text="text" />
</LinearLayout>
@@ -44,6 +44,7 @@
<color name="brave_wallet_dn_error_text_bg_color">#453e2d</color>
<!-- Text colors -->
<color name="brave_theme_subtitle_text">#C2C4CF</color>
<color name="brave_theme_hint_text">#84889C</color>
<!-- Set Default Browser colors -->
+1
View File
@@ -32,6 +32,7 @@
<color name="brave_wallet_dn_error_text_bg_color">#F0F2FF</color>
<!-- Text colors -->
<color name="brave_theme_subtitle_text">#868E96</color>
<color name="brave_theme_hint_text">#868E96</color>
<color name="brave_theme_error">#cc0000</color>
<color name="brave_theme_success">#51cf66</color>
+25
View File
@@ -63,6 +63,23 @@
<item name="android:textSize">14sp</item>
</style>
<style name="BraveWalletTextViewTitle" parent="Widget.AppCompat.TextView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@color/brave_wallet_day_night_text_color</item>
<item name="android:textColorLink">@color/brave_link</item>
<item name="android:textAppearance">?attr/textAppearanceListItem</item>
<item name="android:textStyle">bold</item>
</style>
<style name="BraveWalletTextViewSubTitle" parent="Widget.AppCompat.TextView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@color/brave_theme_subtitle_text</item>
<item name="android:textColorLink">@color/brave_link</item>
<item name="android:textAppearance">?attr/textAppearanceListItem</item>
</style>
<style name="BraveWalletButtonHollow" parent="Widget.AppCompat.Button">
<item name="buttonStyle">?android:attr/borderlessButtonStyle</item>
<item name="android:layout_width">wrap_content</item>
@@ -169,6 +186,14 @@
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="BraveTranslucentMaterial" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@color/translucent_activity_background_color</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="BraveWalletAlertDialogTheme" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="android:background">@color/wallet_bg</item>
<item name="android:colorBackground">@color/wallet_bg</item>