├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── trust
│ │ │ └── web3view
│ │ │ └── MainActivity.java
│ ├── test
│ │ └── java
│ │ │ └── trust
│ │ │ └── web3view
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── trust
│ │ └── web3view
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── lib
├── .gitignore
├── src
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── trust
│ │ │ │ └── web3
│ │ │ │ ├── UrlHandler.java
│ │ │ │ ├── OnSignMessageListener.java
│ │ │ │ ├── OnSignTransactionListener.java
│ │ │ │ ├── OnSignPersonalMessageListener.java
│ │ │ │ ├── OnSignTypedMessageListener.java
│ │ │ │ ├── JsInjectorResponse.java
│ │ │ │ ├── UrlHandlerManager.java
│ │ │ │ ├── WebViewCookieJar.java
│ │ │ │ ├── SignCallbackJSInterface.java
│ │ │ │ ├── Web3ViewClient.java
│ │ │ │ ├── JsInjectorClient.java
│ │ │ │ ├── Web3View.java
│ │ │ │ └── WrapWebSettings.java
│ │ └── res
│ │ │ └── raw
│ │ │ └── init.js
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── trustwallet
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── trustwallet
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── README.md
├── gradlew.bat
├── gradlew
└── LICENSE
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/lib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':lib'
2 |
--------------------------------------------------------------------------------
/lib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Web3View
3 | GO
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trustwallet/Web3View/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/UrlHandler.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import android.net.Uri;
4 |
5 | public interface UrlHandler {
6 |
7 | String getScheme();
8 |
9 | String handle(Uri uri);
10 | }
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/OnSignMessageListener.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import trust.core.entity.Message;
4 |
5 | public interface OnSignMessageListener {
6 | void onSignMessage(Message message);
7 | }
8 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/OnSignTransactionListener.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import trust.core.entity.Transaction;
4 |
5 | public interface OnSignTransactionListener {
6 | void onSignTransaction(Transaction transaction);
7 | }
8 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/OnSignPersonalMessageListener.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import trust.core.entity.Message;
4 |
5 | public interface OnSignPersonalMessageListener {
6 | void onSignPersonalMessage(Message message);
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/OnSignTypedMessageListener.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import trust.core.entity.Message;
4 | import trust.core.entity.TypedData;
5 |
6 | public interface OnSignTypedMessageListener {
7 | void onSignTypedMessage(Message message);
8 | }
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 01 14:12:53 GMT+07:00 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/trust/web3view/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package trust.web3view;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/lib/src/test/java/com/trustwallet/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.trustwallet;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/JsInjectorResponse.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | class JsInjectorResponse {
4 | final String data;
5 | final String url;
6 | final String mime;
7 | final String charset;
8 | final boolean isRedirect;
9 |
10 | JsInjectorResponse(String data, int code, String url, String mime, String charset, boolean isRedirect) {
11 | this.data = data;
12 | this.url = url;
13 | this.mime = mime;
14 | this.charset = charset;
15 | this.isRedirect = isRedirect;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .idea/*
3 | .DS_Store
4 | /captures
5 | .externalNativeBuild
6 |
7 | ### Android ###
8 | # Built application files
9 | *.apk
10 | *.ap_
11 | *.iml
12 | *.swp
13 | *.swo
14 |
15 | # Files for the Dalvik VM
16 | *.dex
17 |
18 | # Java class files
19 | *.class
20 |
21 | # Generated files
22 | bin/
23 | gen/
24 | Trust-strings.zip
25 |
26 | # Gradle files
27 | .gradle/
28 | /build
29 | app/release
30 |
31 | # Fastlane
32 | fastlane/report.xml
33 |
34 | # Local configuration file (sdk path, etc)
35 | /local.properties
36 |
37 | # Proguard folder generated by Eclipse
38 | proguard/
39 |
40 | # Log Files
41 | *.log
42 |
43 | # Android Studio Navigation editor temp files
44 | .navigation/
45 |
46 | ### Android Patch ###
47 | gen-external-apklibs
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/lib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/trust/web3view/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package trust.web3view;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("trust.web3view", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/lib/src/androidTest/java/com/trustwallet/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.trustwallet;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.trustwallet.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
15 |
22 |
28 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 27
5 | defaultConfig {
6 | applicationId "trust.web3view"
7 | minSdkVersion 21
8 | targetSdkVersion 27
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | compileOptions {
20 | sourceCompatibility JavaVersion.VERSION_1_8
21 | targetCompatibility JavaVersion.VERSION_1_8
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation 'com.github.TrustWallet:TrustSdk-android:0.01.13'
27 |
28 | implementation 'com.android.support:appcompat-v7:27.1.1'
29 | implementation 'com.android.support.constraint:constraint-layout:1.1.2'
30 | testImplementation 'junit:junit:4.12'
31 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
32 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
33 | implementation project(':lib')
34 | }
35 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/UrlHandlerManager.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import android.net.Uri;
4 | import android.support.annotation.NonNull;
5 | import android.text.TextUtils;
6 |
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | public class UrlHandlerManager {
11 |
12 | private final Map handlers = new HashMap<>();
13 |
14 | public UrlHandlerManager(UrlHandler... handlers) {
15 | for (UrlHandler urlHandler : handlers) {
16 | this.handlers.put(urlHandler.getScheme(), urlHandler);
17 | }
18 | }
19 |
20 | public void add(@NonNull UrlHandler urlHandler) {
21 | this.handlers.put(urlHandler.getScheme(), urlHandler);
22 | }
23 |
24 | public void remove(@NonNull UrlHandler urlHandler) {
25 | this.handlers.remove(urlHandler.getScheme());
26 | }
27 |
28 | String handle(String url) {
29 | if (TextUtils.isEmpty(url)) {
30 | return null;
31 | }
32 | Uri uri = Uri.parse(url);
33 | return handle(uri);
34 | }
35 |
36 | String handle(Uri uri) {
37 | if (uri == null) {
38 | return null;
39 | }
40 | if (!handlers.containsKey(uri.getScheme())) {
41 | return uri.toString();
42 | }
43 | return handlers.get(uri.getScheme()).handle(uri);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | apply plugin: 'com.github.dcendents.android-maven'
4 |
5 | group='trust.web3'
6 |
7 | android {
8 | compileSdkVersion 27
9 |
10 | defaultConfig {
11 | minSdkVersion 21
12 | targetSdkVersion 27
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 |
26 | compileOptions {
27 | targetCompatibility 1.8
28 | sourceCompatibility 1.8
29 | }
30 |
31 | task androidSourcesJar(type: Jar) {
32 | from android.sourceSets.main.java.source
33 | classifier = 'sources'
34 | }
35 |
36 | artifacts {
37 | archives androidSourcesJar
38 | }
39 | }
40 |
41 | dependencies {
42 | implementation 'com.squareup.okhttp3:okhttp:3.10.0'
43 | implementation 'com.github.TrustWallet:trust-web3-provider:0.1.7'
44 | implementation 'com.google.code.gson:gson:2.8.2'
45 | api 'com.github.TrustWallet:TrustCoreAndroid:0.01.6'
46 |
47 | implementation 'com.android.support:appcompat-v7:27.1.1'
48 | testImplementation 'junit:junit:4.12'
49 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
50 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
51 | }
52 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/WebViewCookieJar.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.text.TextUtils;
5 | import android.webkit.CookieManager;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Collections;
9 | import java.util.List;
10 |
11 | import okhttp3.Cookie;
12 | import okhttp3.CookieJar;
13 | import okhttp3.HttpUrl;
14 |
15 | public class WebViewCookieJar implements CookieJar {
16 | private CookieManager webViewCookieManager;
17 |
18 | public WebViewCookieJar() {
19 | try {
20 | webViewCookieManager = CookieManager.getInstance();
21 | } catch (Exception ex) {
22 | /* Caused by android.content.pm.PackageManager$NameNotFoundException com.google.android.webview */
23 | }
24 | }
25 |
26 | @Override
27 | public void saveFromResponse(@NonNull HttpUrl url, @NonNull List cookies) {
28 | if (webViewCookieManager != null) {
29 | String urlString = url.toString();
30 | for (Cookie cookie : cookies) {
31 | webViewCookieManager.setCookie(urlString, cookie.toString());
32 | }
33 | }
34 | }
35 |
36 | @Override
37 | public List loadForRequest(@NonNull HttpUrl url) {
38 | if (webViewCookieManager != null) {
39 | String urlString = url.toString();
40 | String cookiesString = webViewCookieManager.getCookie(urlString);
41 | if (cookiesString != null && !TextUtils.isEmpty(cookiesString)) {
42 | String[] cookieHeaders = cookiesString.split(";");
43 | List cookies = new ArrayList<>();
44 | for (String cookieHeader : cookieHeaders) {
45 | cookies.add(Cookie.parse(url, cookieHeader));
46 | }
47 | return cookies;
48 | }
49 | }
50 | return Collections.emptyList();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/lib/src/main/res/raw/init.js:
--------------------------------------------------------------------------------
1 |
2 | const addressHex = "%1$s";
3 | const rpcURL = "%2$s";
4 | const chainID = "%3$s";
5 | function executeCallback (id, error, value) {
6 | Trust.executeCallback(id, error, value)
7 | }
8 | function onSignSuccessful(id, value) {
9 | Trust.executeCallback(id, null, value)
10 | }
11 | function onSignError(id, error) {
12 | Trust.executeCallback(id, error, null)
13 | }
14 | window.Trust.init(rpcURL, {
15 | getAccounts: function (cb) { cb(null, [addressHex]) },
16 | processTransaction: function (tx, cb){
17 | console.log('signing a transaction', tx)
18 | const { id = 8888 } = tx
19 | Trust.addCallback(id, cb)
20 | var gasLimit = tx.gasLimit || tx.gas || null;
21 | var gasPrice = tx.gasPrice || null;
22 | var data = tx.data || null;
23 | var nonce = tx.nonce || -1;
24 | trust.signTransaction(id, tx.to || null, tx.value, nonce, gasLimit, gasPrice, data);
25 | },
26 | signMessage: function (msgParams, cb) {
27 | const { data } = msgParams
28 | const { id = 8888 } = msgParams
29 | console.log("signing a message", msgParams)
30 | Trust.addCallback(id, cb)
31 | trust.signMessage(id, data);
32 | },
33 | signPersonalMessage: function (msgParams, cb) {
34 | const { data } = msgParams
35 | const { id = 8888 } = msgParams
36 | console.log("signing a personal message", msgParams)
37 | Trust.addCallback(id, cb)
38 | trust.signPersonalMessage(id, data);
39 | },
40 | signTypedMessage: function (msgParams, cb) {
41 | const { data } = msgParams
42 | const { id = 8888 } = msgParams
43 | Trust.addCallback(id, cb)
44 | trust.signTypedMessage(id, JSON.stringify(data))
45 | }
46 | }, {
47 | address: addressHex,
48 | networkVersion: chainID
49 | })
50 | window.web3.setProvider = function () {
51 | console.debug('Trust Wallet - overrode web3.setProvider')
52 | }
53 | window.web3.eth.defaultAccount = addressHex
54 | window.web3.version.getNetwork = function(cb) {
55 | cb(null, chainID)
56 | }
57 | window.web3.eth.getCoinbase = function(cb) {
58 | return cb(null, addressHex)
59 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Web3View
2 |
3 | [](https://jitpack.io/#TrustWallet/Web3View)
4 |
5 | ### Usage ([sample](https://github.com/TrustWallet/Web3View/tree/master/app))
6 | Add dependency:
7 |
8 | Add it in your root build.gradle at the end of repositories:
9 | ```gradle
10 | allprojects {
11 | repositories {
12 | ...
13 | maven { url 'https://jitpack.io' }
14 | }
15 | }
16 | ```
17 |
18 | ```gradle
19 | dependencies {
20 | implementation 'com.github.TrustWallet:Web3View:0.02'
21 | }
22 | ```
23 | Add internet permission to AndroidManifest.xml
24 | ```xml
25 |
26 | ```
27 | Define a view in your layout file:
28 | ```xml
29 |
30 | ...
31 |
37 | ...
38 | ```
39 | And add following code to your activity or fragment for setup:
40 | Java
41 | ```java
42 | web3.setChainId(1);
43 | web3.setRpcUrl("https://mainnet.infura.io/llyrtzQ3YhkdESt2Fzrk");
44 | web3.setWalletAddress(new Address("0xaa3cc54d7f10fa3a1737e4997ba27c34f330ce16"));
45 | ```
46 | Add listeners:
47 |
48 | ```java
49 | web3.setOnSignMessageListener(message -> {
50 | Toast.makeText(this, "Message: " + message.value, Toast.LENGTH_LONG).show();
51 | web3.onSignCancel(message);
52 | });
53 | web3.setOnSignPersonalMessageListener(message -> {
54 | Toast.makeText(this, "Personal message: " + message.value, Toast.LENGTH_LONG).show();
55 | web3.onSignCancel(message);
56 | });
57 | web3.setOnSignTransactionListener(transaction -> {
58 | Toast.makeText(this, "Transaction: " + transaction.value, Toast.LENGTH_LONG).show();
59 | web3.onSignCancel(transaction);
60 | });
61 | ```
62 | Send results:
63 |
64 | ```java
65 | web3.onSignCancel(Message|Tranasction)
66 | web3.onSignMessageSuccessful(message, "0x....");
67 | web3.onSignPersonalMessageSuccessful(message, "0x...");
68 | web3.onSignTransactionSuccessful(transaction, "0x...");
69 | web3.onSignError(Message|Transaction, "some_error");
70 | ```
71 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/SignCallbackJSInterface.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.text.TextUtils;
5 | import android.webkit.JavascriptInterface;
6 | import android.webkit.WebView;
7 |
8 | import com.google.gson.Gson;
9 |
10 | import java.math.BigInteger;
11 |
12 | import trust.core.entity.Address;
13 | import trust.core.entity.Message;
14 | import trust.core.entity.Transaction;
15 | import trust.core.entity.TypedData;
16 | import trust.core.util.Hex;
17 |
18 | public class SignCallbackJSInterface {
19 |
20 | private final WebView webView;
21 | @NonNull
22 | private final OnSignTransactionListener onSignTransactionListener;
23 | @NonNull
24 | private final OnSignMessageListener onSignMessageListener;
25 | @NonNull
26 | private final OnSignPersonalMessageListener onSignPersonalMessageListener;
27 | @NonNull
28 | private final OnSignTypedMessageListener onSignTypedMessageListener;
29 |
30 | public SignCallbackJSInterface(
31 | WebView webView,
32 | @NonNull OnSignTransactionListener onSignTransactionListener,
33 | @NonNull OnSignMessageListener onSignMessageListener,
34 | @NonNull OnSignPersonalMessageListener onSignPersonalMessageListener,
35 | @NonNull OnSignTypedMessageListener onSignTypedMessageListener) {
36 | this.webView = webView;
37 | this.onSignTransactionListener = onSignTransactionListener;
38 | this.onSignMessageListener = onSignMessageListener;
39 | this.onSignPersonalMessageListener = onSignPersonalMessageListener;
40 | this.onSignTypedMessageListener = onSignTypedMessageListener;
41 | }
42 |
43 | @JavascriptInterface
44 | public void signTransaction(
45 | int callbackId,
46 | String recipient,
47 | String value,
48 | String nonce,
49 | String gasLimit,
50 | String gasPrice,
51 | String payload) {
52 | Transaction transaction = new Transaction(
53 | TextUtils.isEmpty(recipient) ? Address.EMPTY : new Address(recipient),
54 | null,
55 | Hex.hexToBigInteger(value),
56 | Hex.hexToBigInteger(gasPrice, BigInteger.ZERO),
57 | Hex.hexToLong(gasLimit, 0),
58 | Hex.hexToLong(nonce, -1),
59 | payload,
60 | callbackId);
61 | onSignTransactionListener.onSignTransaction(transaction);
62 |
63 | }
64 |
65 | @JavascriptInterface
66 | public void signMessage(int callbackId, String data) {
67 | webView.post(() -> onSignMessageListener.onSignMessage(new Message<>(data, getUrl(), callbackId)));
68 | }
69 |
70 | @JavascriptInterface
71 | public void signPersonalMessage(int callbackId, String data) {
72 | webView.post(() -> onSignPersonalMessageListener.onSignPersonalMessage(new Message<>(data, getUrl(), callbackId)));
73 | }
74 |
75 | @JavascriptInterface
76 | public void signTypedMessage(int callbackId, String data) {
77 | webView.post(() -> {
78 | TrustProviderTypedData[] rawData = new Gson().fromJson(data, TrustProviderTypedData[].class);
79 | int len = rawData.length;
80 | TypedData[] typedData = new TypedData[len];
81 | for (int i = 0; i < len; i++) {
82 | typedData[i] = new TypedData(rawData[i].name, rawData[i].type, rawData[i].value);
83 | }
84 | onSignTypedMessageListener.onSignTypedMessage(new Message<>(typedData, getUrl(), callbackId));
85 | });
86 | }
87 |
88 | private String getUrl() {
89 | return webView == null ? "" : webView.getUrl();
90 | }
91 |
92 | private static class TrustProviderTypedData {
93 | public String name;
94 | public String type;
95 | public Object value;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/Web3ViewClient.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import android.net.http.SslError;
4 | import android.text.TextUtils;
5 | import android.util.Base64;
6 | import android.webkit.SslErrorHandler;
7 | import android.webkit.WebResourceRequest;
8 | import android.webkit.WebResourceResponse;
9 | import android.webkit.WebView;
10 | import android.webkit.WebViewClient;
11 |
12 | import java.io.ByteArrayInputStream;
13 | import java.util.Map;
14 |
15 | import okhttp3.HttpUrl;
16 |
17 | import static android.os.Build.VERSION.SDK_INT;
18 | import static android.os.Build.VERSION_CODES.N;
19 |
20 | public class Web3ViewClient extends WebViewClient {
21 |
22 | private final Object lock = new Object();
23 |
24 | private final JsInjectorClient jsInjectorClient;
25 | private final UrlHandlerManager urlHandlerManager;
26 |
27 | private boolean isInjected;
28 |
29 | public Web3ViewClient(JsInjectorClient jsInjectorClient, UrlHandlerManager urlHandlerManager) {
30 | this.jsInjectorClient = jsInjectorClient;
31 | this.urlHandlerManager = urlHandlerManager;
32 | }
33 |
34 | void addUrlHandler(UrlHandler urlHandler) {
35 | urlHandlerManager.add(urlHandler);
36 | }
37 |
38 | void removeUrlHandler(UrlHandler urlHandler) {
39 | urlHandlerManager.remove(urlHandler);
40 | }
41 |
42 | @Override
43 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
44 | return shouldOverrideUrlLoading(view, url, false, false);
45 | }
46 |
47 | @Override
48 | public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
49 | if (request == null || view == null) {
50 | return false;
51 | }
52 | String url = request.getUrl().toString();
53 | boolean isMainFrame = request.isForMainFrame();
54 | boolean isRedirect = SDK_INT >= N && request.isRedirect();
55 | return shouldOverrideUrlLoading(view, url, isMainFrame, isRedirect);
56 | }
57 |
58 | private boolean shouldOverrideUrlLoading(WebView webView, String url, boolean isMainFrame, boolean isRedirect) {
59 | boolean result = false;
60 | synchronized (lock) {
61 | isInjected = false;
62 | }
63 | String urlToOpen = urlHandlerManager.handle(url);
64 | if (!url.startsWith("http")) {
65 | result = true;
66 | }
67 | if (isMainFrame && isRedirect) {
68 | urlToOpen = url;
69 | result = true;
70 | }
71 |
72 | if (result && !TextUtils.isEmpty(urlToOpen)) {
73 | webView.loadUrl(urlToOpen);
74 | }
75 | return result;
76 | }
77 |
78 | @Override
79 | public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
80 | if (request == null) {
81 | return null;
82 | }
83 | if (!request.getMethod().equalsIgnoreCase("GET") || !request.isForMainFrame()) {
84 | if (request.getMethod().equalsIgnoreCase("GET")
85 | && (request.getUrl().toString().contains(".js")
86 | || request.getUrl().toString().contains("json")
87 | || request.getUrl().toString().contains("css"))) {
88 | synchronized (lock) {
89 | if (!isInjected) {
90 | injectScriptFile(view);
91 | isInjected = true;
92 | }
93 | }
94 | }
95 | super.shouldInterceptRequest(view, request);
96 | return null;
97 | }
98 |
99 | HttpUrl httpUrl = HttpUrl.parse(request.getUrl().toString());
100 | if (httpUrl == null) {
101 | return null;
102 | }
103 | Map headers = request.getRequestHeaders();
104 | JsInjectorResponse response;
105 | try {
106 | response = jsInjectorClient.loadUrl(httpUrl.toString(), headers);
107 | } catch (Exception ex) {
108 | return null;
109 | }
110 | if (response == null || response.isRedirect) {
111 | return null;
112 | } else {
113 | ByteArrayInputStream inputStream = new ByteArrayInputStream(response.data.getBytes());
114 | WebResourceResponse webResourceResponse = new WebResourceResponse(
115 | response.mime, response.charset, inputStream);
116 | synchronized (lock) {
117 | isInjected = true;
118 | }
119 | return webResourceResponse;
120 | }
121 | }
122 |
123 | private void injectScriptFile(WebView view) {
124 | String js = jsInjectorClient.assembleJs(view.getContext(), "%1$s%2$s");
125 | byte[] buffer = js.getBytes();
126 | String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
127 |
128 | view.post(() -> view.loadUrl("javascript:(function() {" +
129 | "var parent = document.getElementsByTagName('head').item(0);" +
130 | "var script = document.createElement('script');" +
131 | "script.type = 'text/javascript';" +
132 | // Tell the browser to BASE64-decode the string into your script !!!
133 | "script.innerHTML = window.atob('" + encoded + "');" +
134 | "parent.appendChild(script)" +
135 | "})()"));
136 | }
137 |
138 | @Override
139 | public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
140 | handler.proceed();
141 | }
142 |
143 | public void onReload() {
144 | synchronized (lock) {
145 | isInjected = false;
146 | }
147 | }
148 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
21 |
26 |
31 |
36 |
41 |
46 |
51 |
56 |
61 |
66 |
71 |
76 |
81 |
86 |
91 |
96 |
101 |
106 |
111 |
116 |
121 |
126 |
131 |
136 |
141 |
146 |
151 |
156 |
161 |
166 |
171 |
172 |
--------------------------------------------------------------------------------
/app/src/main/java/trust/web3view/MainActivity.java:
--------------------------------------------------------------------------------
1 | package trust.web3view;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.webkit.WebView;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 |
10 | import com.google.gson.Gson;
11 |
12 | import trust.Call;
13 | import trust.SignMessageRequest;
14 | import trust.SignPersonalMessageRequest;
15 | import trust.SignTransactionRequest;
16 | import trust.SignTypedMessageRequest;
17 | import trust.Trust;
18 | import trust.core.entity.Address;
19 | import trust.core.entity.Message;
20 | import trust.core.entity.Transaction;
21 | import trust.core.entity.TypedData;
22 | import trust.web3.OnSignMessageListener;
23 | import trust.web3.OnSignPersonalMessageListener;
24 | import trust.web3.OnSignTransactionListener;
25 | import trust.web3.OnSignTypedMessageListener;
26 | import trust.web3.Web3View;
27 |
28 | public class MainActivity extends AppCompatActivity implements
29 | OnSignTransactionListener, OnSignPersonalMessageListener, OnSignTypedMessageListener, OnSignMessageListener {
30 |
31 | private TextView url;
32 | private Web3View web3;
33 | private Call callSignMessage;
34 | private Call callSignPersonalMessage;
35 | private Call callSignTypedMessage;
36 | private Call callSignTransaction;
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(R.layout.activity_main);
42 |
43 | url = findViewById(R.id.url);
44 | web3 = findViewById(R.id.web3view);
45 | findViewById(R.id.go).setOnClickListener(v -> {
46 | web3.loadUrl(url.getText().toString());
47 | web3.requestFocus();
48 | });
49 |
50 | setupWeb3();
51 | }
52 |
53 | private void setupWeb3() {
54 | WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
55 | web3.setChainId(1);
56 | web3.setRpcUrl("https://mainnet.infura.io/llyrtzQ3YhkdESt2Fzrk");
57 | web3.setWalletAddress(new Address("0x242776e7ca6271e416e737adffcfeb22e8dc1b3c"));
58 |
59 | web3.setOnSignMessageListener(message ->
60 | callSignMessage = Trust.signMessage().message(message).call(this));
61 | web3.setOnSignPersonalMessageListener(message ->
62 | callSignPersonalMessage = Trust.signPersonalMessage().message(message).call(this));
63 | web3.setOnSignTransactionListener(transaction ->
64 | callSignTransaction = Trust.signTransaction().transaction(transaction).call(this));
65 | web3.setOnSignTypedMessageListener(message ->
66 | callSignTypedMessage = Trust.signTypedMessage().message(message).call(this));
67 | }
68 |
69 | @Override
70 | public void onSignMessage(Message message) {
71 | Toast.makeText(this, message.value, Toast.LENGTH_LONG).show();
72 | web3.onSignCancel(message);
73 | }
74 |
75 | @Override
76 | public void onSignPersonalMessage(Message message) {
77 | Toast.makeText(this, message.value, Toast.LENGTH_LONG).show();
78 | web3.onSignCancel(message);
79 | }
80 |
81 | @Override
82 | public void onSignTypedMessage(Message message) {
83 | Toast.makeText(this, new Gson().toJson(message), Toast.LENGTH_LONG).show();
84 | web3.onSignCancel(message);
85 | }
86 |
87 | @Override
88 | public void onSignTransaction(Transaction transaction) {
89 | String str = new StringBuilder()
90 | .append(transaction.recipient == null ? "" : transaction.recipient.toString()).append(" : ")
91 | .append(transaction.contract == null ? "" : transaction.contract.toString()).append(" : ")
92 | .append(transaction.value.toString()).append(" : ")
93 | .append(transaction.gasPrice.toString()).append(" : ")
94 | .append(transaction.gasLimit).append(" : ")
95 | .append(transaction.nonce).append(" : ")
96 | .append(transaction.payload).append(" : ")
97 | .toString();
98 | Toast.makeText(this, str, Toast.LENGTH_LONG).show();
99 | web3.onSignCancel(transaction);
100 | }
101 |
102 | @Override
103 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
104 | super.onActivityResult(requestCode, resultCode, data);
105 | if (callSignTransaction != null) {
106 | callSignTransaction.onActivityResult(requestCode, resultCode, data, response -> {
107 | Transaction transaction = response.request.body();
108 | if (response.isSuccess()) {
109 | web3.onSignTransactionSuccessful(transaction, response.result);
110 | } else {
111 | if (response.error == Trust.ErrorCode.CANCELED) {
112 | web3.onSignCancel(transaction);
113 | } else {
114 | web3.onSignError(transaction, "Some error");
115 | }
116 | }
117 | });
118 | }
119 |
120 | if (callSignMessage != null) {
121 | callSignMessage.onActivityResult(requestCode, resultCode, data, response -> {
122 | Message message = response.request.body();
123 | if (response.isSuccess()) {
124 | web3.onSignMessageSuccessful(message, response.result);
125 | } else {
126 | if (response.error == Trust.ErrorCode.CANCELED) {
127 | web3.onSignCancel(message);
128 | } else {
129 | web3.onSignError(message, "Some error");
130 | }
131 | }
132 | });
133 | }
134 |
135 | if (callSignPersonalMessage != null) {
136 | callSignPersonalMessage.onActivityResult(requestCode, resultCode, data, response -> {
137 | Message message = response.request.body();
138 | if (response.isSuccess()) {
139 | web3.onSignMessageSuccessful(message, response.result);
140 | } else {
141 | if (response.error == Trust.ErrorCode.CANCELED) {
142 | web3.onSignCancel(message);
143 | } else {
144 | web3.onSignError(message, "Some error");
145 | }
146 | }
147 | });
148 | }
149 |
150 | if (callSignTypedMessage != null) {
151 | callSignTypedMessage.onActivityResult(requestCode, resultCode, data, response -> {
152 | Message message = response.request.body();
153 | if (response.isSuccess()) {
154 | web3.onSignMessageSuccessful(message, response.result);
155 | } else {
156 | if (response.error == Trust.ErrorCode.CANCELED) {
157 | web3.onSignCancel(message);
158 | } else {
159 | web3.onSignError(message, "Some error");
160 | }
161 | }
162 | });
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/lib/src/main/java/trust/web3/JsInjectorClient.java:
--------------------------------------------------------------------------------
1 | package trust.web3;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.Nullable;
5 | import android.support.annotation.RawRes;
6 | import android.text.TextUtils;
7 | import android.util.Log;
8 |
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.util.HashMap;
12 | import java.util.Map;
13 | import java.util.Set;
14 | import java.util.regex.Matcher;
15 | import java.util.regex.Pattern;
16 |
17 | import okhttp3.Headers;
18 | import okhttp3.HttpUrl;
19 | import okhttp3.OkHttpClient;
20 | import okhttp3.Request;
21 | import okhttp3.Response;
22 | import trust.core.entity.Address;
23 |
24 | class JsInjectorClient {
25 |
26 | private static final String DEFAULT_CHARSET = "utf-8";
27 | private static final String DEFAULT_MIME_TYPE = "text/html";
28 | private final static String JS_TAG_TEMPLATE = "";
29 |
30 | private final Context context;
31 | private final OkHttpClient httpClient;
32 |
33 | private String jsLibrary;
34 |
35 | private int chainId = 1;
36 | private Address walletAddress;
37 | private String rpcUrl = "https://mainnet.infura.io/llyrtzQ3YhkdESt2Fzrk";
38 |
39 | JsInjectorClient(Context context) {
40 | this.context = context;
41 | this.httpClient = createHttpClient();
42 | }
43 |
44 | public Address getWalletAddress() {
45 | return walletAddress;
46 | }
47 |
48 | public void setWalletAddress(Address address) {
49 | this.walletAddress = address;
50 | }
51 |
52 | public int getChainId() {
53 | return chainId;
54 | }
55 |
56 | public void setChainId(int chainId) {
57 | this.chainId = chainId;
58 | }
59 |
60 | public String getRpcUrl() {
61 | return rpcUrl;
62 | }
63 |
64 | public void setRpcUrl(String rpcUrl) {
65 | this.rpcUrl = rpcUrl;
66 | }
67 |
68 | JsInjectorResponse loadUrl(final String url, String userAgent) {
69 | Map headers = new HashMap<>();
70 | headers.put("User-Agent", userAgent);
71 | return loadUrl(url, headers);
72 | }
73 |
74 | @Nullable
75 | JsInjectorResponse loadUrl(final String url, final Map headers) {
76 | Request request = buildRequest(url, headers);
77 | JsInjectorResponse result = null;
78 | try {
79 | Response response = httpClient.newCall(request).execute();
80 | result = buildResponse(response);
81 | } catch (Exception ex) {
82 | Log.d("REQUEST_ERROR", "", ex);
83 | }
84 | return result;
85 | }
86 |
87 | String assembleJs(Context context, String template) {
88 | if (TextUtils.isEmpty(jsLibrary)) {
89 | jsLibrary = loadFile(context, trust.web3jprovider.R.raw.trust);
90 | }
91 | String initJs = loadInitJs(context);
92 | return String.format(template, jsLibrary, initJs);
93 |
94 | }
95 |
96 | @Nullable
97 | private JsInjectorResponse buildResponse(Response response) {
98 | String body = null;
99 | int code = response.code();
100 | try {
101 | if (response.isSuccessful()) {
102 | body = response.body().string();
103 | }
104 | } catch (IOException ex) {
105 | Log.d("READ_BODY_ERROR", "Ex", ex);
106 | }
107 | Request request = response.request();
108 | Response prior = response.priorResponse();
109 | boolean isRedirect = prior != null && prior.isRedirect();
110 | String result = injectJS(body);
111 | String contentType = getContentTypeHeader(response);
112 | String charset = getCharset(contentType);
113 | String mime = getMimeType(contentType);
114 | String finalUrl = request.url().toString();
115 | return new JsInjectorResponse(result, code, finalUrl, mime, charset, isRedirect);
116 | }
117 |
118 | String injectJS(String html) {
119 | String js = assembleJs(context, JS_TAG_TEMPLATE);
120 | return injectJS(html, js);
121 | }
122 |
123 | private String injectJS(String html, String js) {
124 | if (TextUtils.isEmpty(html)) {
125 | return html;
126 | }
127 | int position = getInjectionPosition(html);
128 | if (position > 0) {
129 | String beforeTag = html.substring(0, position);
130 | String afterTab = html.substring(position);
131 | return beforeTag + js + afterTab;
132 | }
133 | return html;
134 | }
135 |
136 | private int getInjectionPosition(String body) {
137 | body = body.toLowerCase();
138 | int ieDetectTagIndex = body.indexOf("