Skip to content

Commit

Permalink
Merge pull request #668 from WalletConnect/develop
Browse files Browse the repository at this point in the history
BOM 1.5.0
  • Loading branch information
Talhaali00 authored Feb 19, 2023
2 parents 268a060 + 3df893e commit 1a590be
Show file tree
Hide file tree
Showing 213 changed files with 5,001 additions and 2,027 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ci_db_migrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,10 @@ jobs:
WC_CLOUD_PROJECT_ID: ${{ secrets.WC_CLOUD_PROJECT_ID }}
run: ./gradlew :auth:sdk:verifyDebugAuthDatabaseMigration

- name: Chat DB Migration Verification
env:
WC_CLOUD_PROJECT_ID: ${{ secrets.WC_CLOUD_PROJECT_ID }}
run: ./gradlew :chat:sdk:verifyDebugChatDatabaseMigration

- name: Stop Gradle
run: ./gradlew --stop
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ captures/
.cxx/

# Google Services (e.g. APIs or Firebase)
# google-services.json
*/*/google-services.json

# Freeline
freeline.py
Expand Down
1 change: 1 addition & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ WalletConnect v2 protocols for Android applications.

| BOM | [Core SDK](androidCore) | [web3wallet](web3/wallet) | [Sign SDK](sign) | [Auth SDK](auth) | [Chat SDK](chat) |
|-------|-------------------------|---------------------------|------------------|------------------|------------------|
| 1.5.0 | 1.10.0 | 1.3.0 | 2.8.0 | 1.8.0 | 1.0.0-beta01 |
| 1.4.1 | 1.9.1 | 1.2.1 | 2.7.1 | 1.7.1 | 1.0.0-alpha09 |
| 1.3.0 | 1.8.0 | 1.1.0 | 2.6.0 | 1.6.0 | 1.0.0-alpha07 |
| 1.2.0 | 1.7.0 | 1.0.0 | 2.5.0 | 1.5.0 | 1.0.0-alpha06 |
Expand Down
2 changes: 2 additions & 0 deletions androidCore/sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ android {
File("${rootDir.path}/gradle/consumer-rules").listFiles()?.forEach { proguardFile ->
consumerProguardFiles(proguardFile.path)
}

ndk.abiFilters += listOf("armeabi-v7a", "x86", "x86_64", "arm64_v8a")
}

buildTypes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ enum class AndroidCoreDITags {
ANDROID_CORE_DATABASE_DRIVER,
ANDROID_CORE_DATABASE,
COLUMN_ADAPTER_LIST,
COLUMN_ADAPTER_APPMETADATATYPE
COLUMN_ADAPTER_APPMETADATATYPE,
COLUMN_ADAPTER_MAP,
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,66 @@

package com.walletconnect.android.echo

import com.walletconnect.android.echo.model.EchoBody
import com.walletconnect.android.echo.network.EchoService
import com.walletconnect.android.echo.network.model.EchoBody
import com.walletconnect.android.internal.common.di.AndroidCommonDITags
import com.walletconnect.android.internal.common.model.ProjectId
import com.walletconnect.android.internal.common.scope
import com.walletconnect.android.internal.common.wcKoinApp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import org.koin.core.qualifier.named

internal object EchoClient: EchoInterface {
internal object EchoClient : EchoInterface {
private val echoService by lazy { wcKoinApp.koin.get<EchoService>() }
private val clientId by lazy { wcKoinApp.koin.get<String>(named(AndroidCommonDITags.CLIENT_ID)) }
private val projectId by lazy { wcKoinApp.koin.get<ProjectId>() }
private const val SUCCESS_STATUS = "SUCCESS"

override fun register(firebaseAccessToken: String, onSuccess: () -> Unit, onError: (Throwable) -> Unit) {
try {
val body = EchoBody(clientId, firebaseAccessToken)
val body = EchoBody(clientId, firebaseAccessToken)

scope.launch(Dispatchers.IO) {
val response = echoService.register(body)
scope.launch(Dispatchers.IO) {
supervisorScope {
try {
val response = echoService.register(projectId.value, body)

if (response.isSuccessful && response.body() != null) {
if (response.body()!!.status == SUCCESS_STATUS) {
onSuccess()
if (response.isSuccessful && response.body() != null) {
if (response.body()!!.status == SUCCESS_STATUS) {
onSuccess()
} else {
onError(IllegalArgumentException(response.body()!!.errors?.first()?.message))
}
} else {
onError(IllegalArgumentException(response.body()!!.errors.first().message))
onError(IllegalArgumentException(response.errorBody()?.string()))
}
} else {
onError(IllegalArgumentException(response.errorBody()?.string()))
} catch (e: Exception) {
onError(e)
}
}
} catch (e: Exception) {
onError(e)
}
}

override fun unregister(onSuccess: () -> Unit, onError: (Throwable) -> Unit) {
try {
scope.launch(Dispatchers.IO) {
val response = echoService.unregister(clientId)
scope.launch(Dispatchers.IO) {
supervisorScope {
try {
val response = echoService.unregister(projectId.value, clientId)

if (response.isSuccessful && response.body() != null) {
if (response.body()!!.status == SUCCESS_STATUS) {
onSuccess()
if (response.isSuccessful && response.body() != null) {
if (response.body()!!.status == SUCCESS_STATUS) {
onSuccess()
} else {
onError(IllegalArgumentException(response.body()!!.errors?.first()?.message))
}
} else {
onError(IllegalArgumentException(response.body()!!.errors.first().message))
onError(IllegalArgumentException(response.errorBody()?.string()))
}
} else {
onError(IllegalArgumentException(response.errorBody()?.string()))
} catch (e: Exception) {
onError(e)
}
}
} catch (e: Exception) {
onError(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.walletconnect.android.echo.network

import com.walletconnect.android.echo.model.EchoBody
import com.walletconnect.android.echo.model.EchoResponse
import com.walletconnect.android.echo.network.model.EchoBody
import com.walletconnect.android.echo.network.model.EchoResponse
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
Expand All @@ -10,9 +10,9 @@ import retrofit2.http.Path

interface EchoService {

@POST("893ad3af-9515-42d6-aaa2-06b53494b9a5/clients")
suspend fun register(@Body echoClientsBody: EchoBody): Response<EchoResponse>
@POST("{projectId}/clients")
suspend fun register(@Path("projectId") projectId: String, @Body echoClientsBody: EchoBody): Response<EchoResponse>

@DELETE("893ad3af-9515-42d6-aaa2-06b53494b9a5/clients/{clientId}")
suspend fun unregister(@Path("clientId") clientID: String): Response<EchoResponse>
@DELETE("{projectId}/clients/{clientId}")
suspend fun unregister(@Path("projectId") projectId: String, @Path("clientId") clientID: String): Response<EchoResponse>
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.walletconnect.android.echo.model
package com.walletconnect.android.echo.network.model

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.walletconnect.android.echo.model
package com.walletconnect.android.echo.network.model

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class EchoResponse(
@Json(name = "errors")
val errors: List<Error>,
val errors: List<Error>?,
@Json(name = "fields")
val fields: List<Field>,
val fields: List<Field>?,
@Json(name = "status")
val status: String
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,29 @@

package com.walletconnect.android.internal.common

import android.util.Base64
import com.walletconnect.android.internal.common.exception.CannotFindKeyPairException
import com.walletconnect.android.internal.common.storage.KeyStore
import com.walletconnect.foundation.common.model.PrivateKey
import com.walletconnect.foundation.common.model.PublicKey
import com.walletconnect.foundation.crypto.data.repository.BaseJwtRepository
import com.walletconnect.foundation.crypto.data.repository.BaseClientIdJwtRepository

internal class JwtRepositoryAndroid(private val keyChain: KeyStore) : BaseJwtRepository() {
internal class ClientIdJwtRepositoryAndroid(private val keyChain: KeyStore) : BaseClientIdJwtRepository() {

override fun setKeyPair(key: String, privateKey: PrivateKey, publicKey: PublicKey) {
keyChain.setKeys(KEY_DID_KEYPAIR, privateKey, publicKey)
}

override fun encodeByteArray(signature: ByteArray): String {
return Base64.encodeToString(signature, Base64.URL_SAFE or Base64.NO_PADDING or Base64.NO_WRAP)
keyChain.setKeys(CLIENT_ID_KEYPAIR_TAG, privateKey, publicKey)
}

override fun getKeyPair(): Pair<String, String> {
return if (doesKeyPairExist()) {
val (privateKey, publicKey) = keyChain.getKeys(KEY_DID_KEYPAIR)
?: throw CannotFindKeyPairException("No key pair for given tag: $KEY_DID_KEYPAIR")
val (privateKey, publicKey) = keyChain.getKeys(CLIENT_ID_KEYPAIR_TAG)
?: throw CannotFindKeyPairException("No key pair for given tag: $CLIENT_ID_KEYPAIR_TAG")
publicKey to privateKey
} else {
getDIDFromNewKeyPair()
generateAndStoreClientIdKeyPair()
}
}

private fun doesKeyPairExist(): Boolean {
return keyChain.checkKeys(KEY_DID_KEYPAIR)
return keyChain.checkKeys(CLIENT_ID_KEYPAIR_TAG)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.walletconnect.android.internal.common.JsonRpcResponse
import com.walletconnect.android.internal.common.model.params.CoreAuthParams
import com.walletconnect.android.internal.common.model.params.CoreChatParams
import com.walletconnect.android.internal.common.model.params.CoreSignParams
import com.walletconnect.android.internal.common.model.params.PushParams
import org.json.JSONArray
import org.json.JSONObject
import java.lang.reflect.Constructor
Expand All @@ -27,6 +28,8 @@ internal class JsonRpcResultAdapter(val moshi: Moshi) : JsonAdapter<JsonRpcRespo
moshi.adapter(CoreAuthParams.ResponseParams::class.java, emptySet(), "result")
private val acceptanceParamsAdapter: JsonAdapter<CoreChatParams.AcceptanceParams> =
moshi.adapter(CoreChatParams.AcceptanceParams::class.java, emptySet(), "result")
private val pushRequestResponseParamsAdapter: JsonAdapter<PushParams.RequestResponseParams> =
moshi.adapter(PushParams.RequestResponseParams::class.java, emptySet(), "result")

@Volatile
private var constructorRef: Constructor<JsonRpcResponse.JsonRpcResult>? = null
Expand Down Expand Up @@ -61,6 +64,9 @@ internal class JsonRpcResultAdapter(val moshi: Moshi) : JsonAdapter<JsonRpcRespo
runCatching { acceptanceParamsAdapter.fromJson(reader.peekJson()) }.isSuccess -> {
acceptanceParamsAdapter.fromJson(reader)
}
runCatching { pushRequestResponseParamsAdapter.fromJson(reader.peekJson()) }.isSuccess -> {
pushRequestResponseParamsAdapter.fromJson(reader)
}
else -> anyAdapter.fromJson(reader)
}
}
Expand Down Expand Up @@ -135,6 +141,12 @@ internal class JsonRpcResultAdapter(val moshi: Moshi) : JsonAdapter<JsonRpcRespo
it.writeUtf8(approvalParamsString)
}
}
(value_.result as? PushParams.RequestResponseParams) != null -> {
val pushRequestParamsString = pushRequestResponseParamsAdapter.toJson(value_.result)
writer.valueSink().use {
it.writeUtf8(pushRequestParamsString)
}
}

value_.result is String && value_.result.startsWith("{") -> {
writer.valueSink().use {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ data class Cacao(
val requestId: String?,
@Json(name = "resources")
val resources: List<String>?,
)
) {
companion object {
const val CURRENT_VERSION = "1"
const val ISO_8601_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
}
}
}

@JvmSynthetic
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.walletconnect.android.internal.common.crypto

import com.walletconnect.util.bytesToHex
import java.security.MessageDigest


private const val SHA_256: String = "SHA-256"

fun sha256(input: ByteArray): String {
val messageDigest: MessageDigest = MessageDigest.getInstance(SHA_256)
val hashedBytes: ByteArray = messageDigest.digest(input)

return hashedBytes.bytesToHex()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package com.walletconnect.android.internal.common.crypto.kmr

import com.walletconnect.android.internal.common.crypto.sha256
import com.walletconnect.android.internal.common.model.MissingKeyException
import com.walletconnect.android.internal.common.model.SymmetricKey
import com.walletconnect.android.internal.common.storage.KeyStore
Expand All @@ -15,7 +16,7 @@ import org.bouncycastle.crypto.digests.SHA256Digest
import org.bouncycastle.crypto.generators.HKDFBytesGenerator
import org.bouncycastle.crypto.params.HKDFParameters
import org.bouncycastle.math.ec.rfc7748.X25519
import java.security.MessageDigest
import org.bouncycastle.math.ec.rfc8032.Ed25519
import java.security.SecureRandom
import javax.crypto.KeyGenerator

Expand Down Expand Up @@ -49,7 +50,17 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor
keyChain.setKeys(tag, self, peer)
}

override fun generateKeyPair(): PublicKey {
override fun generateAndStoreEd25519KeyPair(): PublicKey {
val publicKey = ByteArray(KEY_SIZE)
val privateKey = ByteArray(KEY_SIZE)
Ed25519.generatePrivateKey(SecureRandom(ByteArray(KEY_SIZE)), privateKey)
Ed25519.generatePublicKey(privateKey, 0, publicKey, 0)

setKeyPair(PublicKey(publicKey.bytesToHex().lowercase()), PrivateKey(privateKey.bytesToHex().lowercase()))
return PublicKey(publicKey.bytesToHex().lowercase())
}

override fun generateAndStoreX25519KeyPair(): PublicKey {
val publicKey = ByteArray(KEY_SIZE)
val privateKey = ByteArray(KEY_SIZE)
X25519.generatePrivateKey(SecureRandom(ByteArray(KEY_SIZE)), privateKey)
Expand Down Expand Up @@ -77,13 +88,13 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor

override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic {
val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer)
val topic = Topic(sha256(symmetricKey.keyAsHex))
val topic = Topic(sha256(symmetricKey.keyAsBytes))
keyChain.setKey(topic.value.lowercase(), symmetricKey)
setKeyAgreement(topic, self, peer)
return topic
}

override fun getTopicFromKey(key: Key): Topic = Topic(sha256(key.keyAsHex))
override fun getTopicFromKey(key: Key): Topic = Topic(sha256(key.keyAsBytes))

@Throws(MissingKeyException::class)
override fun removeKeys(tag: String) {
Expand All @@ -99,7 +110,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor
}

@Throws(MissingKeyException::class)
internal fun getKeyPair(key: Key): Pair<PublicKey, PrivateKey> {
override fun getKeyPair(key: PublicKey): Pair<PublicKey, PrivateKey> {
val (publicKeyHex, privateKeyHex) = keyChain.getKeys(key.keyAsHex) ?: throw MissingKeyException("No key pair for tag: ${key.keyAsHex}")

return Pair(PublicKey(publicKeyHex), PrivateKey(privateKeyHex))
Expand All @@ -112,13 +123,6 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor
return keyGenerator.generateKey().encoded
}

private fun sha256(key: String): String {
val messageDigest: MessageDigest = MessageDigest.getInstance(SHA_256)
val hashedBytes: ByteArray = messageDigest.digest(key.hexToBytes())

return hashedBytes.bytesToHex()
}

private fun deriveHKDFKey(sharedSecret: String): ByteArray {
val hkdf = HKDFBytesGenerator(SHA256Digest())
val inputKeyMaterial = sharedSecret.hexToBytes()
Expand All @@ -135,7 +139,6 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor
private companion object {
const val KEY_SIZE: Int = 32
const val SYM_KEY_SIZE: Int = 256
const val SHA_256: String = "SHA-256"
const val AES: String = "AES"

const val KEY_AGREEMENT_CONTEXT = "key_agreement/"
Expand Down
Loading

0 comments on commit 1a590be

Please sign in to comment.