├── .github ├── CODEOWNERS └── ISSUE_TEMPLATE │ ├── bug_report.yaml │ ├── config.yml │ └── feature_request.md ├── .gitignore ├── .idea ├── .gitignore ├── .name ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── deploymentTargetSelector.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── kotlinc.xml ├── migrations.xml ├── misc.xml ├── other.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── metamask │ │ └── dapp │ │ └── ExampleInstrumentedTest.kt │ ├── debug │ ├── app_icon-playstore.png │ └── res │ │ ├── drawable │ │ └── app_icon_foreground.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── app_icon.xml │ │ └── app_icon_round.xml │ │ ├── mipmap-hdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-mdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-xhdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-xxhdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ └── values │ │ └── app_icon_background.xml │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── metamask │ │ │ └── dapp │ │ │ ├── AppModule.kt │ │ │ ├── AppTopBar.kt │ │ │ ├── BatchSignMessageScreen.kt │ │ │ ├── ConnectScreen.kt │ │ │ ├── DappActionsScreen.kt │ │ │ ├── DappButton.kt │ │ │ ├── DappLabel.kt │ │ │ ├── DappScreen.kt │ │ │ ├── EthereumFlowViewModel.kt │ │ │ ├── EthereumViewModel.kt │ │ │ ├── Heading.kt │ │ │ ├── MainActivity.kt │ │ │ ├── MetaMaskDappApplication.kt │ │ │ ├── ReadOnlyCallsScreen.kt │ │ │ ├── ScreenViewModel.kt │ │ │ ├── SendTransactionScreen.kt │ │ │ ├── Setup.kt │ │ │ ├── SignMessageScreen.kt │ │ │ ├── SwitchChainScreen.kt │ │ │ └── ui │ │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ └── stackoverflow.png │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ ├── release │ ├── app_icon-playstore.png │ └── res │ │ ├── drawable │ │ └── app_icon_foreground.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── app_icon.xml │ │ └── app_icon_round.xml │ │ ├── mipmap-hdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-mdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-xhdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-xxhdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── app_icon.png │ │ └── app_icon_round.png │ │ └── values │ │ └── app_icon_background.xml │ └── test │ └── java │ └── com │ └── metamask │ └── dapp │ └── ExampleUnitTest.kt ├── build.gradle ├── ecies ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── metamask │ │ └── ecies │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── metamask │ │ │ └── ecies │ │ │ └── Ecies.kt │ └── jniLibs │ │ ├── arm64-v8a │ │ └── libecies.so │ │ ├── armeabi-v7a │ │ └── libecies.so │ │ ├── x86 │ │ └── libecies.so │ │ └── x86_64 │ │ └── libecies.so │ └── test │ └── java │ └── io │ └── metamask │ └── ecies │ └── ExampleUnitTest.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── metamask-android-sdk ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── metamask │ │ └── androidsdk │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── aidl │ │ └── io │ │ │ └── metamask │ │ │ └── nativesdk │ │ │ ├── IMessegeService.aidl │ │ │ └── IMessegeServiceCallback.aidl │ ├── java │ │ └── io │ │ │ └── metamask │ │ │ └── androidsdk │ │ │ ├── Analytics.kt │ │ │ ├── AnyRequest.kt │ │ │ ├── ClientMessageServiceCallback.kt │ │ │ ├── ClientServiceConnection.kt │ │ │ ├── CommunicationClient.kt │ │ │ ├── CommunicationClientModule.kt │ │ │ ├── CommunicationClientModuleInterface.kt │ │ │ ├── Constants.kt │ │ │ ├── Crypto.kt │ │ │ ├── DappMetadata.kt │ │ │ ├── DeviceInfo.kt │ │ │ ├── Encryption.kt │ │ │ ├── ErrorType.kt │ │ │ ├── Ethereum.kt │ │ │ ├── EthereumEventCallback.kt │ │ │ ├── EthereumFlow.kt │ │ │ ├── EthereumMethod.kt │ │ │ ├── EthereumRequest.kt │ │ │ ├── EthereumState.kt │ │ │ ├── HttpClient.kt │ │ │ ├── InfuraProvider.kt │ │ │ ├── KeyExchange.kt │ │ │ ├── KeyExchangeMessageType.kt │ │ │ ├── KeyStorage.kt │ │ │ ├── Logger.kt │ │ │ ├── MainActivity.kt │ │ │ ├── Message.kt │ │ │ ├── MessageType.kt │ │ │ ├── NativeCurrency.kt │ │ │ ├── Network.kt │ │ │ ├── OriginatorInfo.kt │ │ │ ├── ReadOnlyRPCProvider.kt │ │ │ ├── RequestError.kt │ │ │ ├── RequestInfo.kt │ │ │ ├── Result.kt │ │ │ ├── RpcRequest.kt │ │ │ ├── SDKInfo.kt │ │ │ ├── SDKOptions.kt │ │ │ ├── SecureStorage.kt │ │ │ ├── SessionConfig.kt │ │ │ ├── SessionManager.kt │ │ │ ├── SubmittedRequest.kt │ │ │ └── TimeStampGenerator.kt │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── io │ └── metamask │ └── androidsdk │ ├── CommunicationClientTests.kt │ ├── CryptoTests.kt │ ├── EthereumTests.kt │ ├── KeyExchangeTests.kt │ ├── KeyStorageTests.kt │ ├── MockClientMessageServiceCallback.kt │ ├── MockClientServiceConnection.kt │ ├── MockCommunicationClientModule.kt │ ├── MockCrypto.kt │ ├── MockEthereumEventCallback.kt │ ├── MockKeyStorage.kt │ ├── MockReadOnlyRPCProvider.kt │ ├── MockTracker.kt │ ├── RSAEncryption.kt │ ├── SessionConfigTests.kt │ ├── SessionManagerTests.kt │ └── TestLogger.kt ├── nativesdk ├── .gitignore ├── README.md ├── build.gradle.kts ├── consumer-rules.pro ├── illustrations │ └── architecture.png ├── libs │ └── ecies.aar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── metamask │ │ └── nativesdk │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── aidl │ │ └── io │ │ │ └── metamask │ │ │ └── nativesdk │ │ │ ├── IMessegeService.aidl │ │ │ └── IMessegeServiceCallback.aidl │ └── java │ │ └── io │ │ └── metamask │ │ └── nativesdk │ │ ├── Analytics.kt │ │ ├── CommunicationClient.kt │ │ ├── ConnectionStatusManager.kt │ │ ├── Constants.kt │ │ ├── Crypto.kt │ │ ├── Endpoint.kt │ │ ├── Event.kt │ │ ├── EventType.kt │ │ ├── HttpClient.kt │ │ ├── KeyExchange.kt │ │ ├── KeyExchangeMessageType.kt │ │ ├── Logger.kt │ │ ├── MessageService.kt │ │ ├── MessageType.kt │ │ ├── MetaMaskConnectionStatusCallback.kt │ │ ├── NativeSDKPackage.kt │ │ └── SessionManager.kt │ └── test │ └── java │ └── io │ └── metamask │ └── nativesdk │ └── ExampleUnitTest.kt ├── scripts ├── ecies-publish-module.gradle ├── metamask-android-sdk-publish-module.gradle └── publish-auth.gradle └── settings.gradle /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | * @MetaMask/sdk-devs -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Create a bug report for the MetaMask Android SDK 3 | title: "[Bug]: " 4 | labels: ["template: bug"] 5 | body: 6 | - type: textarea 7 | attributes: 8 | label: Provide environment information 9 | description: "Give us a general overview of the environment where the issue is happening" 10 | validations: 11 | required: true 12 | - type: input 13 | attributes: 14 | label: MetaMask Android SDK Version 15 | description: "Please specify the exact MetaMask SDK version" 16 | validations: 17 | required: true 18 | - type: input 19 | attributes: 20 | label: MetaMask Mobile app Version 21 | description: "Please specify the exact MetaMask Mobile app version" 22 | validations: 23 | required: true 24 | - type: input 25 | attributes: 26 | label: Android Version 27 | description: "Please specify the exact version. For example: Android 12.1" 28 | validations: 29 | required: true 30 | - type: textarea 31 | attributes: 32 | label: Describe the Bug 33 | description: A clear and concise description of what the bug is. 34 | validations: 35 | required: true 36 | - type: textarea 37 | attributes: 38 | label: Expected Behavior 39 | description: A clear and concise description of what you expected to happen. 40 | validations: 41 | required: true 42 | - type: input 43 | attributes: 44 | label: Link to reproduction - Issues with a link to complete (but minimal) reproduction code will be addressed faster 45 | description: A link to a GitHub repository to recreate the issue. Include steps to run the repository and make sure it contains only code to reproduce the bug. I.E. don't invite us to your production application repo. 46 | validations: 47 | required: false 48 | - type: textarea 49 | attributes: 50 | label: To Reproduce 51 | description: Steps to reproduce the behavior, please provide a clear description of how to reproduce the issue, based on the linked minimal reproduction. Screenshots can be provided in the issue body below. If using code blocks, make sure that [syntax highlighting is correct](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) and double check that the rendered preview is not broken. 52 | validations: 53 | required: true 54 | - type: markdown 55 | attributes: 56 | value: Before posting the issue go through the steps you've written down to make sure the steps provided are detailed and clear. 57 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Documentation 4 | url: https://docs.metamask.io/sdk 5 | about: Check the official documentation for help using the SDK 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: enhancement 6 | assignees: "" 7 | --- 8 | 9 | # Feature Request 10 | 11 | 14 | 15 | ## Why it is needed 16 | 17 | 20 | 21 | ## Possible implementation 22 | 23 | 26 | 27 | ### Code sample 28 | 29 | 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | MetaMaskAndroidSDKClient -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetSelector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright ConsenSys Software Inc. 2022. All rights reserved. 2 | 3 | You acknowledge and agree that ConsenSys Software Inc. (“ConsenSys”) (or ConsenSys’s licensors) own all legal right, title and interest in and to the work, software, application, source code, documentation and any other documents in this repository (collectively, the “Program”), including any intellectual property rights which subsist in the Program (whether those rights happen to be registered or not, and wherever in the world those rights may exist), whether in source code or any other form. 4 | 5 | Subject to the limited license below, you may not (and you may not permit anyone else to) distribute, publish, copy, modify, merge, combine with another program, create derivative works of, reverse engineer, decompile or otherwise attempt to extract the source code of, the Program or any part thereof, except that you may contribute to this repository. 6 | 7 | You are granted a non-exclusive, non-transferable, non-sublicensable license to distribute, publish, copy, modify, merge, combine with another program or create derivative works of the Program (such resulting program, collectively, the “Resulting Program”) solely for Non-Commercial Use as long as you: 8 | 9 | 1. give prominent notice (“Notice”) with each copy of the Resulting Program that the Program is used in the Resulting Program and that the Program is the copyright of ConsenSys; and 10 | 2. subject the Resulting Program and any distribution, publication, copy, modification, merger therewith, combination with another program or derivative works thereof to the same Notice requirement and Non-Commercial Use restriction set forth herein. 11 | 12 | “Non-Commercial Use” means each use as described in clauses (1)-(3) below, as reasonably determined by ConsenSys in its sole discretion: 13 | 14 | 1. personal use for research, personal study, private entertainment, hobby projects or amateur pursuits, in each case without any anticipated commercial application; 15 | 2. use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization or government institution; or 16 | 3. the number of monthly active users of the Resulting Program across all versions thereof and platforms globally do not exceed 10,000 at any time. 17 | 18 | You will not use any trade mark, service mark, trade name, logo of ConsenSys or any other company or organization in a way that is likely or intended to cause confusion about the owner or authorized user of such marks, names or logos. 19 | 20 | If you have any questions, comments or interest in pursuing any other use cases, please reach out to us at metamask.license@consensys.net. 21 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | id 'kotlin-kapt' 5 | id 'dagger.hilt.android.plugin' 6 | } 7 | 8 | android { 9 | namespace 'com.metamask.dapp' 10 | compileSdk 33 11 | 12 | defaultConfig { 13 | applicationId "com.metamask.dapp" 14 | minSdk 23 15 | targetSdk 33 16 | versionCode 1 17 | versionName "1.0" 18 | 19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 20 | vectorDrawables { 21 | useSupportLibrary true 22 | } 23 | } 24 | 25 | compileOptions { 26 | sourceCompatibility JavaVersion.VERSION_11 27 | targetCompatibility JavaVersion.VERSION_11 28 | } 29 | kotlinOptions { 30 | jvmTarget = "11" 31 | } 32 | kapt { 33 | javacOptions { 34 | // Set Java version for KAPT explicitly 35 | option("-source", "11") 36 | option("-target", "11") 37 | } 38 | } 39 | buildFeatures { 40 | compose true 41 | } 42 | composeOptions { 43 | kotlinCompilerExtensionVersion '1.4.0' 44 | } 45 | packagingOptions { 46 | resources { 47 | excludes += '/META-INF/{AL2.0,LGPL2.1}' 48 | } 49 | } 50 | } 51 | 52 | kotlin { 53 | jvmToolchain(11) 54 | } 55 | 56 | dependencies { 57 | implementation project(':metamask-android-sdk') 58 | implementation 'androidx.compose.material:material:1.0.4' 59 | implementation 'com.google.android.material:material:1.9.0' 60 | implementation "androidx.navigation:navigation-compose:2.5.0" 61 | implementation 'androidx.compose.runtime:runtime-livedata:1.4.3' 62 | implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1' 63 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' 64 | implementation "com.google.dagger:hilt-android:$hilt_version" 65 | implementation 'androidx.navigation:navigation-runtime-ktx:2.6.0' 66 | kapt "com.google.dagger:hilt-compiler:$hilt_version" 67 | implementation 'androidx.core:core-ktx:1.7.0' 68 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' 69 | implementation 'androidx.activity:activity-compose:1.3.1' 70 | 71 | 72 | implementation "androidx.compose.ui:ui:$compose_version" 73 | implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" 74 | implementation 'androidx.compose.material3:material3:1.0.0' 75 | testImplementation 'junit:junit:4.13.2' 76 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 77 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 78 | androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" 79 | debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" 80 | debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" 81 | } 82 | 83 | kapt { 84 | correctErrorTypes true 85 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /app/src/androidTest/java/com/metamask/dapp/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.metamask.dapp", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/debug/app_icon-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/app_icon-playstore.png -------------------------------------------------------------------------------- /app/src/debug/res/drawable/app_icon_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-anydpi-v26/app_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-anydpi-v26/app_icon_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-hdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-hdpi/app_icon.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-hdpi/app_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-hdpi/app_icon_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-mdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-mdpi/app_icon.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-mdpi/app_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-mdpi/app_icon_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xhdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-xhdpi/app_icon.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xhdpi/app_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-xhdpi/app_icon_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxhdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-xxhdpi/app_icon.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxhdpi/app_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-xxhdpi/app_icon_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-xxxhdpi/app_icon.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi/app_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/debug/res/mipmap-xxxhdpi/app_icon_round.png -------------------------------------------------------------------------------- /app/src/debug/res/values/app_icon_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3DDC84 4 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/AppModule.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import android.content.Context 4 | import dagger.Binds 5 | import dagger.Module 6 | import dagger.Provides 7 | import dagger.hilt.InstallIn 8 | import dagger.hilt.android.qualifiers.ApplicationContext 9 | import dagger.hilt.components.SingletonComponent 10 | import io.metamask.androidsdk.* 11 | 12 | @Module 13 | @InstallIn(SingletonComponent::class) 14 | 15 | internal object AppModule { 16 | @Provides 17 | fun provideDappMetadata(): DappMetadata { 18 | return DappMetadata("Droiddapp", "https://www.droiddapp.io", iconUrl = "https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png") 19 | } 20 | 21 | @Provides 22 | fun provideLogger(): Logger { 23 | return DefaultLogger 24 | } 25 | 26 | @Provides // Add SDKOptions(infuraAPIKey="supply_your_key_here") to Ethereum constructor for read-only calls 27 | fun provideEthereum(@ApplicationContext context: Context, dappMetadata: DappMetadata, logger: Logger): Ethereum { 28 | return Ethereum(context, dappMetadata, null, logger) 29 | } 30 | 31 | @Provides 32 | fun provideEthereumFlow(ethereum: Ethereum): EthereumFlow { 33 | return EthereumFlow(ethereum) 34 | } 35 | } 36 | 37 | @Module 38 | @InstallIn(SingletonComponent::class) 39 | abstract class EthereumModule { 40 | @Binds 41 | abstract fun bindEthereum(ethereumflow: EthereumFlow): EthereumFlowWrapper 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/AppTopBar.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp.com.metamask.dapp 2 | 3 | import androidx.navigation.NavController 4 | import androidx.compose.material.icons.Icons 5 | import androidx.compose.material.icons.filled.ArrowBack 6 | import androidx.compose.material3.* 7 | import androidx.compose.runtime.Composable 8 | 9 | @OptIn(ExperimentalMaterial3Api::class) 10 | @Composable 11 | fun AppTopBar(navController: NavController) { 12 | TopAppBar( 13 | title = { Text("") }, 14 | navigationIcon = { 15 | IconButton(onClick = { navController.popBackStack() }) { 16 | Icon(imageVector = Icons.Default.ArrowBack, contentDescription = "Back") 17 | } 18 | } 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/BatchSignMessageScreen.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.foundation.layout.* 5 | import androidx.compose.foundation.text.BasicTextField 6 | import androidx.compose.material3.Surface 7 | import androidx.compose.runtime.* 8 | import androidx.compose.ui.Alignment 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.graphics.Color 11 | import androidx.compose.ui.res.stringResource 12 | import androidx.compose.ui.text.TextStyle 13 | import androidx.compose.ui.tooling.preview.Preview 14 | import androidx.compose.ui.unit.dp 15 | import androidx.navigation.NavController 16 | import androidx.navigation.compose.rememberNavController 17 | import com.metamask.dapp.com.metamask.dapp.AppTopBar 18 | import io.metamask.androidsdk.EthereumState 19 | import io.metamask.androidsdk.Result 20 | import kotlinx.coroutines.launch 21 | 22 | @Composable 23 | fun BatchSignMessageScreen( 24 | navController: NavController, 25 | ethereumState: EthereumState, 26 | batchSign: suspend (messages: List, address: String) -> Result 27 | ) { 28 | var signResult by remember { mutableStateOf("") } 29 | var errorMessage by remember { mutableStateOf(null) } 30 | 31 | val transactionData = "{\"data\":\"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675\",\"from\": \"0x0000000000000000000000000000000000000000\",\"gas\": \"0x76c0\",\"gasPrice\": \"0x9184e72a000\",\"to\": \"0xd46e8dd67c5d32be8058bb8eb970870f07244567\",\"value\": \"0x9184e72a\"}" 32 | val helloWorld = "Hello, world, signing in!" 33 | val byeWorld = "Last message to sign!" 34 | val batchSignMessages: List = listOf(helloWorld, transactionData, byeWorld) 35 | val coroutineScope = rememberCoroutineScope() 36 | 37 | Surface { 38 | AppTopBar(navController) 39 | 40 | Column( 41 | modifier = Modifier 42 | .fillMaxSize() 43 | .padding(horizontal = 36.dp), 44 | horizontalAlignment = Alignment.CenterHorizontally 45 | ) { 46 | Heading("Sign Message") 47 | 48 | Spacer(modifier = Modifier.weight(1f)) 49 | 50 | BasicTextField( 51 | value = batchSignMessages.joinToString("\n\n=================================\n\n"), 52 | textStyle = TextStyle(color = if (isSystemInDarkTheme()) { Color.White} else { Color.Black}), 53 | onValueChange = { }, 54 | modifier = Modifier.padding(bottom = 36.dp) 55 | ) 56 | 57 | DappButton(buttonText = stringResource(R.string.batch_sign)) { 58 | coroutineScope.launch { 59 | when (val result = batchSign(batchSignMessages, ethereumState.selectedAddress)) { 60 | is Result.Success.Items -> { 61 | errorMessage = null 62 | signResult = result.value.joinToString("\n=================================\n") 63 | } 64 | is Result.Error -> { 65 | errorMessage = result.error.message 66 | } 67 | else -> {} 68 | } 69 | } 70 | } 71 | 72 | Spacer(modifier = Modifier.height(8.dp)) 73 | 74 | DappLabel( 75 | text = errorMessage ?: signResult, 76 | color = if (errorMessage != null) { Color.Red } else { Color.Unspecified }, 77 | modifier = Modifier.padding(bottom = 36.dp) 78 | ) 79 | 80 | Spacer(modifier = Modifier.height(24.dp)) 81 | } 82 | } 83 | } 84 | 85 | @Preview 86 | @Composable 87 | fun PreviewBatchSignMessage() { 88 | BatchSignMessageScreen( 89 | rememberNavController(), 90 | ethereumState = EthereumState("", "", ""), 91 | batchSign = { _, _ -> Result.Success.Items(listOf()) } 92 | ) 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/ConnectScreen.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.layout.* 4 | import androidx.compose.material3.Surface 5 | import androidx.compose.runtime.* 6 | import androidx.compose.ui.Alignment 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.graphics.Color 9 | import androidx.compose.ui.res.stringResource 10 | import androidx.compose.ui.tooling.preview.Preview 11 | import androidx.compose.ui.unit.dp 12 | import io.metamask.androidsdk.EthereumState 13 | import io.metamask.androidsdk.Result 14 | import kotlinx.coroutines.launch 15 | 16 | @Composable 17 | fun ConnectScreen( 18 | ethereumState: EthereumState, 19 | connect: suspend () -> Result, 20 | connectSign: () -> Unit, 21 | connectWith: () -> Unit, 22 | disconnect: () -> Unit, 23 | clearSession: () -> Unit) { 24 | 25 | val bottomMargin = 24.dp 26 | val connected = ethereumState.selectedAddress.isNotEmpty() 27 | 28 | var errorMessage by remember { mutableStateOf(null) } 29 | val coroutineScope = rememberCoroutineScope() 30 | 31 | Surface { 32 | Column( 33 | modifier = Modifier 34 | .fillMaxSize() 35 | .padding(horizontal = 36.dp), 36 | horizontalAlignment = Alignment.CenterHorizontally 37 | ) { 38 | Heading("MetaMask SDK Dapp") 39 | 40 | Spacer(modifier = Modifier.weight(1f)) 41 | 42 | // Connect button 43 | if (connected) { 44 | DappButton(buttonText = stringResource(R.string.disconnect)) { 45 | disconnect() 46 | } 47 | } else { 48 | DappButton(buttonText = stringResource(R.string.connect)) { 49 | coroutineScope.launch { 50 | errorMessage = when(val result = connect()) { 51 | is Result.Error -> { 52 | result.error.message 53 | } 54 | else -> { null } 55 | } 56 | } 57 | } 58 | 59 | Spacer(modifier = Modifier.height(12.dp)) 60 | 61 | // Connect and sign button 62 | DappButton(buttonText = stringResource(R.string.connect_sign)) { 63 | connectSign() 64 | } 65 | 66 | Spacer(modifier = Modifier.height(12.dp)) 67 | 68 | // Connect with button 69 | DappButton(buttonText = stringResource(R.string.connect_with)) { 70 | connectWith() 71 | } 72 | } 73 | 74 | Spacer(modifier = Modifier.height(4.dp)) 75 | 76 | DappLabel( 77 | text = errorMessage ?: ethereumState.selectedAddress, 78 | color = if (errorMessage != null) { Color.Red } else { Color.Unspecified }, 79 | modifier = Modifier.padding(bottom = 12.dp) 80 | ) 81 | 82 | // Clear session button 83 | DappButton(buttonText = stringResource(R.string.clear_session)) { 84 | clearSession() 85 | errorMessage = null 86 | } 87 | 88 | Spacer(modifier = Modifier.height(4.dp)) 89 | 90 | DappLabel( 91 | text = ethereumState.sessionId, 92 | color = Color.Unspecified, 93 | modifier = Modifier.padding(bottom = bottomMargin) 94 | ) 95 | } 96 | } 97 | } 98 | 99 | @Preview 100 | @Composable 101 | fun PreviewConnectClearButtons() { 102 | ConnectScreen( 103 | ethereumState = EthereumState("", "", ""), 104 | connect = { -> Result.Success.Item("")}, 105 | connectSign = { }, 106 | connectWith = { }, 107 | disconnect = { }, 108 | clearSession = { } 109 | ) 110 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/DappActionsScreen.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.layout.* 4 | import androidx.compose.material3.* 5 | import androidx.compose.runtime.* 6 | import androidx.compose.ui.Alignment 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.graphics.Color 9 | import androidx.compose.ui.res.stringResource 10 | import androidx.compose.ui.tooling.preview.Preview 11 | import androidx.compose.ui.unit.dp 12 | import androidx.navigation.NavController 13 | import androidx.navigation.compose.rememberNavController 14 | import com.metamask.dapp.com.metamask.dapp.AppTopBar 15 | import io.metamask.androidsdk.EthereumState 16 | 17 | @Composable 18 | fun DappActionsScreen( 19 | navController: NavController, 20 | ethereumState: EthereumState, 21 | onSignMessage: () -> Unit, 22 | onChainedSign: () -> Unit, 23 | onSendTransaction: () -> Unit, 24 | onSwitchChain: () -> Unit, 25 | onReadOnlyCalls: () -> Unit 26 | ) { 27 | Surface { 28 | AppTopBar(navController) 29 | 30 | Column( 31 | modifier = Modifier 32 | .fillMaxSize() 33 | .padding(horizontal = 36.dp), 34 | horizontalAlignment = Alignment.CenterHorizontally 35 | ) { 36 | Heading("Dapp Actions") 37 | 38 | DappLabel( 39 | heading = "Account:", 40 | text = ethereumState.selectedAddress, 41 | color = Color.Unspecified, 42 | modifier = Modifier.padding(bottom = 36.dp) 43 | ) 44 | 45 | DappLabel( 46 | heading = "ChainId:", 47 | text = ethereumState.chainId, 48 | color = Color.Unspecified, 49 | modifier = Modifier.padding(bottom = 36.dp) 50 | ) 51 | 52 | Spacer(modifier = Modifier.weight(1f)) 53 | 54 | // Sign message button 55 | DappButton(buttonText = stringResource(R.string.sign)) { 56 | onSignMessage() 57 | } 58 | 59 | Spacer(modifier = Modifier.height(12.dp)) 60 | 61 | // Chained signing button 62 | DappButton(buttonText = stringResource(R.string.batch_sign)) { 63 | onChainedSign() 64 | } 65 | 66 | Spacer(modifier = Modifier.height(12.dp)) 67 | 68 | // Send transaction button 69 | DappButton(buttonText = stringResource(R.string.send)) { 70 | onSendTransaction() 71 | } 72 | 73 | Spacer(modifier = Modifier.height(12.dp)) 74 | 75 | // Switch chain button 76 | DappButton(buttonText = stringResource(R.string.switch_chain)) { 77 | onSwitchChain() 78 | } 79 | 80 | Spacer(modifier = Modifier.height(12.dp)) 81 | 82 | // Read only RPC calls 83 | DappButton(buttonText = stringResource(R.string.read_only_calls)) { 84 | onReadOnlyCalls() 85 | } 86 | 87 | Spacer(modifier = Modifier.height(24.dp)) 88 | } 89 | } 90 | } 91 | 92 | 93 | 94 | @Preview 95 | @Composable 96 | fun PreviewDappActions() { 97 | DappActionsScreen(rememberNavController(), EthereumState("","",""), {}, {}, {}, {}, {}) 98 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/DappButton.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.layout.fillMaxWidth 4 | import androidx.compose.foundation.layout.height 5 | import androidx.compose.material3.Button 6 | import androidx.compose.material3.ButtonDefaults 7 | import androidx.compose.material3.Text 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.graphics.Color 11 | import androidx.compose.ui.text.font.FontWeight 12 | import androidx.compose.ui.tooling.preview.Preview 13 | import androidx.compose.ui.unit.Dp 14 | import androidx.compose.ui.unit.dp 15 | import androidx.compose.ui.unit.sp 16 | 17 | @Composable 18 | fun DappButton( 19 | buttonText: String, 20 | buttonHeight: Dp = 48.dp, 21 | buttonBackgroundColor: Color = Color(40, 124, 204), 22 | buttonTextColor: Color = Color.White, 23 | onClick: () -> Unit 24 | ) { 25 | Button( 26 | onClick = onClick, 27 | elevation = null, colors = ButtonDefaults.buttonColors( 28 | containerColor = buttonBackgroundColor, 29 | contentColor = buttonTextColor 30 | ), modifier = Modifier 31 | .height(buttonHeight) 32 | .fillMaxWidth() 33 | ) { 34 | Text( 35 | text = buttonText, 36 | fontSize = 16.sp, 37 | fontWeight = FontWeight.SemiBold, 38 | color = Color.White, 39 | ) 40 | } 41 | } 42 | 43 | @Preview 44 | @Composable 45 | fun PreviewDappButton() { 46 | DappButton( 47 | buttonText = "Connect", 48 | onClick = {} 49 | ) 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/DappLabel.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.layout.padding 4 | import androidx.compose.material3.Text 5 | import androidx.compose.runtime.Composable 6 | import androidx.compose.ui.Modifier 7 | import androidx.compose.ui.graphics.Color 8 | import androidx.compose.ui.tooling.preview.Preview 9 | import androidx.compose.ui.unit.TextUnit 10 | import androidx.compose.ui.unit.dp 11 | import androidx.compose.ui.unit.sp 12 | 13 | @Composable 14 | fun DappLabel( 15 | heading: String = "", 16 | text: String, 17 | color: Color = Color.White, 18 | fontSize: TextUnit = 14.sp, 19 | modifier: Modifier = Modifier.padding(bottom = 12.dp) 20 | ) { 21 | if (heading.isNotEmpty()) { 22 | Text( 23 | text = heading, 24 | color = color, 25 | fontSize = 18.sp, 26 | modifier = Modifier.padding(bottom = 5.dp) 27 | ) 28 | } 29 | Text( 30 | text = text, 31 | color = color, 32 | fontSize = fontSize, 33 | modifier = modifier 34 | ) 35 | } 36 | 37 | @Preview 38 | @Composable 39 | fun PreviewDappLabel() { 40 | DappLabel(text = "Connect") 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/DappScreen.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | enum class DappScreen { 4 | CONNECT, 5 | ACTIONS, 6 | BATCH_SIGN, 7 | SIGN_MESSAGE, 8 | CONNECT_SIGN_MESSAGE, 9 | CONNECT_WITH, 10 | SEND_TRANSACTION, 11 | SWITCH_CHAIN, 12 | READ_ONLY_CALLS 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/EthereumFlowViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.lifecycle.ViewModel 4 | import dagger.hilt.android.lifecycle.HiltViewModel 5 | import io.metamask.androidsdk.* 6 | import kotlinx.coroutines.flow.Flow 7 | import javax.inject.Inject 8 | 9 | @HiltViewModel 10 | class EthereumFlowViewModel @Inject constructor( 11 | private val ethereum: EthereumFlowWrapper 12 | ): ViewModel() { 13 | val ethereumFlow: Flow get() = ethereum.ethereumState 14 | 15 | suspend fun connect() : Result { 16 | return ethereum.connect() 17 | } 18 | 19 | suspend fun connectWith(request: EthereumRequest) : Result { 20 | return ethereum.connectWith(request) 21 | } 22 | 23 | suspend fun connectSign(message: String) : Result { 24 | return ethereum.connectSign(message) 25 | } 26 | 27 | suspend fun connectWithSendTransaction(amount: String, 28 | from: String, 29 | to: String) : Result { 30 | val params: MutableMap = mutableMapOf( 31 | "from" to from, 32 | "to" to to, 33 | "amount" to amount 34 | ) 35 | 36 | val transactionRequest = EthereumRequest( 37 | method = EthereumMethod.ETH_SEND_TRANSACTION.value, 38 | params = listOf(params) 39 | ) 40 | 41 | return connectWith(transactionRequest) 42 | } 43 | 44 | suspend fun sendRequestBatch(requests: List) : Result { 45 | return ethereum.sendRequestBatch(requests) 46 | } 47 | 48 | suspend fun sendRequest(request: EthereumRequest) : Result { 49 | return ethereum.sendRequest(request) 50 | } 51 | 52 | suspend fun sendBatchSigningRequest( 53 | messages: List, 54 | address: String) : Result { 55 | val requestBatch: MutableList = mutableListOf() 56 | 57 | for (message in messages) { 58 | val params: List = listOf(address, message) 59 | val ethereumRequest = EthereumRequest( 60 | method = EthereumMethod.PERSONAL_SIGN.value, 61 | params = params 62 | ) 63 | requestBatch.add(ethereumRequest) 64 | } 65 | 66 | return ethereum.sendRequestBatch(requestBatch) 67 | } 68 | 69 | suspend fun signMessage( 70 | message: String, 71 | address: String, 72 | ) : Result { 73 | return ethereum.ethSignTypedDataV4(typedData = message, address) 74 | } 75 | 76 | suspend fun getBalance(address: String, block: String = "latest") : Result { 77 | return ethereum.getEthBalance(address, block) 78 | } 79 | 80 | suspend fun gasPrice() : Result { 81 | return ethereum.getEthGasPrice() 82 | } 83 | 84 | suspend fun web3ClientVersion() : Result { 85 | return ethereum.getWeb3ClientVersion() 86 | } 87 | 88 | suspend fun sendTransaction( 89 | amount: String, 90 | from: String, 91 | to: String, 92 | ) : Result { 93 | return ethereum.sendTransaction(from = from, to = to, value = amount) 94 | } 95 | 96 | suspend fun switchChain(chainId: String) : SwitchChainResult { 97 | return when (val result = ethereum.switchEthereumChain(chainId)) { 98 | is Result.Success -> { 99 | SwitchChainResult.Success("Successfully switched to ${Network.chainNameFor(chainId)} ($chainId)") 100 | } 101 | is Result.Error -> { 102 | if (result.error.code == ErrorType.UNRECOGNIZED_CHAIN_ID.code || result.error.code == ErrorType.SERVER_ERROR.code) { 103 | val message = "${Network.chainNameFor(chainId)} ($chainId) has not been added to your MetaMask wallet. Add chain?" 104 | SwitchChainResult.Error(result.error.code, message) 105 | } else { 106 | SwitchChainResult.Error(result.error.code,"Add chain error: ${result.error.message}") 107 | } 108 | } 109 | } 110 | } 111 | 112 | suspend fun addEthereumChain(chainId: String) : SwitchChainResult { 113 | return when (val result = ethereum.addEthereumChain( 114 | chainId = chainId, 115 | chainName = Network.chainNameFor(chainId), 116 | rpcUrls = Network.rpcUrls(Network.fromChainId(chainId)), 117 | iconUrls = listOf(), 118 | blockExplorerUrls = null, 119 | nativeCurrency = NativeCurrency(name = Network.chainNameFor(chainId), symbol = Network.symbol(chainId), decimals = 18) 120 | )) { 121 | is Result.Error -> { 122 | SwitchChainResult.Error(result.error.code,"Add chain error: ${result.error.message}") 123 | } 124 | is Result.Success -> { 125 | if (chainId == ethereum.chainId) { 126 | SwitchChainResult.Success("Successfully switched to ${Network.chainNameFor(chainId)} ($chainId)") 127 | } else { 128 | SwitchChainResult.Success("Successfully added ${Network.chainNameFor(chainId)} ($chainId)") 129 | } 130 | } 131 | } 132 | } 133 | 134 | fun disconnect(clearSession: Boolean = false) { 135 | ethereum.disconnect(clearSession) 136 | } 137 | } 138 | 139 | sealed class SwitchChainResult { 140 | data class Success(val value: String) : SwitchChainResult() 141 | data class Error(val error: Int, val message: String): SwitchChainResult() 142 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/Heading.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.layout.padding 4 | import androidx.compose.material3.MaterialTheme 5 | import androidx.compose.material3.Text 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.tooling.preview.Preview 9 | import androidx.compose.ui.unit.dp 10 | 11 | @Composable 12 | fun Heading(title: String) { 13 | Text( 14 | text = title, 15 | style = MaterialTheme.typography.headlineSmall, 16 | modifier = Modifier 17 | .padding(16.dp) 18 | 19 | ) 20 | } 21 | 22 | @Preview 23 | @Composable 24 | fun PreviewHeading() { 25 | Heading(title = "Connect Dapp") 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.activity.viewModels 7 | import androidx.compose.foundation.layout.fillMaxSize 8 | import androidx.compose.material3.* 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.tooling.preview.Preview 12 | import com.metamask.dapp.ui.theme.MetaMaskAndroidSDKClientTheme 13 | import dagger.hilt.android.AndroidEntryPoint 14 | 15 | @AndroidEntryPoint 16 | class MainActivity : ComponentActivity() { 17 | 18 | private val ethereumViewModel: EthereumFlowViewModel by viewModels() 19 | private val screenViewModel: ScreenViewModel by viewModels() 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | 24 | setContent { 25 | MetaMaskAndroidSDKClientTheme { 26 | // A surface container using the 'background' color from the theme 27 | Surface( 28 | modifier = Modifier.fillMaxSize(), 29 | color = MaterialTheme.colorScheme.background 30 | ) { 31 | Setup(ethereumViewModel, screenViewModel) 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | @Composable 39 | fun Greeting(name: String) { 40 | Text(text = "Hello $name!") 41 | } 42 | 43 | @Preview(showBackground = true) 44 | @Composable 45 | fun DefaultPreview() { 46 | MetaMaskAndroidSDKClientTheme { 47 | Greeting("Android") 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/MetaMaskDappApplication.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import android.app.Application 4 | import dagger.hilt.android.HiltAndroidApp 5 | 6 | @HiltAndroidApp 7 | class MetaMaskDappApplication : Application() {} -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/ReadOnlyCallsScreen.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.layout.* 4 | import androidx.compose.material3.* 5 | import androidx.compose.runtime.* 6 | import androidx.compose.ui.Alignment 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.graphics.Color 9 | import androidx.compose.ui.res.stringResource 10 | import androidx.compose.ui.tooling.preview.Preview 11 | import androidx.compose.ui.unit.dp 12 | import androidx.navigation.NavController 13 | import androidx.navigation.compose.rememberNavController 14 | import com.metamask.dapp.com.metamask.dapp.AppTopBar 15 | import io.metamask.androidsdk.EthereumState 16 | import io.metamask.androidsdk.Result 17 | import kotlinx.coroutines.launch 18 | 19 | @Composable 20 | fun ReadOnlyCallsScreen( 21 | navController: NavController, 22 | ethereumState: EthereumState, 23 | getBalance: suspend (address: String) -> Result, 24 | getGasPrice: suspend () -> Result, 25 | getWeb3ClientVersion: suspend () -> Result 26 | ) { 27 | var selectedAddress by remember { mutableStateOf("") } 28 | var balance by remember { mutableStateOf("") } 29 | var gasPrice by remember { mutableStateOf("") } 30 | var web3ClientVersion by remember { mutableStateOf("") } 31 | var getBalanceErrorMessage by remember { mutableStateOf(null) } 32 | var getGasPriceErrorMessage by remember { mutableStateOf(null) } 33 | var getWeb3VersionErrorMessage by remember { mutableStateOf(null) } 34 | val coroutineScope = rememberCoroutineScope() 35 | 36 | LaunchedEffect(ethereumState.selectedAddress) { 37 | selectedAddress = ethereumState.selectedAddress 38 | } 39 | 40 | Surface { 41 | AppTopBar(navController) 42 | 43 | Column( 44 | modifier = Modifier 45 | .fillMaxSize() 46 | .padding(horizontal = 36.dp), 47 | horizontalAlignment = Alignment.CenterHorizontally 48 | ) { 49 | Heading("Read-Only RPCs") 50 | 51 | Spacer(modifier = Modifier.weight(1f)) 52 | 53 | // Get balance 54 | DappButton(buttonText = stringResource(R.string.get_balance)) { 55 | coroutineScope.launch { 56 | when(val result = getBalance(selectedAddress)) { 57 | is Result.Success.Item -> { 58 | balance = result.value 59 | getBalanceErrorMessage = null 60 | } 61 | is Result.Error -> { 62 | getBalanceErrorMessage = result.error.message 63 | } 64 | else -> {} 65 | } 66 | } 67 | } 68 | 69 | Spacer(modifier = Modifier.height(8.dp)) 70 | 71 | DappLabel( 72 | text = getBalanceErrorMessage ?: balance, 73 | color = if (getBalanceErrorMessage != null) { Color.Red } else { Color.Unspecified }, 74 | modifier = Modifier.padding(bottom = 12.dp) 75 | ) 76 | 77 | // Get gas price 78 | DappButton(buttonText = stringResource(R.string.get_gas_price)) { 79 | coroutineScope.launch { 80 | when(val result = getGasPrice()) { 81 | is Result.Success.Item -> { 82 | gasPrice = result.value 83 | getGasPriceErrorMessage = null 84 | } 85 | is Result.Error -> { 86 | getGasPriceErrorMessage = result.error.message 87 | } 88 | else -> {} 89 | } 90 | } 91 | } 92 | 93 | Spacer(modifier = Modifier.height(8.dp)) 94 | 95 | DappLabel( 96 | text = getGasPriceErrorMessage ?: gasPrice, 97 | color = if (getGasPriceErrorMessage != null) { Color.Red } else { Color.Unspecified }, 98 | modifier = Modifier.padding(bottom = 12.dp) 99 | ) 100 | 101 | // Get Web3 client version 102 | DappButton(buttonText = stringResource(R.string.get_web3_client_version)) { 103 | coroutineScope.launch { 104 | when(val result = getWeb3ClientVersion()) { 105 | is Result.Success.Item -> { 106 | web3ClientVersion = result.value 107 | getWeb3VersionErrorMessage = null 108 | } 109 | is Result.Error -> { 110 | getWeb3VersionErrorMessage = result.error.message 111 | } 112 | else -> {} 113 | } 114 | } 115 | } 116 | 117 | Spacer(modifier = Modifier.height(8.dp)) 118 | 119 | DappLabel( 120 | text = getWeb3VersionErrorMessage ?: web3ClientVersion, 121 | color = if (getWeb3VersionErrorMessage != null) { Color.Red } else { Color.Unspecified }, 122 | modifier = Modifier.padding(bottom = 12.dp) 123 | ) 124 | } 125 | } 126 | } 127 | 128 | @Preview 129 | @Composable 130 | fun PreviewReadOnlyCallsScreen() { 131 | ReadOnlyCallsScreen( 132 | rememberNavController(), 133 | ethereumState = EthereumState("", "", ""), 134 | getBalance = {_ -> Result.Success.Item("")}, 135 | getGasPrice = { -> Result.Success.Item("")}, 136 | getWeb3ClientVersion = { -> Result.Success.Item("")} 137 | ) 138 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/ScreenViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.runtime.State 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.lifecycle.ViewModel 6 | import dagger.hilt.android.lifecycle.HiltViewModel 7 | import io.metamask.androidsdk.DefaultLogger 8 | import io.metamask.androidsdk.Logger 9 | import javax.inject.Inject 10 | 11 | @HiltViewModel 12 | class ScreenViewModel @Inject constructor(): ViewModel() { 13 | private val _currentScreen = mutableStateOf(DappScreen.CONNECT) 14 | val currentScreen: State = _currentScreen 15 | 16 | fun setScreen(screen: DappScreen) { 17 | _currentScreen.value = screen 18 | DefaultLogger.log("Navigating to $screen") 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/SignMessageScreen.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.foundation.layout.* 5 | import androidx.compose.foundation.text.BasicTextField 6 | import androidx.compose.material3.* 7 | import androidx.compose.runtime.* 8 | import androidx.compose.ui.Alignment 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.graphics.Color 11 | import androidx.compose.ui.res.stringResource 12 | import androidx.compose.ui.text.TextStyle 13 | import androidx.compose.ui.tooling.preview.Preview 14 | import androidx.compose.ui.unit.dp 15 | import androidx.navigation.NavController 16 | import androidx.navigation.compose.rememberNavController 17 | import com.metamask.dapp.com.metamask.dapp.AppTopBar 18 | import io.metamask.androidsdk.EthereumState 19 | import io.metamask.androidsdk.Result 20 | import kotlinx.coroutines.launch 21 | 22 | @Composable 23 | fun SignMessageScreen( 24 | navController: NavController, 25 | ethereumState: EthereumState, 26 | isConnectSign: Boolean = false, 27 | connectSignMessage: suspend (message: String) -> Result, 28 | signMessage: suspend (message: String, address: String) -> Result 29 | ) { 30 | fun signMessage(chainId: String): String { 31 | return if(isConnectSign) { 32 | "He will win who knows when to fight and when not to fight. He will win who knows how to handle both superior and inferior forces." 33 | } else { 34 | "{\"domain\":{\"chainId\":\"$chainId\",\"name\":\"Ether Mail\",\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\",\"version\":\"1\"},\"message\":{\"contents\":\"Hello, Busa!\",\"from\":{\"name\":\"Kinno\",\"wallets\":[\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\",\"0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF\"]},\"to\":[{\"name\":\"Busa\",\"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[]\"}]}}" 35 | } 36 | } 37 | 38 | var message = signMessage(ethereumState.chainId) 39 | var signResult by remember { mutableStateOf("") } 40 | var errorMessage by remember { mutableStateOf(null) } 41 | val coroutineScope = rememberCoroutineScope() 42 | 43 | LaunchedEffect(ethereumState.chainId) { 44 | message = signMessage(ethereumState.chainId) 45 | } 46 | 47 | Surface { 48 | AppTopBar(navController) 49 | 50 | Column( 51 | modifier = Modifier 52 | .fillMaxSize() 53 | .padding(horizontal = 36.dp), 54 | horizontalAlignment = Alignment.CenterHorizontally 55 | ) { 56 | Heading(if (isConnectSign) { "Connect & Sign Message" } else { "Sign Message"}) 57 | 58 | Spacer(modifier = Modifier.weight(1f)) 59 | 60 | BasicTextField( 61 | value = message, 62 | textStyle = TextStyle(color = if (isSystemInDarkTheme()) { Color.White} else { Color.Black}), 63 | onValueChange = { 64 | message = it 65 | }, 66 | modifier = Modifier.padding(bottom = 36.dp) 67 | ) 68 | 69 | if (isConnectSign) { 70 | DappButton(buttonText = stringResource(R.string.connect_sign)) { 71 | coroutineScope.launch { 72 | val result = connectSignMessage(message) 73 | errorMessage = when (result) { 74 | is Result.Success -> { 75 | null 76 | } 77 | is Result.Error -> { 78 | result.error.message 79 | } 80 | } 81 | } 82 | } 83 | } else { 84 | DappButton(buttonText = stringResource(R.string.sign)) { 85 | coroutineScope.launch { 86 | when (val result = signMessage(message, ethereumState.selectedAddress)) { 87 | is Result.Success.Item -> { 88 | errorMessage = null 89 | signResult = result.value 90 | } 91 | is Result.Error -> { 92 | errorMessage = result.error.message 93 | } 94 | else -> {} 95 | } 96 | } 97 | } 98 | } 99 | 100 | Spacer(modifier = Modifier.height(8.dp)) 101 | 102 | DappLabel( 103 | text = errorMessage ?: signResult, 104 | color = if (errorMessage != null) { Color.Red } else { Color.Unspecified }, 105 | modifier = Modifier.padding(bottom = 36.dp) 106 | ) 107 | 108 | Spacer(modifier = Modifier.height(24.dp)) 109 | } 110 | } 111 | } 112 | 113 | @Preview 114 | @Composable 115 | fun PreviewSignMessage() { 116 | SignMessageScreen( 117 | rememberNavController(), 118 | ethereumState = EthereumState("", "", ""), 119 | false, 120 | signMessage = { _, _ -> Result.Success.Item("") }, 121 | connectSignMessage = { _ -> Result.Success.Item("") } 122 | ) 123 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple80 = Color(0xFFD0BCFF) 6 | val PurpleGrey80 = Color(0xFFCCC2DC) 7 | val Pink80 = Color(0xFFEFB8C8) 8 | 9 | val Purple40 = Color(0xFF6650a4) 10 | val PurpleGrey40 = Color(0xFF625b71) 11 | val Pink40 = Color(0xFF7D5260) -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp.ui.theme 2 | 3 | import android.app.Activity 4 | import android.os.Build 5 | import androidx.compose.foundation.isSystemInDarkTheme 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.darkColorScheme 8 | import androidx.compose.material3.dynamicDarkColorScheme 9 | import androidx.compose.material3.dynamicLightColorScheme 10 | import androidx.compose.material3.lightColorScheme 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.runtime.SideEffect 13 | import androidx.compose.ui.graphics.toArgb 14 | import androidx.compose.ui.platform.LocalContext 15 | import androidx.compose.ui.platform.LocalView 16 | import androidx.core.view.ViewCompat 17 | import androidx.core.view.WindowCompat 18 | 19 | private val DarkColorScheme = darkColorScheme( 20 | primary = Purple80, 21 | secondary = PurpleGrey80, 22 | tertiary = Pink80 23 | ) 24 | 25 | private val LightColorScheme = lightColorScheme( 26 | primary = Purple40, 27 | secondary = PurpleGrey40, 28 | tertiary = Pink40 29 | 30 | /* Other default colors to override 31 | background = Color(0xFFFFFBFE), 32 | surface = Color(0xFFFFFBFE), 33 | onPrimary = Color.White, 34 | onSecondary = Color.White, 35 | onTertiary = Color.White, 36 | onBackground = Color(0xFF1C1B1F), 37 | onSurface = Color(0xFF1C1B1F), 38 | */ 39 | ) 40 | 41 | @Composable 42 | fun MetaMaskAndroidSDKClientTheme( 43 | darkTheme: Boolean = isSystemInDarkTheme(), 44 | // Dynamic color is available on Android 12+ 45 | dynamicColor: Boolean = true, 46 | content: @Composable () -> Unit 47 | ) { 48 | val colorScheme = when { 49 | dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { 50 | val context = LocalContext.current 51 | if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) 52 | } 53 | darkTheme -> DarkColorScheme 54 | else -> LightColorScheme 55 | } 56 | val view = LocalView.current 57 | val context = LocalContext.current 58 | val window = (LocalContext.current as? Activity)?.window 59 | if (!view.isInEditMode) { 60 | SideEffect { 61 | (view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb() 62 | if (context is Activity) { 63 | context.window.statusBarColor = colorScheme.primary.toArgb() 64 | val insetsController = WindowCompat.getInsetsController(context.window, view) 65 | insetsController?.isAppearanceLightStatusBars = darkTheme 66 | } 67 | //ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme 68 | } 69 | } 70 | 71 | MaterialTheme( 72 | colorScheme = colorScheme, 73 | typography = Typography, 74 | content = content 75 | ) 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/metamask/dapp/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.metamask.dapp.ui.theme 2 | 3 | import androidx.compose.material3.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | bodyLarge = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp, 15 | lineHeight = 24.sp, 16 | letterSpacing = 0.5.sp 17 | ) 18 | /* Other default text styles to override 19 | titleLarge = TextStyle( 20 | fontFamily = FontFamily.Default, 21 | fontWeight = FontWeight.Normal, 22 | fontSize = 22.sp, 23 | lineHeight = 28.sp, 24 | letterSpacing = 0.sp 25 | ), 26 | labelSmall = TextStyle( 27 | fontFamily = FontFamily.Default, 28 | fontWeight = FontWeight.Medium, 29 | fontSize = 11.sp, 30 | lineHeight = 16.sp, 31 | letterSpacing = 0.5.sp 32 | ) 33 | */ 34 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/stackoverflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/drawable/stackoverflow.png -------------------------------------------------------------------------------- /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/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetaMask/metamask-android-sdk/a448378fbedc3afbf70759ba71294f7819af2f37/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MetaMaskAndroidSDKClient 3 | Connection result: 4 | SessionId: 5 | Sign result: 6 | Transaction result: 7 | Second Fragment 8 | Dapp Actions 9 | Connect 10 | Disconnect 11 | Clear Session 12 | Sign Message 13 | Batch Signing 14 | Send Transaction 15 | Connect with Send Transaction 16 | Switch Chain 17 | Connect and Sign 18 | Connect With Request 19 | Add Chain 20 | Get Balance 21 | Get Gas Price 22 | Get Web3 Client Version 23 | Read Only Calls 24 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |