From 730f5038386a53be8df089aa1c48e8f54523df11 Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 7 Apr 2023 09:50:46 +0800 Subject: [PATCH 01/19] feat: migrate to web sdk v2 --- .../java/com/portto/valuedapp/evm/EvmChain.kt | 10 +++ .../valuedapp/evm/EvmSignMessageFragment.kt | 62 +++++++++++-------- app/src/main/res/values/strings.xml | 4 +- build.gradle | 10 +-- core/build.gradle | 2 +- .../java/com/portto/sdk/core/BloctoApi.kt | 39 +++++++----- .../java/com/portto/sdk/core/BloctoSDK.kt | 38 ++++++++++-- .../java/com/portto/sdk/core/method/Method.kt | 15 +++++ .../sdk/core/method/RequestAccountMethod.kt | 12 ++++ .../sdk/core/model/SendTransactionResponse.kt | 10 +++ .../sdk/core/model/SignMessageResponse.kt | 10 +++ dependencies.gradle | 8 +-- evm/build.gradle | 1 + .../sdk/evm/method/SendTransactionMethod.kt | 38 +++++++++++- .../sdk/evm/method/SignMessageMethod.kt | 37 ++++++++++- .../sdk/evm/model/SendTransactionRequest.kt | 16 +++++ .../sdk/evm/model/SignMessageRequest.kt | 14 +++++ .../java/com/portto/sdk/flow/FlowService.kt | 9 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- .../com/portto/sdk/solana/SolanaService.kt | 7 ++- .../method/SignAndSendTransactionMethod.kt | 39 +++++++++++- .../solana/model/SendTransactionRequest.kt | 18 ++++++ .../com/portto/sdk/wallet/BloctoSDKError.kt | 4 ++ .../main/java/com/portto/sdk/wallet/Const.kt | 32 +++++++++- 24 files changed, 370 insertions(+), 67 deletions(-) create mode 100644 core/src/main/java/com/portto/sdk/core/model/SendTransactionResponse.kt create mode 100644 core/src/main/java/com/portto/sdk/core/model/SignMessageResponse.kt create mode 100644 evm/src/main/java/com/portto/sdk/evm/model/SendTransactionRequest.kt create mode 100644 evm/src/main/java/com/portto/sdk/evm/model/SignMessageRequest.kt create mode 100644 solana/src/main/java/com/portto/sdk/solana/model/SendTransactionRequest.kt diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt index 260954f..c0e0566 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt @@ -5,6 +5,8 @@ import com.portto.valuedapp.Config enum class EvmChain( val title: String, val symbol: String, + val mainnetChainId: Int, + val testnetChainId: Int, val mainnetContractAddress: String, val testnetContractAddress: String, val mainnetRpcUrl: String, @@ -16,6 +18,8 @@ enum class EvmChain( ETHEREUM( title = "Ethereum", symbol = "ETH", + mainnetChainId = 1, + testnetChainId = 4, mainnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", testnetContractAddress = "0x58F385777aa6699b81f741Dd0d5B272A34C1c774", mainnetRpcUrl = "https://mainnet.infura.io/v3/${Config.INFURA_ID}", @@ -26,6 +30,8 @@ enum class EvmChain( BNB_CHAIN( title = "BNB Chain", symbol = "BNB", + mainnetChainId = 56, + testnetChainId = 97, mainnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", testnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", mainnetRpcUrl = "https://bsc-dataseed.binance.org", @@ -36,6 +42,8 @@ enum class EvmChain( POLYGON( title = "Polygon", symbol = "MATIC", + mainnetChainId = 137, + testnetChainId = 80001, mainnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", testnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", mainnetRpcUrl = "https://polygon-mainnet.infura.io/v3/${Config.INFURA_ID}", @@ -46,6 +54,8 @@ enum class EvmChain( AVALANCHE( title = "Avalanche", symbol = "AVAX", + mainnetChainId = 43114, + testnetChainId = 43113, mainnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", testnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", mainnetRpcUrl = "https://api.avax.network/ext/bc/C/rpc", diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt index bbf5105..4ac6b00 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt @@ -47,41 +47,24 @@ class EvmSignMessageFragment : Fragment(R.layout.fragment_evm_sign_message) { private lateinit var binding: FragmentEvmSignMessageBinding private val viewModel: EvmViewModel by activityViewModels() + private var signType = EvmSignType.ETH_SIGN + private val rpcUrl get() = when (BloctoSDK.env) { BloctoEnv.PROD -> viewModel.currentChain.mainnetRpcUrl BloctoEnv.DEV -> viewModel.currentChain.testnetRpcUrl } + private val chainId get() = when (BloctoSDK.env) { + BloctoEnv.PROD -> viewModel.currentChain.mainnetChainId + BloctoEnv.DEV -> viewModel.currentChain.testnetChainId + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentEvmSignMessageBinding.bind(view) - var signType = EvmSignType.ETH_SIGN - - binding.chipGroup.setOnCheckedStateChangeListener { _, checkedIds -> - val checkedId = checkedIds.firstOrNull() ?: return@setOnCheckedStateChangeListener - when (checkedId) { - binding.ethSign.id -> { - signType = EvmSignType.ETH_SIGN - binding.input.setText("0x416e79206d65737361676520796f752077616e6e61207369676e") - } - binding.personalSign.id -> { - signType = EvmSignType.PERSONAL_SIGN - binding.input.setText("Any message you wanna sign") - } - binding.typedDataV3.id -> { - signType = EvmSignType.TYPED_DATA_SIGN_V3 - binding.input.setText(getString(R.string.default_typed_data_v3)) - } - binding.typedDataV4.id -> { - signType = EvmSignType.TYPED_DATA_SIGN_V4 - binding.input.setText(getString(R.string.default_typed_data_v4)) - } - binding.typedData.id -> { - signType = EvmSignType.TYPED_DATA_SIGN - binding.input.setText(getString(R.string.default_typed_data_v4)) - } - } + binding.chipGroup.setOnCheckedStateChangeListener { _, _ -> + setupMessage() resetView() } @@ -91,6 +74,7 @@ class EvmSignMessageFragment : Fragment(R.layout.fragment_evm_sign_message) { } viewModel.resetView.observe(viewLifecycleOwner) { + setupMessage() resetView() } } @@ -100,6 +84,32 @@ class EvmSignMessageFragment : Fragment(R.layout.fragment_evm_sign_message) { view?.clearFocus() } + private fun setupMessage() { + val checkedId = binding.chipGroup.checkedChipIds.firstOrNull() ?: return + when (checkedId) { + binding.ethSign.id -> { + signType = EvmSignType.ETH_SIGN + binding.input.setText("0x416e79206d65737361676520796f752077616e6e61207369676e") + } + binding.personalSign.id -> { + signType = EvmSignType.PERSONAL_SIGN + binding.input.setText("Any message you wanna sign") + } + binding.typedDataV3.id -> { + signType = EvmSignType.TYPED_DATA_SIGN_V3 + binding.input.setText(getString(R.string.default_typed_data_v3, chainId)) + } + binding.typedDataV4.id -> { + signType = EvmSignType.TYPED_DATA_SIGN_V4 + binding.input.setText(getString(R.string.default_typed_data_v4, chainId)) + } + binding.typedData.id -> { + signType = EvmSignType.TYPED_DATA_SIGN + binding.input.setText(getString(R.string.default_typed_data_v4, chainId)) + } + } + } + private fun signMessage(signType: EvmSignType) { resetView() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ea4d49c..157dfe1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -18,8 +18,8 @@ Typed Data Composite Signatures Sign - {\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":4,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}} - {\"domain\":{\"chainId\":4,\"name\":\"Ether Mail\",\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\",\"version\":\"1\"},\"message\":{\"contents\":\"Hello, Bob!\",\"from\":{\"name\":\"Cow\",\"wallets\":[\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF\"]},\"to\":[{\"name\":\"Bob\",\"wallets\":[\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\",\"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57\",\"0xB0B0b0b0b0b0B000000000000000000000000000\"]}]},\"primaryType\":\"Mail\",\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Group\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"members\",\"type\":\"Person[]\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person[]\"},{\"name\":\"contents\",\"type\":\"string\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallets\",\"type\":\"address[]\"}]}} + {\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":%1$d,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}} + {\"domain\":{\"chainId\":%1$d,\"name\":\"Ether Mail\",\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\",\"version\":\"1\"},\"message\":{\"contents\":\"Hello, Bob!\",\"from\":{\"name\":\"Cow\",\"wallets\":[\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF\"]},\"to\":[{\"name\":\"Bob\",\"wallets\":[\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\",\"0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57\",\"0xB0B0b0b0b0b0B000000000000000000000000000\"]}]},\"primaryType\":\"Mail\",\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Group\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"members\",\"type\":\"Person[]\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person[]\"},{\"name\":\"contents\",\"type\":\"string\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallets\",\"type\":\"address[]\"}]}} Show signature Signature: %1$s isAuthorizedSigner: %1$s diff --git a/build.gradle b/build.gradle index a6b8700..8599104 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { dependencies { - classpath "com.vanniktech:gradle-maven-publish-plugin:0.20.0" - classpath "com.google.gms:google-services:4.3.14" - classpath "com.google.firebase:firebase-appdistribution-gradle:3.0.3" + classpath "com.vanniktech:gradle-maven-publish-plugin:0.22.0" + classpath "com.google.gms:google-services:4.3.15" + classpath "com.google.firebase:firebase-appdistribution-gradle:4.0.0" } } plugins { - id 'com.android.application' version '7.3.0' apply false - id 'com.android.library' version '7.3.0' apply false + id 'com.android.application' version '7.4.2' apply false + id 'com.android.library' version '7.4.2' apply false id 'org.jetbrains.kotlin.android' version '1.7.0' apply false id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.21' } diff --git a/core/build.gradle b/core/build.gradle index cea44a5..e602cca 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -49,7 +49,7 @@ dependencies { implementation "com.google.android.material:material:$versions.material" implementation "com.squareup.okhttp3:okhttp:$versions.okhttp" implementation "com.squareup.okhttp3:logging-interceptor:$versions.okhttp" - implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$versions.serialization" + api "org.jetbrains.kotlinx:kotlinx-serialization-json:$versions.serialization" testImplementation "junit:junit:$versions.junit" testImplementation "io.mockk:mockk:$versions.mockk" diff --git a/core/src/main/java/com/portto/sdk/core/BloctoApi.kt b/core/src/main/java/com/portto/sdk/core/BloctoApi.kt index 74f09ac..1da9e23 100644 --- a/core/src/main/java/com/portto/sdk/core/BloctoApi.kt +++ b/core/src/main/java/com/portto/sdk/core/BloctoApi.kt @@ -2,11 +2,13 @@ package com.portto.sdk.core import androidx.annotation.WorkerThread import androidx.viewbinding.BuildConfig +import com.portto.sdk.core.BloctoApi.toErrorCode import com.portto.sdk.core.BuildConfig.VERSION_NAME -import com.portto.sdk.wallet.BloctoEnv import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient @@ -21,12 +23,6 @@ internal object BloctoApi { val jsonType = "application/json; charset=utf-8".toMediaType() - val baseUrl - get() = when (BloctoSDK.env) { - BloctoEnv.PROD -> "https://api.blocto.app" - BloctoEnv.DEV -> "https://api-dev.blocto.app/" - } - private val loggingInterceptor = HttpLoggingInterceptor().apply { level = if (BuildConfig.DEBUG) { HttpLoggingInterceptor.Level.BODY @@ -54,11 +50,17 @@ internal object BloctoApi { .addInterceptor(headerInterceptor) .addInterceptor(loggingInterceptor) .build() + + fun String.toErrorCode() = json.parseToJsonElement(this) + .jsonObject["error_code"] + ?.jsonPrimitive + ?.content + ?: this } -inline fun get(path: String): T { +inline fun get(url: String): T { val request = Request.Builder() - .url("${BloctoApi.baseUrl}/$path") + .url(url) .get() .build() @@ -66,24 +68,33 @@ inline fun get(path: String): T { if (it.isSuccessful) { return BloctoApi.json.decodeFromString(it.body?.string().orEmpty()) } else { - throw Exception("code: ${it.code}, message=${it.body?.string()}") + throw Exception(it.body?.string()?.toErrorCode()) } } } -inline fun post(path: String, requestBody: U): T { +inline fun post( + url: String, + requestBody: U, + headers: Map? = null +): T { val body = BloctoApi.json.encodeToString(requestBody).toRequestBody(BloctoApi.jsonType) val request = Request.Builder() - .url("${BloctoApi.baseUrl}/$path") + .url(url) .post(body) + .apply { + for ((key, value) in (headers ?: emptyMap())) { + addHeader(key, value) + } + } .build() BloctoApi.client.newCall(request).execute().use { if (it.isSuccessful) { return BloctoApi.json.decodeFromString(it.body?.string().orEmpty()) } else { - throw Exception("code: ${it.code}, message=${it.body?.string()}") + throw Exception(it.body?.string()?.toErrorCode()) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/com/portto/sdk/core/BloctoSDK.kt b/core/src/main/java/com/portto/sdk/core/BloctoSDK.kt index d93b1a8..f2c079d 100644 --- a/core/src/main/java/com/portto/sdk/core/BloctoSDK.kt +++ b/core/src/main/java/com/portto/sdk/core/BloctoSDK.kt @@ -7,14 +7,21 @@ import android.net.Uri import android.util.Log import androidx.annotation.VisibleForTesting import com.portto.sdk.core.method.Method +import com.portto.sdk.core.method.RequestAccountMethod import com.portto.sdk.wallet.BloctoEnv import com.portto.sdk.wallet.BloctoSDKError import com.portto.sdk.wallet.Const +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.util.* object BloctoSDK { private var appId: String? = null + private var webSessionId: String? = null private val requestMap = mutableMapOf>() @JvmStatic @@ -47,14 +54,33 @@ object BloctoSDK { } catch (e: ActivityNotFoundException) { if (method.blockchain == Blockchain.FLOW) Log.w("BloctoSDK", "Flow does not support web fallback") - else { - val url = method.encodeToUri( + else + launchWebSDK(context, method, appId, requestId) + } + } + + private fun launchWebSDK( + context: Context, + method: Method<*>, + appId: String, + requestId: String + ) { + val exceptionHandler = CoroutineExceptionHandler { _, error -> + val err = BloctoSDKError.values().find { it.message == error.message } + ?: BloctoSDKError.UNEXPECTED_ERROR + method.onError(err) + } + + MainScope().launch(exceptionHandler) { + val url = withContext(Dispatchers.IO) { + method.encodeToWebUri( authority = Const.webSDKUrl(env), appId = appId, - requestId = requestId + requestId = requestId, + webSessionId = webSessionId ).build().toString() - context.startActivity(WebSDKActivity.newIntent(context, requestId, url)) } + context.startActivity(WebSDKActivity.newIntent(context, requestId, url)) } } @@ -65,6 +91,9 @@ object BloctoSDK { val method = requestMap[requestId] ?: return requestMap.clear() if (handleError(method, uri)) return + if (method is RequestAccountMethod) { + webSessionId = uri.getQueryParameter(Const.KEY_SESSION_ID) + } method.handleCallback(uri) } @@ -79,6 +108,7 @@ object BloctoSDK { @VisibleForTesting fun resetForTesting() { appId = null + webSessionId = null env = BloctoEnv.PROD } } diff --git a/core/src/main/java/com/portto/sdk/core/method/Method.kt b/core/src/main/java/com/portto/sdk/core/method/Method.kt index bcfa410..03c5211 100644 --- a/core/src/main/java/com/portto/sdk/core/method/Method.kt +++ b/core/src/main/java/com/portto/sdk/core/method/Method.kt @@ -1,6 +1,7 @@ package com.portto.sdk.core.method import android.net.Uri +import androidx.annotation.WorkerThread import com.portto.sdk.core.Blockchain import com.portto.sdk.wallet.BloctoSDKError import com.portto.sdk.wallet.Const @@ -25,4 +26,18 @@ abstract class Method( .appendQueryParameter(Const.KEY_METHOD, name) .appendQueryParameter(Const.KEY_BLOCKCHAIN, blockchain.value) } + + @WorkerThread + open fun encodeToWebUri( + authority: String, + appId: String, + requestId: String, + webSessionId: String? = null + ): Uri.Builder { + return Uri.Builder() + .scheme(Const.HTTPS_SCHEME) + .authority(authority) + .appendPath(appId) + .appendPath(blockchain.value) + } } diff --git a/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt b/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt index b5c796b..67b6bb8 100644 --- a/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt +++ b/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt @@ -22,4 +22,16 @@ class RequestAccountMethod( } onSuccess(address) } + + override fun encodeToWebUri( + authority: String, + appId: String, + requestId: String, + webSessionId: String? + ): Uri.Builder { + return super.encodeToWebUri(authority, appId, requestId, webSessionId) + .appendPath(Const.PATH_AUTHN) + .appendQueryParameter(Const.KEY_REQUEST_ID, requestId) + .appendQueryParameter(Const.KEY_REQUEST_SOURCE, Const.SDK_RESOURCE) + } } diff --git a/core/src/main/java/com/portto/sdk/core/model/SendTransactionResponse.kt b/core/src/main/java/com/portto/sdk/core/model/SendTransactionResponse.kt new file mode 100644 index 0000000..f239952 --- /dev/null +++ b/core/src/main/java/com/portto/sdk/core/model/SendTransactionResponse.kt @@ -0,0 +1,10 @@ +package com.portto.sdk.core.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SendTransactionResponse( + @SerialName("authorizationId") + val authorizationId: String +) diff --git a/core/src/main/java/com/portto/sdk/core/model/SignMessageResponse.kt b/core/src/main/java/com/portto/sdk/core/model/SignMessageResponse.kt new file mode 100644 index 0000000..309fe15 --- /dev/null +++ b/core/src/main/java/com/portto/sdk/core/model/SignMessageResponse.kt @@ -0,0 +1,10 @@ +package com.portto.sdk.core.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SignMessageResponse( + @SerialName("signatureId") + val signatureId: String +) diff --git a/dependencies.gradle b/dependencies.gradle index ee682c8..5ceb004 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -4,9 +4,9 @@ ext.versions = [ versionCode : 5, versionName : '0.4.0', - androidx_activity : '1.6.0', - androidx_appcompat : '1.5.1', - androidx_browser : '1.4.0', + androidx_activity : '1.6.1', + androidx_appcompat : '1.6.1', + androidx_browser : '1.5.0', androidx_core : '1.9.0', androidx_fragment : '1.5.3', androidx_lifecycle : '2.5.1', @@ -14,7 +14,7 @@ ext.versions = [ androidx_constraint : '2.1.4', coroutine : '1.6.4', flow_sdk : '0.7.1', - material : '1.6.1', + material : '1.8.0', okhttp : '4.10.0', serialization : '1.3.2', timber : '5.0.1', diff --git a/evm/build.gradle b/evm/build.gradle index d8fadda..9644235 100644 --- a/evm/build.gradle +++ b/evm/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.library' id 'org.jetbrains.kotlin.android' + id 'kotlinx-serialization' } apply from: "$rootDir/dependencies.gradle" diff --git a/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt b/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt index 03c74aa..c2bb4ac 100644 --- a/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt +++ b/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt @@ -1,8 +1,13 @@ package com.portto.sdk.evm.method import android.net.Uri +import androidx.annotation.WorkerThread import com.portto.sdk.core.Blockchain +import com.portto.sdk.core.BloctoSDK import com.portto.sdk.core.method.Method +import com.portto.sdk.core.model.SendTransactionResponse +import com.portto.sdk.core.post +import com.portto.sdk.evm.model.SendTransactionRequest import com.portto.sdk.wallet.BloctoSDKError import com.portto.sdk.wallet.Const import java.math.BigInteger @@ -12,7 +17,7 @@ class SendTransactionMethod( private val toAddress: String, private val data: String, private val value: BigInteger = BigInteger.ZERO, - blockchain: Blockchain, + private val blockchain: Blockchain, onSuccess: (String) -> Unit, onError: (BloctoSDKError) -> Unit ) : Method(blockchain, onSuccess, onError) { @@ -36,4 +41,35 @@ class SendTransactionMethod( .appendQueryParameter(Const.KEY_DATA, data) .appendQueryParameter(Const.KEY_VALUE, String.format("%#x", value)) } + + @WorkerThread + override fun encodeToWebUri( + authority: String, + appId: String, + requestId: String, + webSessionId: String? + ): Uri.Builder { + val sessionId = webSessionId ?: kotlin.run { + throw Throwable(BloctoSDKError.SESSION_ID_REQUIRED.message) + } + + val requestBody = SendTransactionRequest( + from = fromAddress, + to = toAddress, + data = data, + value = String.format("%#x", value) + ) + + val headers = mapOf( + Const.HEADER_SESSION_ID to sessionId, + Const.HEADER_REQUEST_ID to requestId, + Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE + ) + + val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_AUTHZ_DAPP}" + val response: SendTransactionResponse = post(url, listOf(requestBody), headers) + return super.encodeToWebUri(authority, appId, requestId, webSessionId) + .appendPath(Const.PATH_AUTHZ) + .appendPath(response.authorizationId) + } } diff --git a/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt b/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt index c22b266..f7f0ab9 100644 --- a/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt +++ b/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt @@ -1,8 +1,13 @@ package com.portto.sdk.evm.method import android.net.Uri +import androidx.annotation.WorkerThread import com.portto.sdk.core.Blockchain +import com.portto.sdk.core.BloctoSDK import com.portto.sdk.core.method.Method +import com.portto.sdk.core.model.SignMessageResponse +import com.portto.sdk.core.post +import com.portto.sdk.evm.model.SignMessageRequest import com.portto.sdk.wallet.BloctoSDKError import com.portto.sdk.wallet.Const import com.portto.sdk.wallet.evm.EvmSignType @@ -11,7 +16,7 @@ class SignMessageMethod( private val fromAddress: String, private val signType: EvmSignType, private val message: String, - blockchain: Blockchain, + private val blockchain: Blockchain, onSuccess: (String) -> Unit, onError: (BloctoSDKError) -> Unit ) : Method(blockchain, onSuccess, onError) { @@ -34,4 +39,34 @@ class SignMessageMethod( .appendQueryParameter(Const.KEY_TYPE, signType.type) .appendQueryParameter(Const.KEY_MESSAGE, message) } + + @WorkerThread + override fun encodeToWebUri( + authority: String, + appId: String, + requestId: String, + webSessionId: String? + ): Uri.Builder { + val sessionId = webSessionId ?: kotlin.run { + throw Throwable(BloctoSDKError.SESSION_ID_REQUIRED.message) + } + + val requestBody = SignMessageRequest( + from = fromAddress, + message = message, + method = signType.type + ) + + val headers = mapOf( + Const.HEADER_SESSION_ID to sessionId, + Const.HEADER_REQUEST_ID to requestId, + Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE + ) + + val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_USER_SIGNATURE_DAPP}" + val response: SignMessageResponse = post(url, requestBody, headers) + return super.encodeToWebUri(authority, appId, requestId, webSessionId) + .appendPath(Const.PATH_USER_SIGNATURE) + .appendPath(response.signatureId) + } } diff --git a/evm/src/main/java/com/portto/sdk/evm/model/SendTransactionRequest.kt b/evm/src/main/java/com/portto/sdk/evm/model/SendTransactionRequest.kt new file mode 100644 index 0000000..0448132 --- /dev/null +++ b/evm/src/main/java/com/portto/sdk/evm/model/SendTransactionRequest.kt @@ -0,0 +1,16 @@ +package com.portto.sdk.evm.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +class SendTransactionRequest( + @SerialName("from") + val from: String, + @SerialName("to") + val to: String, + @SerialName("data") + val data: String, + @SerialName("value") + val value: String +) diff --git a/evm/src/main/java/com/portto/sdk/evm/model/SignMessageRequest.kt b/evm/src/main/java/com/portto/sdk/evm/model/SignMessageRequest.kt new file mode 100644 index 0000000..f5b23bb --- /dev/null +++ b/evm/src/main/java/com/portto/sdk/evm/model/SignMessageRequest.kt @@ -0,0 +1,14 @@ +package com.portto.sdk.evm.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SignMessageRequest( + @SerialName("from") + val from: String, + @SerialName("message") + val message: String, + @SerialName("method") + val method: String +) diff --git a/flow/src/main/java/com/portto/sdk/flow/FlowService.kt b/flow/src/main/java/com/portto/sdk/flow/FlowService.kt index bc7661a..339f333 100644 --- a/flow/src/main/java/com/portto/sdk/flow/FlowService.kt +++ b/flow/src/main/java/com/portto/sdk/flow/FlowService.kt @@ -1,11 +1,14 @@ package com.portto.sdk.flow import androidx.annotation.WorkerThread +import com.portto.sdk.core.BloctoSDK import com.portto.sdk.core.get import com.portto.sdk.flow.model.FeePayerResponse - +import com.portto.sdk.wallet.Const object FlowService { @WorkerThread - fun getFeePayer(): FeePayerResponse = get("flow/feePayer") -} \ No newline at end of file + fun getFeePayer(): FeePayerResponse = get( + url = "${Const.bloctoApiUrl(BloctoSDK.env)}/flow/feePayer" + ) +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 47ccf25..66c025c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Mar 09 10:37:29 CST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/solana/src/main/java/com/portto/sdk/solana/SolanaService.kt b/solana/src/main/java/com/portto/sdk/solana/SolanaService.kt index aba8fde..26b89de 100644 --- a/solana/src/main/java/com/portto/sdk/solana/SolanaService.kt +++ b/solana/src/main/java/com/portto/sdk/solana/SolanaService.kt @@ -1,14 +1,17 @@ package com.portto.sdk.solana import androidx.annotation.WorkerThread +import com.portto.sdk.core.BloctoSDK import com.portto.sdk.core.post import com.portto.sdk.solana.model.SolanaRawTxRequest import com.portto.sdk.solana.model.SolanaRawTxResponse +import com.portto.sdk.wallet.Const object SolanaService { @WorkerThread fun createRawTransaction(requestBody: SolanaRawTxRequest): SolanaRawTxResponse { - return post("/solana/createRawTransaction", requestBody) + val url = "${Const.bloctoApiUrl(BloctoSDK.env)}/solana/createRawTransaction" + return post(url, requestBody) } -} \ No newline at end of file +} diff --git a/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt b/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt index cc68615..4c2e735 100644 --- a/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt +++ b/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt @@ -1,8 +1,13 @@ package com.portto.sdk.solana.method import android.net.Uri +import androidx.annotation.WorkerThread import com.portto.sdk.core.Blockchain +import com.portto.sdk.core.BloctoSDK import com.portto.sdk.core.method.Method +import com.portto.sdk.core.model.SendTransactionResponse +import com.portto.sdk.core.post +import com.portto.sdk.solana.model.SendTransactionRequest import com.portto.sdk.wallet.BloctoSDKError import com.portto.sdk.wallet.Const @@ -12,7 +17,7 @@ class SignAndSendTransactionMethod( val isInvokeWrapped: Boolean, val publicKeySignaturePairs: Map? = null, val appendTx: Map? = null, - blockchain: Blockchain, + private val blockchain: Blockchain, onSuccess: (String) -> Unit, onError: (BloctoSDKError) -> Unit ) : Method(blockchain, onSuccess, onError) { @@ -49,4 +54,36 @@ class SignAndSendTransactionMethod( } } } + + @WorkerThread + override fun encodeToWebUri( + authority: String, + appId: String, + requestId: String, + webSessionId: String? + ): Uri.Builder { + val sessionId = webSessionId ?: kotlin.run { + throw Throwable(BloctoSDKError.SESSION_ID_REQUIRED.message) + } + + val requestBody = SendTransactionRequest( + from = fromAddress, + message = message, + isInvokeWrapped = isInvokeWrapped, + publicKeySignaturePairs = publicKeySignaturePairs, + appendTx = appendTx + ) + + val headers = mapOf( + Const.HEADER_SESSION_ID to sessionId, + Const.HEADER_REQUEST_ID to requestId, + Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE + ) + + val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_AUTHZ_DAPP}" + val response: SendTransactionResponse = post(url, requestBody, headers) + return super.encodeToWebUri(authority, appId, requestId, webSessionId) + .appendPath(Const.PATH_AUTHZ) + .appendPath(response.authorizationId) + } } diff --git a/solana/src/main/java/com/portto/sdk/solana/model/SendTransactionRequest.kt b/solana/src/main/java/com/portto/sdk/solana/model/SendTransactionRequest.kt new file mode 100644 index 0000000..46c0c41 --- /dev/null +++ b/solana/src/main/java/com/portto/sdk/solana/model/SendTransactionRequest.kt @@ -0,0 +1,18 @@ +package com.portto.sdk.solana.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SendTransactionRequest( + @SerialName("from") + val from: String, + @SerialName("message") + val message: String, + @SerialName("isInvokeWrapped") + val isInvokeWrapped: Boolean, + @SerialName("publicKeySignaturePairs") + val publicKeySignaturePairs: Map?, + @SerialName("appendTx") + val appendTx: Map? +) diff --git a/wallet/src/main/java/com/portto/sdk/wallet/BloctoSDKError.kt b/wallet/src/main/java/com/portto/sdk/wallet/BloctoSDKError.kt index d1bd1fe..6cf916d 100644 --- a/wallet/src/main/java/com/portto/sdk/wallet/BloctoSDKError.kt +++ b/wallet/src/main/java/com/portto/sdk/wallet/BloctoSDKError.kt @@ -8,4 +8,8 @@ enum class BloctoSDKError(val message: String) { UNEXPECTED_ERROR("unexpected_error"), ETH_SIGN_INVALID_HEX_STRING("eth_sign_invalid_hex_string"), FLOW_MISSING_ARG("flow_app_id_and_nonce_are_required_by_authn"), + SESSION_ID_REQUIRED("session_id_required"), + INVALID_SESSION_ID("invalid_session_id"), + MESSAGE_REQUIRED("message_required"), + METHOD_NOT_SUPPORTED("method_not_supported"), } diff --git a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt index 887b857..2cee5fa 100644 --- a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt +++ b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt @@ -17,12 +17,19 @@ object Const { private const val BLOCTO_URI_AUTHORITY_PROD = "blocto.app" private const val BLOCTO_URI_AUTHORITY_DEV = "dev.blocto.app" - private const val WEB_SDK_URL_PROD = "wallet.blocto.app" - private const val WEB_SDK_URL_DEV = "wallet-testnet.blocto.app" + private const val BLOCTO_API_URL_PROD = "https://api.blocto.app" + private const val BLOCTO_API_URL_DEV = "https://api-dev.blocto.app" + + private const val WEB_SDK_URL_PROD = "wallet-v2.blocto.app" + private const val WEB_SDK_URL_DEV = "wallet-v2-dev.blocto.app" + + private const val WEB_API_URL_PROD = "https://wallet-v2.blocto.app/api" + private const val WEB_API_URL_DEV = "https://wallet-v2-dev.blocto.app/api" const val HTTPS_SCHEME = "https" const val BLOCTO_SCHEME = "blocto" const val BLOCTO_URI_PATH = "sdk" + const val SDK_RESOURCE = "sdk_android" const val KEY_APP_ID = "app_id" const val KEY_REQUEST_ID = "request_id" @@ -47,7 +54,18 @@ object Const { const val KEY_FLOW_APP_ID = "flow_app_id" // Since 0.3.0 (Flow) const val KEY_FLOW_NONCE = "flow_nonce" // Since 0.3.0 (Flow) const val KEY_FLOW_TX = "flow_transaction" // Since 0.3.0 (Flow) + const val KEY_SESSION_ID = "session_id" + const val KEY_REQUEST_SOURCE = "request_source" + const val PATH_AUTHN = "authn" + const val PATH_AUTHZ = "authz" + const val PATH_AUTHZ_DAPP = "authz-dapp" + const val PATH_USER_SIGNATURE = "user-signature" + const val PATH_USER_SIGNATURE_DAPP = "user-signature-dapp" + + const val HEADER_SESSION_ID = "Blocto-Session-Identifier" + const val HEADER_REQUEST_ID = "Blocto-Request-Identifier" + const val HEADER_REQUEST_SOURCE = "Blocto-Request-Source" fun bloctoAuthority(env: BloctoEnv): String = when (env) { BloctoEnv.PROD -> BLOCTO_URI_AUTHORITY_PROD @@ -59,8 +77,18 @@ object Const { BloctoEnv.DEV -> BLOCTO_PACKAGE_DEV } + fun bloctoApiUrl(env: BloctoEnv): String = when (env) { + BloctoEnv.PROD -> BLOCTO_API_URL_PROD + BloctoEnv.DEV -> BLOCTO_API_URL_DEV + } + fun webSDKUrl(env: BloctoEnv): String = when (env) { BloctoEnv.PROD -> WEB_SDK_URL_PROD BloctoEnv.DEV -> WEB_SDK_URL_DEV } + + fun webApiUrl(env: BloctoEnv): String = when (env) { + BloctoEnv.PROD -> WEB_API_URL_PROD + BloctoEnv.DEV -> WEB_API_URL_DEV + } } From 7aae11b596f3f519bc646df9e91f18c9df2dcea3 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 24 Apr 2023 16:20:27 +0800 Subject: [PATCH 02/19] feat: adjust api endpoints --- .../java/com/portto/sdk/evm/method/SendTransactionMethod.kt | 2 +- .../main/java/com/portto/sdk/evm/method/SignMessageMethod.kt | 2 +- .../portto/sdk/solana/method/SignAndSendTransactionMethod.kt | 2 +- wallet/src/main/java/com/portto/sdk/wallet/Const.kt | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt b/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt index c2bb4ac..b0fbd4b 100644 --- a/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt +++ b/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt @@ -66,7 +66,7 @@ class SendTransactionMethod( Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE ) - val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_AUTHZ_DAPP}" + val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_DAPP}/${Const.PATH_AUTHZ}" val response: SendTransactionResponse = post(url, listOf(requestBody), headers) return super.encodeToWebUri(authority, appId, requestId, webSessionId) .appendPath(Const.PATH_AUTHZ) diff --git a/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt b/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt index f7f0ab9..f16b93b 100644 --- a/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt +++ b/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt @@ -63,7 +63,7 @@ class SignMessageMethod( Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE ) - val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_USER_SIGNATURE_DAPP}" + val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_DAPP}/${Const.PATH_USER_SIGNATURE}" val response: SignMessageResponse = post(url, requestBody, headers) return super.encodeToWebUri(authority, appId, requestId, webSessionId) .appendPath(Const.PATH_USER_SIGNATURE) diff --git a/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt b/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt index 4c2e735..242bdb0 100644 --- a/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt +++ b/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt @@ -80,7 +80,7 @@ class SignAndSendTransactionMethod( Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE ) - val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_AUTHZ_DAPP}" + val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_DAPP}/${Const.PATH_AUTHZ}" val response: SendTransactionResponse = post(url, requestBody, headers) return super.encodeToWebUri(authority, appId, requestId, webSessionId) .appendPath(Const.PATH_AUTHZ) diff --git a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt index 2cee5fa..7834465 100644 --- a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt +++ b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt @@ -57,11 +57,10 @@ object Const { const val KEY_SESSION_ID = "session_id" const val KEY_REQUEST_SOURCE = "request_source" + const val PATH_DAPP = "dapp" const val PATH_AUTHN = "authn" const val PATH_AUTHZ = "authz" - const val PATH_AUTHZ_DAPP = "authz-dapp" const val PATH_USER_SIGNATURE = "user-signature" - const val PATH_USER_SIGNATURE_DAPP = "user-signature-dapp" const val HEADER_SESSION_ID = "Blocto-Session-Identifier" const val HEADER_REQUEST_ID = "Blocto-Request-Identifier" From e165a573728eca865c862672e273523e89cefdfb Mon Sep 17 00:00:00 2001 From: Jack Date: Thu, 4 May 2023 16:50:31 +0800 Subject: [PATCH 03/19] chore: adjust naming --- .../java/com/portto/sdk/core/method/RequestAccountMethod.kt | 2 +- .../java/com/portto/sdk/evm/method/SendTransactionMethod.kt | 2 +- .../main/java/com/portto/sdk/evm/method/SignMessageMethod.kt | 2 +- .../portto/sdk/solana/method/SignAndSendTransactionMethod.kt | 2 +- wallet/src/main/java/com/portto/sdk/wallet/Const.kt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt b/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt index 67b6bb8..25fc4b5 100644 --- a/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt +++ b/core/src/main/java/com/portto/sdk/core/method/RequestAccountMethod.kt @@ -32,6 +32,6 @@ class RequestAccountMethod( return super.encodeToWebUri(authority, appId, requestId, webSessionId) .appendPath(Const.PATH_AUTHN) .appendQueryParameter(Const.KEY_REQUEST_ID, requestId) - .appendQueryParameter(Const.KEY_REQUEST_SOURCE, Const.SDK_RESOURCE) + .appendQueryParameter(Const.KEY_REQUEST_SOURCE, Const.SDK_SOURCE) } } diff --git a/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt b/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt index b0fbd4b..b37eee7 100644 --- a/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt +++ b/evm/src/main/java/com/portto/sdk/evm/method/SendTransactionMethod.kt @@ -63,7 +63,7 @@ class SendTransactionMethod( val headers = mapOf( Const.HEADER_SESSION_ID to sessionId, Const.HEADER_REQUEST_ID to requestId, - Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE + Const.HEADER_REQUEST_SOURCE to Const.SDK_SOURCE ) val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_DAPP}/${Const.PATH_AUTHZ}" diff --git a/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt b/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt index f16b93b..7b4ce67 100644 --- a/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt +++ b/evm/src/main/java/com/portto/sdk/evm/method/SignMessageMethod.kt @@ -60,7 +60,7 @@ class SignMessageMethod( val headers = mapOf( Const.HEADER_SESSION_ID to sessionId, Const.HEADER_REQUEST_ID to requestId, - Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE + Const.HEADER_REQUEST_SOURCE to Const.SDK_SOURCE ) val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_DAPP}/${Const.PATH_USER_SIGNATURE}" diff --git a/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt b/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt index 242bdb0..2d66b4f 100644 --- a/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt +++ b/solana/src/main/java/com/portto/sdk/solana/method/SignAndSendTransactionMethod.kt @@ -77,7 +77,7 @@ class SignAndSendTransactionMethod( val headers = mapOf( Const.HEADER_SESSION_ID to sessionId, Const.HEADER_REQUEST_ID to requestId, - Const.HEADER_REQUEST_SOURCE to Const.SDK_RESOURCE + Const.HEADER_REQUEST_SOURCE to Const.SDK_SOURCE ) val url = "${Const.webApiUrl(BloctoSDK.env)}/${blockchain.value}/${Const.PATH_DAPP}/${Const.PATH_AUTHZ}" diff --git a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt index 7834465..ba28bf8 100644 --- a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt +++ b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt @@ -29,7 +29,7 @@ object Const { const val HTTPS_SCHEME = "https" const val BLOCTO_SCHEME = "blocto" const val BLOCTO_URI_PATH = "sdk" - const val SDK_RESOURCE = "sdk_android" + const val SDK_SOURCE = "sdk_android" const val KEY_APP_ID = "app_id" const val KEY_REQUEST_ID = "request_id" From 80c62f78879f6e711c91a33b3c456ec6851afa49 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 8 May 2023 17:21:26 +0800 Subject: [PATCH 04/19] feat: update app id --- app/src/main/java/com/portto/valuedapp/Config.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/portto/valuedapp/Config.kt b/app/src/main/java/com/portto/valuedapp/Config.kt index b940d44..99da5f3 100644 --- a/app/src/main/java/com/portto/valuedapp/Config.kt +++ b/app/src/main/java/com/portto/valuedapp/Config.kt @@ -4,8 +4,8 @@ object Config { const val INFURA_ID = "" // Your Blocto App ID - const val APP_ID_MAINNET = "49618b1e-461b-4134-8f52-4307dd542a88" - const val APP_ID_TESTNET = "57f397df-263c-4e97-b61f-15b67b9ce285" + const val APP_ID_MAINNET = "0896e44c-20fd-443b-b664-d305b52fe8e8" + const val APP_ID_TESTNET = "0896e44c-20fd-443b-b664-d305b52fe8e8" // Required by Flow const val FLOW_APP_IDENTIFIER = "Awesome App (v0.0)" From 37dfd2c52b2b188bb68a77c9da16b14e36daf07d Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 10 May 2023 14:28:56 +0800 Subject: [PATCH 05/19] feat: update to goerli --- app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt index c0e0566..c6fb968 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt @@ -19,13 +19,13 @@ enum class EvmChain( title = "Ethereum", symbol = "ETH", mainnetChainId = 1, - testnetChainId = 4, + testnetChainId = 5, mainnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", - testnetContractAddress = "0x58F385777aa6699b81f741Dd0d5B272A34C1c774", + testnetContractAddress = "0x806243c7368a90D957592B55875eF4C3353C5bEa", mainnetRpcUrl = "https://mainnet.infura.io/v3/${Config.INFURA_ID}", - testnetRpcUrl = "https://rinkeby.blocto.app", + testnetRpcUrl = "https://goerli.infura.io/v3/${Config.INFURA_ID}", mainnetExplorerDomain = "etherscan.io", - testnetExplorerDomain = "rinkeby.etherscan.io" + testnetExplorerDomain = "goerli.etherscan.io" ), BNB_CHAIN( title = "BNB Chain", From e5f9b1d65ca390cb0cc1c647c9a724a6203e93fb Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 10 May 2023 17:45:13 +0800 Subject: [PATCH 06/19] feat: update contract addresses --- .../java/com/portto/valuedapp/evm/EvmChain.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt index c6fb968..57c29b2 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt @@ -20,8 +20,8 @@ enum class EvmChain( symbol = "ETH", mainnetChainId = 1, testnetChainId = 5, - mainnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", - testnetContractAddress = "0x806243c7368a90D957592B55875eF4C3353C5bEa", + mainnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", + testnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", mainnetRpcUrl = "https://mainnet.infura.io/v3/${Config.INFURA_ID}", testnetRpcUrl = "https://goerli.infura.io/v3/${Config.INFURA_ID}", mainnetExplorerDomain = "etherscan.io", @@ -32,8 +32,8 @@ enum class EvmChain( symbol = "BNB", mainnetChainId = 56, testnetChainId = 97, - mainnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", - testnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", + mainnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", + testnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", mainnetRpcUrl = "https://bsc-dataseed.binance.org", testnetRpcUrl = "https://data-seed-prebsc-1-s1.binance.org:8545", mainnetExplorerDomain = "bscscan.com", @@ -44,8 +44,8 @@ enum class EvmChain( symbol = "MATIC", mainnetChainId = 137, testnetChainId = 80001, - mainnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", - testnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", + mainnetContractAddress = "0xD76bAA840e3D5AE1C5E5C7cEeF1C1A238687860e", + testnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", mainnetRpcUrl = "https://polygon-mainnet.infura.io/v3/${Config.INFURA_ID}", testnetRpcUrl = "https://polygon-mumbai.infura.io/v3/${Config.INFURA_ID}", mainnetExplorerDomain = "polygonscan.com", @@ -56,8 +56,8 @@ enum class EvmChain( symbol = "AVAX", mainnetChainId = 43114, testnetChainId = 43113, - mainnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", - testnetContractAddress = "0xfde90c9Bc193F520d119302a2dB8520D3A4408c8", + mainnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", + testnetContractAddress = "0xD76bAA840e3D5AE1C5E5C7cEeF1C1A238687860e", mainnetRpcUrl = "https://api.avax.network/ext/bc/C/rpc", testnetRpcUrl = "https://api.avax-test.network/ext/bc/C/rpc", mainnetExplorerDomain = "snowtrace.io", From 422e172edf9b022e3caf3ec1d98e72c2cf59fe5e Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 12 May 2023 11:43:50 +0800 Subject: [PATCH 07/19] feat: add pull request template --- .github/pull_request_template.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..e8ecb4c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,8 @@ +## Ticket + + +## Changes + + +## Screenshots + From 11849af2f1725902f70d57f32fae13c9e2f7839a Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 12 May 2023 13:58:11 +0800 Subject: [PATCH 08/19] feat: add github action for creating asana attachment --- .github/workflows/create-asana-attachment.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/create-asana-attachment.yml diff --git a/.github/workflows/create-asana-attachment.yml b/.github/workflows/create-asana-attachment.yml new file mode 100644 index 0000000..3913a20 --- /dev/null +++ b/.github/workflows/create-asana-attachment.yml @@ -0,0 +1,17 @@ +name: Asana +on: + pull_request: + types: [opened, reopened] + +jobs: + create-asana-attachment-job: + runs-on: ubuntu-latest + name: Create pull request attachments on Asana tasks + steps: + - name: Create pull request attachments + uses: Asana/create-app-attachment-github-action@latest + id: postAttachment + with: + asana-secret: ${{ secrets.ASANA_SECRET }} + - name: Log output status + run: echo "Status is ${{ steps.postAttachment.outputs.status }}" \ No newline at end of file From 12548f5b37d0e95c44e6c20af27b433f24a78865 Mon Sep 17 00:00:00 2001 From: Jack Date: Sun, 23 Apr 2023 20:20:10 +0800 Subject: [PATCH 09/19] feat: add optimism and arbitrum chains --- .../java/com/portto/valuedapp/evm/EvmChain.kt | 34 +++++++++++- .../evm/EvmSendTransactionFragment.kt | 53 ++++--------------- .../valuedapp/evm/EvmSignMessageFragment.kt | 48 ++++------------- .../valuedapp/evm/EvmValueDappActivity.kt | 33 +++--------- .../java/com/portto/sdk/core/Blockchain.kt | 2 + .../main/java/com/portto/sdk/evm/Avalanche.kt | 12 ----- .../main/java/com/portto/sdk/evm/BNBChain.kt | 12 ----- .../main/java/com/portto/sdk/evm/Ethereum.kt | 12 ----- evm/src/main/java/com/portto/sdk/evm/Evm.kt | 12 +++-- .../main/java/com/portto/sdk/evm/Polygon.kt | 12 ----- 10 files changed, 71 insertions(+), 159 deletions(-) delete mode 100644 evm/src/main/java/com/portto/sdk/evm/Avalanche.kt delete mode 100644 evm/src/main/java/com/portto/sdk/evm/BNBChain.kt delete mode 100644 evm/src/main/java/com/portto/sdk/evm/Ethereum.kt delete mode 100644 evm/src/main/java/com/portto/sdk/evm/Polygon.kt diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt index 57c29b2..ce0d6f3 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmChain.kt @@ -1,8 +1,10 @@ package com.portto.valuedapp.evm +import com.portto.sdk.core.Blockchain import com.portto.valuedapp.Config enum class EvmChain( + val blockchain: Blockchain, val title: String, val symbol: String, val mainnetChainId: Int, @@ -16,6 +18,7 @@ enum class EvmChain( ) { ETHEREUM( + blockchain = Blockchain.ETHEREUM, title = "Ethereum", symbol = "ETH", mainnetChainId = 1, @@ -28,6 +31,7 @@ enum class EvmChain( testnetExplorerDomain = "goerli.etherscan.io" ), BNB_CHAIN( + blockchain = Blockchain.BNB_CHAIN, title = "BNB Chain", symbol = "BNB", mainnetChainId = 56, @@ -40,6 +44,7 @@ enum class EvmChain( testnetExplorerDomain = "testnet.bscscan.com" ), POLYGON( + blockchain = Blockchain.POLYGON, title = "Polygon", symbol = "MATIC", mainnetChainId = 137, @@ -52,6 +57,7 @@ enum class EvmChain( testnetExplorerDomain = "mumbai.polygonscan.com" ), AVALANCHE( + blockchain = Blockchain.AVALANCHE, title = "Avalanche", symbol = "AVAX", mainnetChainId = 43114, @@ -62,5 +68,31 @@ enum class EvmChain( testnetRpcUrl = "https://api.avax-test.network/ext/bc/C/rpc", mainnetExplorerDomain = "snowtrace.io", testnetExplorerDomain = "testnet.snowtrace.io" - ) + ), + ARBITRUM( + blockchain = Blockchain.ARBITRUM, + title = "Arbitrum", + symbol = "ETH", + mainnetChainId = 42161, + testnetChainId = 421613, + mainnetContractAddress = "0x806243c7368a90D957592B55875eF4C3353C5bEa", + testnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", + mainnetRpcUrl = "https://arb1.arbitrum.io/rpc", + testnetRpcUrl = "https://arbitrum-goerli.public.blastapi.io", + mainnetExplorerDomain = "arbiscan.io", + testnetExplorerDomain = "goerli.arbiscan.io" + ), + OPTIMISM( + blockchain = Blockchain.OPTIMISM, + title = "Optimism", + symbol = "ETH", + mainnetChainId = 10, + testnetChainId = 420, + mainnetContractAddress = "0x806243c7368a90D957592B55875eF4C3353C5bEa", + testnetContractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739", + mainnetRpcUrl = "https://mainnet.optimism.io", + testnetRpcUrl = "https://endpoints.omniatech.io/v1/op/goerli/public", + mainnetExplorerDomain = "optimistic.etherscan.io", + testnetExplorerDomain = "goerli-optimism.etherscan.io" + ), } diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmSendTransactionFragment.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmSendTransactionFragment.kt index 15f2a0c..7ecc552 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmSendTransactionFragment.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmSendTransactionFragment.kt @@ -9,10 +9,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import com.portto.sdk.core.BloctoSDK -import com.portto.sdk.evm.avalanche -import com.portto.sdk.evm.bnb -import com.portto.sdk.evm.ethereum -import com.portto.sdk.evm.polygon +import com.portto.sdk.evm.evm import com.portto.sdk.wallet.BloctoEnv import com.portto.sdk.wallet.BloctoSDKError import com.portto.valuedapp.R @@ -206,44 +203,16 @@ class EvmSendTransactionFragment : Fragment(R.layout.fragment_evm_send_transacti onSuccess: (String) -> Unit, onError: (BloctoSDKError) -> Unit ) { - when (viewModel.currentChain) { - EvmChain.ETHEREUM -> BloctoSDK.ethereum.sendTransaction( - context = requireContext(), - fromAddress = fromAddress, - toAddress = contractAddress, - data = data, - value = value, - onSuccess = onSuccess, - onError = onError - ) - EvmChain.BNB_CHAIN -> BloctoSDK.bnb.sendTransaction( - context = requireContext(), - fromAddress = fromAddress, - toAddress = contractAddress, - data = data, - value = value, - onSuccess = onSuccess, - onError = onError - ) - EvmChain.POLYGON -> BloctoSDK.polygon.sendTransaction( - context = requireContext(), - fromAddress = fromAddress, - toAddress = contractAddress, - data = data, - value = value, - onSuccess = onSuccess, - onError = onError - ) - EvmChain.AVALANCHE -> BloctoSDK.avalanche.sendTransaction( - context = requireContext(), - fromAddress = fromAddress, - toAddress = contractAddress, - data = data, - value = value, - onSuccess = onSuccess, - onError = onError - ) - } + BloctoSDK.evm.sendTransaction( + context = requireContext(), + blockchain = viewModel.currentChain.blockchain, + fromAddress = fromAddress, + toAddress = contractAddress, + data = data, + value = value, + onSuccess = onSuccess, + onError = onError + ) } private fun openExplorer(txHash: String) { diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt index 4ac6b00..d489712 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmSignMessageFragment.kt @@ -9,10 +9,7 @@ import androidx.lifecycle.lifecycleScope import com.portto.ethereum.sign.EthSigUtil import com.portto.sdk.core.BloctoSDK import com.portto.sdk.core.decodeHex -import com.portto.sdk.evm.avalanche -import com.portto.sdk.evm.bnb -import com.portto.sdk.evm.ethereum -import com.portto.sdk.evm.polygon +import com.portto.sdk.evm.evm import com.portto.sdk.wallet.BloctoEnv import com.portto.sdk.wallet.BloctoSDKError import com.portto.sdk.wallet.evm.EvmSignType @@ -163,40 +160,15 @@ class EvmSignMessageFragment : Fragment(R.layout.fragment_evm_sign_message) { viewModel.showError(it) } - when (viewModel.currentChain) { - EvmChain.ETHEREUM -> BloctoSDK.ethereum.signMessage( - context = requireContext(), - fromAddress = address, - signType = signType, - message = message, - onSuccess = onSuccess, - onError = onError - ) - EvmChain.BNB_CHAIN -> BloctoSDK.bnb.signMessage( - context = requireContext(), - fromAddress = address, - signType = signType, - message = message, - onSuccess = onSuccess, - onError = onError - ) - EvmChain.POLYGON -> BloctoSDK.polygon.signMessage( - context = requireContext(), - fromAddress = address, - signType = signType, - message = message, - onSuccess = onSuccess, - onError = onError - ) - EvmChain.AVALANCHE -> BloctoSDK.avalanche.signMessage( - context = requireContext(), - fromAddress = address, - signType = signType, - message = message, - onSuccess = onSuccess, - onError = onError - ) - } + BloctoSDK.evm.signMessage( + context = requireContext(), + blockchain = viewModel.currentChain.blockchain, + fromAddress = address, + signType = signType, + message = message, + onSuccess = onSuccess, + onError = onError + ) } private fun verifySignature(hash: ByteArray, signature: ByteArray): Boolean { diff --git a/app/src/main/java/com/portto/valuedapp/evm/EvmValueDappActivity.kt b/app/src/main/java/com/portto/valuedapp/evm/EvmValueDappActivity.kt index 82b1647..94e81c1 100644 --- a/app/src/main/java/com/portto/valuedapp/evm/EvmValueDappActivity.kt +++ b/app/src/main/java/com/portto/valuedapp/evm/EvmValueDappActivity.kt @@ -8,10 +8,7 @@ import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator import com.portto.sdk.core.BloctoSDK -import com.portto.sdk.evm.avalanche -import com.portto.sdk.evm.bnb -import com.portto.sdk.evm.ethereum -import com.portto.sdk.evm.polygon +import com.portto.sdk.evm.evm import com.portto.sdk.wallet.BloctoEnv import com.portto.sdk.wallet.BloctoSDKError import com.portto.valuedapp.Config.APP_ID_MAINNET @@ -134,27 +131,11 @@ class EvmValueDappActivity : AppCompatActivity() { viewModel.showError(it) } - when (viewModel.currentChain) { - EvmChain.ETHEREUM -> BloctoSDK.ethereum.requestAccount( - context = this, - onSuccess = requestAccountOnSuccess, - onError = requestAccountOnError - ) - EvmChain.BNB_CHAIN -> BloctoSDK.bnb.requestAccount( - context = this, - onSuccess = requestAccountOnSuccess, - onError = requestAccountOnError - ) - EvmChain.POLYGON -> BloctoSDK.polygon.requestAccount( - context = this, - onSuccess = requestAccountOnSuccess, - onError = requestAccountOnError - ) - EvmChain.AVALANCHE -> BloctoSDK.avalanche.requestAccount( - context = this, - onSuccess = requestAccountOnSuccess, - onError = requestAccountOnError - ) - } + BloctoSDK.evm.requestAccount( + context = this, + blockchain = viewModel.currentChain.blockchain, + onSuccess = requestAccountOnSuccess, + onError = requestAccountOnError + ) } } diff --git a/core/src/main/java/com/portto/sdk/core/Blockchain.kt b/core/src/main/java/com/portto/sdk/core/Blockchain.kt index 71c0251..efc48f0 100644 --- a/core/src/main/java/com/portto/sdk/core/Blockchain.kt +++ b/core/src/main/java/com/portto/sdk/core/Blockchain.kt @@ -6,5 +6,7 @@ enum class Blockchain(val value: String) { BNB_CHAIN("bsc"), POLYGON("polygon"), AVALANCHE("avalanche"), + ARBITRUM("arbitrum"), + OPTIMISM("optimism"), FLOW("flow"), } diff --git a/evm/src/main/java/com/portto/sdk/evm/Avalanche.kt b/evm/src/main/java/com/portto/sdk/evm/Avalanche.kt deleted file mode 100644 index 08ee5ba..0000000 --- a/evm/src/main/java/com/portto/sdk/evm/Avalanche.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.portto.sdk.evm - -import com.portto.sdk.core.Blockchain -import com.portto.sdk.core.BloctoSDK - -val BloctoSDK.avalanche by lazy { Avalanche() } - -class Avalanche : Evm() { - - override val blockchain: Blockchain - get() = Blockchain.AVALANCHE -} diff --git a/evm/src/main/java/com/portto/sdk/evm/BNBChain.kt b/evm/src/main/java/com/portto/sdk/evm/BNBChain.kt deleted file mode 100644 index 7b43d46..0000000 --- a/evm/src/main/java/com/portto/sdk/evm/BNBChain.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.portto.sdk.evm - -import com.portto.sdk.core.Blockchain -import com.portto.sdk.core.BloctoSDK - -val BloctoSDK.bnb by lazy { BNBChain() } - -class BNBChain : Evm() { - - override val blockchain: Blockchain - get() = Blockchain.BNB_CHAIN -} diff --git a/evm/src/main/java/com/portto/sdk/evm/Ethereum.kt b/evm/src/main/java/com/portto/sdk/evm/Ethereum.kt deleted file mode 100644 index be75287..0000000 --- a/evm/src/main/java/com/portto/sdk/evm/Ethereum.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.portto.sdk.evm - -import com.portto.sdk.core.Blockchain -import com.portto.sdk.core.BloctoSDK - -val BloctoSDK.ethereum by lazy { Ethereum() } - -class Ethereum : Evm() { - - override val blockchain: Blockchain - get() = Blockchain.ETHEREUM -} diff --git a/evm/src/main/java/com/portto/sdk/evm/Evm.kt b/evm/src/main/java/com/portto/sdk/evm/Evm.kt index 5af38e0..ec5e817 100644 --- a/evm/src/main/java/com/portto/sdk/evm/Evm.kt +++ b/evm/src/main/java/com/portto/sdk/evm/Evm.kt @@ -1,9 +1,8 @@ package com.portto.sdk.evm import android.content.Context -import com.portto.sdk.core.Account +import com.portto.sdk.core.Blockchain import com.portto.sdk.core.BloctoSDK -import com.portto.sdk.core.Chain import com.portto.sdk.core.isValidHex import com.portto.sdk.core.method.RequestAccountMethod import com.portto.sdk.evm.method.SendTransactionMethod @@ -12,10 +11,13 @@ import com.portto.sdk.wallet.BloctoSDKError import com.portto.sdk.wallet.evm.EvmSignType import java.math.BigInteger -abstract class Evm : Chain, Account { +val BloctoSDK.evm by lazy { Evm() } - override fun requestAccount( +class Evm { + + fun requestAccount( context: Context, + blockchain: Blockchain, onSuccess: (String) -> Unit, onError: (BloctoSDKError) -> Unit ) { @@ -29,6 +31,7 @@ abstract class Evm : Chain, Account { fun signMessage( context: Context, + blockchain: Blockchain, fromAddress: String, signType: EvmSignType, message: String, @@ -52,6 +55,7 @@ abstract class Evm : Chain, Account { fun sendTransaction( context: Context, + blockchain: Blockchain, fromAddress: String, toAddress: String, data: String, diff --git a/evm/src/main/java/com/portto/sdk/evm/Polygon.kt b/evm/src/main/java/com/portto/sdk/evm/Polygon.kt deleted file mode 100644 index 67c8175..0000000 --- a/evm/src/main/java/com/portto/sdk/evm/Polygon.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.portto.sdk.evm - -import com.portto.sdk.core.Blockchain -import com.portto.sdk.core.BloctoSDK - -val BloctoSDK.polygon by lazy { Polygon() } - -class Polygon : Evm() { - - override val blockchain: Blockchain - get() = Blockchain.POLYGON -} From 91133a6b9ab774a309a95a735426949564c8d1c1 Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 5 May 2023 15:56:28 +0800 Subject: [PATCH 10/19] feat: add platform key --- core/src/main/java/com/portto/sdk/core/method/Method.kt | 1 + wallet/src/main/java/com/portto/sdk/wallet/Const.kt | 1 + 2 files changed, 2 insertions(+) diff --git a/core/src/main/java/com/portto/sdk/core/method/Method.kt b/core/src/main/java/com/portto/sdk/core/method/Method.kt index 03c5211..70582e4 100644 --- a/core/src/main/java/com/portto/sdk/core/method/Method.kt +++ b/core/src/main/java/com/portto/sdk/core/method/Method.kt @@ -25,6 +25,7 @@ abstract class Method( .appendQueryParameter(Const.KEY_REQUEST_ID, requestId) .appendQueryParameter(Const.KEY_METHOD, name) .appendQueryParameter(Const.KEY_BLOCKCHAIN, blockchain.value) + .appendQueryParameter(Const.KEY_PLATFORM, Const.SDK_SOURCE) } @WorkerThread diff --git a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt index ba28bf8..8b63c72 100644 --- a/wallet/src/main/java/com/portto/sdk/wallet/Const.kt +++ b/wallet/src/main/java/com/portto/sdk/wallet/Const.kt @@ -56,6 +56,7 @@ object Const { const val KEY_FLOW_TX = "flow_transaction" // Since 0.3.0 (Flow) const val KEY_SESSION_ID = "session_id" const val KEY_REQUEST_SOURCE = "request_source" + const val KEY_PLATFORM = "platform" const val PATH_DAPP = "dapp" const val PATH_AUTHN = "authn" From c987a3beab9cb2d18a54fbf72bc45872131256c5 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 15 May 2023 17:00:04 +0800 Subject: [PATCH 11/19] feat: apply CI to run tasks automatically --- .github/actions/setup/action.yml | 31 ++++++++++++ .github/workflows/ci.yml | 85 ++++++++++++++++++++++++++++++++ app/build.gradle | 5 ++ scripts/distribute.sh | 2 + 4 files changed, 123 insertions(+) create mode 100644 .github/actions/setup/action.yml create mode 100644 .github/workflows/ci.yml create mode 100644 scripts/distribute.sh diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 0000000..5f11316 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,31 @@ +name: Setup + +description: Setup + +inputs: + google_services: + description: 'Google Services file' + required: true + +runs: + using: "composite" + steps: + - uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: 17 + - uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} + + - name: Check Gradle wrapper + uses: gradle/wrapper-validation-action@v1 + + - name: Put Google Services file + env: + GOOGLE_SERVICES: ${{ inputs.google_services }} + run: echo "$GOOGLE_SERVICES" | base64 -d > app/google-services.json + shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ac14b71 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,85 @@ +name: CI + +on: push + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup + with: + google_services: ${{ secrets.GOOGLE_SERVICES }} + + - name: Run lint + run: ./gradlew lint + + test: + name: Test + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup + with: + google_services: ${{ secrets.GOOGLE_SERVICES }} + + - name: Run test + run: ./gradlew test + + build: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: [ lint, test ] + steps: + - uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup + with: + google_services: ${{ secrets.GOOGLE_SERVICES }} + + - name: Build release + run: ./gradlew clean assembleRelease --stacktrace + + distribute: + if: startsWith(github.ref_name, 'release/') + name: Distribute + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: build + steps: + - uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup + with: + google_services: ${{ secrets.GOOGLE_SERVICES }} + + - name: Put files + env: + KEYSTORE: ${{ secrets.KEYSTORE } }} + SIGNING: ${{ secrets.SIGNING }} + APP_DISTRIBUTION: ${{ secrets.APP_DISTRIBUTION }} + run: | + echo "Adding files" + TMP_SECRETS_PATH=secrets + mkdir ${TMP_SECRETS_PATH} + echo $KEYSTORE | base64 -d > "${TMP_SECRETS_PATH}"/portto.jjs + echo $SIGNING | base64 -d > "${TMP_SECRETS_PATH}"/signing.properties + echo $APP_DISTRIBUTION | base64 -d > "${TMP_SECRETS_PATH}"/app-distribution.json + echo "All files Added ✅" + + - name: Distribute sample app + run: ./scripts/distribute.sh diff --git a/app/build.gradle b/app/build.gradle index 7c170b9..9c3234a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,6 +18,7 @@ android { targetSdk versions.compileSdk versionCode 1 versionName "1.0.0" + versionNameSuffix "-" + getDate() } def signingFilePath = "secrets/signing.properties" @@ -67,6 +68,10 @@ android { } } +static def getDate() { + return new Date().format('yyyyMMddHHmm') +} + dependencies { implementation project(':evm') implementation project(':solana') diff --git a/scripts/distribute.sh b/scripts/distribute.sh new file mode 100644 index 0000000..c67c112 --- /dev/null +++ b/scripts/distribute.sh @@ -0,0 +1,2 @@ +#!/bin/bash +./gradlew clean app:assembleRelease app:appDistributionUploadRelease From 0aad60c33c7c7fb62001ef3ee1cb10056394d253 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 15 May 2023 17:02:22 +0800 Subject: [PATCH 12/19] fix: fix action --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac14b71..84708bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,7 +69,7 @@ jobs: - name: Put files env: - KEYSTORE: ${{ secrets.KEYSTORE } }} + KEYSTORE: ${{ secrets.KEYSTORE }} SIGNING: ${{ secrets.SIGNING }} APP_DISTRIBUTION: ${{ secrets.APP_DISTRIBUTION }} run: | From 72ad017adac5c1171977a9b121ea8b87bdf5e0db Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 15 May 2023 18:41:43 +0800 Subject: [PATCH 13/19] fix: run bash script --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84708bf..68dcb85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,4 +82,4 @@ jobs: echo "All files Added ✅" - name: Distribute sample app - run: ./scripts/distribute.sh + run: bash ./scripts/distribute.sh From 7295a9bf9dde136ccd5ffd29707c41d387cf46a1 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 15 May 2023 21:21:33 +0800 Subject: [PATCH 14/19] feat: add publish job --- .github/workflows/ci.yml | 52 ++++++++++++++++++++++++++++++++++++++++ scripts/publish.sh | 3 +++ 2 files changed, 55 insertions(+) create mode 100644 scripts/publish.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68dcb85..b6d24fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,3 +83,55 @@ jobs: - name: Distribute sample app run: bash ./scripts/distribute.sh + + publish: + if: github.ref_name == 'main' + name: Publish + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: build + steps: + - uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup + with: + google_services: ${{ secrets.GOOGLE_SERVICES }} + + - name: Publish library + env: + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_PASSWORD }} + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + run: bash ./scripts/publish.sh + + - name: Get version + run: | + echo "version=$(grep "versionName" dependencies.gradle | awk -F: '{print $2}' | tr -d ' '\',)" >> $GITHUB_ENV + + - name: Create and push tag + run: | + git config user.name "GitHub Actions" + git config user.email noreply@github.com + git tag -a ${{ env.version }} -m "Release v${{ env.version }}" + git push origin ${{ env.version }} + + - name: Create release + uses: softprops/action-gh-release@v1 + with: + name: v${{ env.version }} + tag_name: ${{ env.version }} + draft: false + prerelease: false + + - name: Create pull request (main -> develop) + run: > + gh pr create + --base develop + --head main + --title '[${{ env.version }}] Merge main into develop' + --body 'Created by Github Actions' + --reviewer Doge-is-Dope,kihonyoo,imjacklai + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100644 index 0000000..6538c12 --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,3 @@ +#!/bin/bash +# Build and upload the artifacts to 'mavenCentral'. +./gradlew clean publish --no-daemon --no-parallel From fd56c6d9332b749aadc8809787e98a3bea26b776 Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 16 May 2023 10:41:15 +0800 Subject: [PATCH 15/19] feat: fill Infura id for sample app distribution --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6d24fc..3a8a9e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,6 +81,9 @@ jobs: echo $APP_DISTRIBUTION | base64 -d > "${TMP_SECRETS_PATH}"/app-distribution.json echo "All files Added ✅" + - name: Fill Infura id + run: sed -i 's/INFURA_ID.*/INFURA_ID = \"${{ secrets.INFURA_ID }}\"/' app/src/main/java/com/portto/valuedapp/Config.kt + - name: Distribute sample app run: bash ./scripts/distribute.sh From 4e0a45b9819291e3732a22f3ed713e57f4940963 Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 16 May 2023 11:01:49 +0800 Subject: [PATCH 16/19] feat: remove circleci config --- .circleci/config.yml | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index d5a88ba..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: 2 -jobs: - build: - working_directory: ~/code - docker: - - image: cimg/android:2021.10.2-node - environment: - JVM_OPTS: -Xmx3200m - steps: - - checkout - - run: - name: Generate google-services.json - command: echo $GOOGLE_SERVICES | base64 --decode > app/google-services.json - - run: - name: Download Dependencies - command: ./gradlew androidDependencies - - run: - name: Assemble - command: ./gradlew assemble - - run: - name: Unit Tests - command: ./gradlew lint test - - store_artifacts: - path: core/build/reports - destination: core/reports - - store_artifacts: - path: solana/build/reports - destination: solana/reports - - store_test_results: - path: core/build/test-results - - store_test_results: - path: solana/build/test-results - -workflows: - version: 2 - workflow: - jobs: - - build From 63f6cc9be8024632e3c76f4ed0c8aec0a345e2ab Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 15 May 2023 22:36:15 +0800 Subject: [PATCH 17/19] feat: upgrade agp --- app/build.gradle | 4 ++-- build.gradle | 6 +++--- core/src/main/java/com/portto/sdk/core/BloctoApi.kt | 1 - dependencies.gradle | 10 +++++----- gradle.properties | 3 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9c3234a..91efeab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,9 +97,9 @@ dependencies { exclude module: 'bcprov-jdk15on' } - implementation("com.nftco:flow-jvm-sdk:0.7.1") { + implementation("com.nftco:flow-jvm-sdk:0.7.3") { exclude module: 'bcprov-jdk15on' } - implementation("io.grpc:grpc-okhttp:1.47.0") + implementation("io.grpc:grpc-okhttp:1.50.2") implementation platform("com.google.firebase:firebase-bom:29.3.1") } diff --git a/build.gradle b/build.gradle index 8599104..80cd6a6 100644 --- a/build.gradle +++ b/build.gradle @@ -7,9 +7,9 @@ buildscript { } } plugins { - id 'com.android.application' version '7.4.2' apply false - id 'com.android.library' version '7.4.2' apply false - id 'org.jetbrains.kotlin.android' version '1.7.0' apply false + id 'com.android.application' version '8.0.1' apply false + id 'com.android.library' version '8.0.1' apply false + id 'org.jetbrains.kotlin.android' version '1.8.21' apply false id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.21' } task clean(type: Delete) { diff --git a/core/src/main/java/com/portto/sdk/core/BloctoApi.kt b/core/src/main/java/com/portto/sdk/core/BloctoApi.kt index 1da9e23..b6032ad 100644 --- a/core/src/main/java/com/portto/sdk/core/BloctoApi.kt +++ b/core/src/main/java/com/portto/sdk/core/BloctoApi.kt @@ -1,7 +1,6 @@ package com.portto.sdk.core import androidx.annotation.WorkerThread -import androidx.viewbinding.BuildConfig import com.portto.sdk.core.BloctoApi.toErrorCode import com.portto.sdk.core.BuildConfig.VERSION_NAME import kotlinx.serialization.decodeFromString diff --git a/dependencies.gradle b/dependencies.gradle index 5ceb004..ff3eb35 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -4,17 +4,17 @@ ext.versions = [ versionCode : 5, versionName : '0.4.0', - androidx_activity : '1.6.1', + androidx_activity : '1.7.1', androidx_appcompat : '1.6.1', androidx_browser : '1.5.0', - androidx_core : '1.9.0', - androidx_fragment : '1.5.3', - androidx_lifecycle : '2.5.1', + androidx_core : '1.10.1', + androidx_fragment : '1.5.7', + androidx_lifecycle : '2.6.1', androidx_viewmodel : '2.4.1', androidx_constraint : '2.1.4', coroutine : '1.6.4', flow_sdk : '0.7.1', - material : '1.8.0', + material : '1.9.0', okhttp : '4.10.0', serialization : '1.3.2', timber : '5.0.1', diff --git a/gradle.properties b/gradle.properties index 773b72f..4986f87 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,8 @@ kotlin.code.style=official # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true -android.disableAutomaticComponentCreation=true +android.defaults.buildfeatures.buildconfig=true +android.nonFinalResIds=false SONATYPE_HOST=S01 RELEASE_SIGNING_ENABLED=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 66c025c..83a8ada 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Mar 09 10:37:29 CST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME From c58c89a6a250a5c8f0bc45a6d0751ef6c6dfc954 Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 16 May 2023 17:06:13 +0800 Subject: [PATCH 18/19] Bump version to 0.5.0 --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index ff3eb35..95e90d4 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,8 @@ ext.versions = [ minSdk : 21, compileSdk : 33, - versionCode : 5, - versionName : '0.4.0', + versionCode : 6, + versionName : '0.5.0', androidx_activity : '1.7.1', androidx_appcompat : '1.6.1', From 6e1ad1c9d7e51a057d94432d9f92dbe411da9f8a Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 17 May 2023 10:46:46 +0800 Subject: [PATCH 19/19] doc: update README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a0daa2..2856ea9 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,20 @@ # BloctoSDK ![Maven Central](https://img.shields.io/maven-central/v/com.portto.sdk/core) -![CircleCI](https://img.shields.io/circleci/build/gh/portto/blocto-android-sdk/main) +![Github Action](https://github.com/portto/blocto-android-sdk/actions/workflows/ci.yml/badge.svg) ![GitHub](https://img.shields.io/github/license/portto/blocto-android-sdk) Integrate Blocto service into your dApp on Android. Currently support -* Solana * Ethereum +* Arbitrum +* Optimism * BNB Chain * Polygon * Avalanche +* Solana * More blockchains are coming soon > For Flow, it's recommended to use [fcl](https://github.com/portto/fcl-android). Check the [documents](https://docs.blocto.app/blocto-sdk/android-sdk/flow) for more info.