<NME> trackAddressMismatch.kt
<BEF> /**
 * BreadWallet
 *
 * Created by Drew Carlson <drew.carlson@breadwallet.com> on 2/27/20.
 * Copyright (c) 2020 breadwallet LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.breadwallet.util

import com.breadwallet.tools.crypto.CryptoHelper.hexEncode
import com.breadwallet.tools.crypto.CryptoHelper.keccak256
import com.breadwallet.tools.util.EventUtils
import com.google.firebase.crashlytics.FirebaseCrashlytics

private const val ETH_ADDRESS_BYTES = 20

fun ByteArray?.pubKeyToEthAddress(): String? = when {
    this == null || isEmpty() -> null
    else -> {
        val addressBytes = keccak256(sliceArray(1..lastIndex))
            ?.takeLast(ETH_ADDRESS_BYTES)
            ?.toByteArray()
        if (addressBytes?.size == ETH_ADDRESS_BYTES) {
            "0x${hexEncode(addressBytes)}"
        } else null
    }
}

private fun sendMismatchEvent(
    ethAddressHash: String,
import kotlinx.coroutines.flow.transform
import org.kodein.di.erased.instance

private const val ETH_PUB_KEY_LENGTH = 20

@Suppress("LongMethod", "ReturnCount")
suspend fun BreadApp.trackAddressMismatch(breadBox: BreadBox) {
    val oldPubKeyBytes = BRKeyStore.getEthPublicKey(this)
    if (oldPubKeyBytes?.isEmpty() == true) {
        return
    }
    val oldEthAddressBytes = keccak256(oldPubKeyBytes)
        ?.takeLast(ETH_PUB_KEY_LENGTH)?.toByteArray()
    if (oldEthAddressBytes == null) {
        logError("Failed to read old address bytes.")
        return
    }
    val ethWallet = breadBox.wallet("eth").first()
    val oldAddressString = "0x${hexEncode(oldEthAddressBytes)}"
    val coreAddressOld = ethWallet.addressFor(oldAddressString)
    if (coreAddressOld == null) {
        logError("Failed to get core Address for old eth address.")
    }
}

private fun balanceString(string: String) = when (string) {
    "unknown" -> "unknown"
    "0x0", "0" -> "no"
    else -> "yes"
}

<MSG> Merge branch 'drew/DROID-1629' into 'develop'

DROID-1629: Include old address in send logs

Closes DROID-1629

See merge request breadwallet/breadwallet-android!1033
<DFF> @@ -48,22 +48,24 @@ import kotlinx.coroutines.flow.toList
 import kotlinx.coroutines.flow.transform
 import org.kodein.di.erased.instance
 
-private const val ETH_PUB_KEY_LENGTH = 20
+private const val ETH_ADDRESS_BYTES = 20
+
+fun ByteArray?.pubKeyToEthAddress(): String? = when {
+    this == null || isEmpty() -> null
+    else -> {
+        val addressBytes = keccak256(this)
+            ?.takeLast(ETH_ADDRESS_BYTES)
+            ?.toByteArray()
+        if (addressBytes?.size == ETH_ADDRESS_BYTES) {
+            "0x${hexEncode(addressBytes)}"
+        } else null
+    }
+}
 
 @Suppress("LongMethod", "ReturnCount")
 suspend fun BreadApp.trackAddressMismatch(breadBox: BreadBox) {
-    val oldPubKeyBytes = BRKeyStore.getEthPublicKey(this)
-    if (oldPubKeyBytes?.isEmpty() == true) {
-        return
-    }
-    val oldEthAddressBytes = keccak256(oldPubKeyBytes)
-        ?.takeLast(ETH_PUB_KEY_LENGTH)?.toByteArray()
-    if (oldEthAddressBytes == null) {
-        logError("Failed to read old address bytes.")
-        return
-    }
+    val oldAddressString = BRKeyStore.getEthPublicKey(this).pubKeyToEthAddress() ?: return
     val ethWallet = breadBox.wallet("eth").first()
-    val oldAddressString = "0x${hexEncode(oldEthAddressBytes)}"
     val coreAddressOld = ethWallet.addressFor(oldAddressString)
     if (coreAddressOld == null) {
         logError("Failed to get core Address for old eth address.")

{'commit': 'diff --git a/app/src/main/java/com/breadwallet/app/BreadApp.kt b/app/src/main/java/com/breadwallet/app/BreadApp.kt\nindex 30fbfdbab..f36c554d8 100644\n--- a/app/src/main/java/com/breadwallet/app/BreadApp.kt\n+++ b/app/src/main/java/com/breadwallet/app/BreadApp.kt\n@@ -240,7 +240,7 @@ class BreadApp : Application(), KodeinAware {\n         // TODO: This entire operation should be moved into a separate class.\n         @Synchronized\n         @Suppress("ReturnCount")\n-        private fun generateWalletId(address: String): String? {\n+        fun generateWalletId(address: String): String? {\n             try {\n                 // Remove the first 2 characters i.e. 0x\n                 val rawAddress = address.drop(2)\ndiff --git a/app/src/main/java/com/breadwallet/tools/util/LogsUtils.java b/app/src/main/java/com/breadwallet/tools/util/LogsUtils.java\nindex 834a35742..d0cbb890c 100644\n--- a/app/src/main/java/com/breadwallet/tools/util/LogsUtils.java\n+++ b/app/src/main/java/com/breadwallet/tools/util/LogsUtils.java\n@@ -5,18 +5,25 @@ import android.content.Context;\n import android.content.Intent;\n import android.net.Uri;\n import android.os.Build;\n-import androidx.core.content.FileProvider;\n import android.widget.Toast;\n-\n+import androidx.core.content.FileProvider;\n import com.breadwallet.BuildConfig;\n import com.breadwallet.R;\n+import com.breadwallet.app.BreadApp;\n+import com.breadwallet.crypto.Address;\n+import com.breadwallet.crypto.Network;\n+import com.breadwallet.crypto.System;\n+import com.breadwallet.crypto.Wallet;\n import com.breadwallet.legacy.presenter.customviews.BRToast;\n import com.breadwallet.tools.manager.BRSharedPrefs;\n-\n+import com.breadwallet.tools.security.BRKeyStore;\n import org.apache.commons.io.IOUtils;\n \n import java.io.File;\n import java.io.IOException;\n+import java.util.List;\n+\n+import static com.breadwallet.util.TrackAddressMismatchKt.pubKeyToEthAddress;\n \n /**\n  * BreadWallet\n@@ -88,6 +95,36 @@ public class LogsUtils {\n         stringBuilder.append("\\nOS Version: " + Build.VERSION.RELEASE);\n         stringBuilder.append("\\nDevice Type: " + (Build.MANUFACTURER + " " + Build.MODEL + "\\n"));\n \n+        System system = BreadApp.Companion.getBreadBox().getSystemUnsafe();\n+        if (system != null) {\n+            List<? extends Wallet> wallets = system.getWallets();\n+            Wallet ethWallet = null;\n+\n+            for (Wallet wallet : wallets) {\n+                if (wallet.getCurrency().getCode().equalsIgnoreCase("eth")) {\n+                    ethWallet = wallet;\n+                    break;\n+                }\n+            }\n+\n+            String storedAddress = pubKeyToEthAddress(BRKeyStore.getEthPublicKey(context));\n+            if (storedAddress != null) {\n+                Network network = ethWallet.getWalletManager().getNetwork();\n+                Address coreAddress = Address.create(storedAddress, network).orNull();\n+\n+                if (coreAddress != null && ethWallet.getTarget() != coreAddress) {\n+                    String walletId = null;\n+                    try {\n+                        walletId = BreadApp.Companion.generateWalletId(storedAddress);\n+                    } catch (Exception error) {\n+                        error.printStackTrace();\n+                    }\n+                    stringBuilder.append("Address: " + storedAddress);\n+                    stringBuilder.append("Id: " + walletId);\n+                }\n+            }\n+        }\n+\n         return stringBuilder.toString();\n     }\n \ndiff --git a/app/src/main/java/com/breadwallet/util/trackAddressMismatch.kt b/app/src/main/java/com/breadwallet/util/trackAddressMismatch.kt\nindex 17cdf73ef..91664e34e 100644\n--- a/app/src/main/java/com/breadwallet/util/trackAddressMismatch.kt\n+++ b/app/src/main/java/com/breadwallet/util/trackAddressMismatch.kt\n@@ -48,22 +48,24 @@ import kotlinx.coroutines.flow.toList\n import kotlinx.coroutines.flow.transform\n import org.kodein.di.erased.instance\n \n-private const val ETH_PUB_KEY_LENGTH = 20\n+private const val ETH_ADDRESS_BYTES = 20\n+\n+fun ByteArray?.pubKeyToEthAddress(): String? = when {\n+    this == null || isEmpty() -> null\n+    else -> {\n+        val addressBytes = keccak256(this)\n+            ?.takeLast(ETH_ADDRESS_BYTES)\n+            ?.toByteArray()\n+        if (addressBytes?.size == ETH_ADDRESS_BYTES) {\n+            "0x${hexEncode(addressBytes)}"\n+        } else null\n+    }\n+}\n \n @Suppress("LongMethod", "ReturnCount")\n suspend fun BreadApp.trackAddressMismatch(breadBox: BreadBox) {\n-    val oldPubKeyBytes = BRKeyStore.getEthPublicKey(this)\n-    if (oldPubKeyBytes?.isEmpty() == true) {\n-        return\n-    }\n-    val oldEthAddressBytes = keccak256(oldPubKeyBytes)\n-        ?.takeLast(ETH_PUB_KEY_LENGTH)?.toByteArray()\n-    if (oldEthAddressBytes == null) {\n-        logError("Failed to read old address bytes.")\n-        return\n-    }\n+    val oldAddressString = BRKeyStore.getEthPublicKey(this).pubKeyToEthAddress() ?: return\n     val ethWallet = breadBox.wallet("eth").first()\n-    val oldAddressString = "0x${hexEncode(oldEthAddressBytes)}"\n     val coreAddressOld = ethWallet.addressFor(oldAddressString)\n     if (coreAddressOld == null) {\n         logError("Failed to get core Address for old eth address.")\n', 'commit_subject': "Merge branch 'drew/DROID-1629' into 'develop'", 'repo_name': 'breadwallet/breadwallet-android', 'committer': {'name': 'Drew Carlson', 'email': '98e34cb345eb537e565243a679c3e011566996b4@pm.me', 'time_sec': '1582930716', 'tz_offset': '0', 'date': {'seconds': '1582930716'}}, 'commit_tree': '7a5857c62d40feddef2f50f112a842ae8057b3ac', 'commit_message': "Merge branch 'drew/DROID-1629' into 'develop'\n\nDROID-1629: Include old address in send logs\n\nCloses DROID-1629\n\nSee merge request breadwallet/breadwallet-android!1033", 'language_name': 'HTML', 'license': 'mit', 'hunks': '@@ -48,22 +48,24 @@ import kotlinx.coroutines.flow.toList\n import kotlinx.coroutines.flow.transform\n import org.kodein.di.erased.instance\n \n-private const val ETH_PUB_KEY_LENGTH = 20\n+private const val ETH_ADDRESS_BYTES = 20\n+\n+fun ByteArray?.pubKeyToEthAddress(): String? = when {\n+    this == null || isEmpty() -> null\n+    else -> {\n+        val addressBytes = keccak256(this)\n+            ?.takeLast(ETH_ADDRESS_BYTES)\n+            ?.toByteArray()\n+        if (addressBytes?.size == ETH_ADDRESS_BYTES) {\n+            "0x${hexEncode(addressBytes)}"\n+        } else null\n+    }\n+}\n \n @Suppress("LongMethod", "ReturnCount")\n suspend fun BreadApp.trackAddressMismatch(breadBox: BreadBox) {\n-    val oldPubKeyBytes = BRKeyStore.getEthPublicKey(this)\n-    if (oldPubKeyBytes?.isEmpty() == true) {\n-        return\n-    }\n-    val oldEthAddressBytes = keccak256(oldPubKeyBytes)\n-        ?.takeLast(ETH_PUB_KEY_LENGTH)?.toByteArray()\n-    if (oldEthAddressBytes == null) {\n-        logError("Failed to read old address bytes.")\n-        return\n-    }\n+    val oldAddressString = BRKeyStore.getEthPublicKey(this).pubKeyToEthAddress() ?: return\n     val ethWallet = breadBox.wallet("eth").first()\n-    val oldAddressString = "0x${hexEncode(oldEthAddressBytes)}"\n     val coreAddressOld = ethWallet.addressFor(oldAddressString)\n     if (coreAddressOld == null) {\n         logError("Failed to get core Address for old eth address.")\n', 'addition_count': 14, 'deletion_count': 12, 'src_file': 'a/app/src/main/java/com/breadwallet/util/trackAddressMismatch.kt', 'tgt_file': 'b/app/src/main/java/com/breadwallet/util/trackAddressMismatch.kt', 'file_extension': '.kt', 'before_file': '/**\n * BreadWallet\n *\n * Created by Drew Carlson <drew.carlson@breadwallet.com> on 2/27/20.\n * Copyright (c) 2020 breadwallet LLC\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the "Software"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.breadwallet.util\n\nimport com.breadwallet.tools.crypto.CryptoHelper.hexEncode\nimport com.breadwallet.tools.crypto.CryptoHelper.keccak256\nimport com.breadwallet.tools.util.EventUtils\nimport com.google.firebase.crashlytics.FirebaseCrashlytics\n\nprivate const val ETH_ADDRESS_BYTES = 20\n\nfun ByteArray?.pubKeyToEthAddress(): String? = when {\n    this == null || isEmpty() -> null\n    else -> {\n        val addressBytes = keccak256(sliceArray(1..lastIndex))\n            ?.takeLast(ETH_ADDRESS_BYTES)\n            ?.toByteArray()\n        if (addressBytes?.size == ETH_ADDRESS_BYTES) {\n            "0x${hexEncode(addressBytes)}"\n        } else null\n    }\n}\n\nprivate fun sendMismatchEvent(\n    ethAddressHash: String,\nimport kotlinx.coroutines.flow.transform\nimport org.kodein.di.erased.instance\n\nprivate const val ETH_PUB_KEY_LENGTH = 20\n\n@Suppress("LongMethod", "ReturnCount")\nsuspend fun BreadApp.trackAddressMismatch(breadBox: BreadBox) {\n    val oldPubKeyBytes = BRKeyStore.getEthPublicKey(this)\n    if (oldPubKeyBytes?.isEmpty() == true) {\n        return\n    }\n    val oldEthAddressBytes = keccak256(oldPubKeyBytes)\n        ?.takeLast(ETH_PUB_KEY_LENGTH)?.toByteArray()\n    if (oldEthAddressBytes == null) {\n        logError("Failed to read old address bytes.")\n        return\n    }\n    val ethWallet = breadBox.wallet("eth").first()\n    val oldAddressString = "0x${hexEncode(oldEthAddressBytes)}"\n    val coreAddressOld = ethWallet.addressFor(oldAddressString)\n    if (coreAddressOld == null) {\n        logError("Failed to get core Address for old eth address.")\n    }\n}\n\nprivate fun balanceString(string: String) = when (string) {\n    "unknown" -> "unknown"\n    "0x0", "0" -> "no"\n    else -> "yes"\n}\n', 'message': "Merge branch 'drew/DROID-1629' into 'develop'\n\nDROID-1629: Include old address in send logs\n\nCloses DROID-1629\n\nSee merge request breadwallet/breadwallet-android!1033", 'author_name': 'Drew Carlson', 'lang': 'kt'}