Skip to content

Commit

Permalink
Merge pull request #11 from ProtonProtocol/develop
Browse files Browse the repository at this point in the history
Account Verification Handling and Initial ESR
  • Loading branch information
Joey Harward authored Nov 13, 2020
2 parents 4d4eeea + 69e1db2 commit 8d13433
Show file tree
Hide file tree
Showing 18 changed files with 364 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Then add the following dependency to your module's build.gradle
```gradle
dependencies {
...
implementation "com.metallicus:protonsdk:0.6.1"
implementation "com.metallicus:protonsdk:0.7.0"
}
```

Expand Down
15 changes: 7 additions & 8 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ const val kotlinVersion = "1.4.10"
const val orchidVersion = "0.21.1"

object ProtonSdk {
const val versionCode = 22
const val versionName = "0.6.1"
const val versionCode = 23
const val versionName = "0.7.0"
}

object BuildPlugins {
object Versions {
const val gradle = "4.1.0"
const val dokka = "0.10.1"
const val gradle = "4.1.1"
const val dokka = "0.10.1" // TODO: 1.4.0
const val bintray = "1.8.5"
}

Expand All @@ -49,7 +49,7 @@ object Android {
const val minSdk = 21
const val compileSdk = 30
const val targetSdk = compileSdk
const val buildTools = "30.0.1"
const val buildTools = "30.0.2"

object Progaurd {
const val consumeFile = "consumer-rules.pro"
Expand All @@ -72,6 +72,7 @@ object Libraries {
const val timber = "4.7.1"
const val gson = "2.8.6"
const val guava = "29.0-jre"
const val esr = "1.0.2"
}

const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
Expand Down Expand Up @@ -99,9 +100,7 @@ object Libraries {
const val orchidKotlindoc = "io.github.javaeden.orchid:OrchidKotlindoc:$orchidVersion"
const val orchidPluginDocs = "io.github.javaeden.orchid:OrchidPluginDocs:$orchidVersion"
const val orchidGithub = "io.github.javaeden.orchid:OrchidGithub:$orchidVersion"

// Greymass ESR
//implementation "com.greymass:esrsdk:1.0.1"
const val greymassESR = "com.greymass:esrsdk:${Versions.esr}"
}

object TestLibraries {
Expand Down
2 changes: 1 addition & 1 deletion protonsdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ dependencies {
implementation(Libraries.guava)

// Greymass ESR
//implementation "com.greymass:esrsdk:1.0.1"
implementation(Libraries.greymassESR)
}

// Dokka
Expand Down
111 changes: 109 additions & 2 deletions protonsdk/src/main/java/com/metallicus/protonsdk/AccountModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ package com.metallicus.protonsdk

import android.content.Context
import android.util.Base64
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.google.gson.*
import com.greymass.esr.ESR
import com.greymass.esr.SigningRequest
import com.metallicus.protonsdk.common.SecureKeys
import com.metallicus.protonsdk.common.Prefs
import com.metallicus.protonsdk.common.Resource
Expand All @@ -34,6 +35,8 @@ import com.metallicus.protonsdk.eosio.commander.ec.EosPrivateKey
import com.metallicus.protonsdk.model.*
import com.metallicus.protonsdk.repository.AccountContactRepository
import com.metallicus.protonsdk.repository.AccountRepository
import com.metallicus.protonsdk.repository.ChainProviderRepository
import com.metallicus.protonsdk.repository.ESRRepository
import timber.log.Timber
import javax.inject.Inject

Expand All @@ -47,9 +50,15 @@ class AccountModule {
@Inject
lateinit var accountRepository: AccountRepository

@Inject
lateinit var chainProviderRepository: ChainProviderRepository

@Inject
lateinit var accountContactRepository: AccountContactRepository

@Inject
lateinit var esrRepository: ESRRepository

@Inject
lateinit var prefs: Prefs

Expand Down Expand Up @@ -138,6 +147,8 @@ class AccountModule {
val userInfo = rows?.get(0)?.asJsonObject
accountContact.name = userInfo?.get("name")?.asString.orEmpty()
accountContact.avatar = userInfo?.get("avatar")?.asString.orEmpty()
val verifiedInt = userInfo?.get("verified")?.asInt ?: 0
accountContact.verified = verifiedInt == 1
}
} else {
val msg = response.errorBody()?.string()
Expand Down Expand Up @@ -389,4 +400,100 @@ class AccountModule {
Resource.error(errorMsg)
}
}

suspend fun decodeESR(chainAccount: ChainAccount, originalESRUrl: String): ProtonESR {
val originalESRUrlScheme = originalESRUrl.substringBefore(":")
val esrUrl = "esr:" + originalESRUrl.substringAfter(":")

val chainId = chainAccount.chainProvider.chainId
val chainUrl = chainAccount.chainProvider.chainUrl

val esr = ESR(context) { account ->
val response = chainProviderRepository.getAbi(chainUrl, account)
if (response.isSuccessful) {
response.body()?.toString()
} else {
response.errorBody()?.toString()
}
}

val signingRequest = SigningRequest(esr)
signingRequest.load(esrUrl)

// TODO: need chainId original string from esr request
//val esrChainId = signingRequest.chainId.toVariant()
//if (esrChainId == chainAccount.chainProvider.chainId) {

val requestAccountName = signingRequest.info["req_account"].orEmpty()

val requestKey = ""
if (signingRequest.isIdentity) {
val linkStr = signingRequest.info["link"]

// TODO: deserialize link as LinkCreate obj
}

val returnPath = signingRequest.info["return_path"].orEmpty()

val requestAccount: Account? = if (requestAccountName.isNotEmpty()) {
fetchAccount(chainId, chainUrl, requestAccountName)
} else {
null
}

return ProtonESR(
requestKey,
chainAccount,
signingRequest,
originalESRUrlScheme,
requestAccount,
returnPath
)
}

suspend fun cancelAuthorizeESR(protonESR: ProtonESR): Resource<String> {
return try {
val callback = protonESR.signingRequest.callback

val response =
esrRepository.cancelAuthorizeESR(callback, "User canceled request")
if (response.isSuccessful) {
Resource.success(response.body())
} else {
val msg = response.errorBody()?.string()
val errorMsg = if (msg.isNullOrEmpty()) {
response.message()
} else {
msg
}

Resource.error(errorMsg)
}
} catch (e: Exception) {
Resource.error(e.localizedMessage.orEmpty())
}
}

suspend fun authorizeESR(protonESR: ProtonESR): Resource<JsonObject> {
return try {
val callback = protonESR.signingRequest.callback

val response =
esrRepository.authorizeESR(callback, "")
if (response.isSuccessful) {
Resource.success(response.body())
} else {
val msg = response.errorBody()?.string()
val errorMsg = if (msg.isNullOrEmpty()) {
response.message()
} else {
msg
}

Resource.error(errorMsg)
}
} catch (e: Exception) {
Resource.error(e.localizedMessage.orEmpty())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class ActionsModule {
val userInfo = rows?.get(0)?.asJsonObject
accountContact.name = userInfo?.get("name")?.asString.orEmpty()
accountContact.avatar = userInfo?.get("avatar")?.asString.orEmpty()
val verifiedInt = userInfo?.get("verified")?.asInt ?: 0
accountContact.verified = verifiedInt == 1
}
} else {
val msg = response.errorBody()?.string()
Expand Down
44 changes: 44 additions & 0 deletions protonsdk/src/main/java/com/metallicus/protonsdk/Proton.kt
Original file line number Diff line number Diff line change
Expand Up @@ -488,4 +488,48 @@ class Proton private constructor(context: Context) {
emit(error)
}
}

fun decodeESR(esrUri: String): LiveData<Resource<ProtonESR>> = liveData {
emit(Resource.loading())

try {
val activeAccount = getActiveAccountAsync()

emit(Resource.success(accountModule.decodeESR(activeAccount, esrUri)))
} catch (e: ProtonException) {
val error: Resource<ProtonESR> = Resource.error(e)
emit(error)
} catch (e: Exception) {
val error: Resource<ProtonESR> = Resource.error(e.localizedMessage.orEmpty())
emit(error)
}
}

fun cancelAuthorizeESR(protonESR: ProtonESR): LiveData<Resource<String>> = liveData {
emit(Resource.loading())

try {
emit(accountModule.cancelAuthorizeESR(protonESR))
} catch (e: ProtonException) {
val error: Resource<String> = Resource.error(e)
emit(error)
} catch (e: Exception) {
val error: Resource<String> = Resource.error(e.localizedMessage.orEmpty())
emit(error)
}
}

fun authorizeESR(protonESR: ProtonESR): LiveData<Resource<JsonObject>> = liveData {
emit(Resource.loading())

try {
emit(accountModule.authorizeESR(protonESR))
} catch (e: ProtonException) {
val error: Resource<JsonObject> = Resource.error(e)
emit(error)
} catch (e: Exception) {
val error: Resource<JsonObject> = Resource.error(e.localizedMessage.orEmpty())
emit(error)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2020 Proton Chain LLC, Delaware
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.metallicus.protonsdk.api

import com.google.gson.JsonObject
import retrofit2.Response
import retrofit2.http.*

data class CancelAuthorizeESRBody(val error: String)
data class AuthorizeESRBody(val error: String)

interface ESRCallbackService {
@POST
suspend fun cancelAuthorizeESR(
@Url url: String,
@Body body: CancelAuthorizeESRBody): Response<String>

@POST
suspend fun authorizeESR(
@Url url: String,
@Body body: AuthorizeESRBody): Response<JsonObject>
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ interface ProtonChainService {
@Body body: AccountBody
): Response<Account>

@POST//("/v1/chain/get_abi")
fun getAbi(
@Url url: String,
@Body body: AccountBody
): Response<JsonObject>

@GET//("/v2/state/get_tokens?account=")
suspend fun getCurrencyBalances(
@Url url: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ package com.metallicus.protonsdk.db
import androidx.room.TypeConverter
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.metallicus.protonsdk.model.AccountContact
import timber.log.Timber

object DefaultTypeConverters {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import com.metallicus.protonsdk.model.*
AccountContact::class,
CurrencyBalance::class,
Action::class],
version = 19,
version = 20,
exportSchema = false
)
abstract class ProtonDb : RoomDatabase() {
Expand Down
Loading

0 comments on commit 8d13433

Please sign in to comment.