diff --git a/app/src/main/java/net/mynero/wallet/MainActivity.kt b/app/src/main/java/net/mynero/wallet/MainActivity.kt index 947d324..ca83c96 100644 --- a/app/src/main/java/net/mynero/wallet/MainActivity.kt +++ b/app/src/main/java/net/mynero/wallet/MainActivity.kt @@ -1,7 +1,6 @@ package net.mynero.wallet import android.os.Bundle -import android.os.PersistableBundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity diff --git a/app/src/main/java/net/mynero/wallet/adapter/CoinsInfoAdapter.kt b/app/src/main/java/net/mynero/wallet/adapter/CoinsInfoAdapter.kt index 484d8a0..ea0080f 100644 --- a/app/src/main/java/net/mynero/wallet/adapter/CoinsInfoAdapter.kt +++ b/app/src/main/java/net/mynero/wallet/adapter/CoinsInfoAdapter.kt @@ -33,6 +33,7 @@ class CoinsInfoAdapter(val listener: CoinsInfoAdapterListener?) : RecyclerView.Adapter() { private var localDataSet // : List + @JvmField val selectedUtxos // : HashMap diff --git a/app/src/main/java/net/mynero/wallet/adapter/SubaddressAdapter.kt b/app/src/main/java/net/mynero/wallet/adapter/SubaddressAdapter.kt index bf22b27..855d0f9 100644 --- a/app/src/main/java/net/mynero/wallet/adapter/SubaddressAdapter.kt +++ b/app/src/main/java/net/mynero/wallet/adapter/SubaddressAdapter.kt @@ -71,9 +71,10 @@ class SubaddressAdapter(val listener: SubaddressAdapterListener?) : * Provide a reference to the type of views that you are using * (custom ViewHolder). */ - class ViewHolder(view: View, val listener: SubaddressAdapterListener?) : RecyclerView.ViewHolder( - view - ) { + class ViewHolder(view: View, val listener: SubaddressAdapterListener?) : + RecyclerView.ViewHolder( + view + ) { fun bind(subaddress: Subaddress) { val addressTextView = diff --git a/app/src/main/java/net/mynero/wallet/adapter/TransactionInfoAdapter.kt b/app/src/main/java/net/mynero/wallet/adapter/TransactionInfoAdapter.kt index d923937..e1446b0 100644 --- a/app/src/main/java/net/mynero/wallet/adapter/TransactionInfoAdapter.kt +++ b/app/src/main/java/net/mynero/wallet/adapter/TransactionInfoAdapter.kt @@ -75,7 +75,8 @@ class TransactionInfoAdapter(val listener: TxInfoAdapterListener?) : * Provide a reference to the type of views that you are using * (custom ViewHolder). */ - class ViewHolder(val listener: TxInfoAdapterListener?, view: View) : RecyclerView.ViewHolder(view) { + class ViewHolder(val listener: TxInfoAdapterListener?, view: View) : + RecyclerView.ViewHolder(view) { private val outboundColour: Int private val inboundColour: Int private val pendingColour: Int diff --git a/app/src/main/java/net/mynero/wallet/data/DefaultNodes.kt b/app/src/main/java/net/mynero/wallet/data/DefaultNodes.kt index 4a5a7b7..0106b41 100644 --- a/app/src/main/java/net/mynero/wallet/data/DefaultNodes.kt +++ b/app/src/main/java/net/mynero/wallet/data/DefaultNodes.kt @@ -19,8 +19,84 @@ import org.json.JSONException import org.json.JSONObject // Nodes stolen from https://moneroworld.com/#nodes -enum class DefaultNodes(val address: String, private val port: Int, private val network: String, private val nodeName: String) { - SAMOURAI("163.172.56.213", 18089, "mainnet", "SamouraiWallet"), MONERUJO("nodex.monerujo.io", 18081, "mainnet", "monerujo"), SUPPORTXMR("node.supportxmr.com", 18081, "mainnet", "SupportXMR"), HASHVAULT("nodes.hashvault.pro", 18081, "mainnet", "Hashvault"), MONEROWORLD("node.moneroworld.com", 18089, "mainnet", "MoneroWorld"), XMRTW("opennode.xmr-tw.org", 18089, "mainnet", "XMRTW"), MYNERO_I2P("ynk3hrwte23asonojqeskoulek2g2cd6tqg4neghnenfyljrvhga.b32.i2p", 0, "mainnet", "node.mysu.i2p"), MYNERO_ONION("tiopyrxseconw73thwlv2pf5hebfcqxj5zdolym7z6pbq6gl4z7xz4ad.onion", 18081, "mainnet", "node.mysu.onion"), SAMOURAI_ONION("446unwib5vc7pfbzflosy6m6vtyuhddnalr3hutyavwe4esfuu5g6ryd.onion", 18089, "mainnet", "SamouraiWallet.onion"), MONERUJO_ONION("monerujods7mbghwe6cobdr6ujih6c22zu5rl7zshmizz2udf7v7fsad.onion", 18081, "mainnet", "monerujo.onion"), Criminales78("56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion", 18089, "mainnet", "Criminales78.onion"), xmrfail("mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion", 18081, "mainnet", "xmrfail.onion"), boldsuck("6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion", 18081, "mainnet", "boldsuck.onion"); +enum class DefaultNodes( + val address: String, + private val port: Int, + private val network: String, + private val nodeName: String +) { + SAMOURAI("163.172.56.213", 18089, "mainnet", "SamouraiWallet"), MONERUJO( + "nodex.monerujo.io", + 18081, + "mainnet", + "monerujo" + ), + SUPPORTXMR( + "node.supportxmr.com", + 18081, + "mainnet", + "SupportXMR" + ), + HASHVAULT( + "nodes.hashvault.pro", + 18081, + "mainnet", + "Hashvault" + ), + MONEROWORLD( + "node.moneroworld.com", + 18089, + "mainnet", + "MoneroWorld" + ), + XMRTW( + "opennode.xmr-tw.org", + 18089, + "mainnet", + "XMRTW" + ), + MYNERO_I2P( + "ynk3hrwte23asonojqeskoulek2g2cd6tqg4neghnenfyljrvhga.b32.i2p", + 0, + "mainnet", + "node.mysu.i2p" + ), + MYNERO_ONION( + "tiopyrxseconw73thwlv2pf5hebfcqxj5zdolym7z6pbq6gl4z7xz4ad.onion", + 18081, + "mainnet", + "node.mysu.onion" + ), + SAMOURAI_ONION( + "446unwib5vc7pfbzflosy6m6vtyuhddnalr3hutyavwe4esfuu5g6ryd.onion", + 18089, + "mainnet", + "SamouraiWallet.onion" + ), + MONERUJO_ONION( + "monerujods7mbghwe6cobdr6ujih6c22zu5rl7zshmizz2udf7v7fsad.onion", + 18081, + "mainnet", + "monerujo.onion" + ), + Criminales78( + "56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion", + 18089, + "mainnet", + "Criminales78.onion" + ), + xmrfail( + "mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion", + 18081, + "mainnet", + "xmrfail.onion" + ), + boldsuck( + "6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion", + 18081, + "mainnet", + "boldsuck.onion" + ); val nodeString: String get() = "$address:$port/$network/$nodeName" diff --git a/app/src/main/java/net/mynero/wallet/data/Node.kt b/app/src/main/java/net/mynero/wallet/data/Node.kt index d592f69..14b6d3a 100644 --- a/app/src/main/java/net/mynero/wallet/data/Node.kt +++ b/app/src/main/java/net/mynero/wallet/data/Node.kt @@ -51,8 +51,10 @@ class Node { this.username = "" this.password = "" } + 2 -> { // credentials - val userPassword = a[0].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val userPassword = + a[0].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() require(userPassword.size == 2) { "User:Password invalid" } this.username = userPassword[0] this.password = if (this.username.isNotEmpty()) { @@ -62,11 +64,13 @@ class Node { } daemonAddress = a[1] } + else -> { throw IllegalArgumentException("Too many @") } } - val daParts = daemonAddress.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val daParts = + daemonAddress.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() require(!(daParts.size > 3 || daParts.isEmpty())) { "Too many '/' or too few" } daemonAddress = daParts[0] val da = daemonAddress.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() @@ -240,6 +244,7 @@ class Node { const val TESTNET = "testnet" private var DEFAULT_LEVIN_PORT = 0 private var DEFAULT_RPC_PORT = 0 + @JvmStatic fun fromString(nodeString: String?): Node? { return try { diff --git a/app/src/main/java/net/mynero/wallet/data/Subaddress.kt b/app/src/main/java/net/mynero/wallet/data/Subaddress.kt index f00b7f4..074a801 100644 --- a/app/src/main/java/net/mynero/wallet/data/Subaddress.kt +++ b/app/src/main/java/net/mynero/wallet/data/Subaddress.kt @@ -17,7 +17,12 @@ package net.mynero.wallet.data import java.util.regex.Pattern -class Subaddress(private val accountIndex: Int, @JvmField val addressIndex: Int, @JvmField val address: String, val label: String) : Comparable { +class Subaddress( + private val accountIndex: Int, + @JvmField val addressIndex: Int, + @JvmField val address: String, + val label: String +) : Comparable { @JvmField var amount: Long = 0 @@ -29,10 +34,13 @@ class Subaddress(private val accountIndex: Int, @JvmField val addressIndex: Int, val squashedAddress: String get() = address.substring(0, 8) + "…" + address.substring(address.length - 8) val displayLabel: String - get() = if (label.isEmpty() || DEFAULT_LABEL_FORMATTER.matcher(label).matches()) "#$addressIndex" else label + get() = if (label.isEmpty() || DEFAULT_LABEL_FORMATTER.matcher(label) + .matches() + ) "#$addressIndex" else label companion object { @JvmField - val DEFAULT_LABEL_FORMATTER: Pattern = Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}:[0-9]{2}:[0-9]{2}$") + val DEFAULT_LABEL_FORMATTER: Pattern = + Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}:[0-9]{2}:[0-9]{2}$") } } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/data/TxData.kt b/app/src/main/java/net/mynero/wallet/data/TxData.kt index 84443ec..1cb1ce4 100644 --- a/app/src/main/java/net/mynero/wallet/data/TxData.kt +++ b/app/src/main/java/net/mynero/wallet/data/TxData.kt @@ -41,11 +41,13 @@ class TxData : Parcelable { preferredInputs = txData.preferredInputs } - constructor(dstAddr: String?, - amount: Long, - mixin: Int, - priority: PendingTransaction.Priority?, - preferredInputs: ArrayList?) { + constructor( + dstAddr: String?, + amount: Long, + mixin: Int, + priority: PendingTransaction.Priority?, + preferredInputs: ArrayList? + ) { destinationAddress = dstAddr this.amount = amount this.mixin = mixin diff --git a/app/src/main/java/net/mynero/wallet/data/UserNotes.kt b/app/src/main/java/net/mynero/wallet/data/UserNotes.kt index 4ed985e..83e5ea5 100644 --- a/app/src/main/java/net/mynero/wallet/data/UserNotes.kt +++ b/app/src/main/java/net/mynero/wallet/data/UserNotes.kt @@ -19,15 +19,20 @@ import java.util.regex.Pattern class UserNotes(txNotes: String?) { var txNotes: String? = "" + @JvmField var note: String? = "" + @JvmField var xmrtoTag: String? = null + @JvmField var xmrtoKey: String? = null + @JvmField var xmrtoAmount: String? = null // could be a double - but we are not doing any calculations var xmrtoCurrency: String? = null + @JvmField var xmrtoDestination: String? = null diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/AddNodeBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/AddNodeBottomSheetDialog.java index a460d6f..51c9937 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/AddNodeBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/AddNodeBottomSheetDialog.java @@ -4,7 +4,6 @@ import android.content.Context; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -import android.util.Patterns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -48,11 +47,17 @@ public class AddNodeBottomSheetDialog extends BottomSheetDialogFragment { ImageButton pastePasswordImageButton = view.findViewById(R.id.paste_password_imagebutton); usernameEditText.addTextChangedListener(new TextWatcher() { - @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} - @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + @Override public void afterTextChanged(Editable editable) { - if(editable.toString().isEmpty()) { + if (editable.toString().isEmpty()) { passwordEditText.setText(null); passwordEditText.setVisibility(View.GONE); pastePasswordImageButton.setVisibility(View.GONE); @@ -73,13 +78,13 @@ public class AddNodeBottomSheetDialog extends BottomSheetDialogFragment { String name = nodeNameEditText.getText().toString(); String user = usernameEditText.getText().toString(); String pass = passwordEditText.getText().toString(); - if(name.isEmpty()) { + if (name.isEmpty()) { Toast.makeText(getContext(), "Enter node name", Toast.LENGTH_SHORT).show(); return; - } else if(nodeAddr.isEmpty() || portString.isEmpty()) { + } else if (nodeAddr.isEmpty() || portString.isEmpty()) { Toast.makeText(getContext(), "Enter node address", Toast.LENGTH_SHORT).show(); return; - } else if(!user.isEmpty() && pass.isEmpty()) { + } else if (!user.isEmpty() && pass.isEmpty()) { Toast.makeText(getContext(), "Enter password", Toast.LENGTH_SHORT).show(); return; } diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/EditAddressLabelBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/EditAddressLabelBottomSheetDialog.java index f99ae20..c87c290 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/EditAddressLabelBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/EditAddressLabelBottomSheetDialog.java @@ -19,10 +19,8 @@ import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.service.AddressService; import net.mynero.wallet.util.Helper; -import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Locale; public class EditAddressLabelBottomSheetDialog extends BottomSheetDialogFragment { @@ -47,18 +45,19 @@ public class EditAddressLabelBottomSheetDialog extends BottomSheetDialogFragment try { new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.US).parse(wallet.getSubaddressLabel(addressIndex)); isDate = true; - } catch (ParseException ignored) { } + } catch (ParseException ignored) { + } labelEditText.setText(isDate ? null : wallet.getSubaddressLabel(addressIndex)); pasteButton.setOnClickListener(view1 -> labelEditText.setText(Helper.getClipBoardText(view.getContext()))); saveLabelButton.setOnClickListener(view1 -> { String label = labelEditText.getText().toString(); - if(addressService.getLatestAddressIndex() == addressIndex) { + if (addressService.getLatestAddressIndex() == addressIndex) { addressService.freshSubaddress(); } wallet.setSubaddressLabel(addressIndex, label); wallet.store(); - if(listener != null) { + if (listener != null) { listener.onDismiss(); } dismiss(); diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java index 88db903..40f91b5 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java @@ -4,7 +4,6 @@ import android.content.Context; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -import android.util.Patterns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -20,19 +19,11 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import net.mynero.wallet.R; import net.mynero.wallet.data.Node; -import net.mynero.wallet.service.PrefService; -import net.mynero.wallet.util.Constants; import net.mynero.wallet.util.Helper; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; - -import timber.log.Timber; - public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment { public EditNodeListener listener = null; public Node node = null; @@ -54,23 +45,29 @@ public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment { EditText passwordEditText = view.findViewById(R.id.password_edittext); ImageButton pastePasswordImageButton = view.findViewById(R.id.paste_password_imagebutton); - if(node == null) return; + if (node == null) return; addressEditText.setText(node.getHost()); - portEditText.setText(""+node.getRpcPort()); + portEditText.setText("" + node.getRpcPort()); nodeNameEditText.setText(node.getName()); usernameEditText.setText(node.getUsername()); - if(!node.getPassword().isEmpty()) { + if (!node.getPassword().isEmpty()) { passwordEditText.setText(node.getPassword()); passwordEditText.setVisibility(View.VISIBLE); pastePasswordImageButton.setVisibility(View.VISIBLE); } usernameEditText.addTextChangedListener(new TextWatcher() { - @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} - @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + @Override public void afterTextChanged(Editable editable) { - if(editable.toString().isEmpty()) { + if (editable.toString().isEmpty()) { passwordEditText.setText(null); passwordEditText.setVisibility(View.GONE); pastePasswordImageButton.setVisibility(View.GONE); @@ -96,13 +93,13 @@ public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment { String user = usernameEditText.getText().toString(); String pass = passwordEditText.getText().toString(); - if(nodeName.isEmpty()) { + if (nodeName.isEmpty()) { Toast.makeText(getContext(), "Enter node name", Toast.LENGTH_SHORT).show(); return; - } else if(nodeAddr.isEmpty() || portString.isEmpty()) { + } else if (nodeAddr.isEmpty() || portString.isEmpty()) { Toast.makeText(getContext(), "Enter node address", Toast.LENGTH_SHORT).show(); return; - } else if(!user.isEmpty() && pass.isEmpty()) { + } else if (!user.isEmpty() && pass.isEmpty()) { Toast.makeText(getContext(), "Enter password", Toast.LENGTH_SHORT).show(); return; } @@ -141,6 +138,7 @@ public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment { public interface EditNodeListener { void onNodeDeleted(Node node); + void onNodeEdited(Node oldNode, Node newNode); } } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java index 4d8df07..cd36d20 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java @@ -60,7 +60,9 @@ public class NodeSelectionBottomSheetDialog extends BottomSheetDialogFragment im JSONArray jsonArray = null; try { jsonArray = new JSONArray(nodesArray); - } catch (JSONException e) { throw new RuntimeException(e); } + } catch (JSONException e) { + throw new RuntimeException(e); + } for (int i = 0; i < jsonArray.length(); i++) { JSONObject nodeJsonObject = null; @@ -122,7 +124,9 @@ public class NodeSelectionBottomSheetDialog extends BottomSheetDialogFragment im public interface NodeSelectionDialogListener { void onNodeSelected(); + void onClickedEditNode(Node node); + void onClickedAddNode(); } } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/SendBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/SendBottomSheetDialog.java index 8b9cfa1..173d12b 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/SendBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/SendBottomSheetDialog.java @@ -46,7 +46,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { private final MutableLiveData _pendingTransaction = new MutableLiveData<>(null); public ArrayList selectedUtxos = new ArrayList<>(); public LiveData sendingMax = _sendingMax; - private final ActivityResultLauncher cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), + public LiveData pendingTransaction = _pendingTransaction; private final ActivityResultLauncher cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), granted -> { if (granted) { onScan(); @@ -54,7 +54,6 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { Toast.makeText(getActivity(), getString(R.string.no_camera_permission), Toast.LENGTH_SHORT).show(); } }); - public LiveData pendingTransaction = _pendingTransaction; public UriData uriData = null; public boolean isChurning = false; public Listener listener = null; @@ -123,7 +122,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { String valueString = Wallet.getDisplayAmount(selectedValue); selectedUtxosValueTextView.setVisibility(View.VISIBLE); - if(isChurning) { + if (isChurning) { _sendingMax.postValue(true); sendMaxButton.setEnabled(false); selectedUtxosValueTextView.setText(getResources().getString(R.string.selected_utxos_value_churning, valueString)); @@ -141,7 +140,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { private void bindObservers() { BalanceService.getInstance().balanceInfo.observe(getViewLifecycleOwner(), balanceInfo -> { createButton.setEnabled(balanceInfo.getRawUnlocked() != 0); - if(!isChurning) { + if (!isChurning) { sendMaxButton.setEnabled(balanceInfo.getRawUnlocked() != 0); } }); @@ -206,7 +205,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { createButton.setOnClickListener(view1 -> { FragmentActivity activity = getActivity(); - if(activity != null) { + if (activity != null) { boolean sendAll = sendingMax.getValue() != null ? sendingMax.getValue() : false; String address = addressEditText.getText().toString().trim(); String amount = amountEditText.getText().toString().trim(); @@ -274,7 +273,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { private void createTx(String address, String amount, boolean sendAll, PendingTransaction.Priority feePriority) { Activity activity = getActivity(); if (activity != null) { - ((MoneroApplication)activity.getApplication()).getExecutor().execute(() -> { + ((MoneroApplication) activity.getApplication()).getExecutor().execute(() -> { try { PendingTransaction pendingTx = TxService.getInstance().createTx(address, amount, sendAll, feePriority, selectedUtxos); if (pendingTx != null && pendingTx.getStatus() == PendingTransaction.Status.Status_Ok) { @@ -282,7 +281,7 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { } else { activity.runOnUiThread(() -> { createButton.setEnabled(true); - if(pendingTx != null) { + if (pendingTx != null) { Toast.makeText(activity, getString(R.string.error_creating_tx, pendingTx.getErrorString()), Toast.LENGTH_SHORT).show(); } }); @@ -350,4 +349,6 @@ public class SendBottomSheetDialog extends BottomSheetDialogFragment { public interface Listener { void onSentTransaction(); } + + } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java index 3576ba1..579e787 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java @@ -38,7 +38,7 @@ public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment { Wallet wallet = WalletManager.getInstance().getWallet(); String seed = wallet.getSeed(""); boolean usesOffset = PrefService.getInstance().getBoolean(Constants.PREF_USES_OFFSET, false); - if(usesOffset) { + if (usesOffset) { seed = wallet.getSeed(password); view.findViewById(R.id.wallet_seed_offset_textview).setVisibility(View.VISIBLE); } @@ -46,7 +46,7 @@ public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment { informationTextView.setText(seed); viewKeyTextView.setText(privateViewKey); - restoreHeightTextView.setText(wallet.getRestoreHeight()+""); + restoreHeightTextView.setText(wallet.getRestoreHeight() + ""); copyViewKeyImageButton.setOnClickListener(view1 -> Helper.clipBoardCopy(getContext(), "private view-key", privateViewKey)); } diff --git a/app/src/main/java/net/mynero/wallet/fragment/home/HomeFragment.java b/app/src/main/java/net/mynero/wallet/fragment/home/HomeFragment.java index edfa4fb..a381afa 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/home/HomeFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/home/HomeFragment.java @@ -11,7 +11,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.constraintlayout.widget.ConstraintLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; @@ -24,7 +23,6 @@ import androidx.recyclerview.widget.RecyclerView; import net.mynero.wallet.MainActivity; import net.mynero.wallet.R; import net.mynero.wallet.adapter.TransactionInfoAdapter; -import net.mynero.wallet.fragment.dialog.SendBottomSheetDialog; import net.mynero.wallet.model.TransactionInfo; import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.WalletManager; @@ -91,7 +89,7 @@ public class HomeFragment extends Fragment implements TransactionInfoAdapter.TxI if (balanceService != null) { balanceService.balanceInfo.observe(getViewLifecycleOwner(), balanceInfo -> { - if(balanceInfo != null) { + if (balanceInfo != null) { unlockedBalanceTextView.setText(balanceInfo.getUnlockedDisplay()); if (balanceInfo.getLockedDisplay().equals(Constants.STREET_MODE_BALANCE) || balanceInfo.isLockedBalanceZero()) { @@ -140,7 +138,7 @@ public class HomeFragment extends Fragment implements TransactionInfoAdapter.TxI // DISPLAYING EMPTY WALLET HISTORY Wallet wallet = WalletManager.getInstance().getWallet(); int textResId, botImgResId = 0; - if(wallet != null && wallet.isSynchronized()) { + if (wallet != null && wallet.isSynchronized()) { textResId = R.string.no_history_nget_some_monero_in_here; botImgResId = R.drawable.xmrchan_empty; // img for synchronized } else { @@ -189,7 +187,7 @@ public class HomeFragment extends Fragment implements TransactionInfoAdapter.TxI ImageView botImageView = view.findViewById(R.id.monerochan_imageview); view.findViewById(R.id.no_history_layout).setVisibility(display ? View.VISIBLE : View.GONE); boolean displayMonerochan = PrefService.getInstance().getBoolean(Constants.PREF_MONEROCHAN, true); - if(displayMonerochan) { + if (displayMonerochan) { botImageView.setVisibility(View.VISIBLE); mnrjTextView.setVisibility(View.VISIBLE); textView.setVisibility(View.GONE); diff --git a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java index f1eb22e..7518f64 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java @@ -47,7 +47,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS public void afterTextChanged(Editable editable) { if (mViewModel != null) { mViewModel.setProxyAddress(editable.toString()); - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); } } }; @@ -64,7 +64,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS public void afterTextChanged(Editable editable) { if (mViewModel != null) { mViewModel.setProxyPort(editable.toString()); - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); } } }; @@ -136,7 +136,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS mViewModel.seedType.observe(getViewLifecycleOwner(), seedType -> { seedTypeButton.setText(seedType.toString()); seedTypeDescTextView.setText(getText(seedType.getDescResId())); - if(seedType == OnboardingViewModel.SeedType.LEGACY) { + if (seedType == OnboardingViewModel.SeedType.LEGACY) { seedOffsetCheckbox.setVisibility(View.VISIBLE); walletRestoreHeightEditText.setVisibility(View.VISIBLE); walletPasswordEditText.setHint(getString(R.string.password_optional)); @@ -151,9 +151,13 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS private void bindListeners() { seedOffsetCheckbox.setChecked(useOffset); // Disable onBack click - OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { } }; + OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + } + }; FragmentActivity activity = getActivity(); - if(activity != null) + if (activity != null) activity.getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), onBackPressedCallback); moreOptionsDropdownTextView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked()); @@ -163,7 +167,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS createWalletButton.setOnClickListener(view1 -> { prepareDefaultNode(); onBackPressedCallback.setEnabled(false); - ((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> { + ((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> { createOrImportWallet( walletPasswordEditText.getText().toString(), walletPasswordConfirmEditText.getText().toString(), @@ -229,13 +233,13 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS addProxyTextListeners(); } - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); }); showXmrchanSwitch.setChecked(PrefService.getInstance().getBoolean(Constants.PREF_MONEROCHAN, true)); showXmrchanSwitch.setOnCheckedChangeListener((compoundButton, b) -> { PrefService.getInstance().edit().putBoolean(Constants.PREF_MONEROCHAN, b).apply(); - if(b) { + if (b) { xmrchanOnboardingImage.setVisibility(View.VISIBLE); } else { xmrchanOnboardingImage.setVisibility(View.GONE); @@ -253,11 +257,11 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS private void toggleSeedType() { OnboardingViewModel.SeedType seedType = mViewModel.seedType.getValue(); - if(seedType == null) return; + if (seedType == null) return; OnboardingViewModel.SeedType newSeedType = OnboardingViewModel.SeedType.UNKNOWN; - if(seedType == OnboardingViewModel.SeedType.POLYSEED) { + if (seedType == OnboardingViewModel.SeedType.POLYSEED) { newSeedType = OnboardingViewModel.SeedType.LEGACY; - } else if(seedType == OnboardingViewModel.SeedType.LEGACY) { + } else if (seedType == OnboardingViewModel.SeedType.LEGACY) { newSeedType = OnboardingViewModel.SeedType.POLYSEED; } @@ -270,7 +274,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS private void createOrImportWallet(String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText) { Activity activity = getActivity(); - if(activity != null) { + if (activity != null) { mViewModel.createOrImportWallet(activity, walletPassword, confirmedPassword, walletSeed, restoreHeightText, useOffset); } } @@ -299,11 +303,12 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS public void onNodeSelected() { Node node = PrefService.getInstance().getNode(); selectNodeButton.setText(getString(R.string.node_button_text, node.getAddress())); - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); } @Override - public void onClickedEditNode(Node node) { } + public void onClickedEditNode(Node node) { + } @Override public void onClickedAddNode() { diff --git a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java index c3ea781..f20f789 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java +++ b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java @@ -22,10 +22,10 @@ import java.util.Calendar; public class OnboardingViewModel extends ViewModel { private final MutableLiveData _showMoreOptions = new MutableLiveData<>(false); - public LiveData showMoreOptions = _showMoreOptions; private final MutableLiveData _enableCreateButton = new MutableLiveData<>(true); - public LiveData enableCreateButton = _enableCreateButton; private final MutableLiveData _seedType = new MutableLiveData<>(SeedType.POLYSEED); + public LiveData showMoreOptions = _showMoreOptions; + public LiveData enableCreateButton = _enableCreateButton; public LiveData seedType = _seedType; private String proxyAddress = ""; private String proxyPort = ""; @@ -69,12 +69,12 @@ public class OnboardingViewModel extends ViewModel { } public void createOrImportWallet(Activity mainActivity, String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText, boolean useOffset) { - MoneroApplication application = (MoneroApplication)mainActivity.getApplication(); + MoneroApplication application = (MoneroApplication) mainActivity.getApplication(); application.getExecutor().execute(() -> { _enableCreateButton.postValue(false); String offset = useOffset ? walletPassword : ""; if (!walletPassword.isEmpty()) { - if(!walletPassword.equals(confirmedPassword)) { + if (!walletPassword.equals(confirmedPassword)) { _enableCreateButton.postValue(true); mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, application.getString(R.string.invalid_confirmed_password), Toast.LENGTH_SHORT).show()); return; @@ -84,16 +84,16 @@ public class OnboardingViewModel extends ViewModel { long restoreHeight = getNewRestoreHeight(); File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME); Wallet wallet = null; - if(!offset.isEmpty()) { + if (!offset.isEmpty()) { PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_OFFSET, true).apply(); } if (walletSeed.isEmpty()) { SeedType seedTypeValue = seedType.getValue(); - if(seedTypeValue == null) return; + if (seedTypeValue == null) return; - if(seedTypeValue == SeedType.POLYSEED) { - if(offset.isEmpty()) { + if (seedTypeValue == SeedType.POLYSEED) { + if (offset.isEmpty()) { mainActivity.runOnUiThread(() -> { _enableCreateButton.postValue(true); Toast.makeText(mainActivity, application.getString(R.string.invalid_empty_passphrase), Toast.LENGTH_SHORT).show(); @@ -102,7 +102,7 @@ public class OnboardingViewModel extends ViewModel { } else { wallet = WalletManager.getInstance().createWalletPolyseed(walletFile, walletPassword, offset, Constants.MNEMONIC_LANGUAGE); } - } else if(seedTypeValue == SeedType.LEGACY) { + } else if (seedTypeValue == SeedType.LEGACY) { File tmpWalletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME + "_tmp"); Wallet tmpWallet = createTempWallet(tmpWalletFile); //we do this to get seed, then recover wallet so we can use seed offset wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, tmpWallet.getSeed(""), offset, restoreHeight); @@ -127,7 +127,7 @@ public class OnboardingViewModel extends ViewModel { walletFile.delete(); // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too. if (ok) { - ((MainActivity)mainActivity).init(walletFile, walletPassword); + ((MainActivity) mainActivity).init(walletFile, walletPassword); mainActivity.runOnUiThread(mainActivity::onBackPressed); } else { mainActivity.runOnUiThread(() -> { @@ -147,10 +147,10 @@ public class OnboardingViewModel extends ViewModel { public SeedType getMnemonicType(String seed) { String[] words = seed.split("\\s"); SeedType seedTypeValue = seedType.getValue(); - if(seedTypeValue == null) return SeedType.LEGACY; - if(words.length == 16 && seedTypeValue == SeedType.POLYSEED) { + if (seedTypeValue == null) return SeedType.LEGACY; + if (words.length == 16 && seedTypeValue == SeedType.POLYSEED) { return SeedType.POLYSEED; - } else if (words.length == 25 && seedTypeValue == SeedType.LEGACY){ + } else if (words.length == 25 && seedTypeValue == SeedType.LEGACY) { return SeedType.LEGACY; } else { return SeedType.UNKNOWN; @@ -166,7 +166,7 @@ public class OnboardingViewModel extends ViewModel { POLYSEED(R.string.seed_desc_polyseed), UNKNOWN(0); - private int descResId; + private final int descResId; SeedType(int descResId) { this.descResId = descResId; diff --git a/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveFragment.java b/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveFragment.java index eb8f8d4..79a6b58 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveFragment.java @@ -27,9 +27,7 @@ import net.mynero.wallet.R; import net.mynero.wallet.adapter.SubaddressAdapter; import net.mynero.wallet.data.Subaddress; import net.mynero.wallet.fragment.dialog.EditAddressLabelBottomSheetDialog; -import net.mynero.wallet.util.DayNightMode; import net.mynero.wallet.util.Helper; -import net.mynero.wallet.util.NightmodeHelper; import java.nio.charset.StandardCharsets; import java.util.HashMap; diff --git a/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveViewModel.java b/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveViewModel.java index d39405f..1a3a673 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveViewModel.java +++ b/app/src/main/java/net/mynero/wallet/fragment/receive/ReceiveViewModel.java @@ -15,8 +15,8 @@ import java.util.List; public class ReceiveViewModel extends ViewModel { private final MutableLiveData _address = new MutableLiveData<>(); - public LiveData address = _address; private final MutableLiveData> _addresses = new MutableLiveData<>(); + public LiveData address = _address; public LiveData> addresses = _addresses; public void init() { @@ -28,7 +28,7 @@ public class ReceiveViewModel extends ViewModel { Wallet wallet = WalletManager.getInstance().getWallet(); ArrayList subaddresses = new ArrayList<>(); int addressesSize = AddressService.getInstance().getLatestAddressIndex(); - for(int i = addressesSize - 1; i >= 0; i--) { + for (int i = addressesSize - 1; i >= 0; i--) { subaddresses.add(wallet.getSubaddressObject(i)); } return Collections.unmodifiableList(subaddresses); diff --git a/app/src/main/java/net/mynero/wallet/fragment/send/SendFragment.java b/app/src/main/java/net/mynero/wallet/fragment/send/SendFragment.java index de99318..43ad222 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/send/SendFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/send/SendFragment.java @@ -2,7 +2,6 @@ package net.mynero.wallet.fragment.send; import android.app.Activity; import android.content.Context; -import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; @@ -25,8 +24,6 @@ import androidx.constraintlayout.widget.ConstraintLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import com.google.zxing.client.android.Intents; import com.journeyapps.barcodescanner.ScanContract; @@ -48,6 +45,7 @@ import java.util.List; import kotlin.Pair; public class SendFragment extends Fragment { + public PendingTransaction.Priority priority; private SendViewModel mViewModel; private Button sendMaxButton; private ImageButton addOutputImageView; @@ -57,22 +55,24 @@ public class SendFragment extends Fragment { private SlideToActView sendTxSlider; private RadioGroup feeRadioGroup; private TextView feeRadioGroupLabelTextView; - private TextView feeTextView; private TextView addressTextView; private TextView amountTextView; - - public PendingTransaction.Priority priority; private int currentEntryIndex = -1; private final ActivityResultLauncher qrCodeLauncher = registerForActivityResult(new ScanContract(), result -> { if (result.getContents() != null) { - if(currentEntryIndex != -1) { + if (currentEntryIndex != -1) { pasteAddress(getDestView(currentEntryIndex), result.getContents(), false); currentEntryIndex = -1; } } }); - private final ActivityResultLauncher cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_send, container, false); + } private final ActivityResultLauncher cameraPermissionsLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), granted -> { if (granted) { onScan(currentEntryIndex); @@ -82,12 +82,6 @@ public class SendFragment extends Fragment { } }); - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_send, container, false); - } - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -105,7 +99,7 @@ public class SendFragment extends Fragment { feeRadioGroupLabelTextView = view.findViewById(R.id.tx_fee_radiogroup_label_textview); FragmentActivity activity = getActivity(); - if(activity != null) { + if (activity != null) { inflater = activity.getLayoutInflater(); } bindListeners(); @@ -133,7 +127,7 @@ public class SendFragment extends Fragment { addOutputImageView.setOnClickListener(view1 -> { sendMaxButton.setVisibility(View.GONE); int outputCount = getDestCount(); - if(outputCount < 8) { + if (outputCount < 8) { addOutput(false); } else { Toast.makeText(getActivity(), getString(R.string.max_outputs_allowed), Toast.LENGTH_SHORT).show(); @@ -145,7 +139,7 @@ public class SendFragment extends Fragment { createButton.setOnClickListener(view1 -> { boolean outputsValid = checkDestsValidity(isSendAll()); - if(outputsValid) { + if (outputsValid) { Toast.makeText(getActivity(), getString(R.string.creating_tx), Toast.LENGTH_SHORT).show(); createButton.setEnabled(false); sendMaxButton.setEnabled(false); @@ -166,11 +160,11 @@ public class SendFragment extends Fragment { private boolean checkDestsValidity(boolean sendAll) { List> dests = getRawDests(); - for(Pair dest : dests) { + for (Pair dest : dests) { String address = dest.component1(); String amount = dest.component2(); - if(!sendAll) { - if(amount.isEmpty()) { + if (!sendAll) { + if (amount.isEmpty()) { Toast.makeText(getActivity(), getString(R.string.send_amount_empty), Toast.LENGTH_SHORT).show(); return false; } @@ -181,19 +175,19 @@ public class SendFragment extends Fragment { Toast.makeText(getActivity(), getString(R.string.send_amount_invalid), Toast.LENGTH_SHORT).show(); return false; } - } else if(dests.size() > 1) { + } else if (dests.size() > 1) { Toast.makeText(getActivity(), getString(R.string.send_amount_invalid_sendall_paytomany), Toast.LENGTH_SHORT).show(); return false; } UriData uriData = UriData.parse(address); boolean isValidAddress = uriData != null; - if(!isValidAddress) { + if (!isValidAddress) { Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show(); return false; } - if(dests.size() > 1 && uriData.hasPaymentId()) { + if (dests.size() > 1 && uriData.hasPaymentId()) { Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show(); return false; } @@ -204,11 +198,11 @@ public class SendFragment extends Fragment { private boolean destsHasPaymentId() { List> dests = getRawDests(); - for(Pair dest : dests) { + for (Pair dest : dests) { String address = dest.component1(); UriData uriData = UriData.parse(address); - if(uriData == null) return false; - if(uriData.hasPaymentId()) return true; + if (uriData == null) return false; + if (uriData.hasPaymentId()) return true; } return false; } @@ -245,28 +239,34 @@ public class SendFragment extends Fragment { private void addOutput(boolean initial) { if (inflater != null) { int index = getDestCount(); - ConstraintLayout entryView = (ConstraintLayout)inflater.inflate(R.layout.transaction_output_item, null); + ConstraintLayout entryView = (ConstraintLayout) inflater.inflate(R.layout.transaction_output_item, null); ImageButton removeOutputImageButton = entryView.findViewById(R.id.remove_output_imagebutton); EditText addressField = entryView.findViewById(R.id.address_edittext); addressField.addTextChangedListener(new TextWatcher() { - @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} - @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + @Override public void afterTextChanged(Editable editable) { int currentOutputs = getDestCount(); UriData uriData = UriData.parse(editable.toString()); - if(uriData != null) { + if (uriData != null) { // we have valid address boolean hasPaymentId = uriData.hasPaymentId(); - if(currentOutputs > 1 && hasPaymentId) { + if (currentOutputs > 1 && hasPaymentId) { // multiple outputs when pasting/editing in integrated address. this is not allowed Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show(); addressField.setText(null); - } else if(currentOutputs == 1 && hasPaymentId) { + } else if (currentOutputs == 1 && hasPaymentId) { // show add output button: we are sending to integrated address mViewModel.setShowAddOutputButton(false); } - } else if(currentOutputs == 1 && !isSendAll()) { + } else if (currentOutputs == 1 && !isSendAll()) { // when send-all is false and this is our only dest and address is invalid, then show add output button mViewModel.setShowAddOutputButton(true); } @@ -291,7 +291,7 @@ public class SendFragment extends Fragment { } }); entryView.findViewById(R.id.scan_address_imagebutton).setOnClickListener(view -> onScan(index)); - if(initial) { + if (initial) { removeOutputImageButton.setVisibility(View.INVISIBLE); } else { removeOutputImageButton.setOnClickListener(view -> { @@ -314,7 +314,7 @@ public class SendFragment extends Fragment { private List> getRawDests() { ArrayList> dests = new ArrayList<>(); - for(int i = 0; i < getDestCount(); i++) { + for (int i = 0; i < getDestCount(); i++) { ConstraintLayout entryView = getDestView(i); EditText amountField = entryView.findViewById(R.id.amount_edittext); EditText addressField = entryView.findViewById(R.id.address_edittext); @@ -391,7 +391,7 @@ public class SendFragment extends Fragment { } private void pasteAddress(ConstraintLayout entryView, String clipboard, boolean pastingAmount) { - if(pastingAmount) { + if (pastingAmount) { try { Double.parseDouble(clipboard); setAmount(entryView, clipboard); @@ -404,10 +404,10 @@ public class SendFragment extends Fragment { UriData uriData = UriData.parse(clipboard); if (uriData != null) { int currentOutputs = getDestCount(); - if(currentOutputs > 1 && uriData.hasPaymentId()) { + if (currentOutputs > 1 && uriData.hasPaymentId()) { Toast.makeText(getActivity(), getString(R.string.paymentid_paytomany), Toast.LENGTH_SHORT).show(); return; - } else if(currentOutputs == 1 && uriData.hasPaymentId()) { + } else if (currentOutputs == 1 && uriData.hasPaymentId()) { mViewModel.setShowAddOutputButton(false); } EditText addressField = entryView.findViewById(R.id.address_edittext); @@ -427,7 +427,7 @@ public class SendFragment extends Fragment { } private void createTx(List> dests, boolean sendAll, PendingTransaction.Priority feePriority) { - ((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> { + ((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> { try { PendingTransaction pendingTx = TxService.getInstance().createTx(dests, sendAll, feePriority, new ArrayList<>()); if (pendingTx != null && pendingTx.getStatus() == PendingTransaction.Status.Status_Ok) { @@ -438,7 +438,7 @@ public class SendFragment extends Fragment { activity.runOnUiThread(() -> { createButton.setEnabled(true); sendMaxButton.setEnabled(true); - if(pendingTx.getErrorString() != null) + if (pendingTx.getErrorString() != null) Toast.makeText(activity, getString(R.string.error_creating_tx, pendingTx.getErrorString()), Toast.LENGTH_SHORT).show(); }); } @@ -458,7 +458,7 @@ public class SendFragment extends Fragment { } private void sendTx(PendingTransaction pendingTx) { - ((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> { + ((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> { boolean success = TxService.getInstance().sendTx(pendingTx); Activity activity = getActivity(); if (activity != null) { @@ -478,4 +478,6 @@ public class SendFragment extends Fragment { private void setAddOutputButtonVisibility(int visibility) { addOutputImageView.setVisibility(visibility); } + + } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/fragment/send/SendViewModel.java b/app/src/main/java/net/mynero/wallet/fragment/send/SendViewModel.java index 7282c3c..2b33a31 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/send/SendViewModel.java +++ b/app/src/main/java/net/mynero/wallet/fragment/send/SendViewModel.java @@ -8,10 +8,10 @@ import net.mynero.wallet.model.PendingTransaction; public class SendViewModel extends ViewModel { private final MutableLiveData _sendingMax = new MutableLiveData<>(false); - public LiveData sendingMax = _sendingMax; private final MutableLiveData _showAddOutputButton = new MutableLiveData<>(true); - public LiveData showAddOutputButton = _showAddOutputButton; private final MutableLiveData _pendingTransaction = new MutableLiveData<>(null); + public LiveData sendingMax = _sendingMax; + public LiveData showAddOutputButton = _showAddOutputButton; public LiveData pendingTransaction = _pendingTransaction; public void setSendingMax(boolean value) { diff --git a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java index 2148ad7..f89f630 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java @@ -24,13 +24,12 @@ import androidx.navigation.fragment.NavHostFragment; import net.mynero.wallet.MoneroApplication; import net.mynero.wallet.R; -import net.mynero.wallet.data.DefaultNodes; import net.mynero.wallet.data.Node; import net.mynero.wallet.fragment.dialog.AddNodeBottomSheetDialog; import net.mynero.wallet.fragment.dialog.EditNodeBottomSheetDialog; -import net.mynero.wallet.fragment.dialog.WalletKeysBottomSheetDialog; import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog; import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog; +import net.mynero.wallet.fragment.dialog.WalletKeysBottomSheetDialog; import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.service.BalanceService; @@ -38,8 +37,6 @@ import net.mynero.wallet.service.BlockchainService; import net.mynero.wallet.service.HistoryService; import net.mynero.wallet.service.PrefService; import net.mynero.wallet.util.Constants; -import net.mynero.wallet.util.DayNightMode; -import net.mynero.wallet.util.NightmodeHelper; import org.json.JSONArray; import org.json.JSONObject; @@ -60,7 +57,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia public void afterTextChanged(Editable editable) { if (mViewModel != null) { mViewModel.setProxyAddress(editable.toString()); - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); } } }; @@ -77,7 +74,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia public void afterTextChanged(Editable editable) { if (mViewModel != null) { mViewModel.setProxyPort(editable.toString()); - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); } } }; @@ -155,7 +152,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia proxySettingsLayout.setVisibility(View.GONE); } - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); }); displaySeedButton.setOnClickListener(view1 -> { @@ -233,8 +230,8 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia public void onNodeSelected() { Node node = PrefService.getInstance().getNode(); selectNodeButton.setText(getString(R.string.node_button_text, node.getAddress())); - mViewModel.updateProxy(((MoneroApplication)getActivity().getApplication())); - ((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> { + mViewModel.updateProxy(((MoneroApplication) getActivity().getApplication())); + ((MoneroApplication) getActivity().getApplication()).getExecutor().execute(() -> { WalletManager.getInstance().getWallet().init(0); WalletManager.getInstance().getWallet().startRefresh(); }); diff --git a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsViewModel.java b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsViewModel.java index 523bcd9..106156e 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsViewModel.java +++ b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsViewModel.java @@ -5,7 +5,6 @@ import android.util.Patterns; import androidx.lifecycle.ViewModel; import net.mynero.wallet.MoneroApplication; -import net.mynero.wallet.data.DefaultNodes; import net.mynero.wallet.data.Node; import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.service.PrefService; diff --git a/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionFragment.java b/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionFragment.java index 3e1f9f8..8ea4112 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionFragment.java @@ -92,16 +92,16 @@ public class TransactionFragment extends Fragment { HistoryService.getInstance().history.observe(getViewLifecycleOwner(), transactionInfos -> { TransactionInfo newTransactionInfo = findNewestVersionOfTransaction(this.transactionInfo, transactionInfos); - if(newTransactionInfo == null) return; + if (newTransactionInfo == null) return; txHashTextView.setText(newTransactionInfo.hash); txConfTextView.setText("" + newTransactionInfo.confirmations); txDateTextView.setText(getDateTime(newTransactionInfo.timestamp)); - if(newTransactionInfo.confirmations > 1) { + if (newTransactionInfo.confirmations > 1) { confLabel2.setText(getString(R.string.transaction_conf_desc2_confirmed)); blockHeightTextView.setText("" + newTransactionInfo.blockheight); blockHeightTextView.setVisibility(View.VISIBLE); - } else if(newTransactionInfo.confirmations == 1) { + } else if (newTransactionInfo.confirmations == 1) { confLabel2.setText(getString(R.string.transaction_conf_1_desc2_confirmed)); blockHeightTextView.setText("" + newTransactionInfo.blockheight); blockHeightTextView.setVisibility(View.VISIBLE); @@ -111,7 +111,7 @@ public class TransactionFragment extends Fragment { } Context ctx = getContext(); - if(ctx != null) { + if (ctx != null) { boolean streetModeEnabled = PrefService.getInstance().getBoolean(Constants.PREF_STREET_MODE, false); String balanceString = streetModeEnabled ? Constants.STREET_MODE_BALANCE : Helper.getDisplayAmount(newTransactionInfo.amount, 12); if (newTransactionInfo.direction == TransactionInfo.Direction.Direction_In) { @@ -147,8 +147,8 @@ public class TransactionFragment extends Fragment { } private TransactionInfo findNewestVersionOfTransaction(TransactionInfo oldTransactionInfo, List transactionInfoList) { - for(TransactionInfo transactionInfo : transactionInfoList) { - if(transactionInfo.hash.equals(oldTransactionInfo.hash)) { + for (TransactionInfo transactionInfo : transactionInfoList) { + if (transactionInfo.hash.equals(oldTransactionInfo.hash)) { this.transactionInfo = transactionInfo; return this.transactionInfo; } diff --git a/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionViewModel.java b/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionViewModel.java index e86ded1..da2e4b4 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionViewModel.java +++ b/app/src/main/java/net/mynero/wallet/fragment/transaction/TransactionViewModel.java @@ -1,12 +1,6 @@ package net.mynero.wallet.fragment.transaction; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; -import net.mynero.wallet.model.TransactionInfo; -import net.mynero.wallet.model.Wallet; -import net.mynero.wallet.model.WalletManager; - public class TransactionViewModel extends ViewModel { } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/fragment/utxos/UtxosFragment.java b/app/src/main/java/net/mynero/wallet/fragment/utxos/UtxosFragment.java index 98f4571..b318c5f 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/utxos/UtxosFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/utxos/UtxosFragment.java @@ -24,14 +24,12 @@ import net.mynero.wallet.util.MoneroThreadPoolExecutor; import net.mynero.wallet.util.UriData; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; -import java.util.List; public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInfoAdapterListener, SendBottomSheetDialog.Listener { - private UtxosViewModel mViewModel; private final CoinsInfoAdapter adapter = new CoinsInfoAdapter(this); + private UtxosViewModel mViewModel; private Button sendUtxosButton; private Button churnUtxosButton; private Button freezeUtxosButton; @@ -71,7 +69,7 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf }); sendUtxosButton.setOnClickListener(view1 -> { ArrayList selectedKeyImages = new ArrayList<>(); - for(CoinsInfo coinsInfo : adapter.selectedUtxos.values()) { + for (CoinsInfo coinsInfo : adapter.selectedUtxos.values()) { selectedKeyImages.add(coinsInfo.keyImage); } SendBottomSheetDialog sendDialog = new SendBottomSheetDialog(); @@ -81,7 +79,7 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf }); churnUtxosButton.setOnClickListener(view1 -> { ArrayList selectedKeyImages = new ArrayList<>(); - for(CoinsInfo coinsInfo : adapter.selectedUtxos.values()) { + for (CoinsInfo coinsInfo : adapter.selectedUtxos.values()) { selectedKeyImages.add(coinsInfo.keyImage); } SendBottomSheetDialog sendDialog = new SendBottomSheetDialog(); @@ -126,8 +124,8 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf } boolean frozenExists = false, unfrozenExists = false, bothExist = false; - for(CoinsInfo selectedUtxo : adapter.selectedUtxos.values()) { - if(selectedUtxo.isFrozen() || UTXOService.getInstance().isCoinFrozen(selectedUtxo)) + for (CoinsInfo selectedUtxo : adapter.selectedUtxos.values()) { + if (selectedUtxo.isFrozen() || UTXOService.getInstance().isCoinFrozen(selectedUtxo)) frozenExists = true; else { unfrozenExists = true; @@ -141,7 +139,7 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf freezeUtxosButton.setVisibility(View.GONE); freezeUtxosButton.setBackgroundResource(R.drawable.button_bg_left); } else { - if(frozenExists) { + if (frozenExists) { freezeUtxosButton.setBackgroundResource(R.drawable.button_bg); sendUtxosButton.setVisibility(View.GONE); churnUtxosButton.setVisibility(View.GONE); @@ -153,11 +151,11 @@ public class UtxosFragment extends Fragment implements CoinsInfoAdapter.CoinsInf freezeUtxosButton.setVisibility(View.VISIBLE); } - if(bothExist) { + if (bothExist) { freezeUtxosButton.setText(R.string.toggle_freeze); - } else if(frozenExists) { + } else if (frozenExists) { freezeUtxosButton.setText(R.string.unfreeze); - } else if(unfrozenExists) { + } else if (unfrozenExists) { freezeUtxosButton.setText(R.string.freeze); } } diff --git a/app/src/main/java/net/mynero/wallet/livedata/SingleLiveEvent.kt b/app/src/main/java/net/mynero/wallet/livedata/SingleLiveEvent.kt index 1b84b76..c9f1464 100644 --- a/app/src/main/java/net/mynero/wallet/livedata/SingleLiveEvent.kt +++ b/app/src/main/java/net/mynero/wallet/livedata/SingleLiveEvent.kt @@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicBoolean */ class SingleLiveEvent : MutableLiveData() { private val mPending = AtomicBoolean(false) + @MainThread override fun observe(owner: LifecycleOwner, observer: Observer) { if (hasActiveObservers()) { diff --git a/app/src/main/java/net/mynero/wallet/model/CoinsInfo.kt b/app/src/main/java/net/mynero/wallet/model/CoinsInfo.kt index c85ffec..9e63dfe 100644 --- a/app/src/main/java/net/mynero/wallet/model/CoinsInfo.kt +++ b/app/src/main/java/net/mynero/wallet/model/CoinsInfo.kt @@ -23,18 +23,24 @@ class CoinsInfo : Parcelable, Comparable { @JvmField var globalOutputIndex: Long var isSpent = false + @JvmField var keyImage: String? = null + @JvmField var amount: Long = 0 + @JvmField var hash: String? = null + @JvmField var pubKey: String? = null var isUnlocked = false + @JvmField var localOutputIndex: Long = 0 var isFrozen = false + @JvmField var address: String? = null @@ -89,7 +95,7 @@ class CoinsInfo : Parcelable, Comparable { companion object { @JvmField val CREATOR: Creator = object : Creator { - override fun createFromParcel(`in`: Parcel): CoinsInfo? { + override fun createFromParcel(`in`: Parcel): CoinsInfo { return CoinsInfo(`in`) } diff --git a/app/src/main/java/net/mynero/wallet/model/PendingTransaction.kt b/app/src/main/java/net/mynero/wallet/model/PendingTransaction.kt index a3a3a80..6fd5264 100644 --- a/app/src/main/java/net/mynero/wallet/model/PendingTransaction.kt +++ b/app/src/main/java/net/mynero/wallet/model/PendingTransaction.kt @@ -18,6 +18,7 @@ package net.mynero.wallet.model class PendingTransaction internal constructor(var handle: Long) { val status: Status get() = Status.values()[getStatusJ()] + external fun getStatusJ(): Int external fun getErrorString(): String? @@ -29,6 +30,7 @@ class PendingTransaction internal constructor(var handle: Long) { external fun getFee(): Long val firstTxId: String get() = getFirstTxIdJ() ?: throw IndexOutOfBoundsException() + external fun getFirstTxIdJ(): String? external fun getTxCount(): Long diff --git a/app/src/main/java/net/mynero/wallet/model/TransactionInfo.java b/app/src/main/java/net/mynero/wallet/model/TransactionInfo.java index aaff1e4..6f00568 100644 --- a/app/src/main/java/net/mynero/wallet/model/TransactionInfo.java +++ b/app/src/main/java/net/mynero/wallet/model/TransactionInfo.java @@ -170,10 +170,6 @@ public class TransactionInfo implements Parcelable, Comparable this.value = value; } - public int getValue() { - return value; - } - public static Direction fromInteger(int n) { switch (n) { case 0: @@ -183,5 +179,9 @@ public class TransactionInfo implements Parcelable, Comparable } return null; } + + public int getValue() { + return value; + } } } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/model/Transfer.kt b/app/src/main/java/net/mynero/wallet/model/Transfer.kt index c515df0..637a26c 100644 --- a/app/src/main/java/net/mynero/wallet/model/Transfer.kt +++ b/app/src/main/java/net/mynero/wallet/model/Transfer.kt @@ -21,6 +21,7 @@ import android.os.Parcelable.Creator class Transfer : Parcelable { var amount: Long + @JvmField var address: String? diff --git a/app/src/main/java/net/mynero/wallet/model/Wallet.kt b/app/src/main/java/net/mynero/wallet/model/Wallet.kt index 2b35f70..82077f6 100644 --- a/app/src/main/java/net/mynero/wallet/model/Wallet.kt +++ b/app/src/main/java/net/mynero/wallet/model/Wallet.kt @@ -85,6 +85,7 @@ class Wallet { } private external fun statusWithErrorString(): Status + @Synchronized external fun setPassword(password: String?): Boolean val address: String @@ -126,6 +127,7 @@ class Wallet { subaddress.amount = amount return subaddress } + external fun getPath(): String? val networkType: NetworkType? get() = fromInteger(nettype()) @@ -217,6 +219,7 @@ class Wallet { external fun getBalanceAll(): Long val unlockedBalance: Long get() = getUnlockedBalance(accountIndex) + external fun getUnlockedBalanceAll(): Long external fun getUnlockedBalance(accountIndex: Int): Long @@ -349,6 +352,7 @@ class Wallet { external fun setUserNote(txid: String?, note: String?): Boolean external fun getUserNote(txid: String?): String? external fun getTxKey(txid: String?): String? + @JvmOverloads external fun addAccount(label: String? = NEW_ACCOUNT_NAME) var accountLabel: String? @@ -428,6 +432,7 @@ class Wallet { class Status internal constructor(status: Int, @JvmField val errorString: String) { val status: StatusEnum + @JvmField var connectionStatus: ConnectionStatus? = null // optional @@ -454,22 +459,30 @@ class Wallet { @JvmStatic external fun getDisplayAmount(amount: Long): String + @JvmStatic external fun getAmountFromString(amount: String?): Long + @JvmStatic external fun getAmountFromDouble(amount: Double): Long + @JvmStatic external fun generatePaymentId(): String + @JvmStatic external fun isPaymentIdValid(payment_id: String): Boolean + @JvmStatic fun isAddressValid(address: String): Boolean { return instance?.networkType?.value?.let { isAddressValid(address, it) } == true } + @JvmStatic external fun isAddressValid(address: String?, networkType: Int): Boolean + @JvmStatic external fun getPaymentIdFromAddress(address: String?, networkType: Int): String? + @JvmStatic external fun getMaximumAllowedAmount(): Long } diff --git a/app/src/main/java/net/mynero/wallet/model/WalletManager.kt b/app/src/main/java/net/mynero/wallet/model/WalletManager.kt index 7f9664a..cd4e331 100644 --- a/app/src/main/java/net/mynero/wallet/model/WalletManager.kt +++ b/app/src/main/java/net/mynero/wallet/model/WalletManager.kt @@ -245,7 +245,8 @@ class WalletManager { fun findWallets(path: File): List { val wallets: MutableList = ArrayList() Timber.d("Scanning: %s", path.absolutePath) - val found = path.listFiles { dir, filename -> filename.endsWith(".keys") } ?: return emptyList() + val found = + path.listFiles { dir, filename -> filename.endsWith(".keys") } ?: return emptyList() for (i in found.indices) { val filename = found[i].name val f = File( @@ -354,16 +355,22 @@ class WalletManager { @JvmStatic external fun initLogger(argv0: String?, defaultLogBaseName: String?) + @JvmStatic external fun setLogLevel(level: Int) + @JvmStatic external fun logDebug(category: String?, message: String?) + @JvmStatic external fun logInfo(category: String?, message: String?) + @JvmStatic external fun logWarning(category: String?, message: String?) + @JvmStatic external fun logError(category: String?, message: String?) + @JvmStatic external fun moneroVersion(): String? } diff --git a/app/src/main/java/net/mynero/wallet/service/AddressService.java b/app/src/main/java/net/mynero/wallet/service/AddressService.java index 2b883e7..8e82491 100644 --- a/app/src/main/java/net/mynero/wallet/service/AddressService.java +++ b/app/src/main/java/net/mynero/wallet/service/AddressService.java @@ -1,15 +1,11 @@ package net.mynero.wallet.service; -import net.mynero.wallet.MoneroApplication; import net.mynero.wallet.data.Subaddress; -import net.mynero.wallet.model.TransactionInfo; import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.WalletManager; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; -import java.util.List; import java.util.Locale; public class AddressService extends ServiceBase { diff --git a/app/src/main/java/net/mynero/wallet/service/BalanceService.java b/app/src/main/java/net/mynero/wallet/service/BalanceService.java index 8bce1b6..4b4e76c 100644 --- a/app/src/main/java/net/mynero/wallet/service/BalanceService.java +++ b/app/src/main/java/net/mynero/wallet/service/BalanceService.java @@ -5,9 +5,6 @@ import androidx.lifecycle.MutableLiveData; import net.mynero.wallet.model.BalanceInfo; import net.mynero.wallet.model.CoinsInfo; -import net.mynero.wallet.model.Wallet; -import net.mynero.wallet.model.WalletManager; -import net.mynero.wallet.util.Constants; public class BalanceService extends ServiceBase { public static BalanceService instance = null; @@ -31,8 +28,8 @@ public class BalanceService extends ServiceBase { public long getUnlockedBalanceRaw() { long unlocked = 0; - for(CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) { - if(!coinsInfo.isSpent() && !coinsInfo.isFrozen() && coinsInfo.isUnlocked() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) { + for (CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) { + if (!coinsInfo.isSpent() && !coinsInfo.isFrozen() && coinsInfo.isUnlocked() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) { unlocked += coinsInfo.amount; } } @@ -41,8 +38,8 @@ public class BalanceService extends ServiceBase { public long getTotalBalanceRaw() { long total = 0; - for(CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) { - if(!coinsInfo.isSpent() && !coinsInfo.isFrozen() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) { + for (CoinsInfo coinsInfo : UTXOService.getInstance().getUtxos()) { + if (!coinsInfo.isSpent() && !coinsInfo.isFrozen() && !UTXOService.getInstance().isCoinFrozen(coinsInfo)) { total += coinsInfo.amount; } } diff --git a/app/src/main/java/net/mynero/wallet/service/MoneroHandlerThread.java b/app/src/main/java/net/mynero/wallet/service/MoneroHandlerThread.java index f2ef98f..663a0bd 100644 --- a/app/src/main/java/net/mynero/wallet/service/MoneroHandlerThread.java +++ b/app/src/main/java/net/mynero/wallet/service/MoneroHandlerThread.java @@ -120,7 +120,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener { private void refresh(boolean walletSynced) { wallet.refreshHistory(); - if(walletSynced) { + if (walletSynced) { wallet.refreshCoins(); } listener.onRefresh(walletSynced); @@ -136,7 +136,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener { long totalAmount = 0; ArrayList outputs = new ArrayList<>(); - for(Pair dest : dests) { + for (Pair dest : dests) { long amount = Wallet.getAmountFromString(dest.component2()); totalAmount += amount; outputs.add(new TransactionOutput(dest.component1(), amount)); @@ -150,7 +150,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener { checkSelectedAmounts(preferredInputs, totalAmount, sendAll); } - if(sendAll) { + if (sendAll) { Pair dest = dests.get(0); String address = dest.component1(); return wallet.createSweepTransaction(address, feePriority, preferredInputs); @@ -165,7 +165,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener { String paymentId = Wallet.getPaymentIdFromAddress(mainDestination.destination, WalletManager.getInstance().networkType.value); ArrayList newOutputs = new ArrayList<>(outputs); boolean donatePerTx = PrefService.getInstance().getBoolean(Constants.PREF_DONATE_PER_TX, false); - if(donatePerTx && paymentId.isEmpty()) { // only attach donation when no payment id is needed (i.e. integrated address) + if (donatePerTx && paymentId.isEmpty()) { // only attach donation when no payment id is needed (i.e. integrated address) SecureRandom rand = new SecureRandom(); float randomDonatePct = getRandomDonateAmount(0.005f, 0.015f); // occasionally attaches a 0.5% to 1.5% donation. It is random so that not even I know how much exactly you are sending. /* @@ -173,14 +173,14 @@ public class MoneroHandlerThread extends Thread implements WalletListener { it will periodically split it up into multiple outputs instead of one. */ int attachDonationRoll = rand.nextInt(100); - if(attachDonationRoll > 90) { // 10% chance of being added + if (attachDonationRoll > 90) { // 10% chance of being added int splitDonationRoll = rand.nextInt(100); - long donateAmount = (long) (amount*randomDonatePct); - if(splitDonationRoll > 50) { // 50% chance of being split + long donateAmount = (long) (amount * randomDonatePct); + if (splitDonationRoll > 50) { // 50% chance of being split // split int split = genRandomDonationSplit(1, 4); // splits into at most 4 outputs, for a total of 6 outputs in the transaction (real dest + change. we don't add donations to send-all/sweep transactions) long splitAmount = donateAmount / split; - for(int i = 0; i < split; i++) { + for (int i = 0; i < split; i++) { // TODO this can be expanded upon into the future to perform an auto-splitting/auto-churning for the user if their wallet is fresh and has few utxos. // randomly split between multiple wallets int randomDonationAddress = rand.nextInt(Constants.DONATION_ADDRESSES.length); @@ -232,6 +232,7 @@ public class MoneroHandlerThread extends Thread implements WalletListener { public interface Listener { void onRefresh(boolean walletSynced); + void onConnectionFail(); } } diff --git a/app/src/main/java/net/mynero/wallet/service/PrefService.java b/app/src/main/java/net/mynero/wallet/service/PrefService.java index bea2a25..150bd2b 100644 --- a/app/src/main/java/net/mynero/wallet/service/PrefService.java +++ b/app/src/main/java/net/mynero/wallet/service/PrefService.java @@ -8,7 +8,6 @@ import net.mynero.wallet.data.DefaultNodes; import net.mynero.wallet.data.Node; import net.mynero.wallet.util.Constants; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -22,6 +21,10 @@ public class PrefService extends ServiceBase { instance = this; } + public static PrefService getInstance() { + return instance; + } + public SharedPreferences.Editor edit() { return preferences.edit(); } @@ -29,11 +32,11 @@ public class PrefService extends ServiceBase { public Node getNode() { boolean usesProxy = getBoolean(Constants.PREF_USES_TOR, false); DefaultNodes defaultNode = DefaultNodes.SAMOURAI; - if(usesProxy) { + if (usesProxy) { String proxyPort = getProxyPort(); if (!proxyPort.isEmpty()) { int port = Integer.parseInt(proxyPort); - if(port == 4447) { + if (port == 4447) { defaultNode = DefaultNodes.MYNERO_I2P; } else { defaultNode = DefaultNodes.MYNERO_ONION; @@ -51,9 +54,9 @@ public class PrefService extends ServiceBase { } private Node upgradeOldNode(String nodeString) { - if(!nodeString.isEmpty()) { + if (!nodeString.isEmpty()) { Node node = Node.fromString(nodeString); - if(node != null) { + if (node != null) { edit().putString(Constants.PREF_NODE_2, node.toJson().toString()).apply(); return node; } @@ -88,7 +91,7 @@ public class PrefService extends ServiceBase { public String getString(String key, String defaultValue) { String value = preferences.getString(key, ""); - if(value.isEmpty() && !defaultValue.isEmpty()) { + if (value.isEmpty() && !defaultValue.isEmpty()) { edit().putString(key, defaultValue).apply(); return defaultValue; } @@ -98,14 +101,10 @@ public class PrefService extends ServiceBase { public boolean getBoolean(String key, boolean defaultValue) { boolean containsKey = preferences.contains(key); boolean value = preferences.getBoolean(key, false); - if(!value && defaultValue && !containsKey) { + if (!value && defaultValue && !containsKey) { edit().putBoolean(key, true).apply(); return true; } return value; } - - public static PrefService getInstance() { - return instance; - } } diff --git a/app/src/main/java/net/mynero/wallet/service/UTXOService.java b/app/src/main/java/net/mynero/wallet/service/UTXOService.java index 364f7ad..b7aa222 100644 --- a/app/src/main/java/net/mynero/wallet/service/UTXOService.java +++ b/app/src/main/java/net/mynero/wallet/service/UTXOService.java @@ -21,9 +21,9 @@ import java.util.List; public class UTXOService extends ServiceBase { public static UTXOService instance = null; - private List internalCachedUtxos = new ArrayList<>(); private final MutableLiveData> _utxos = new MutableLiveData<>(); public LiveData> utxos = _utxos; + private List internalCachedUtxos = new ArrayList<>(); private ArrayList frozenCoins = new ArrayList<>(); public UTXOService(MoneroHandlerThread thread) { @@ -56,8 +56,8 @@ public class UTXOService extends ServiceBase { public void toggleFrozen(HashMap selectedCoins) { ArrayList frozenCoinsCopy = new ArrayList<>(frozenCoins); - for(CoinsInfo coin : selectedCoins.values()) { - if(frozenCoinsCopy.contains(coin.pubKey)) { + for (CoinsInfo coin : selectedCoins.values()) { + if (frozenCoinsCopy.contains(coin.pubKey)) { frozenCoinsCopy.remove(coin.pubKey); } else { frozenCoinsCopy.add(coin.pubKey); @@ -77,7 +77,7 @@ public class UTXOService extends ServiceBase { PrefService prefService = PrefService.getInstance(); String frozenCoinsArrayString = prefService.getString(Constants.PREF_FROZEN_COINS, "[]"); JSONArray frozenCoinsArray = new JSONArray(frozenCoinsArrayString); - for(int i = 0; i < frozenCoinsArray.length(); i++) { + for (int i = 0; i < frozenCoinsArray.length(); i++) { String pubKey = frozenCoinsArray.getString(i); frozenCoins.add(pubKey); } @@ -88,7 +88,7 @@ public class UTXOService extends ServiceBase { PrefService prefService = PrefService.getInstance(); JSONArray jsonArray = new JSONArray(); ArrayList frozenCoinsCopy = new ArrayList<>(frozenCoins); - for(String pubKey : frozenCoinsCopy) { + for (String pubKey : frozenCoinsCopy) { jsonArray.put(pubKey); } prefService.edit().putString(Constants.PREF_FROZEN_COINS, jsonArray.toString()).apply(); diff --git a/app/src/main/java/net/mynero/wallet/util/Constants.kt b/app/src/main/java/net/mynero/wallet/util/Constants.kt index 4b988c7..d031e6b 100644 --- a/app/src/main/java/net/mynero/wallet/util/Constants.kt +++ b/app/src/main/java/net/mynero/wallet/util/Constants.kt @@ -18,6 +18,7 @@ object Constants { const val URI_ARG_AMOUNT2 = "amount" const val NAV_ARG_TXINFO = "nav_arg_txinfo" const val STREET_MODE_BALANCE = "#.############" + @JvmField val DONATION_ADDRESSES = arrayOf( "87BqQYkugEzh6Tuyotm2uc3DzJzKM6MuZaC161e6u1TsQxxPmXVPHpdNRyK47JY4d1hhbe25YVz4e9vTXCLDxvHkRXEAeBC", // primary Mysu Donation address diff --git a/app/src/main/java/net/mynero/wallet/util/DateHelper.kt b/app/src/main/java/net/mynero/wallet/util/DateHelper.kt index 1f6ae29..3b5777f 100644 --- a/app/src/main/java/net/mynero/wallet/util/DateHelper.kt +++ b/app/src/main/java/net/mynero/wallet/util/DateHelper.kt @@ -22,6 +22,7 @@ import java.util.Date object DateHelper { @JvmField val DATETIME_FORMATTER = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + @Throws(ParseException::class) fun parse(dateString: String): Date { return DATETIME_FORMATTER.parse(dateString.replace("Z$".toRegex(), "+0000")) diff --git a/app/src/main/java/net/mynero/wallet/util/Helper.kt b/app/src/main/java/net/mynero/wallet/util/Helper.kt index 91c019a..3f3d120 100644 --- a/app/src/main/java/net/mynero/wallet/util/Helper.kt +++ b/app/src/main/java/net/mynero/wallet/util/Helper.kt @@ -45,7 +45,6 @@ import java.io.File import java.io.IOException import java.io.InputStreamReader import java.math.BigDecimal -import java.math.BigInteger import java.net.MalformedURLException import java.net.SocketTimeoutException import java.net.URL @@ -63,6 +62,7 @@ object Helper { private const val MONERO_DIR = "monero" private val HexArray = "0123456789ABCDEF".toCharArray() var ALLOW_SHIFT = false + @JvmField var DISPLAY_DIGITS_INFO = 5 private var ShakeAnimation: Animation? = null diff --git a/app/src/main/java/net/mynero/wallet/util/RestoreHeight.kt b/app/src/main/java/net/mynero/wallet/util/RestoreHeight.kt index 06c4f19..4092cf6 100644 --- a/app/src/main/java/net/mynero/wallet/util/RestoreHeight.kt +++ b/app/src/main/java/net/mynero/wallet/util/RestoreHeight.kt @@ -194,6 +194,7 @@ class RestoreHeight internal constructor() { companion object { const val DIFFICULTY_TARGET = 120 // seconds private var Singleton: RestoreHeight? = null + @JvmStatic val instance: RestoreHeight? get() { diff --git a/app/src/main/java/net/mynero/wallet/util/UriData.kt b/app/src/main/java/net/mynero/wallet/util/UriData.kt index f1b9575..105a905 100644 --- a/app/src/main/java/net/mynero/wallet/util/UriData.kt +++ b/app/src/main/java/net/mynero/wallet/util/UriData.kt @@ -7,7 +7,8 @@ import net.mynero.wallet.model.WalletManager.Companion.instance class UriData(@JvmField val address: String, val params: HashMap) { fun hasPaymentId(): Boolean { - return instance?.wallet?.nettype()?.let { getPaymentIdFromAddress(address, it) }?.isNotEmpty() == true + return instance?.wallet?.nettype()?.let { getPaymentIdFromAddress(address, it) } + ?.isNotEmpty() == true } val amount: String? @@ -21,13 +22,13 @@ class UriData(@JvmField val address: String, val params: HashMap companion object { @JvmStatic fun parse(uri: String): UriData? { - if(uri.isEmpty()) return null + if (uri.isEmpty()) return null val params = HashMap() val uriParts = uri.replace(Constants.URI_PREFIX, "").split("\\?".toRegex()) .dropLastWhile { it.isEmpty() } .toTypedArray() - if(uriParts.isEmpty()) return null + if (uriParts.isEmpty()) return null val finalAddress = uriParts[0] var queryParams = "" if (uriParts.size > 1) {