From 8af2042039e3be781c12976edfc590a375a47c75 Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Thu, 25 Apr 2019 17:43:07 -0500 Subject: [PATCH] Verify that the node is synced before trying to broadcast a transaction in TransactionsActivity, to avoid users confusion. Ideally, the app should not be connected to an out of sync node, but this is in case that still happens. --- .../fragments/SendTransactionFragment.kt | 31 ++++++++++++------- .../bitsybitshareswallet/utils/Constants.kt | 3 ++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SendTransactionFragment.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SendTransactionFragment.kt index 224255e..1e7b174 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SendTransactionFragment.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SendTransactionFragment.kt @@ -1,6 +1,5 @@ package cy.agorise.bitsybitshareswallet.fragments -import android.Manifest import android.content.pm.PackageManager import android.os.Bundle import android.os.Handler @@ -10,6 +9,7 @@ import android.view.* import android.widget.AdapterView import android.widget.Toast import androidx.appcompat.widget.Toolbar +import androidx.collection.LongSparseArray import androidx.core.content.ContextCompat import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders @@ -99,7 +99,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand private var mSelectedUserAccount: UserAccount? = null // Map used to keep track of request and response id pairs - private val responseMap = HashMap() + private val responseMap = LongSparseArray() /** Transaction being built */ private var transaction: Transaction? = null @@ -147,7 +147,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand mViewModel= ViewModelProviders.of(this).get(SendTransactionViewModel::class.java) mViewModel.getWIF(userId, AuthorityType.ACTIVE.ordinal).observe(this, - androidx.lifecycle.Observer { encryptedWIF -> + Observer { encryptedWIF -> context?.let { try { wifKey = CryptoUtils.decrypt(it, encryptedWIF) @@ -243,8 +243,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand override fun handleJsonRpcResponse(response: JsonRpcResponse<*>) { if (responseMap.containsKey(response.id)) { - val responseType = responseMap[response.id] - when (responseType) { + when (responseMap[response.id]) { RESPONSE_GET_ACCOUNT_BY_NAME -> handleAccountProperties(response.result) RESPONSE_GET_DYNAMIC_GLOBAL_PROPERTIES -> handleDynamicGlobalProperties(response.result) RESPONSE_GET_REQUIRED_FEES -> handleRequiredFees(response.result) @@ -285,7 +284,17 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand * calls the next step which is [GetRequiredFees] else it shows an error */ private fun handleDynamicGlobalProperties(result: Any?) { if (result is DynamicGlobalProperties) { - val expirationTime = (result.time.time / 1000) + Transaction.DEFAULT_EXPIRATION_TIME + + val now = System.currentTimeMillis() / 1000 + val time = result.time.time / 1000 + + // Show an error if the current connected node is out of sync + if (now - time > Constants.CHECK_NODE_OUT_OF_SYNC) { + context?.toast(getString(R.string.msg__transaction_not_sent)) + return + } + + val expirationTime = time + Transaction.DEFAULT_EXPIRATION_TIME val headBlockId = result.head_block_id val headBlockNumber = result.head_block_number @@ -294,7 +303,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand val asset = Asset(mBalancesDetailsAdapter!!.getItem(spAsset.selectedItemPosition)!!.id) val id = mNetworkService?.sendMessage(GetRequiredFees(transaction!!, asset), GetRequiredFees.REQUIRED_API) - if (id != null) responseMap[id] = RESPONSE_GET_REQUIRED_FEES + if (id != null) responseMap.append(id, RESPONSE_GET_REQUIRED_FEES) } else { context?.toast(getString(R.string.msg__transaction_not_sent)) } @@ -308,7 +317,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand transaction!!.setFees(result as List) // TODO find how to remove this warning val id = mNetworkService?.sendMessage(BroadcastTransaction(transaction), BroadcastTransaction.REQUIRED_API) - if (id != null) responseMap[id] = RESPONSE_BROADCAST_TRANSACTION + if (id != null) responseMap.append(id, RESPONSE_BROADCAST_TRANSACTION) } else { context?.toast(getString(R.string.msg__transaction_not_sent)) } @@ -329,7 +338,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand /** Verifies if the user has already granted the Camera permission, if not the asks for it */ private fun verifyCameraPermission() { - if (ContextCompat.checkSelfPermission(activity!!, Manifest.permission.CAMERA) + if (ContextCompat.checkSelfPermission(activity!!, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // Permission is not already granted requestPermissions(arrayOf(android.Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION) @@ -442,7 +451,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand private fun validateAccount(accountName: String) { isToAccountCorrect = false val id = mNetworkService?.sendMessage(GetAccountByName(accountName), GetAccountByName.REQUIRED_API) - if (id != null) responseMap[id] = RESPONSE_GET_ACCOUNT_BY_NAME + if (id != null) responseMap.append(id, RESPONSE_GET_ACCOUNT_BY_NAME) } private fun validateAmount() { @@ -570,7 +579,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand // Start the send transaction procedure which includes a series of calls val id = mNetworkService?.sendMessage(GetDynamicGlobalProperties(), GetDynamicGlobalProperties.REQUIRED_API) - if (id != null ) responseMap[id] = RESPONSE_GET_DYNAMIC_GLOBAL_PROPERTIES + if (id != null ) responseMap.append(id, RESPONSE_GET_DYNAMIC_GLOBAL_PROPERTIES) } else Log.d(TAG, "Network Service is not connected") } diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/Constants.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/Constants.kt index bb01c6e..55d87ea 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/Constants.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/Constants.kt @@ -122,6 +122,9 @@ object Constants { /** Name of the external storage folder used to save files like PDF and CSV exports and Backups **/ const val EXTERNAL_STORAGE_FOLDER = "BiTSy" + /** Constant used to check if the current connected node is out of sync */ + const val CHECK_NODE_OUT_OF_SYNC = 10 // 10 seconds + /////////////////////// Crashlytics custom keys ///////////////////////