Skip to content

Commit

Permalink
Add rpcUrl to EthereumRepository; change chainId type to BigInteger (#53
Browse files Browse the repository at this point in the history
)

* ChianId is now BigInteger in pm.gnosis.model.Transaction
* Multiple networks support: Add modifiable rpcUrl property to ethereum repo
* Adjust compileSdk & targetSdk versions
  • Loading branch information
Dirk Jäckel authored Aug 2, 2021
1 parent 1eadce6 commit 98799b9
Show file tree
Hide file tree
Showing 19 changed files with 80 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class GethAccountManager(private val preferencesManager: PreferencesManager, pri
fun getActiveAccount(): Account = getAccounts().first()

fun getAccountPassphrase(): String {
var passphrase = preferencesManager.prefs.getString(PreferencesManager.Companion.PASSPHRASE_KEY, "")
var passphrase = preferencesManager.prefs.getString(PreferencesManager.Companion.PASSPHRASE_KEY, "")!!
if (passphrase.isEmpty()) {
preferencesManager.prefs.edit {
passphrase = generateRandomString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class GethAccountsRepository(
}.subscribeOn(Schedulers.computation())

override fun loadMnemonic(): Single<String> = Single.fromCallable {
val encryptedMnemonic = preferencesManager.prefs.getString(PreferencesManager.MNEMONIC_KEY, "")
val encryptedMnemonic = preferencesManager.prefs.getString(PreferencesManager.MNEMONIC_KEY, "")!!
encryptedStringConverter.fromStorage(encryptedMnemonic).value(encryptionManager)
}.subscribeOn(Schedulers.computation())
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class KethereumAccountsRepository(
}.subscribeOn(Schedulers.computation())

override fun loadMnemonic(): Single<String> = Single.fromCallable {
val encryptedMnemonic = preferencesManager.prefs.getString(PreferencesManager.MNEMONIC_KEY, "")
val encryptedMnemonic = preferencesManager.prefs.getString(PreferencesManager.MNEMONIC_KEY, "")!!
encryptedStringConverter.fromStorage(encryptedMnemonic).value(encryptionManager)
}.subscribeOn(Schedulers.computation())
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fun Transaction.rlp(signature: ECDSASignature? = null): ByteArray {
items.add(adjustV(signature.v).toRLP())
items.add(signature.r.toRLP())
items.add(signature.s.toRLP())
} else if (chainId > 0) {
} else if (chainId > BigInteger.ZERO) {
items.add(chainId.toRLP())
items.add(0.toRLP())
items.add(0.toRLP())
Expand All @@ -35,8 +35,15 @@ fun Transaction.rlp(signature: ECDSASignature? = null): ByteArray {
fun Transaction.hash(ecdsaSignature: ECDSASignature? = null) = rlp(ecdsaSignature).let { Sha3Utils.keccak(it) }

private fun Transaction.adjustV(v: Byte): Byte {
if (chainId > 0) {
return (v.toInt() + 8 + 2 * chainId).toByte()
if (chainId > BigInteger.ZERO) {
return chainId
.multiply(
BigInteger.valueOf(2)
)
.plus(
BigInteger.valueOf(v.toLong() + 8)
)
.toByte()
}
return v
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class KethereumAccountsRepositoryTest {
val value = Wei(BigInteger("1000000000000000000"))
val gas = BigInteger("21000")
val gasPrice = BigInteger("20000000000")
val transaction = Transaction(address = address, nonce = nonce, value = value, gas = gas, gasPrice = gasPrice, chainId = 1)
val transaction = Transaction(address = address, nonce = nonce, value = value, gas = gas, gasPrice = gasPrice, chainId = BigInteger.ONE)

repository.signTransaction(transaction).subscribe(testObserver)

Expand All @@ -101,7 +101,8 @@ class KethereumAccountsRepositoryTest {
val nonce = BigInteger("13")
val gas = BigInteger("2034776")
val gasPrice = BigInteger("20000000000")
val transaction = Transaction(address = address, nonce = nonce, data = "0xe411526d", gas = gas, gasPrice = gasPrice, chainId = 28)
val transaction =
Transaction(address = address, nonce = nonce, data = "0xe411526d", gas = gas, gasPrice = gasPrice, chainId = BigInteger.valueOf(28))
val expectedString = "e90d8504a817c800831f0c589419fd8863ea1185d8ef7ab3f2a8f4d469dc35dd528084e411526d1c8080"
assertEquals(expectedString, transaction.rlp().toHexString())
}
Expand Down Expand Up @@ -143,7 +144,7 @@ class KethereumAccountsRepositoryTest {
val nonce = BigInteger("13")
val gas = BigInteger("2034776")
val gasPrice = BigInteger("20000000000")
val transaction = Transaction(address = address, nonce = nonce, data = CREATE_SAFE_DATA, gas = gas, gasPrice = gasPrice, chainId = 0)
val transaction = Transaction(address = address, nonce = nonce, data = CREATE_SAFE_DATA, gas = gas, gasPrice = gasPrice, chainId = BigInteger.ZERO)

repository.signTransaction(transaction).subscribe(testObserver)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,34 @@ abstract class TrackingActivityLifecycleCallbacks : Application.ActivityLifecycl

abstract fun inactive()

override fun onActivityPaused(activity: Activity?) {
override fun onActivityPaused(activity: Activity) {
}

override fun onActivityResumed(activity: Activity?) {
override fun onActivityResumed(activity: Activity) {
}

override fun onActivityStarted(activity: Activity?) {
override fun onActivityStarted(activity: Activity) {
if (activeActivityCount == 0) {
// We had no active activities, so we just became active
active()
}
activeActivityCount++
}

override fun onActivityDestroyed(activity: Activity?) {
override fun onActivityDestroyed(activity: Activity) {
}

override fun onActivitySaveInstanceState(activity: Activity?, bundle: Bundle?) {
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {
}

override fun onActivityStopped(activity: Activity?) {
override fun onActivityStopped(activity: Activity) {
activeActivityCount--
if (activeActivityCount == 0) {
// We have no more active activities, so we are inactive
inactive()
}
}

override fun onActivityCreated(activity: Activity?, bundle: Bundle?) {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fun Context.getSimplePlural(@PluralsRes stringId: Int, quantity: Long): String =

fun Context.copyToClipboard(label: String, text: String, onCopy: (String) -> Unit = {}) {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.primaryClip = ClipData.newPlainText(label, text)
clipboard.setPrimaryClip(ClipData.newPlainText(label, text))
onCopy(text)
}

Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ subprojects {
afterEvaluate { project ->
if (project.hasProperty("android")) {
android {
compileSdkVersion 28
compileSdkVersion 30
buildToolsVersion "28.0.3"

defaultConfig {
minSdkVersion 19
targetSdkVersion 28
targetSdkVersion 30
}

lintOptions {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
package pm.gnosis.ethereum.rpc.retrofit

import pm.gnosis.ethereum.rpc.models.*
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
import retrofit2.http.Url

interface RetrofitEthereumRpcApi {
@POST(".")
suspend fun receipt(@Body jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionReceiptResult
@POST
suspend fun receipt(@Url rpcUrl: String, @Body jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionReceiptResult

@POST(".")
suspend fun block(@Body jsonRpcRequest: JsonRpcRequest): JsonRpcBlockResult
@POST
suspend fun block(@Url rpcUrl: String, @Body jsonRpcRequest: JsonRpcRequest): JsonRpcBlockResult

@POST(".")
suspend fun transaction(@Body jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionResult
@POST
suspend fun transaction(@Url rpcUrl: String, @Body jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionResult

@POST(".")
suspend fun post(@Body jsonRpcRequest: JsonRpcRequest): JsonRpcResult
@POST
suspend fun post(@Url rpcUrl: String, @Body jsonRpcRequest: JsonRpcRequest): JsonRpcResult

@POST(".")
suspend fun post(@Body jsonRpcRequest: Collection<JsonRpcRequest>): Collection<JsonRpcResult>
@POST
suspend fun post(@Url rpcUrl: String, @Body jsonRpcRequest: Collection<JsonRpcRequest>): Collection<JsonRpcResult>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,27 @@ package pm.gnosis.ethereum.rpc.retrofit

import pm.gnosis.ethereum.rpc.EthereumRpcConnector
import pm.gnosis.ethereum.rpc.models.*
import retrofit2.HttpException
import retrofit2.Response

class RetrofitEthereumRpcConnector(private val api: RetrofitEthereumRpcApi) : EthereumRpcConnector {
class RetrofitEthereumRpcConnector(private val api: RetrofitEthereumRpcApi, override var rpcUrl: String) : EthereumRpcConnector {

override suspend fun receipt(jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionReceiptResult {
return api.receipt(jsonRpcRequest)
return api.receipt(rpcUrl,jsonRpcRequest)
}

override suspend fun block(jsonRpcRequest: JsonRpcRequest): JsonRpcBlockResult {
return api.block(jsonRpcRequest)
return api.block(rpcUrl, jsonRpcRequest)
}

override suspend fun transaction(jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionResult {
return api.transaction(jsonRpcRequest)
return api.transaction(rpcUrl, jsonRpcRequest)
}

override suspend fun post(jsonRpcRequest: JsonRpcRequest): JsonRpcResult {
return api.post(jsonRpcRequest)
return api.post(rpcUrl, jsonRpcRequest)
}

override suspend fun post(jsonRpcRequest: Collection<JsonRpcRequest>): Collection<JsonRpcResult> {
return api.post(jsonRpcRequest)
return api.post(rpcUrl, jsonRpcRequest)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ class RetrofitEthereumRpcConnectorTest {
private lateinit var connector: RetrofitEthereumRpcConnector

private val api = object : RetrofitEthereumRpcApi {
override suspend fun receipt(jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionReceiptResult {
override suspend fun receipt(rpcUrl: String, jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionReceiptResult {
TODO("Not yet implemented")
}

override suspend fun block(jsonRpcRequest: JsonRpcRequest): JsonRpcBlockResult {
override suspend fun block(rpcUrl: String, jsonRpcRequest: JsonRpcRequest): JsonRpcBlockResult {
TODO("Not yet implemented")
}

override suspend fun transaction(jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionResult {
override suspend fun transaction(rpcUrl: String, jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionResult {
TODO("Not yet implemented")
}

override suspend fun post(jsonRpcRequest: JsonRpcRequest): JsonRpcResult {
override suspend fun post(rpcUrl: String, jsonRpcRequest: JsonRpcRequest): JsonRpcResult {
TODO("Not yet implemented")
}

override suspend fun post(jsonRpcRequest: Collection<JsonRpcRequest>): Collection<JsonRpcResult> {
override suspend fun post(rpcUrl: String, jsonRpcRequest: Collection<JsonRpcRequest>): Collection<JsonRpcResult> {
TODO("Not yet implemented")
}
}
Expand All @@ -40,7 +40,7 @@ class RetrofitEthereumRpcConnectorTest {

@Before
fun setUp() {
connector = RetrofitEthereumRpcConnector(apiSpy)
connector = RetrofitEthereumRpcConnector(apiSpy, "")
}

@Test
Expand All @@ -51,7 +51,7 @@ class RetrofitEthereumRpcConnectorTest {
assert(isFailure)
assert(exceptionOrNull() is NotImplementedError)
}
coVerify(exactly = 1) { apiSpy.receipt(request) }
coVerify(exactly = 1) { apiSpy.receipt(any(), request) }
}

@Test
Expand All @@ -62,7 +62,7 @@ class RetrofitEthereumRpcConnectorTest {
assert(isFailure)
assert(exceptionOrNull() is NotImplementedError)
}
coVerify(exactly = 1) { apiSpy.block(request) }
coVerify(exactly = 1) { apiSpy.block(any(), request) }
}

@Test
Expand All @@ -73,7 +73,7 @@ class RetrofitEthereumRpcConnectorTest {
assert(isFailure)
assert(exceptionOrNull() is NotImplementedError)
}
coVerify(exactly = 1) { apiSpy.transaction(request) }
coVerify(exactly = 1) { apiSpy.transaction(any(), request) }
}

@Test
Expand All @@ -84,7 +84,7 @@ class RetrofitEthereumRpcConnectorTest {
assert(isFailure)
assert(exceptionOrNull() is NotImplementedError)
}
coVerify(exactly = 1) { apiSpy.post(request) }
coVerify(exactly = 1) { apiSpy.post(any(), request) }
}

@Test
Expand All @@ -95,6 +95,6 @@ class RetrofitEthereumRpcConnectorTest {
assert(isFailure)
assert(exceptionOrNull() is NotImplementedError)
}
coVerify(exactly = 1) { apiSpy.post(listOf(request)) }
coVerify(exactly = 1) { apiSpy.post(any(), listOf(request)) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ interface EthereumRpcConnector {
const val FUNCTION_SEND_RAW_TRANSACTION = "eth_sendRawTransaction"
}

var rpcUrl: String

suspend fun receipt(jsonRpcRequest: JsonRpcRequest): JsonRpcTransactionReceiptResult

suspend fun block(jsonRpcRequest: JsonRpcRequest): JsonRpcBlockResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@ import pm.gnosis.models.Wei
import java.math.BigDecimal

class RpcEthereumRepository(
private val ethereumRpcApi: EthereumRpcConnector
private val ethereumRpcApi: EthereumRpcConnector,
rpcUrl: String
) : EthereumRepository {

override var rpcUrl: String = rpcUrl
set(value) {
ethereumRpcApi.rpcUrl = value
field = value
}

override suspend fun <R : BulkRequest> request(bulk: R): R =
bulk.requests.associate { it.id to it.toRpcRequest() }
.let { rpcRequests ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class RpcEthereumRepositoryTest {

@Before
fun setup() {
repository = RpcEthereumRepository(apiMock)
repository = RpcEthereumRepository(apiMock, "")
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import java.math.BigInteger

interface EthereumRepository {

var rpcUrl: String

suspend fun <R : BulkRequest> request(bulk: R): R

suspend fun <R : EthRequest<*>> request(request: R): R
Expand Down
4 changes: 2 additions & 2 deletions models/src/main/java/pm/gnosis/models/Transaction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ data class Transaction(
var gasPrice: BigInteger? = null,
val data: String? = null,
var nonce: BigInteger? = null,
val chainId: Int = CHAIN_ID_ANY
val chainId: BigInteger = CHAIN_ID_ANY
) {
fun signable() = nonce != null && gas != null && gasPrice != null

fun parcelable() = TransactionParcelable(this)

companion object {
const val CHAIN_ID_ANY = 0
val CHAIN_ID_ANY = BigInteger.ZERO
}
}
10 changes: 5 additions & 5 deletions models/src/main/java/pm/gnosis/models/TransactionParcelable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import pm.gnosis.utils.nullOnThrow
data class TransactionParcelable(val transaction: Transaction) : Parcelable {
constructor(parcel: Parcel) : this(
Transaction(
parcel.readString().asEthereumAddress()!!,
nullOnThrow { Wei(parcel.readString().hexAsBigInteger()) },
nullOnThrow { parcel.readString().hexAsBigInteger() },
nullOnThrow { parcel.readString().hexAsBigInteger() },
parcel.readString()!!.asEthereumAddress()!!,
nullOnThrow { Wei(parcel.readString()!!.hexAsBigInteger()) },
nullOnThrow { parcel.readString()!!.hexAsBigInteger() },
nullOnThrow { parcel.readString()!!.hexAsBigInteger() },
parcel.readString(),
nullOnThrow { parcel.readString().hexAsBigInteger() })
nullOnThrow { parcel.readString()!!.hexAsBigInteger() })
)

override fun writeToParcel(parcel: Parcel, flags: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class AesEncryptionManager(

override fun active() {
lockRunnable?.let {
handler.removeCallbacks(lockRunnable)
handler.removeCallbacks(it)
}
lockRunnable = null
}
Expand Down
Loading

0 comments on commit 98799b9

Please sign in to comment.