diff --git a/build.gradle b/build.gradle index f0eeb00..800a1e7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,50 +1,50 @@ +/** + * The buildscript block is where you configure the repositories and + * dependencies for Gradle itself—meaning, you should not include dependencies + * for your modules here. For example, this block includes the Android plugin for + * Gradle as a dependency because it provides the additional instructions Gradle + * needs to build Android app modules. + */ buildscript { ext { versions = [ - kotlin : "1.4.31", - moshi : '1.8.0', - okhttp : '3.11.0', - jupiter : '5.7.0', + kotlin : "1.5.31", + moshi : '1.12.0', + okhttp : '4.9.1', + jupiter : '5.8.1', - 'minSdk' : 14, - 'compileSdk' : 28, - 'buildTools' : '28.0.3', - 'androidPlugin' : '4.0.0', + 'minSdk' : 28, + 'compileSdk' : 31, - androidx_app_compat : '1.0.2', - androidx_card_view : '1.0.0', - androidx_constraint_layout: '1.1.3', - androidx_lifecycle : '2.0.0', - androidx_test_ext : '1.1.0', - androidx_recycler_view : '1.0.0', - androidx_room : '2.0.0', + androidx_app_compat : '1.3.1', + androidx_card_view : '1.0.0', + androidx_constraint_layout: '1.1.3', + androidx_lifecycle : '2.0.0', + androidx_test_ext : '1.1.0', + androidx_recycler_view : '1.0.0', + androidx_room : '2.0.0', - multidex : '2.0.1', + khex : '1.1.2' ] - - ext.deps = [ - android: [ - 'runtime' : 'com.google.android:android:4.1.1.4', - 'gradlePlugin': "com.android.tools.build:gradle:${versions.androidPlugin}", - ] - ] - versions.kotlin = '1.3.72' - } - - repositories { - google() - jcenter() - gradlePluginPortal() - mavenCentral() } + /** + * The dependencies block configures the dependencies Gradle needs to use + * to build your project. The following line adds Android plugin for Gradle + * version 4.2.0 as a classpath dependency. + */ dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:7.0.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin" - classpath 'com.github.ben-manes:gradle-versions-plugin:0.38.0' - // How can we move this to the sample folder - //classpath deps.android.gradlePlugin + } + repositories { + google() } } -apply plugin: "com.github.ben-manes.versions" +// By default, the plugins {} DSL resolves plugins from the public Gradle Plugin Portal. Apply not +// needed when using this. +plugins { + // Checks for newer lib versions. + id "com.github.ben-manes.versions" version "0.39.0" +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..98bed16 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8cf6eb5..29e4134 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/lib/build.gradle b/lib/build.gradle index 95ea957..9d8cb43 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -1,30 +1,31 @@ -apply plugin: "kotlin" -apply plugin: 'maven' - -repositories { - mavenCentral() - maven { url 'https://jitpack.io' } +plugins { + id 'java-library' + id 'kotlin' + id 'maven-publish' } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin" - - implementation "com.github.komputing:khex:1.1.0" + // KHex is a Kotlin multiplatform library to deal with hexadecimal encoding and decoding. + implementation "com.github.komputing:khex:$versions.khex" - implementation "org.bouncycastle:bcprov-jdk15to18:1.68" + implementation "org.bouncycastle:bcprov-jdk15to18:1.69" - implementation 'com.squareup.moshi:moshi:1.8.0' + implementation "com.squareup.moshi:moshi:${versions.moshi}" // TODO: it would be better to use the generated adapter by moshi // but for that we should move the implementations in different modules //kapt "com.squareup.moshi:moshi-kotlin-codegen:$versions.moshi" + implementation "com.squareup.moshi:moshi-kotlin:$versions.moshi" implementation "com.squareup.okhttp3:okhttp:$versions.okhttp" testImplementation 'org.assertj:assertj-core:3.19.0' + + // (Required) Writing and executing Unit Tests on the JUnit Platform testImplementation "org.junit.jupiter:junit-jupiter-api:${versions.jupiter}" - testImplementation "org.junit.jupiter:junit-jupiter-params:${versions.jupiter}" - testRuntime "org.junit.jupiter:junit-jupiter-engine:${versions.jupiter}" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${versions.jupiter}" + // (Optional) If you need "Parameterized Tests" + testImplementation "org.junit.jupiter:junit-jupiter-params:${versions.jupiter}" testImplementation "com.squareup.okhttp3:mockwebserver:$versions.okhttp" } @@ -32,3 +33,25 @@ dependencies { test { useJUnitPlatform() } + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +afterEvaluate { + publishing { + publications { + // Creates a Maven publication called “walletconnectPublication”. + walletconnectPublication(MavenPublication) { + // Applies the component for the debug build variant. + from components.java + + groupId = 'com.github.WalletConnect' + artifactId = 'kotlin-walletconnect-lib' + version = '0.9.7' + } + } + } +} + diff --git a/lib/src/test/java/org/walletconnect/WalletConnectBridgeRepositoryIntegrationTest.kt b/lib/src/test/java/org/walletconnect/WalletConnectBridgeRepositoryIntegrationTest.kt index c027031..14e895f 100644 --- a/lib/src/test/java/org/walletconnect/WalletConnectBridgeRepositoryIntegrationTest.kt +++ b/lib/src/test/java/org/walletconnect/WalletConnectBridgeRepositoryIntegrationTest.kt @@ -1,6 +1,7 @@ package org.walletconnect import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import okhttp3.OkHttpClient import org.junit.Test import org.walletconnect.impls.FileWCSessionStore @@ -19,7 +20,7 @@ class WalletConnectBridgeRepositoryIntegrationTest { //@Test fun approveSession() { val client = OkHttpClient.Builder().pingInterval(1000, TimeUnit.MILLISECONDS).build() - val moshi = Moshi.Builder().build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() val sessionDir = File("build/tmp/").apply { mkdirs() } val sessionStore = FileWCSessionStore(File(sessionDir, "test_store.json").apply { createNewFile() }, moshi) val uri = diff --git a/sample/app/build.gradle b/sample/app/build.gradle index 9a4acef..9da8de3 100644 --- a/sample/app/build.gradle +++ b/sample/app/build.gradle @@ -1,14 +1,12 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' android { compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } defaultConfig { @@ -19,49 +17,66 @@ android { versionName '1.0.0' } - dexOptions { - jumboMode = true - } - lintOptions { textReport true textOutput 'stdout' + checkDependencies true } + /** + * The buildTypes block is where you can configure multiple build types. + * By default, the build system defines two build types: debug and release. The + * debug build type is not explicitly shown in the default build configuration, + * but it includes debugging tools and is signed with the debug key. The release + * build type applies Proguard settings and is not signed by default. + */ buildTypes { + + /** + * By default, Android Studio configures the release build type to enable code + * shrinking, using minifyEnabled, and specifies the default Proguard rules file. + */ debug { applicationIdSuffix ".debug" versionNameSuffix "-debug" minifyEnabled false } + + release { + minifyEnabled true // Enables code shrinking for the release build type. + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + // The kotlinx-coroutines-core artifact contains a resource file that is not required for the coroutines to operate normally and is only used by the debugger. To exclude it at no loss of functionality, add the following snippet to the android block in your Gradle file for the application subproject: + // https://github.com/Kotlin/kotlinx.coroutines + packagingOptions { + resources.excludes += "DebugProbesKt.bin" } -} -repositories { - repositories { - google() - jcenter() - mavenCentral() - maven { url 'https://www.jitpack.io' } + buildFeatures { + viewBinding true } } dependencies { implementation project(":lib") + // Instead of adding ":lib" you could add the url below: + //implementation 'com.github.WalletConnect:kotlin-walletconnect-lib:0.9.6' - implementation "org.java-websocket:Java-WebSocket:1.4.0" + implementation "org.java-websocket:Java-WebSocket:1.5.2" - implementation "com.github.komputing:khex:1.0.0-RC6" - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" + // KHex is a Kotlin multiplatform library to deal with hexadecimal encoding and decoding. + implementation "com.github.komputing:khex:$versions.khex" implementation "androidx.appcompat:appcompat:$versions.androidx_app_compat" - implementation "androidx.multidex:multidex:$versions.multidex" - implementation 'com.squareup.moshi:moshi:1.8.0' + implementation 'com.squareup.moshi:moshi:1.12.0' + implementation "com.squareup.moshi:moshi-kotlin:$versions.moshi" + implementation "com.squareup.okhttp3:okhttp:$versions.okhttp" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0' } diff --git a/sample/app/src/main/AndroidManifest.xml b/sample/app/src/main/AndroidManifest.xml index f1cca81..0d3bf1f 100644 --- a/sample/app/src/main/AndroidManifest.xml +++ b/sample/app/src/main/AndroidManifest.xml @@ -8,8 +8,10 @@ android:allowBackup="true" android:label="@string/app_name" android:supportsRtl="true" - android:name=".ExampleApplication"> - + android:name=".ExampleApplication" + android:networkSecurityConfig="@xml/network_config"> + diff --git a/sample/app/src/main/java/io/walletconnect/example/ExampleApplication.kt b/sample/app/src/main/java/io/walletconnect/example/ExampleApplication.kt index 2e29037..07f0dd6 100644 --- a/sample/app/src/main/java/io/walletconnect/example/ExampleApplication.kt +++ b/sample/app/src/main/java/io/walletconnect/example/ExampleApplication.kt @@ -1,7 +1,8 @@ package io.walletconnect.example -import androidx.multidex.MultiDexApplication +import android.app.Application import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import io.walletconnect.example.server.BridgeServer import okhttp3.OkHttpClient import org.komputing.khex.extensions.toNoPrefixHexString @@ -11,7 +12,7 @@ import org.walletconnect.nullOnThrow import java.io.File import java.util.* -class ExampleApplication : MultiDexApplication() { +class ExampleApplication : Application() { override fun onCreate() { super.onCreate() initMoshi() @@ -25,7 +26,7 @@ class ExampleApplication : MultiDexApplication() { } private fun initMoshi() { - moshi = Moshi.Builder().build() + moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() } diff --git a/sample/app/src/main/java/io/walletconnect/example/MainActivity.kt b/sample/app/src/main/java/io/walletconnect/example/MainActivity.kt index 7c373dd..eea839d 100644 --- a/sample/app/src/main/java/io/walletconnect/example/MainActivity.kt +++ b/sample/app/src/main/java/io/walletconnect/example/MainActivity.kt @@ -2,10 +2,12 @@ package io.walletconnect.example import android.app.Activity import android.os.Bundle -import kotlinx.android.synthetic.main.screen_main.* import android.content.Intent import android.net.Uri +import android.util.Log import android.view.View +import android.widget.TextView +import io.walletconnect.example.databinding.ScreenMainBinding import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -15,60 +17,76 @@ import org.walletconnect.nullOnThrow class MainActivity : Activity(), Session.Callback { - private var txRequest: Long? = null - private val uiScope = CoroutineScope(Dispatchers.Main) + private var mTxRequest: Long? = null + private val mUiScope = CoroutineScope(Dispatchers.Main) + private lateinit var mScreenMainBinding: ScreenMainBinding override fun onStatus(status: Session.Status) { when(status) { - Session.Status.Approved -> sessionApproved() - Session.Status.Closed -> sessionClosed() - Session.Status.Connected, - Session.Status.Disconnected, + Session.Status.Approved -> adaptUIAfterSessionApproved() + Session.Status.Closed -> adaptUIAfterSessionClosed() + Session.Status.Connected -> { + requestConnectionToWallet() + } + Session.Status.Disconnected -> { + Log.e("+++", "Disconnected") + } is Session.Status.Error -> { - // Do Stuff + Log.e("+++", "Error:" + status.throwable.localizedMessage) } } } override fun onMethodCall(call: Session.MethodCall) { } - private fun sessionApproved() { - uiScope.launch { - screen_main_status.text = "Connected: ${ExampleApplication.session.approvedAccounts()}" - screen_main_connect_button.visibility = View.GONE - screen_main_disconnect_button.visibility = View.VISIBLE - screen_main_tx_button.visibility = View.VISIBLE + + private fun requestConnectionToWallet() { + val i = Intent(Intent.ACTION_VIEW) + i.data = Uri.parse(ExampleApplication.config.toWCUri()) + startActivity(i) + } + + private fun navigateToWallet() { + val i = Intent(Intent.ACTION_VIEW) + i.data = Uri.parse("wc:") + startActivity(i) + } + + private fun adaptUIAfterSessionApproved() { + mUiScope.launch { + mScreenMainBinding.screenMainStatus.text = "Connected: ${ExampleApplication.session.approvedAccounts()}" + mScreenMainBinding.screenMainConnectButton.visibility = View.GONE + mScreenMainBinding.screenMainDisconnectButton.visibility = View.VISIBLE + mScreenMainBinding.screenMainTxButton.visibility = View.VISIBLE } } - private fun sessionClosed() { - uiScope.launch { - screen_main_status.text = "Disconnected" - screen_main_connect_button.visibility = View.VISIBLE - screen_main_disconnect_button.visibility = View.GONE - screen_main_tx_button.visibility = View.GONE + private fun adaptUIAfterSessionClosed() { + mUiScope.launch { + mScreenMainBinding.screenMainStatus.text = "Disconnected" + mScreenMainBinding.screenMainConnectButton.visibility = View.VISIBLE + mScreenMainBinding.screenMainDisconnectButton.visibility = View.GONE + mScreenMainBinding.screenMainTxButton.visibility = View.GONE } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.screen_main) + mScreenMainBinding = ScreenMainBinding.inflate(layoutInflater) + setContentView(mScreenMainBinding.root) } override fun onStart() { super.onStart() initialSetup() - screen_main_connect_button.setOnClickListener { + mScreenMainBinding.screenMainConnectButton.setOnClickListener { ExampleApplication.resetSession() ExampleApplication.session.addCallback(this) - val i = Intent(Intent.ACTION_VIEW) - i.data = Uri.parse(ExampleApplication.config.toWCUri()) - startActivity(i) } - screen_main_disconnect_button.setOnClickListener { + mScreenMainBinding.screenMainDisconnectButton.setOnClickListener { ExampleApplication.session.kill() } - screen_main_tx_button.setOnClickListener { + mScreenMainBinding.screenMainTxButton.setOnClickListener { val from = ExampleApplication.session.approvedAccounts()?.first() ?: return@setOnClickListener val txRequest = System.currentTimeMillis() @@ -85,22 +103,26 @@ class MainActivity : Activity(), Session.Callback { ), ::handleResponse ) - this.txRequest = txRequest + this.mTxRequest = txRequest + navigateToWallet() } } private fun initialSetup() { + // if ExampleApplication.session is not initialized then return val session = nullOnThrow { ExampleApplication.session } ?: return + session.addCallback(this) - sessionApproved() + adaptUIAfterSessionApproved() } private fun handleResponse(resp: Session.MethodCall.Response) { - if (resp.id == txRequest) { - txRequest = null - uiScope.launch { - screen_main_response.visibility = View.VISIBLE - screen_main_response.text = "Last response: " + ((resp.result as? String) ?: "Unknown response") + if (resp.id == mTxRequest) { + mTxRequest = null + mUiScope.launch { + val textView = findViewById(R.id.screen_main_response) + textView.visibility = View.VISIBLE + textView.text = "Last response: " + ((resp.result as? String) ?: "Unknown response") } } } diff --git a/sample/app/src/main/java/io/walletconnect/example/server/BridgeServer.kt b/sample/app/src/main/java/io/walletconnect/example/server/BridgeServer.kt index 4c372fd..b6833cd 100644 --- a/sample/app/src/main/java/io/walletconnect/example/server/BridgeServer.kt +++ b/sample/app/src/main/java/io/walletconnect/example/server/BridgeServer.kt @@ -14,11 +14,11 @@ import java.util.concurrent.ConcurrentHashMap class BridgeServer(moshi: Moshi) : WebSocketServer(InetSocketAddress(PORT)) { - private val adapter = moshi.adapter>( + private val adapter = moshi.adapter>( Types.newParameterizedType( Map::class.java, String::class.java, - String::class.java + Any::class.java ) ) @@ -41,8 +41,8 @@ class BridgeServer(moshi: Moshi) : WebSocketServer(InetSocketAddress(PORT)) { conn ?: error("Unknown socket") message?.also { val msg = adapter.fromJson(it) ?: error("Invalid message") - val type: String = msg["type"] ?: error("Type not found") - val topic: String = msg["topic"] ?: error("Topic not found") + val type: String = msg["type"] as String? ?: error("Type not found") + val topic: String = msg["topic"] as String? ?: error("Topic not found") when (type) { "pub" -> { var sendMessage = false diff --git a/sample/app/src/main/res/layout/screen_main.xml b/sample/app/src/main/res/layout/screen_main.xml index 99b84b6..20835cc 100644 --- a/sample/app/src/main/res/layout/screen_main.xml +++ b/sample/app/src/main/res/layout/screen_main.xml @@ -34,6 +34,6 @@ android:id="@+id/screen_main_disconnect_button" android:layout_width="wrap_content" android:layout_height="64dp" - android:text="Disonnect" + android:text="Disconnect" android:visibility="gone" /> \ No newline at end of file diff --git a/sample/app/src/main/res/xml/network_config.xml b/sample/app/src/main/res/xml/network_config.xml new file mode 100644 index 0000000..a8f0840 --- /dev/null +++ b/sample/app/src/main/res/xml/network_config.xml @@ -0,0 +1,8 @@ + + + + sslip.io + localhost + + + diff --git a/settings.gradle b/settings.gradle index 066033c..4c79ea4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,11 @@ -include ':lib', ':sample:app' +// Repositories used by convention by every subproject can be declared here. +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + } +} +include ':lib', ':sample:app'