Skip to content

Commit

Permalink
Repaired the sending funds and confirmation functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitryBespalov committed Apr 12, 2024
1 parent 242261a commit 7530c0b
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 71 deletions.
27 changes: 4 additions & 23 deletions app/src/main/java/io/gnosis/safe/ErrorHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ sealed class Error(
override fun message(context: Context): String {
return "${context.getString(reason)}. ${context.getString(howToFix)}"
}
};
}


open fun message(context: Context): String {
Expand Down Expand Up @@ -158,25 +158,7 @@ fun Throwable.toError(): Error =
this.code() == HttpCodes.FORBIDDEN -> Error.Error403
this.code() == HttpCodes.NOT_FOUND -> Error.Error404
this.code() == HttpCodes.SERVER_ERROR -> Error.Error500(500)
this.code() == 422 -> {

val serverError = errorBodyString?.let {
if (errorBodyString.isNotEmpty()) {
serverErrorAdapter.fromJson(errorBodyString)
} else {
null
}
}

when {
serverError?.code == 1 -> Error.Error42201
serverError?.code == 50 -> Error.Error42250
serverError?.code == null -> Error.Error42200
serverError.code in 2..9 -> Error.Error422xx("4220${serverError.code}".toInt())
serverError.code >= 10 -> Error.Error422xx("422${serverError.code}".toInt())
else -> Error.Error42200
}
}
this.code() == 422 -> Error.Error42200
this.code() in 300..599 -> Error.Error500(this.code())
else -> Error.ErrorUnknown
}
Expand Down Expand Up @@ -210,9 +192,8 @@ fun errorSnackbar(view: View, text: CharSequence, duration: Int = 6000, action:

@JsonClass(generateAdapter = true)
data class ServerError(
@Json(name = "code") val code: Int,
@Json(name = "message") val message: String?,
@Json(name = "arguments") val arguments: List<String>?
@Json(name = "code") val code: String,
@Json(name = "message") val message: String?
)

private val serverErrorAdapter = dataMoshi.adapter(ServerError::class.java)
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import io.gnosis.safe.ui.settings.app.SettingsHandler
import io.gnosis.safe.ui.transactions.details.MissingOwnerCredential
import io.gnosis.safe.ui.transactions.details.SigningMode
import pm.gnosis.model.Solidity
import pm.gnosis.utils.addHexPrefix
import pm.gnosis.utils.asEthereumAddress
import pm.gnosis.utils.asEthereumAddressString
import pm.gnosis.utils.hexToByteArray
Expand Down Expand Up @@ -82,22 +83,31 @@ class SendAssetReviewViewModel
SendAssetReviewState(EstimationDataLoaded)
}
}
val txEstimation = transactionRepository.estimateTransaction(
chainId,
from,
to,
transferAmount
)
minSafeNonce = txEstimation.currentNonce
if (safeNonce == null) {
safeNonce = txEstimation.recommendedNonce
}
if (SemVer.parse(activeSafe.version!!, ignoreExtensions = true) < SemVer(1, 3, 0)) {
val txEstimation = transactionRepository.estimateTransaction(
chainId,
from,
to,
transferAmount
)
minSafeNonce = txEstimation.currentNonce
if (safeNonce == null) {
safeNonce = txEstimation.recommendedNonce
}
proposedSafeTxGas = txEstimation.safeTxGas
if (safeTxGas == null) {
safeTxGas = proposedSafeTxGas
}
} else {
val nonces = safeRepository.getSafeNonces(activeSafe)
minSafeNonce = nonces.currentNonce
if (safeNonce == null) {
safeNonce = nonces.recommendedNonce
}
proposedSafeTxGas = null
safeTxGas = null
}

updateState {
SendAssetReviewState(EstimationDataLoaded)
}
Expand Down Expand Up @@ -207,7 +217,7 @@ class SendAssetReviewViewModel
safeAddress = activeSafe.address,
transaction = txDetails,
executionInfo = txExecutionInfo
).toHexString()
).toHexString().addHexPrefix()

updateState {
SendAssetReviewState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ object LedgerWrapper {
val r = data.slice(1..32).toByteArray().asBigInteger()
val s = data.slice(33..64).toByteArray().asBigInteger()

return r.toString(16).padStart(64, '0').substring(0, 64) +
return "0x" + r.toString(16).padStart(64, '0').substring(0, 64) +
s.toString(16).padStart(64, '0').substring(0, 64) +
v.toString(16).padStart(2, '0')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class ConfirmRejectionViewModel
safeAddress = safe.address,
transaction = rejectionTxDetails,
executionInfo = rejectionExecutionInfo
).toHexString()
).toHexString().addHexPrefix()

val selectedOwner = credentialsRepository.owner(owner) ?: throw MissingOwnerCredential
kotlin.runCatching {
Expand Down Expand Up @@ -125,7 +125,7 @@ class ConfirmRejectionViewModel
}
}

private suspend fun validateSafeTxHash(
private fun validateSafeTxHash(
safe: Safe,
transaction: TransactionDetails,
executionInfo: DetailedExecutionInfo.MultisigExecutionDetails
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class TxReviewViewModel
TxReviewState(viewAction = Loading(true))
}
val owners = credentialsRepository.owners().map { OwnerViewData(it.address, it.name, it.type) }
activeSafe.signingOwners?.let {
activeSafe.signingOwners.let {
val acceptedOwners = owners.filter { localOwner ->
activeSafe.signingOwners.any {
localOwner.address == it
Expand Down Expand Up @@ -154,7 +154,7 @@ class TxReviewViewModel

fun updateDefaultKey(address: Solidity.Address) {
safeLaunch {
address?.let {
address.let {
val owner = credentialsRepository.owner(it)!!
if (executionKey?.address != address) {
tracker.logTxExecKeyChanged()
Expand Down
49 changes: 24 additions & 25 deletions data/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,47 +39,46 @@ android {

debug {
buildConfigField ("String", "CLIENT_GATEWAY_URL", '"https://safe-client.staging.5afe.dev/"')
buildConfigField (javaTypes.INT, "CHAIN_ID", "5")
buildConfigField (javaTypes.INT, "CHAIN_ID", "11155111")
buildConfigField (javaTypes.STRING, "CHAIN_TEXT_COLOR", asString("#ffffff"))
buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#4D99EB"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Goerli"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("gor"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://goerli.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://goerli.etherscan.io/"))
buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#B8AAD5"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Sepolia"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("sep"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.etherscan.io/"))
}

profile {
buildConfigField javaTypes.STRING, "CLIENT_GATEWAY_URL", asString(getKey("CLIENT_GATEWAY_URL", "https://safe-client.staging.5afe.dev/"))
buildConfigField (javaTypes.INT, "CHAIN_ID", "5")
buildConfigField (javaTypes.INT, "CHAIN_ID", "11155111")
buildConfigField (javaTypes.STRING, "CHAIN_TEXT_COLOR", asString("#ffffff"))
buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#4D99EB"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Goerli"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("gor"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://goerli.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://goerli.etherscan.io/"))
buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#B8AAD5"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Sepolia"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("sep"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.etherscan.io/"))
}

unsafe {
buildConfigField javaTypes.STRING, "CLIENT_GATEWAY_URL", asString(getKey("CLIENT_GATEWAY_URL", "https://safe-client-nest.staging.5afe.dev/"))
buildConfigField (javaTypes.INT, "CHAIN_ID", "5")
buildConfigField (javaTypes.INT, "CHAIN_ID", "11155111")
buildConfigField (javaTypes.STRING, "CHAIN_TEXT_COLOR", asString("#ffffff"))
buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#4D99EB"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Goerli"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("gor"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://goerli.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://goerli.etherscan.io/"))
buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#B8AAD5"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Sepolia"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("sep"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.etherscan.io/"))
}

internal {
buildConfigField javaTypes.STRING, "CLIENT_GATEWAY_URL", asString(getKey("CLIENT_GATEWAY_URL", "https://safe-client.staging.5afe.dev/"))
buildConfigField (javaTypes.INT, "CHAIN_ID", "5")
buildConfigField (javaTypes.INT, "CHAIN_ID", "11155111")
buildConfigField (javaTypes.STRING, "CHAIN_TEXT_COLOR", asString("#ffffff"))
buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#4D99EB"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Goerli"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("gor"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://guerli.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://goerli.etherscan.io/"))

buildConfigField (javaTypes.STRING, "CHAIN_BACKGROUND_COLOR", asString("#B8AAD5"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_NAME", asString("Sepolia"))
buildConfigField (javaTypes.STRING, "BLOCKCHAIN_SHORT_NAME", asString("sep"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_NET_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.infura.io/v3/"))
buildConfigField javaTypes.STRING, "BLOCKCHAIN_EXPLORER_URL", asString(getKey("BLOCKCHAIN_NET_URL", "https://sepolia.etherscan.io/"))
}

release {
Expand Down
7 changes: 7 additions & 0 deletions data/src/main/java/io/gnosis/data/backend/GatewayApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.gnosis.data.BuildConfig
import io.gnosis.data.models.ChainInfo
import io.gnosis.data.models.Page
import io.gnosis.data.models.SafeInfo
import io.gnosis.data.models.SafeNonces
import io.gnosis.data.models.assets.CoinBalances
import io.gnosis.data.models.assets.Collectible
import io.gnosis.data.models.transaction.*
Expand Down Expand Up @@ -91,6 +92,12 @@ interface GatewayApi {
@Body transactionEstimationRequest: TransactionEstimationRequest
): TransactionEstimation

@GET("/v1/chains/{chainId}/safes/{address}/nonces")
suspend fun loadSafeNonces(
@Path("chainId") chainId: BigInteger,
@Path("address") address: String
): SafeNonces

companion object {
const val BASE_URL = BuildConfig.CLIENT_GATEWAY_URL
}
Expand Down
14 changes: 14 additions & 0 deletions data/src/main/java/io/gnosis/data/models/SafeNonces.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.gnosis.data.models

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import java.math.BigInteger

@JsonClass(generateAdapter = true)
data class SafeNonces(
@Json(name = "currentNonce")
val currentNonce: BigInteger,

@Json(name = "recommendedNonce")
val recommendedNonce: BigInteger
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ data class TransactionEstimationRequest(
val value: BigInteger,

@Json(name = "data")
val data: String = "",
val data: String?,

@Json(name = "operation")
val operation: Operation = Operation.CALL,
Expand Down
12 changes: 8 additions & 4 deletions data/src/main/java/io/gnosis/data/repositories/SafeRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import io.gnosis.data.db.daos.SafeDao
import io.gnosis.data.models.Chain
import io.gnosis.data.models.Safe
import io.gnosis.data.models.SafeInfo
import io.gnosis.data.models.SafeNonces
import io.gnosis.data.utils.SemVer
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.*
Expand Down Expand Up @@ -61,14 +62,14 @@ class SafeRepository(

suspend fun removeSafe(safe: Safe) = safeDao.delete(safe)

suspend fun clearActiveSafe() {
fun clearActiveSafe() {
preferencesManager.prefs.edit {
remove(ACTIVE_SAFE)
remove(ACTIVE_SAFE_SIGNING_OWNERS)
}
}

suspend fun setActiveSafe(safe: Safe) {
fun setActiveSafe(safe: Safe) {
preferencesManager.prefs.edit {
putString(ACTIVE_SAFE, "${safe.address.asEthereumAddressString()};${safe.localName};${safe.chainId}")
putString(
Expand All @@ -94,7 +95,7 @@ class SafeRepository(
return safe
}

suspend fun setActiveSafeSigningOwners(owners: List<Solidity.Address>) {
fun setActiveSafeSigningOwners(owners: List<Solidity.Address>) {
preferencesManager.prefs.edit {
putString(
ACTIVE_SAFE_SIGNING_OWNERS,
Expand All @@ -109,7 +110,7 @@ class SafeRepository(
}
}

suspend fun getActiveSafeSigningOwners(): List<Solidity.Address> {
fun getActiveSafeSigningOwners(): List<Solidity.Address> {
return preferencesManager.prefs
.getString(ACTIVE_SAFE_SIGNING_OWNERS, null)
?.split(SEPARATOR)
Expand Down Expand Up @@ -157,6 +158,9 @@ class SafeRepository(
suspend fun getSafeInfo(safe: Safe): SafeInfo =
gatewayApi.getSafeInfo(address = safe.address.asEthereumAddressChecksumString(), chainId = safe.chainId)

suspend fun getSafeNonces(safe: Safe): SafeNonces =
gatewayApi.loadSafeNonces(address = safe.address.asEthereumAddressChecksumString(), chainId = safe.chainId)

suspend fun clearUserData() {
getSafes().forEach {
removeSafe(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class TransactionRepository(
safeAddress: Solidity.Address,
to: Solidity.Address,
value: BigInteger = BigInteger.ZERO,
data: String = "",
data: String? = null,
operation: Operation = Operation.DELEGATE,
): TransactionEstimation {
return gatewayApi.estimateTransaction(
Expand Down
3 changes: 2 additions & 1 deletion data/src/main/java/io/gnosis/data/utils/SignatureUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package io.gnosis.data.utils
import pm.gnosis.crypto.ECDSASignature
import pm.gnosis.utils.removeHexPrefix


fun ECDSASignature.toSignatureString() =
r.toString(16).padStart(64, '0').substring(0, 64) +
"0x" + r.toString(16).padStart(64, '0').substring(0, 64) +
s.toString(16).padStart(64, '0').substring(0, 64) +
v.toString(16).padStart(2, '0')

Expand Down

0 comments on commit 7530c0b

Please sign in to comment.