Skip to content

Commit

Permalink
Feature/#40 add moshi type adapters (#44)
Browse files Browse the repository at this point in the history
* Add TypeAdapters and Factory
* Introducing common-adapter-moshi module
* Adding more tests
* DefaultNumberAdapter should parse decimal numbers
* Adds tests for parseToBigInteger
  • Loading branch information
biafra23 authored Apr 24, 2020
1 parent 09a420c commit 69334e5
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 1 deletion.
1 change: 1 addition & 0 deletions common-adapter-moshi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
24 changes: 24 additions & 0 deletions common-adapter-moshi/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply from: '../buildsystem/coverageReport.gradle'

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

dependencies {
// We specify junit before anything else to make sure that this version is prioritized over the
// one bundled in the android.jar
testImplementation "junit:junit:$versions.junit"

implementation project(":models")
implementation project(":utils")
implementation project(":crypto")

implementation "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin"
implementation "com.github.gnosis.bivrost-kotlin:bivrost-solidity-types:$versions.bivrost"

// Moshi
implementation "com.squareup.moshi:moshi:$versions.moshi"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$versions.moshi"
}
5 changes: 5 additions & 0 deletions common-adapter-moshi/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="pm.gnosis.common.adapter.moshi">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package pm.gnosis.common.adapters.moshi

import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonQualifier
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import pm.gnosis.crypto.utils.asEthereumAddressChecksumString
import pm.gnosis.model.Solidity
import pm.gnosis.models.Wei
import pm.gnosis.utils.asEthereumAddress
import pm.gnosis.utils.hexAsBigInteger
import pm.gnosis.utils.parseToBigInteger
import pm.gnosis.utils.toHexString
import java.math.BigInteger

object MoshiBuilderFactory {
fun makeMoshiBuilder(): Moshi.Builder {
return Moshi.Builder()
.add(WeiAdapter())
.add(HexNumberAdapter())
.add(DecimalNumberAdapter())
.add(DefaultNumberAdapter())
.add(SolidityAddressAdapter())
}
}

class WeiAdapter {
@ToJson
fun toJson(wei: Wei): String =
wei.value.toHexString()

@FromJson
fun fromJson(wei: String): Wei {
return Wei(wei.parseToBigInteger())
}
}

class HexNumberAdapter {
@ToJson
fun toJson(@HexNumber hexNumber: BigInteger): String = hexNumber.toHexString()

@FromJson
@HexNumber
fun fromJson(hexNumber: String): BigInteger = hexNumber.hexAsBigInteger()
}

class DecimalNumberAdapter {
@ToJson
fun toJson(@DecimalNumber bigInteger: BigInteger): String = bigInteger.toString()

@FromJson
@DecimalNumber
fun fromJson(decimalNumber: String): BigInteger = decimalNumber.toBigInteger()
}

class DefaultNumberAdapter {
@ToJson
fun toJson(hexNumber: BigInteger): String = hexNumber.toHexString()

@FromJson
fun fromJson(hexNumber: String): BigInteger = hexNumber.parseToBigInteger()
}

class SolidityAddressAdapter {
@ToJson
fun toJson(address: Solidity.Address): String = address.asEthereumAddressChecksumString()

@FromJson
fun fromJson(address: String): Solidity.Address = address.asEthereumAddress()!!
}

@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class HexNumber

@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class DecimalNumber
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package pm.gnosis.common.adapters.moshi

import org.junit.Assert.assertEquals
import org.junit.Test
import pm.gnosis.model.Solidity
import pm.gnosis.models.Wei
import java.math.BigInteger

class TypeAdaptersTest {

@Test
fun testWeiAdapterFromJson() {
val weiValue = WeiAdapter().fromJson("0xde0b6b3a7640000")
assertEquals(BigInteger("1000000000000000000"), weiValue.value)
}

@Test
fun testWeiAdapterToJson() {
val weiString = WeiAdapter().toJson(Wei(BigInteger("1000000000000000000")))
assertEquals("0xde0b6b3a7640000", weiString)
}

@Test
fun testHexNumberAdapterFromJson() {
val value = HexNumberAdapter().fromJson("0xde0b6b3a7640000")
assertEquals(BigInteger("1000000000000000000"), value)
}

@Test
fun testHexNumberAdapterToJson() {
val hexNumberString = HexNumberAdapter().toJson(BigInteger("1000000000000000000"))
assertEquals("0xde0b6b3a7640000", hexNumberString)
}

@Test
fun testDecimalNumberAdapterFromJson() {
val value = DecimalNumberAdapter().fromJson("1000000000000000000")
assertEquals(BigInteger("1000000000000000000"), value)
}

@Test
fun testDecimalNumberAdapterToJson() {
val decimalString = DecimalNumberAdapter().toJson(BigInteger("1000000000000000000"))
assertEquals("1000000000000000000", decimalString)
}

@Test
fun testDefaultNumberAdapterFromJsonWithHexNumber() {
val value = DefaultNumberAdapter().fromJson("0xde0b6b3a7640000")
assertEquals(BigInteger("1000000000000000000"), value)
}

@Test
fun testDefaultNumberAdapterFromJsonWithDecimalNumber() {
val value = DefaultNumberAdapter().fromJson("1000000000000000000")
assertEquals(BigInteger("1000000000000000000"), value)
}

@Test
fun testDefaultNumberAdapterToJson() {
val numberString = DefaultNumberAdapter().toJson(BigInteger("1000000000000000000"))
assertEquals("0xde0b6b3a7640000", numberString)
}

@Test
fun testSolidityAddressAdapterFromJson() {
val addressValue = SolidityAddressAdapter().fromJson("0x0000000000000000000000000de0b6B3a7640000")
assertEquals(BigInteger("1000000000000000000"), addressValue.value)
}

@Test
fun testSolidityAddressAdapterToJson() {
val addressString = SolidityAddressAdapter().toJson(Solidity.Address(BigInteger("1000000000000000000")))
assertEquals("0x0000000000000000000000000de0b6B3a7640000", addressString)
}
}
2 changes: 1 addition & 1 deletion eip712-adapter-moshi/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies {
implementation project(":eip712")
implementation project(":utils")

implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin"

// Force Okio 2.X
implementation "com.squareup.okio:okio:$versions.okio"
Expand Down
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include ':accounts-geth'
include ':accounts-kethereum'
include ':android-common'
include ':blockies'
include ':common-adapter-moshi'
include ':crypto'
include ':eip712'
include ':eip712-adapter-moshi'
Expand Down
3 changes: 3 additions & 0 deletions utils/src/main/java/pm/gnosis/utils/NumberUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import java.math.BigInteger

fun String.asEthereumAddress() = nullOnThrow { Solidity.Address(hexAsBigInteger()) }

fun String.parseToBigInteger(): BigInteger =
if (startsWith("0x")) hexAsBigInteger() else decimalAsBigInteger()

fun String.hexAsBigInteger() = BigInteger(this.removePrefix("0x"), 16)
fun String.hexAsBigIntegerOrNull() = nullOnThrow { this.hexAsBigInteger() }
fun String.decimalAsBigInteger() = BigInteger(this, 10)
Expand Down
10 changes: 10 additions & 0 deletions utils/src/test/java/pm/gnosis/utils/NumberUtilsKtTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,14 @@ class NumberUtilsKtTest {
assertEquals("0", BigDecimal.valueOf(0.0).setScale(6).stringWithNoTrailingZeroes())
assertEquals("1.4", BigDecimal.valueOf(1.4).setScale(6).stringWithNoTrailingZeroes())
}

@Test
fun parseHexStringToBigInteger() {
assertEquals(BigInteger("1000000000000000000"), "0xde0b6b3a7640000".parseToBigInteger())
}

@Test
fun parseDecimalStringToBigInteger() {
assertEquals(BigInteger("1000000000000000000"), "1000000000000000000".parseToBigInteger())
}
}

0 comments on commit 69334e5

Please sign in to comment.