diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni index 475def6129b..941ae022bb8 100644 --- a/android/brave_java_sources.gni +++ b/android/brave_java_sources.gni @@ -248,6 +248,7 @@ if (brave_wallet_enabled) { brave_java_sources += [ "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/AssetRatioControllerFactory.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/ERCTokenRegistryFactory.java", + "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/EthJsonRpcControllerFactory.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/KeyringControllerFactory.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/activities/AccountDetailActivity.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/activities/AccountDetailsWithQrActivity.java", diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/EthJsonRpcControllerFactory.java b/android/java/org/chromium/chrome/browser/crypto_wallet/EthJsonRpcControllerFactory.java new file mode 100644 index 00000000000..68af5a3f3f6 --- /dev/null +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/EthJsonRpcControllerFactory.java @@ -0,0 +1,56 @@ +/* Copyright (c) 2021 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; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; +import org.chromium.brave_wallet.mojom.EthJsonRpcController; +import org.chromium.mojo.bindings.ConnectionErrorHandler; +import org.chromium.mojo.bindings.Interface; +import org.chromium.mojo.bindings.Interface.Proxy.Handler; +import org.chromium.mojo.system.MessagePipeHandle; +import org.chromium.mojo.system.MojoException; +import org.chromium.mojo.system.impl.CoreImpl; + +@JNINamespace("chrome::android") +public class EthJsonRpcControllerFactory { + private static final Object lock = new Object(); + private static EthJsonRpcControllerFactory instance; + + public static EthJsonRpcControllerFactory getInstance() { + synchronized (lock) { + if (instance == null) { + instance = new EthJsonRpcControllerFactory(); + } + } + return instance; + } + + private EthJsonRpcControllerFactory() {} + + public EthJsonRpcController getEthJsonRpcController( + ConnectionErrorHandler connectionErrorHandler) { + int nativeHandle = + EthJsonRpcControllerFactoryJni.get().getInterfaceToEthJsonRpcController(); + MessagePipeHandle handle = wrapNativeHandle(nativeHandle); + EthJsonRpcController ethJsonRpcController = + EthJsonRpcController.MANAGER.attachProxy(handle, 0); + Handler handler = ((Interface.Proxy) ethJsonRpcController).getProxyHandler(); + handler.setErrorHandler(connectionErrorHandler); + + return ethJsonRpcController; + } + + private MessagePipeHandle wrapNativeHandle(int nativeHandle) { + return CoreImpl.getInstance().acquireNativeHandle(nativeHandle).toMessagePipeHandle(); + } + + @NativeMethods + interface Natives { + int getInterfaceToEthJsonRpcController(); + } +} diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletActivity.java b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletActivity.java index 0dfc3f1087d..7d65bdcff65 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletActivity.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletActivity.java @@ -26,9 +26,11 @@ import com.google.android.material.tabs.TabLayout; import org.chromium.base.Log; import org.chromium.brave_wallet.mojom.ErcTokenRegistry; +import org.chromium.brave_wallet.mojom.EthJsonRpcController; import org.chromium.brave_wallet.mojom.KeyringController; import org.chromium.chrome.R; import org.chromium.chrome.browser.crypto_wallet.ERCTokenRegistryFactory; +import org.chromium.chrome.browser.crypto_wallet.EthJsonRpcControllerFactory; import org.chromium.chrome.browser.crypto_wallet.KeyringControllerFactory; import org.chromium.chrome.browser.crypto_wallet.adapters.CryptoFragmentPageAdapter; import org.chromium.chrome.browser.crypto_wallet.adapters.CryptoWalletOnboardingPagerAdapter; @@ -60,6 +62,7 @@ public class BraveWalletActivity private CryptoWalletOnboardingPagerAdapter cryptoWalletOnboardingPagerAdapter; private KeyringController mKeyringController; private ErcTokenRegistry mErcTokenRegistry; + private EthJsonRpcController mEthJsonRpcController; @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -140,6 +143,7 @@ public class BraveWalletActivity mErcTokenRegistry = null; InitKeyringController(); InitErcTokenRegistry(); + InitEthJsonRpcController(); } private void InitKeyringController() { @@ -158,6 +162,15 @@ public class BraveWalletActivity mErcTokenRegistry = ERCTokenRegistryFactory.getInstance().getERCTokenRegistry(this); } + private void InitEthJsonRpcController() { + if (mEthJsonRpcController != null) { + return; + } + + mEthJsonRpcController = + EthJsonRpcControllerFactory.getInstance().getEthJsonRpcController(this); + } + public KeyringController getKeyringController() { return mKeyringController; } @@ -166,11 +179,16 @@ public class BraveWalletActivity return mErcTokenRegistry; } + public EthJsonRpcController getEthJsonRpcController() { + return mEthJsonRpcController; + } + @Override public void finishNativeInitialization() { super.finishNativeInitialization(); InitKeyringController(); InitErcTokenRegistry(); + InitEthJsonRpcController(); if (Utils.shouldShowCryptoOnboarding()) { setNavigationFragments(ONBOARDING_ACTION); } else if (mKeyringController != null) { diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BuySendSwapActivity.java b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BuySendSwapActivity.java index 4ce5a876365..a3cf5cac8d4 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BuySendSwapActivity.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BuySendSwapActivity.java @@ -9,29 +9,37 @@ import android.content.Intent; import android.os.Bundle; import android.view.MenuItem; import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RadioGroup; +import android.widget.Spinner; import android.widget.TextView; import androidx.appcompat.widget.Toolbar; import org.chromium.brave_wallet.mojom.ErcTokenRegistry; +import org.chromium.brave_wallet.mojom.EthJsonRpcController; import org.chromium.chrome.R; import org.chromium.chrome.browser.crypto_wallet.ERCTokenRegistryFactory; +import org.chromium.chrome.browser.crypto_wallet.EthJsonRpcControllerFactory; import org.chromium.chrome.browser.crypto_wallet.adapters.WalletCoinAdapter; import org.chromium.chrome.browser.crypto_wallet.fragments.EditVisibleAssetsBottomSheetDialogFragment; +import org.chromium.chrome.browser.crypto_wallet.util.Utils; import org.chromium.chrome.browser.init.AsyncInitializationActivity; import org.chromium.mojo.bindings.ConnectionErrorHandler; import org.chromium.mojo.system.MojoException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -public class BuySendSwapActivity - extends AsyncInitializationActivity implements ConnectionErrorHandler { +public class BuySendSwapActivity extends AsyncInitializationActivity + implements ConnectionErrorHandler, AdapterView.OnItemSelectedListener { public enum ActivityType { BUY(0), SEND(1), @@ -60,6 +68,7 @@ public class BuySendSwapActivity } private ErcTokenRegistry mErcTokenRegistry; + private EthJsonRpcController mEthJsonRpcController; private ActivityType mActivityType; @Override @@ -110,10 +119,46 @@ public class BuySendSwapActivity TextView slippingToleranceValueText = findViewById(R.id.slipping_tolerance_value_text); slippingToleranceValueText.setText("2%"); + Spinner spinner = findViewById(R.id.spinner); + spinner.setOnItemSelectedListener(this); + // Creating adapter for spinner + ArrayAdapter dataAdapter = new ArrayAdapter( + this, android.R.layout.simple_spinner_item, Utils.getNetworksList(this)); + dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(dataAdapter); + onInitialLayoutInflationComplete(); adjustControls(); InitErcTokenRegistry(); + InitEthJsonRpcController(); + + if (mEthJsonRpcController != null) { + mEthJsonRpcController.getNetwork( + network -> { spinner.setSelection(getIndexOf(spinner, network)); }); + } + } + + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + String item = parent.getItemAtPosition(position).toString(); + if (mEthJsonRpcController != null) { + mEthJsonRpcController.setNetwork(Utils.getNetworkId(this, item)); + } + } + + @Override + public void onNothingSelected(AdapterView arg0) {} + + private int getIndexOf(Spinner spinner, int network) { + String strNetwork = Utils.getNetworkText(this, network).toString(); + for (int i = 0; i < spinner.getCount(); i++) { + if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(strNetwork)) { + return i; + } + } + + return 0; } private void adjustControls() { @@ -216,7 +261,9 @@ public class BuySendSwapActivity @Override public void onConnectionError(MojoException e) { mErcTokenRegistry = null; + mEthJsonRpcController = null; InitErcTokenRegistry(); + InitEthJsonRpcController(); } private void InitErcTokenRegistry() { @@ -227,6 +274,15 @@ public class BuySendSwapActivity mErcTokenRegistry = ERCTokenRegistryFactory.getInstance().getERCTokenRegistry(this); } + private void InitEthJsonRpcController() { + if (mEthJsonRpcController != null) { + return; + } + + mEthJsonRpcController = + EthJsonRpcControllerFactory.getInstance().getEthJsonRpcController(this); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java index 05f1dd6db57..e2529576076 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java @@ -6,12 +6,16 @@ package org.chromium.chrome.browser.crypto_wallet.fragments; import android.annotation.SuppressLint; +import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.Button; +import android.widget.Spinner; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -19,7 +23,9 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.chromium.brave_wallet.mojom.EthJsonRpcController; import org.chromium.chrome.R; +import org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletActivity; import org.chromium.chrome.browser.crypto_wallet.adapters.WalletCoinAdapter; import org.chromium.chrome.browser.crypto_wallet.listeners.OnWalletListItemClick; import org.chromium.chrome.browser.crypto_wallet.model.WalletListItemModel; @@ -29,11 +35,23 @@ import org.chromium.chrome.browser.crypto_wallet.util.Utils; import java.util.ArrayList; import java.util.List; -public class PortfolioFragment extends Fragment implements OnWalletListItemClick { +public class PortfolioFragment + extends Fragment implements OnWalletListItemClick, AdapterView.OnItemSelectedListener { + Spinner mSpinner; + public static PortfolioFragment newInstance() { return new PortfolioFragment(); } + private EthJsonRpcController getEthJsonRpcController() { + Activity activity = getActivity(); + if (activity instanceof BraveWalletActivity) { + return ((BraveWalletActivity) activity).getEthJsonRpcController(); + } + + return null; + } + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -65,9 +83,55 @@ public class PortfolioFragment extends Fragment implements OnWalletListItemClick } }); + mSpinner = view.findViewById(R.id.spinner); + mSpinner.setOnItemSelectedListener(this); + + // Creating adapter for spinner + ArrayAdapter dataAdapter = new ArrayAdapter(getActivity(), + android.R.layout.simple_spinner_item, Utils.getNetworksList(getActivity())); + dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mSpinner.setAdapter(dataAdapter); + return view; } + private void updateNetwork() { + EthJsonRpcController ethJsonRpcController = getEthJsonRpcController(); + if (ethJsonRpcController != null) { + ethJsonRpcController.getNetwork( + network -> { mSpinner.setSelection(getIndexOf(mSpinner, network)); }); + } + } + + @Override + public void onResume() { + super.onResume(); + updateNetwork(); + } + + private int getIndexOf(Spinner spinner, int network) { + String strNetwork = Utils.getNetworkText(getActivity(), network).toString(); + for (int i = 0; i < spinner.getCount(); i++) { + if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(strNetwork)) { + return i; + } + } + + return 0; + } + + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + String item = parent.getItemAtPosition(position).toString(); + EthJsonRpcController ethJsonRpcController = getEthJsonRpcController(); + if (ethJsonRpcController != null) { + ethJsonRpcController.setNetwork(Utils.getNetworkId(getActivity(), item)); + } + } + + @Override + public void onNothingSelected(AdapterView arg0) {} + @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java b/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java index 63590155013..ec216673e5b 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/util/Utils.java @@ -16,6 +16,7 @@ import android.content.SharedPreferences; import android.view.inputmethod.InputMethodManager; import org.chromium.base.ContextUtils; +import org.chromium.brave_wallet.mojom.Network; import org.chromium.chrome.R; import org.chromium.chrome.browser.crypto_wallet.activities.AccountDetailActivity; import org.chromium.chrome.browser.crypto_wallet.activities.AddAccountActivity; @@ -127,4 +128,65 @@ public class Utils { Intent accountDetailActivityIntent = new Intent(activity, AccountDetailActivity.class); activity.startActivity(accountDetailActivityIntent); } + + public static List getNetworksList(Activity activity) { + List categories = new ArrayList(); + categories.add(activity.getText(R.string.mainnet).toString()); + categories.add(activity.getText(R.string.rinkeby).toString()); + categories.add(activity.getText(R.string.ropsten).toString()); + categories.add(activity.getText(R.string.goerli).toString()); + categories.add(activity.getText(R.string.kovan).toString()); + categories.add(activity.getText(R.string.localhost).toString()); + categories.add(activity.getText(R.string.custom).toString()); + + return categories; + } + + public static CharSequence getNetworkText(Activity activity, int network) { + CharSequence strNetwork = activity.getText(R.string.mainnet); + switch (network) { + case Network.RINKEBY: + strNetwork = activity.getText(R.string.rinkeby); + break; + case Network.ROPSTEN: + strNetwork = activity.getText(R.string.ropsten); + break; + case Network.GOERLI: + strNetwork = activity.getText(R.string.goerli); + break; + case Network.KOVAN: + strNetwork = activity.getText(R.string.kovan); + break; + case Network.LOCALHOST: + strNetwork = activity.getText(R.string.localhost); + break; + case Network.CUSTOM: + strNetwork = activity.getText(R.string.custom); + break; + case Network.MAINNET: + default: + strNetwork = activity.getText(R.string.mainnet); + } + + return strNetwork; + } + + public static int getNetworkId(Activity activity, String network) { + int networkId = Network.MAINNET; + if (network.equals(activity.getText(R.string.rinkeby).toString())) { + networkId = Network.RINKEBY; + } else if (network.equals(activity.getText(R.string.ropsten).toString())) { + networkId = Network.ROPSTEN; + } else if (network.equals(activity.getText(R.string.goerli).toString())) { + networkId = Network.GOERLI; + } else if (network.equals(activity.getText(R.string.kovan).toString())) { + networkId = Network.KOVAN; + } else if (network.equals(activity.getText(R.string.localhost).toString())) { + networkId = Network.LOCALHOST; + } else if (network.equals(activity.getText(R.string.custom).toString())) { + networkId = Network.CUSTOM; + } + + return networkId; + } } diff --git a/android/java/res/layout/activity_buy_send_swap.xml b/android/java/res/layout/activity_buy_send_swap.xml index 4f4b1f357f4..462eb656deb 100644 --- a/android/java/res/layout/activity_buy_send_swap.xml +++ b/android/java/res/layout/activity_buy_send_swap.xml @@ -58,25 +58,18 @@ - + android:paddingBottom="2dp" /> diff --git a/android/java/res/layout/fragment_portfolio.xml b/android/java/res/layout/fragment_portfolio.xml index bc3136bf0c5..83ee8f9eb47 100644 --- a/android/java/res/layout/fragment_portfolio.xml +++ b/android/java/res/layout/fragment_portfolio.xml @@ -12,17 +12,42 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + android:orientation="horizontal"> + + + + + + GetForContext(profile); + + return static_cast(pending.PassPipe().release().value()); +} + +} // namespace android +} // namespace chrome diff --git a/browser/ui/android/strings/android_brave_strings.grd b/browser/ui/android/strings/android_brave_strings.grd index a2ecf22e8f0..faaf25e5ac5 100644 --- a/browser/ui/android/strings/android_brave_strings.grd +++ b/browser/ui/android/strings/android_brave_strings.grd @@ -1855,9 +1855,27 @@ until they verify, or until 90 days have passed. Account recovery failed. Please try again. - + Mainnet + + Rinkeby + + + Ropsten + + + Goerli + + + Kovan + + + Localhost + + + Custom + Market Price in ETH diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index 9cc71ccf08b..6221dd832e5 100755 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn @@ -193,6 +193,7 @@ generate_jni("jni_headers") { sources += [ "//brave/android/java/org/chromium/chrome/browser/crypto_wallet/AssetRatioControllerFactory.java", "//brave/android/java/org/chromium/chrome/browser/crypto_wallet/ERCTokenRegistryFactory.java", + "//brave/android/java/org/chromium/chrome/browser/crypto_wallet/EthJsonRpcControllerFactory.java", "//brave/android/java/org/chromium/chrome/browser/crypto_wallet/KeyringControllerFactory.java", ] }