Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

add web3 sign in #38

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 32
Expand Down Expand Up @@ -44,7 +45,7 @@ dependencies {

implementation 'com.google.android.gms:play-services-auth:20.1.0'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.jakewharton.timber:timber:5.0.1'
implementation 'com.jakewharton.timber:timber:4.7.1'

// AndroidX
implementation 'androidx.appcompat:appcompat:1.2.0'
Expand All @@ -58,9 +59,23 @@ dependencies {
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.13.0'

testImplementation 'junit:junit:4.13.2'

androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

// Web3
implementation 'com.github.mobilekosmos:kotlin-walletconnect-lib:0.9.9.8'
implementation 'org.java-websocket:Java-WebSocket:1.5.3'
implementation ('org.web3j:core:4.8.7-android'){
exclude group: 'org.bouncycastle', module: '*'
}

//1.5.0 is currently the latest stable version of AndroidX Core for Kotlin.
//If you already have "androidx.core:core" implemented, remove it.
implementation 'androidx.core:core-ktx:1.5.+'
implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.5.+'
}

7 changes: 6 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="ai.elimu.crowdsource">

<uses-permission android:name="android.permission.INTERNET" />
Expand All @@ -11,8 +12,10 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:networkSecurityConfig="@xml/network_config"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
tools:targetApi="n">

<activity android:name=".MainActivity"
android:exported="true">
Expand All @@ -24,6 +27,8 @@

<activity android:name=".ui.language.SelectLanguageActivity" />

<activity android:name=".ui.authentication.SignInWithWeb3Activity" />

<activity android:name=".ui.authentication.SignInWithGoogleActivity" />

<activity android:name=".ui.BottomNavigationActivity" />
Expand Down
148 changes: 145 additions & 3 deletions app/src/main/java/ai/elimu/crowdsource/BaseApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,57 @@
import android.app.Application;
import android.util.Log;

import androidx.annotation.NonNull;

import com.squareup.moshi.Moshi;
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory;

import org.jetbrains.annotations.NotNull;
import org.walletconnect.Session;
import org.walletconnect.impls.FileWCSessionStore;
import org.walletconnect.impls.MoshiPayloadAdapter;
import org.walletconnect.impls.OkHttpTransport;
import org.walletconnect.impls.WCSession;
import org.walletconnect.impls.WCSessionStore;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Random;
import java.util.UUID;

import ai.elimu.crowdsource.server.BridgeServer;
import ai.elimu.crowdsource.util.SharedPreferencesHelper;
import ai.elimu.crowdsource.util.VersionHelper;
import ai.elimu.model.v2.enums.Language;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import kotlin.jvm.internal.Intrinsics;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import timber.log.Timber;

public class BaseApplication extends Application {
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static Session.FullyQualifiedConfig config;
public static Session session;
private static OkHttpClient client;
private static Moshi moshi;
private static BridgeServer bridge;
private static WCSessionStore storage;

@Override
public void onCreate() {
Log.i(getClass().getName(), "onCreate");
super.onCreate();

// Log config
Timber.plant(new Timber.DebugTree());
this.initMoshi();
this.initClient();
this.initBridge();
this.initSessionStorage();
if(BuildConfig.DEBUG){
Timber.plant(new Timber.DebugTree());
}
Timber.i("onCreate");

VersionHelper.updateAppVersion(getApplicationContext());
Expand Down Expand Up @@ -48,4 +83,111 @@ public String getBaseUrl() {
public String getRestUrl() {
return getBaseUrl() + "/rest/v2";
}


private void initClient() {
OkHttpClient var10000 = (new OkHttpClient.Builder()).build();
Intrinsics.checkNotNullExpressionValue(var10000, "OkHttpClient.Builder().build()");
client = var10000;
}

private void initMoshi() {
Moshi var10000 = (new com.squareup.moshi.Moshi.Builder()).add(new KotlinJsonAdapterFactory()).build();
Intrinsics.checkNotNullExpressionValue(var10000, "Moshi.Builder().build()");
moshi = var10000;
}

private void initBridge() {
bridge = new BridgeServer(moshi);
bridge.start();
}

private void initSessionStorage() {
File tmp = new File(this.getCacheDir(), "session_store.json");
try {
tmp.createNewFile();
storage = new FileWCSessionStore(tmp, moshi);
} catch (IOException e) {
e.printStackTrace();
}

}


@NotNull
public static String bytesToHex(byte[] bytes) {
Intrinsics.checkNotNullParameter(bytes, "bytes");
char[] hexChars = new char[bytes.length * 2];
int j = 0;

for (int var4 = bytes.length; j < var4; ++j) {
int v = bytes[j] & 255;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 15];
}

return new String(hexChars);
}

public static void resetSession() throws Exception {
if (session != null) {
session.clearCallbacks();
}
byte[] randomBytes = new byte[32];
Random r = new Random();
r.nextBytes(randomBytes);
String key = bytesToHex(randomBytes);
String uuid = UUID.randomUUID().toString();
config = new Session.FullyQualifiedConfig(uuid, "http://localhost:" + BridgeServer.Companion.getPORT(), key, "wc", 1);
// config = new Session.FullyQualifiedConfig(uuid, "https://bridge.walletconnect.org", "f70af2060965927b7e709503e71b3cbf", "wc", 1);
session = new WCSession(
config,
new WrappedMoshiPayloadAdapter(new MoshiPayloadAdapter(moshi)),
storage,
new WrappedOkHttpTransportBuilder(new OkHttpTransport.Builder(client, moshi)),
new Session.PeerMeta(
"elimu.ai",
"Elimu Crowdsource App",
"Elimu Crowdsource App",
Collections.emptyList()
),
null,
null
);
session.offer();
}

static class WrappedMoshiPayloadAdapter implements Session.PayloadAdapter {
private final MoshiPayloadAdapter wrapped;

public WrappedMoshiPayloadAdapter(MoshiPayloadAdapter wrapped) {
this.wrapped = wrapped;
}

@NonNull
@Override
public Session.MethodCall parse(@NonNull String s, @NonNull String s1) {
return this.wrapped.parse(s, s1);
}

@NonNull
@Override
public String prepare(@NonNull Session.MethodCall methodCall, @NonNull String s) {
return this.wrapped.prepare(methodCall, s);
}
}

static class WrappedOkHttpTransportBuilder implements Session.Transport.Builder {
private final OkHttpTransport.Builder wrapped;

public WrappedOkHttpTransportBuilder(OkHttpTransport.Builder wrapped) {
this.wrapped = wrapped;
}

@NonNull
@Override
public Session.Transport build(@NonNull String s, @NonNull Function1<? super Session.Transport.Status, Unit> function1, @NonNull Function1<? super Session.Transport.Message, Unit> function11) {
return this.wrapped.build(s, function1, function11);
}
}
}
34 changes: 27 additions & 7 deletions app/src/main/java/ai/elimu/crowdsource/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,54 @@
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

import ai.elimu.crowdsource.ui.BottomNavigationActivity;
import ai.elimu.crowdsource.ui.authentication.SignInWithGoogleActivity;
import ai.elimu.crowdsource.ui.authentication.SignInWithWeb3Activity;
import ai.elimu.crowdsource.ui.language.SelectLanguageActivity;
import ai.elimu.crowdsource.ui.BottomNavigationActivity;
import ai.elimu.crowdsource.util.SharedPreferencesHelper;
import ai.elimu.model.v2.enums.Language;
import timber.log.Timber;

public class MainActivity extends AppCompatActivity {

private Button signInWeb3Button, signInGoogleButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
Timber.i("onCreate");
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);
signInWeb3Button = findViewById(R.id.w3_sign_in);
signInGoogleButton = findViewById(R.id.g_sign_in);
signInWeb3Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent signInWithWeb3Intent = new Intent(getApplicationContext(), SignInWithWeb3Activity.class);
startActivity(signInWithWeb3Intent);
}
});
signInGoogleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Redirect to sign-in with Google
Intent signInWithGoogleIntent = new Intent(getApplicationContext(), SignInWithGoogleActivity.class);
startActivity(signInWithGoogleIntent);
}
});
}

@Override
protected void onStart() {
Timber.i("onStart");
super.onStart();


// Check if language has been selected
Language language = SharedPreferencesHelper.getLanguage(getApplicationContext());
Timber.i("language: " + language);
Expand All @@ -39,13 +62,10 @@ protected void onStart() {
} else {
// Check for an existing signed-in Contributor
String providerIdGoogle = SharedPreferencesHelper.getProviderIdGoogle(getApplicationContext());
String web3Account = SharedPreferencesHelper.getProviderIdWeb3(getApplicationContext());
Timber.i("providerIdGoogle: " + providerIdGoogle);
if (TextUtils.isEmpty(providerIdGoogle)) {
// Redirect to sign-in with Google
Intent signInWithGoogleIntent = new Intent(getApplicationContext(), SignInWithGoogleActivity.class);
startActivity(signInWithGoogleIntent);
finish();
} else {
Timber.i("web3 account: " + web3Account);
if (!TextUtils.isEmpty(providerIdGoogle) || !TextUtils.isEmpty(web3Account)) {
// Redirect to crowdsourcing activity selection
Intent intent = new Intent(getApplicationContext(), BottomNavigationActivity.class);
startActivity(intent);
Expand Down
Loading