├── .babelrc ├── .gitattributes ├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── android ├── README.md ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── io │ └── github │ └── cawfree │ └── web3 │ ├── BundleJSONConverter.java │ ├── Web3Module.java │ └── Web3Package.java ├── docs ├── keystore.md ├── wallet.md └── web3.md ├── example ├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── App.js ├── README.md ├── __tests__ │ └── App-test.js ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── 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 │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── Podfile │ ├── example-tvOS │ │ └── Info.plist │ ├── example-tvOSTests │ │ └── Info.plist │ ├── example.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── example-tvOS.xcscheme │ │ │ └── example.xcscheme │ ├── example.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── example │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── exampleTests │ │ ├── Info.plist │ │ └── exampleTests.m ├── metro.config.js ├── package.json ├── src │ ├── configureStore.js │ ├── dashboard │ │ ├── actionTypes.js │ │ ├── actions.js │ │ ├── components │ │ │ └── Dashboard.js │ │ ├── containers │ │ │ └── Dashboard.js │ │ ├── index.js │ │ ├── model.js │ │ └── reducer.js │ ├── network │ │ ├── actionTypes.js │ │ ├── actions.js │ │ ├── index.js │ │ ├── model.js │ │ └── reducer.js │ ├── routes │ │ ├── actionTypes.js │ │ ├── actions.js │ │ ├── components │ │ │ └── Routes.js │ │ ├── containers │ │ │ └── Routes.js │ │ ├── index.js │ │ ├── model.js │ │ └── reducer.js │ ├── transaction │ │ ├── actionTypes.js │ │ ├── actions.js │ │ ├── components │ │ │ ├── MakeTransaction.js │ │ │ ├── Transaction.js │ │ │ └── Transactions.js │ │ ├── containers │ │ │ ├── MakeTransaction.js │ │ │ ├── Transaction.js │ │ │ └── Transactions.js │ │ ├── index.js │ │ ├── model.js │ │ └── reducer.js │ └── wallet │ │ ├── actionTypes.js │ │ ├── actions.js │ │ ├── components │ │ ├── AddWalletButton.js │ │ ├── Wallet.js │ │ └── Wallets.js │ │ ├── containers │ │ ├── AddWalletButton.js │ │ ├── Wallet.js │ │ └── Wallets.js │ │ ├── index.js │ │ ├── model.js │ │ └── reducer.js └── yarn.lock ├── ios ├── RNWeb3.swift ├── Web3-Bridging-Header.h ├── Web3.h ├── Web3.m ├── Web3.xcodeproj │ └── project.pbxproj └── Web3.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── package.json ├── public └── logo.png ├── src └── index.js ├── web3-react-native.podspec └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | android/src/main/java/io/github/cawfree/web3/javac* 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IntelliJ 33 | # 34 | build/ 35 | .idea 36 | .gradle 37 | local.properties 38 | *.iml 39 | 40 | # BUCK 41 | buck-out/ 42 | \.buckd/ 43 | *.keystore 44 | 45 | dist 46 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | public 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior. Maintainers are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned with our Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ 93 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Alexander Thomas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 | 7 | # web3-react-native 8 | [**Web3**](https://web3js.readthedocs.io/en/v1.2.6/) Native Modules for [**React Native**](https://reactnative.dev/). 9 | 10 | ## 🚀 Getting Started 11 | 12 | Using [`npm`](): 13 | 14 | ```bash 15 | npm install --save web3-react-native 16 | ``` 17 | 18 | Using [`yarn`](): 19 | 20 | ```bash 21 | yarn add web3-react-native 22 | ``` 23 | 24 | For versions less than [**React Native 0.60**](https://reactnative.dev/blog/2019/07/03/version-60), be sure to execute `react-native link` to make the native library dependencies visible to your compiled application. 25 | 26 | ### iOS 27 | After installing, append the following lines to your app's `ios/Podfile`, then execute `pod install`: 28 | 29 | ``` 30 | # web3-react-native 31 | pod 'secp256k1.c', '0.1.2', :modular_headers => true 32 | pod 'web3swift', '2.2.1', :modular_headers => true 33 | ``` 34 | 35 | > ⚠️ This is an ugly workaround for existing definition constraints in the [Podspec](https://github.com/cawfree/web3-react-native/blob/63664f366c436aed73083b6b0a5cbf0b7374bfd3/web3-react-native.podspec#L26). ([View Issue](https://github.com/cawfree/web3-react-native/issues/1)). 36 | 37 | ### Android 38 | In your app's `AndroidManifest.xml`, [you need to](https://github.com/web3j/web3j/issues/915) enable [`android:largeHeap`](https://developer.android.com/guide/topics/manifest/application-element) under the `` tag: 39 | 40 | ```diff 41 | 44 | ``` 45 | 46 | Perform a rebuild of your compiled application by calling `react-native run-android`. 47 | 48 | For usage details, please see the [**documentation**](./docs). 49 | 50 | ## ✌️ License 51 | [**MIT**](./LICENSE) 52 | -------------------------------------------------------------------------------- /android/README.md: -------------------------------------------------------------------------------- 1 | README 2 | ====== 3 | 4 | If you want to publish the lib as a maven dependency, follow these steps before publishing a new version to npm: 5 | 6 | 1. Be sure to have the Android [SDK](https://developer.android.com/studio/index.html) and [NDK](https://developer.android.com/ndk/guides/index.html) installed 7 | 2. Be sure to have a `local.properties` file in this folder that points to the Android SDK and NDK 8 | ``` 9 | ndk.dir=/Users/{username}/Library/Android/sdk/ndk-bundle 10 | sdk.dir=/Users/{username}/Library/Android/sdk 11 | ``` 12 | 3. Delete the `maven` folder 13 | 4. Run `./gradlew installArchives` 14 | 5. Verify that latest set of generated files is in the maven folder with the correct version number 15 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // android/build.gradle 2 | 3 | // based on: 4 | // 5 | // * https://github.com/facebook/react-native/blob/0.60-stable/template/android/build.gradle 6 | // original location: 7 | // - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/build.gradle 8 | // 9 | // * https://github.com/facebook/react-native/blob/0.60-stable/template/android/app/build.gradle 10 | // original location: 11 | // - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/app/build.gradle 12 | 13 | def DEFAULT_COMPILE_SDK_VERSION = 28 14 | def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3' 15 | def DEFAULT_MIN_SDK_VERSION = 16 16 | def DEFAULT_TARGET_SDK_VERSION = 28 17 | 18 | def safeExtGet(prop, fallback) { 19 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | apply plugin: 'maven' 24 | 25 | buildscript { 26 | // The Android Gradle plugin is only required when opening the android folder stand-alone. 27 | // This avoids unnecessary downloads and potential conflicts when the library is included as a 28 | // module dependency in an application project. 29 | // ref: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies 30 | if (project == rootProject) { 31 | repositories { 32 | google() 33 | jcenter() 34 | } 35 | dependencies { 36 | classpath 'com.android.tools.build:gradle:3.4.1' 37 | } 38 | } 39 | } 40 | 41 | apply plugin: 'com.android.library' 42 | apply plugin: 'maven' 43 | 44 | android { 45 | compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION) 46 | buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION) 47 | defaultConfig { 48 | minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION) 49 | targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION) 50 | versionCode 1 51 | versionName "1.0" 52 | } 53 | compileOptions { 54 | sourceCompatibility JavaVersion.VERSION_1_8 55 | targetCompatibility JavaVersion.VERSION_1_8 56 | } 57 | lintOptions { 58 | abortOnError false 59 | } 60 | } 61 | 62 | repositories { 63 | // ref: https://www.baeldung.com/maven-local-repository 64 | mavenLocal() 65 | maven { 66 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 67 | url "$rootDir/../node_modules/react-native/android" 68 | } 69 | maven { 70 | // Android JSC is installed from npm 71 | url "$rootDir/../node_modules/jsc-android/dist" 72 | } 73 | google() 74 | jcenter() 75 | } 76 | 77 | dependencies { 78 | //noinspection GradleDynamicVersion 79 | implementation 'com.facebook.react:react-native:+' // From node_modules 80 | implementation 'org.web3j:core:4.2.0-android' 81 | } 82 | 83 | def configureReactNativePom(def pom) { 84 | def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text) 85 | 86 | pom.project { 87 | name packageJson.title 88 | artifactId packageJson.name 89 | version = packageJson.version 90 | group = "io.github.cawfree.web3" 91 | description packageJson.description 92 | url packageJson.repository.baseUrl 93 | 94 | licenses { 95 | license { 96 | name packageJson.license 97 | url packageJson.repository.baseUrl + '/blob/master/' + packageJson.licenseFilename 98 | distribution 'repo' 99 | } 100 | } 101 | 102 | developers { 103 | developer { 104 | id packageJson.author.username 105 | name packageJson.author.name 106 | } 107 | } 108 | } 109 | } 110 | 111 | afterEvaluate { project -> 112 | // some Gradle build hooks ref: 113 | // https://www.oreilly.com/library/view/gradle-beyond-the/9781449373801/ch03.html 114 | task androidJavadoc(type: Javadoc) { 115 | source = android.sourceSets.main.java.srcDirs 116 | classpath += files(android.bootClasspath) 117 | classpath += files(project.getConfigurations().getByName('compile').asList()) 118 | include '**/*.java' 119 | } 120 | 121 | task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) { 122 | classifier = 'javadoc' 123 | from androidJavadoc.destinationDir 124 | } 125 | 126 | task androidSourcesJar(type: Jar) { 127 | classifier = 'sources' 128 | from android.sourceSets.main.java.srcDirs 129 | include '**/*.java' 130 | } 131 | 132 | android.libraryVariants.all { variant -> 133 | def name = variant.name.capitalize() 134 | def javaCompileTask = variant.javaCompileProvider.get() 135 | 136 | task "jar${name}"(type: Jar, dependsOn: javaCompileTask) { 137 | from javaCompileTask.destinationDir 138 | } 139 | } 140 | 141 | artifacts { 142 | archives androidSourcesJar 143 | archives androidJavadocJar 144 | } 145 | 146 | task installArchives(type: Upload) { 147 | configuration = configurations.archives 148 | repositories.mavenDeployer { 149 | // Deploy to react-native-event-bridge/maven, ready to publish to npm 150 | repository url: "file://${projectDir}/../android/maven" 151 | configureReactNativePom pom 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/java/io/github/cawfree/web3/BundleJSONConverter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 3 | * 4 | * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 5 | * copy, modify, and distribute this software in source code or binary form for use 6 | * in connection with the web services and APIs provided by Facebook. 7 | * 8 | * As with any software that integrates with the Facebook platform, your use of 9 | * this software is subject to the Facebook Developer Principles and Policies 10 | * [http://developers.facebook.com/policy/]. This copyright notice shall be 11 | * included in all copies or substantial portions of the software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | package io.github.cawfree.web3; 22 | 23 | import android.os.Bundle; 24 | import org.json.JSONArray; 25 | import org.json.JSONException; 26 | import org.json.JSONObject; 27 | 28 | import java.util.*; 29 | 30 | /** 31 | * com.facebook.internal is solely for the use of other packages within the Facebook SDK for 32 | * Android. Use of any of the classes in this package is unsupported, and they may be modified or 33 | * removed without warning at any time. 34 | * 35 | * A helper class that can round trip between JSON and Bundle objects that contains the types: 36 | * Boolean, Integer, Long, Double, String 37 | * If other types are found, an IllegalArgumentException is thrown. 38 | */ 39 | public class BundleJSONConverter { 40 | private static final Map, Setter> SETTERS = new HashMap, Setter>(); 41 | 42 | static { 43 | SETTERS.put(Boolean.class, new Setter() { 44 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException { 45 | bundle.putBoolean(key, (Boolean) value); 46 | } 47 | 48 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException { 49 | json.put(key, value); 50 | } 51 | }); 52 | SETTERS.put(Integer.class, new Setter() { 53 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException { 54 | bundle.putInt(key, (Integer) value); 55 | } 56 | 57 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException { 58 | json.put(key, value); 59 | } 60 | }); 61 | SETTERS.put(Long.class, new Setter() { 62 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException { 63 | bundle.putLong(key, (Long) value); 64 | } 65 | 66 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException { 67 | json.put(key, value); 68 | } 69 | }); 70 | SETTERS.put(Double.class, new Setter() { 71 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException { 72 | bundle.putDouble(key, (Double) value); 73 | } 74 | 75 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException { 76 | json.put(key, value); 77 | } 78 | }); 79 | SETTERS.put(String.class, new Setter() { 80 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException { 81 | bundle.putString(key, (String) value); 82 | } 83 | 84 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException { 85 | json.put(key, value); 86 | } 87 | }); 88 | SETTERS.put(String[].class, new Setter() { 89 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException { 90 | throw new IllegalArgumentException("Unexpected type from JSON"); 91 | } 92 | 93 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException { 94 | JSONArray jsonArray = new JSONArray(); 95 | for (String stringValue : (String[])value) { 96 | jsonArray.put(stringValue); 97 | } 98 | json.put(key, jsonArray); 99 | } 100 | }); 101 | 102 | SETTERS.put(JSONArray.class, new Setter() { 103 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException { 104 | JSONArray jsonArray = (JSONArray)value; 105 | ArrayList stringArrayList = new ArrayList(); 106 | // Empty list, can't even figure out the type, assume an ArrayList 107 | if (jsonArray.length() == 0) { 108 | bundle.putStringArrayList(key, stringArrayList); 109 | return; 110 | } 111 | 112 | // Only strings are supported for now 113 | for (int i = 0; i < jsonArray.length(); i++) { 114 | Object current = jsonArray.get(i); 115 | if (current instanceof String) { 116 | stringArrayList.add((String)current); 117 | } else { 118 | throw new IllegalArgumentException("Unexpected type in an array: " + current.getClass()); 119 | } 120 | } 121 | bundle.putStringArrayList(key, stringArrayList); 122 | } 123 | 124 | @Override 125 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException { 126 | throw new IllegalArgumentException("JSONArray's are not supported in bundles."); 127 | } 128 | }); 129 | } 130 | 131 | public interface Setter { 132 | public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException; 133 | public void setOnJSON(JSONObject json, String key, Object value) throws JSONException; 134 | } 135 | 136 | public static JSONObject convertToJSON(Bundle bundle) throws JSONException { 137 | JSONObject json = new JSONObject(); 138 | 139 | for(String key : bundle.keySet()) { 140 | Object value = bundle.get(key); 141 | if (value == null) { 142 | // Null is not supported. 143 | continue; 144 | } 145 | 146 | // Special case List as getClass would not work, since List is an interface 147 | if (value instanceof List) { 148 | JSONArray jsonArray = new JSONArray(); 149 | @SuppressWarnings("unchecked") 150 | List listValue = (List)value; 151 | for (String stringValue : listValue) { 152 | jsonArray.put(stringValue); 153 | } 154 | json.put(key, jsonArray); 155 | continue; 156 | } 157 | 158 | // Special case Bundle as it's one way, on the return it will be JSONObject 159 | if (value instanceof Bundle) { 160 | json.put(key, convertToJSON((Bundle)value)); 161 | continue; 162 | } 163 | 164 | Setter setter = SETTERS.get(value.getClass()); 165 | if (setter == null) { 166 | throw new IllegalArgumentException("Unsupported type: " + value.getClass()); 167 | } 168 | setter.setOnJSON(json, key, value); 169 | } 170 | 171 | return json; 172 | } 173 | 174 | public static Bundle convertToBundle(JSONObject jsonObject) throws JSONException { 175 | Bundle bundle = new Bundle(); 176 | @SuppressWarnings("unchecked") 177 | Iterator jsonIterator = jsonObject.keys(); 178 | while (jsonIterator.hasNext()) { 179 | String key = jsonIterator.next(); 180 | Object value = jsonObject.get(key); 181 | if (value == null || value == JSONObject.NULL) { 182 | // Null is not supported. 183 | continue; 184 | } 185 | 186 | // Special case JSONObject as it's one way, on the return it would be Bundle. 187 | if (value instanceof JSONObject) { 188 | bundle.putBundle(key, convertToBundle((JSONObject)value)); 189 | continue; 190 | } 191 | 192 | Setter setter = SETTERS.get(value.getClass()); 193 | if (setter == null) { 194 | throw new IllegalArgumentException("Unsupported type: " + value.getClass()); 195 | } 196 | setter.setOnBundle(bundle, key, value); 197 | } 198 | 199 | return bundle; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /android/src/main/java/io/github/cawfree/web3/Web3Module.java: -------------------------------------------------------------------------------- 1 | package io.github.cawfree.web3; 2 | 3 | import com.facebook.react.bridge.ReactApplicationContext; 4 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 5 | import com.facebook.react.bridge.ReactMethod; 6 | import com.facebook.react.bridge.Promise; 7 | import com.facebook.react.bridge.Arguments; 8 | import com.facebook.react.bridge.ReadableMap; 9 | import com.facebook.react.bridge.WritableMap; 10 | 11 | import org.web3j.crypto.Credentials; 12 | import org.web3j.crypto.CipherException; 13 | import org.web3j.crypto.WalletUtils; 14 | import org.web3j.protocol.Web3j; 15 | import org.web3j.protocol.core.methods.response.TransactionReceipt; 16 | import org.web3j.protocol.http.HttpService; 17 | import org.web3j.tx.Transfer; 18 | import org.web3j.tx.gas.ContractGasProvider; 19 | import org.web3j.tx.gas.DefaultGasProvider; 20 | import org.web3j.utils.Convert; 21 | import org.web3j.utils.Numeric; 22 | 23 | import org.json.JSONObject; 24 | 25 | import java.security.Security; 26 | import java.security.Provider; 27 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 28 | 29 | import java.io.File; 30 | import java.io.IOException; 31 | import java.io.FileWriter; 32 | import java.io.FileReader; 33 | import java.io.BufferedReader; 34 | import java.util.UUID; 35 | import java.util.Map; 36 | import java.util.HashMap; 37 | import java.math.BigDecimal; 38 | import java.lang.StringBuilder; 39 | 40 | // TODO: Remove this! 41 | import android.util.Log; 42 | 43 | // Heavily influenced by (thanks guys!): 44 | // https://github.com/web3j/sample-project-gradle/blob/master/src/main/java/org/web3j/sample/Application.java 45 | public final class Web3Module extends ReactContextBaseJavaModule { 46 | 47 | /* Static Declarations */ 48 | public static final String TAG = "Web3Module"; 49 | 50 | /** A simple utility method to print via ADB. */ 51 | private static final void debug(final String pString) { 52 | Log.d(TAG, pString); 53 | return; 54 | } 55 | 56 | /* Member Variables. */ 57 | private final Map mWallets; 58 | 59 | // https://github.com/web3j/web3j/issues/915#issuecomment-483145928 60 | private static final void setupBouncyCastle() { 61 | final Provider p = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); 62 | if (p == null || p.getClass().equals(BouncyCastleProvider.class)) { 63 | return; 64 | } 65 | Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); 66 | Security.insertProviderAt(new BouncyCastleProvider(), 1); 67 | } 68 | 69 | /** Constructor */ 70 | public Web3Module(final ReactApplicationContext pReactApplicationContext) { 71 | super(pReactApplicationContext); 72 | // Initialize Member Variables. 73 | this.mWallets = new HashMap(); 74 | } 75 | 76 | /** Module name when imported via NativeModules. **/ 77 | @Override public String getName() { return "Web3"; } 78 | 79 | @ReactMethod 80 | public final void createKeystore(final String pPassword, final Promise pPromise) { 81 | try { 82 | // Setup Bouncy Castle. 83 | Web3Module.setupBouncyCastle(); 84 | // Fetch the cache directory. 85 | final File dir = this.getReactApplicationContext().getCacheDir(); 86 | // Generate the new Wallet. 87 | final String name = WalletUtils.generateNewWalletFile(pPassword, dir); 88 | final File f = new File(dir.getAbsolutePath() + File.separator + name); 89 | // Parse the Keystore into a JSONObject. 90 | final JSONObject ks = new JSONObject(Web3Module.readFile(f)); 91 | // Delete the temporary file. 92 | f.delete(); 93 | // Propagate the keystore back to the caller. 94 | pPromise.resolve(Arguments.fromBundle(new BundleJSONConverter().convertToBundle(ks))); 95 | } 96 | catch (final Exception pException) { 97 | pPromise.reject(pException); 98 | } 99 | return; 100 | } 101 | 102 | @ReactMethod 103 | public final void loadWallet(final ReadableMap pKeystore, final String pPassword, final Promise pPromise) { 104 | try { 105 | // XXX: Attempt to create the Wallet. 106 | final String addr = this.addWallet(pKeystore, pPassword); 107 | final WritableMap args = Arguments.createMap(); 108 | // XXX: Propagate useful properties back to the caller. 109 | args.putString("address", addr); 110 | // XXX: Return the allocated wallet instance to the caller. 111 | pPromise.resolve(args); 112 | } 113 | catch (final Exception pException) { 114 | pPromise.reject(pException); 115 | } 116 | return; 117 | } 118 | 119 | @ReactMethod 120 | public final void sendFunds(final ReadableMap pWallet, final String pUrl, final String pPassword, final String pToAddress, final String pAmount, final String pUnits, final Promise pPromise) { 121 | try { 122 | // Fetch the Credentials. 123 | final Credentials c = this.getWallets().get(pWallet.getString("address")); 124 | if (c != null) { 125 | // XXX: Allocate the HttpService we'll use for this transaction. 126 | // TODO: Does this need to be destroyed? Is it worth caching? 127 | final Web3j web3j = Web3j.build(new HttpService(pUrl)); 128 | final TransactionReceipt tr = Transfer.sendFunds( 129 | web3j, 130 | c, 131 | pToAddress, 132 | new BigDecimal(pAmount), 133 | Convert.Unit.valueOf(pUnits) 134 | ) 135 | .send(); 136 | // Declare the callback parameters. 137 | final WritableMap args = Arguments.createMap(); 138 | // Buffer the hash for the transaction. 139 | args.putString("transactionHash", tr.getTransactionHash()); 140 | // Propagate the arguments to the caller. 141 | pPromise.resolve(args); 142 | return; 143 | } 144 | throw new IllegalStateException("No credentials found!"); 145 | } 146 | catch (final Exception pException) { 147 | pPromise.reject(pException); 148 | } 149 | return; 150 | } 151 | 152 | /** Reads the string contents of a File. **/ 153 | private static final String readFile(final File pFile) throws IOException { 154 | final StringBuilder sb = new StringBuilder(); 155 | final BufferedReader br = new BufferedReader(new FileReader(pFile)); 156 | String s; 157 | while ((s = br.readLine()) != null) { 158 | sb.append(s); 159 | sb.append('\n'); 160 | } 161 | br.close(); 162 | return sb.toString(); 163 | } 164 | 165 | /** Writes string contents to a designated File. **/ 166 | private static final void writeFile(final File pFile, final String pContent) throws IOException { 167 | final FileWriter fw = new FileWriter(pFile, true); 168 | fw.write(pContent); 169 | // XXX: Ensure all of the bytes are written. 170 | fw.flush(); 171 | fw.close(); 172 | } 173 | 174 | /** Creates a temporary file reference. **/ 175 | private final File createTempFile() throws IOException { 176 | return File.createTempFile(UUID.randomUUID().toString(), "json", this.getReactApplicationContext().getCacheDir()); 177 | } 178 | 179 | /** Adds a Wallet to the in-memory map. */ 180 | private final String addWallet(final ReadableMap pKeystore, final String pPassword) throws IOException, CipherException { 181 | final File f = this.createTempFile(); 182 | // XXX: Write the supplied data to a temporary file. 183 | // TODO: Use loadJsonCredentials. 184 | Web3Module.writeFile(f, new JSONObject(pKeystore.toHashMap()).toString()); 185 | 186 | // Load the Credentials. 187 | final Credentials c = WalletUtils.loadCredentials(pPassword, f.getAbsolutePath()); 188 | // Delete the allocated file; it serves no purpose now. 189 | f.delete(); 190 | // Fetch the Address of the Wallet. 191 | final String addr = c.getAddress(); 192 | // Here we track the wallet for future reference. Any attempts to 193 | // re-create the same wallet will resolve to the same place in memory. 194 | this.getWallets().put(addr, c); 195 | // Return the Wallet's address. 196 | return addr; 197 | } 198 | 199 | private final Map getWallets() { 200 | return this.mWallets; 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /android/src/main/java/io/github/cawfree/web3/Web3Package.java: -------------------------------------------------------------------------------- 1 | package io.github.cawfree.web3; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.bridge.NativeModule; 9 | import com.facebook.react.bridge.ReactApplicationContext; 10 | import com.facebook.react.uimanager.ViewManager; 11 | import com.facebook.react.bridge.JavaScriptModule; 12 | 13 | public class Web3Package implements ReactPackage { 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Arrays.asList(new Web3Module(reactContext)); 17 | } 18 | 19 | @Override 20 | public List createViewManagers(ReactApplicationContext reactContext) { 21 | return Collections.emptyList(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docs/keystore.md: -------------------------------------------------------------------------------- 1 | # `Keystore` 2 | - [1. Creating a Keystore](#creating) 3 | - [1.1 `create`](#create) 4 | 5 | ## 1. Creating a Keystore 6 | 7 | The `Keystore` is our gateway to accessing an Ethereum [`Wallet`](./wallet.md), which can be used to make transactions on the network. 8 | 9 | Sometimes, a user may not have an existing keystore, and will need to create a new one from scratch. To do this, we can use the `Keystore` object exported from a call to [`Web3`](./web3.md): 10 | 11 | ```javascript 12 | import { Web3 } from "web3-react-native"; 13 | 14 | (async () => { 15 | const { Keystore } = await Web3('https://ropsten.infura.io/v3/'); 16 | })(); 17 | ``` 18 | 19 | To create a `Keystore`, we need to specify a password. This can be whatever non-null, non-empty `String` you like, but the standard password allocation rules apply; they should be significantly complex to reduce the likelihood of theft. 20 | 21 | New keystores can be created using the `Keystore.create(password:String)` method: 22 | 23 | ```javascript 24 | import { Web3 } from "web3-react-native"; 25 | 26 | (async () => { 27 | const password = 'S3cr3tPassw0rd!'; 28 | const { Keystore } = await Web3('https://ropsten.infura.io/v3/'); 29 | const { ...keystoreJson } = await Keystore.create(password); 30 | })(); 31 | ``` 32 | 33 | In the example below, we show how a dynamically allocated `Keystore` can be used to generate a new `Wallet` object: 34 | 35 | ```javascript 36 | import { Web3 } from "web3-react-native"; 37 | 38 | (async () => { 39 | const password = 'S3cr3tPassw0rd!'; 40 | const { Keystore, Wallet } = await Web3('https://ropsten.infura.io/v3/'); 41 | const ks = await Keystore.create(password); 42 | // Here, we generate a new wallet using the generated keystore. 43 | const { address, sendFunds } = await Wallet.create(ks, password); 44 | })(); 45 | ``` 46 | 47 | For more information on making transactions, please head over to the `Wallet` [documentation](./wallet.md). 48 | 49 | ## 1.1 `create(password:String)` 50 | 51 | **`password:String`** 52 | 53 | The password to use when encrypting the keystore data. This should be significantly complex, such as the result of a call to [`uuidv4()`](https://www.npmjs.com/package/uuid). 54 | -------------------------------------------------------------------------------- /docs/wallet.md: -------------------------------------------------------------------------------- 1 | # `Wallet` 2 | - [1. Loading a Wallet](#loading-a-wallet) 3 | - [2. Using a Wallet](#using-a-wallet) 4 | - [2.1 `sendFunds`](#sending-funds) 5 | - [2.2 `{ ...extras }`](#wallet-extras) 6 | 7 | ## 1. Loading a Wallet 8 | 9 | A wallet is a public address which can be used to participate in ethereum transactions. You can use a wallet to both send and receive funds. Under the hood, a wallet represents your unique address on the ethereum network and the digital fingerprint which guarantees its authenticity. 10 | 11 | Wallets are created by calling `load()` on the `Wallet` object that is produced from a call to [`Web3(url)`](./web3.md). 12 | 13 | To load a wallet, you need to provide two required parameters: 14 | - The JSON keystore. 15 | - You can easily create and download a new keystore over at [MyEtherWallet](https://www.myetherwallet.com/create-wallet). Just be sure to specify you'd like to create one `By Keystore File`, and be sure to keep the password created for you in a safe place. 16 | - The keystore password. 17 | - This is the [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) which is used to unlock the keystore and grant access to the wallet and all of the funds it holds. Never share this with anybody! 18 | 19 | In the example below, we call the promisified function `load(keystore:Object, password:String)` on the `Wallet` object to unlock our ethereum wallet. 20 | 21 | ```javascript 22 | import React, { useEffect, useState } from "react"; 23 | import { Web3 } from "web3-react-native"; 24 | 25 | // You should consider safe handling of sensitive keystore information 26 | // such as serving it to the application via a https api. 27 | import keystore from "./keystore.json"; 28 | 29 | export default () => { 30 | const [wallet, setWallet] = useState(null); 31 | // When the component is mounted, attempt to load the ethereum wallet. 32 | useEffect( 33 | () => Web3('https://ropsten.infura.io/v3/') 34 | // XXX: Pass the keystore JSON. 35 | .then(({ Wallet }) => Wallet.load( 36 | keystore, 37 | "my-keystore-password", 38 | )) 39 | .then(setWallet) 40 | // XXX: If the password is wrong, or the keystore is malformed, 41 | // an Error will be thrown in the Promise chain. 42 | .catch(console.warn), 43 | [], 44 | ); 45 | }; 46 | ``` 47 | 48 | > You must consider using [environment variables](https://github.com/zetachang/react-native-dotenv) to safely manage your configuration. This will greatly reduce your risks of loss or misuse. 49 | 50 | ## 2. Using a Wallet 51 | 52 | The`Wallet` object returned from the call to [`Wallet.load()`](#loading-a-wallet) exposes all of the functionality to interact with the ethereum network. 53 | 54 | For demonstration, the `Wallet` object can be interacted with as follows: 55 | 56 | ```javascript 57 | (async () => { 58 | // XXX: Wallet operations can be accessed like this: 59 | const { sendFunds, ...extras } = await Wallet.load(keystore, password); 60 | })(); 61 | ``` 62 | 63 | In the following sections, we outline the usage of all properties of the `Wallet` object. 64 | 65 | ### 2.1 `sendFunds` 66 | 67 | `sendFunds` is a high-level function which can be used to easily send funds to another address on the ethereum network. 68 | 69 | In the following example, we show how to send funds from the wallet to another address on the [`ropsten`](https://ropsten.etherscan.io/) public test network, or "testnet". 70 | 71 | Your wallet will first need some ethereum to be able to make a transaction. You can have test ether sent to your wallet via the [Ropsten Faucet](https://faucet.ropsten.be/). Just specify your wallet's address (don't forget the `0x` hexadecimal prefix) to receive `1 ETH`. 72 | 73 | Creating a transaction takes the following form: 74 | 75 | ```javascript 76 | import { Web3 } from "web3-react-native"; 77 | import { Linking } from "react-native"; 78 | 79 | (async () => { 80 | const { Wallet } = await Web3('https://ropsten.infura.io/v3/'); 81 | const { sendFunds } = await Wallet.load(keystore, password); 82 | // XXX: You can view your transaction by navigating to: https://ropsten.etherscan.io/tx/ 83 | const { transactionHash } = await sendFunds( 84 | '0x19e03255f667bdfd50a32722df860b1eeaf4d635', // address of wallet you'd like to send to 85 | '1', // amount 86 | 'wei', // 1 wei = 10^-18 Ether 87 | ); 88 | // Finally, view your transaction! 89 | const url = `https://ropsten.etherscan.io/tx/${transactionHash}`; 90 | await Linking.canOpenURL(url) 91 | .then(canOpen => (!!canOpen) && Linking.openURL(url)); 92 | })(); 93 | ``` 94 | 95 | #### `sendFunds(url:String, toAddress:String, amount:String, units:String)` 96 | 97 | **`toAddress:String`** 98 | 99 | The wallet address where to send funds to. Previously, we used this [example address](https://github.com/web3j/sample-project-gradle/blob/5b935d42b0f52d97b72029881990aa60cd38a312/src/main/java/org/web3j/sample/Application.java#L76). 100 | 101 | **`amount:String`** 102 | 103 | The amount to send to the address. Although we're representing a numeric quantity, we use a `String` to avoid rounding errors which occur due to limits [floating point precision](https://docs.python.org/3/tutorial/floatingpoint.html). This way, you can be _exact_ about the amounts involved. 104 | 105 | **`units:String`** 106 | 107 | The units of the amount to send to the `toAddress`. This can be one of the following units: 108 | 109 | | Unit | Wei Value | Wei | 110 | |---------- |----------- |--------------------------- | 111 | | `"wei" ` | 1 wei | 1 | 112 | | `"kwei" ` | 1e3 wei | 1,000 | 113 | | `"mwei"` | 1e6 wei | 1,000,000 | 114 | | `"gwei" ` | 1e9 wei | 1,000,000,000 | 115 | | `"finney"` | 1e15 wei | 1,000,000,000,000,000 | 116 | | `"eth"` | 1e18 wei | 1,000,000,000,000,000,000 | 117 | 118 | ### 2.2 `{ ...extras }` 119 | 120 | In addition to functionality, a `Wallet` also defines useful properties. 121 | 122 | **`address:String`** 123 | 124 | The address of the `Wallet`. 125 | -------------------------------------------------------------------------------- /docs/web3.md: -------------------------------------------------------------------------------- 1 | # `Web3` 2 | - [1. Connecting to a Network](#connecting) 3 | - [1.1 `Web3`](#web3) 4 | 5 | ## 1. Connecting to a Network 6 | 7 | Every transaction you make using `Web3` is required to take place on a designated ethereum network. This is how addresses on the network can send funds to one-another. 8 | 9 | In the example below, we show how to initialize a connection. 10 | 11 | ```javascript 12 | import { Web3 } from "web3-react-native"; 13 | 14 | (async () => { 15 | await Web3('https://ropsten.infura.io/v3/'); 16 | })(); 17 | ``` 18 | 19 | The network `url` dictates where all of your transactions will take place. In this documentation, we'll frequently be using the [Ropsten](https://ropsten.etherscan.io/) test network, which ensures that all of the transactions we perform will be made using **test ether**. 20 | 21 | However, with a simple switch it's easy to start using the same code to make transactions using **real ether**, with real monetary value. 22 | 23 | In the example below, we demonstrate one way of how we could dynamically swap between production and test networks: 24 | 25 | ```javascript 26 | import { Web3 } from "web3-react-native"; 27 | 28 | (async () => { 29 | const test = 'https://ropsten.infura.io/v3/'; 30 | const production = ''; 31 | await Web3(__DEV__ ? test : production); 32 | })(); 33 | ``` 34 | 35 | > ⚠️ This kind of implementation is **not recommended**, because developers often switch between `development` and `production` bundler modes to test certain features and may not necessarily wish to use real currency. You should make ethereum network `url`s a function of [environment config](https://github.com/zetachang/react-native-dotenv) to prevent mistakes or misuse. You can find a demonstration of this in the [example application](../example/App.js). 36 | 37 | It is also possible to instantiate multiple simultaneous connections. These are guaranteed not to interfere with one-another: 38 | 39 | ```javascript 40 | import { Web3 } from "web3-react-native"; 41 | 42 | (async () => { 43 | const [...connections] = await Promise.all([ 44 | Web3('https://ropsten.infura.io/v3/'), 45 | Web3('https://ropsten.infura.io/v3/'), 46 | ]); 47 | })(); 48 | ``` 49 | 50 | ## 1.1 `web3(url:String)` 51 | 52 | **`url:String`** 53 | 54 | The address of the ethereum network you'd like to make the transaction. In the previous example, we use the Ropsten test network. The structure of this call allows the same [`Wallet`](./wallet.md) instance to be reused across different ethereum networks. 55 | 56 | A successful invocation of `Web3()` will resolve with a `Promise` which returns the functionality of `web3-react-native` scoped to the specified `url`. 57 | 58 | In the example below, we show how to access the [`Wallet`](./wallet.md) and [`Keystore`](./keystore.md) objects: 59 | 60 | ```javascript 61 | import { Web3 } from "web3-react-native"; 62 | 63 | (async () => { 64 | const { Wallet, Keystore } = await Web3('https://ropsten.infura.io/v3/'); 65 | })(); 66 | ``` 67 | -------------------------------------------------------------------------------- /example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /example/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 40 | module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 41 | 42 | suppress_type=$FlowIssue 43 | suppress_type=$FlowFixMe 44 | suppress_type=$FlowFixMeProps 45 | suppress_type=$FlowFixMeState 46 | 47 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 50 | 51 | [lints] 52 | sketchy-null-number=warn 53 | sketchy-null-mixed=warn 54 | sketchy-number=warn 55 | untyped-type-import=warn 56 | nonstrict-import=warn 57 | deprecated-type=warn 58 | unsafe-getters-setters=warn 59 | inexact-spread=warn 60 | unnecessary-invariant=warn 61 | signature-verification-failure=warn 62 | deprecated-utility=error 63 | 64 | [strict] 65 | deprecated-type 66 | nonstrict-import 67 | sketchy-null 68 | unclear-type 69 | unsafe-getters-setters 70 | untyped-import 71 | untyped-type-import 72 | 73 | [version] 74 | ^0.113.0 75 | -------------------------------------------------------------------------------- /example/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/Podfile.lock 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | !debug.keystore 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://docs.fastlane.tools/best-practices/source-control/ 51 | 52 | */fastlane/report.xml 53 | */fastlane/Preview.html 54 | */fastlane/screenshots 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # CocoaPods 60 | /ios/Pods/ 61 | 62 | # Config files 63 | .env 64 | -------------------------------------------------------------------------------- /example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | import 'react-native-gesture-handler'; 2 | 3 | import React from "react"; 4 | import { View, Image, StyleSheet, ScrollView, SafeAreaView, Dimensions } from "react-native"; 5 | import { Provider } from "react-redux"; 6 | import { NavigationContainer } from '@react-navigation/native'; 7 | 8 | import configureStore from "./src/configureStore"; 9 | import { Routes } from "./src/routes"; 10 | 11 | const store = configureStore(); 12 | 13 | const { width } = Dimensions.get('window'); 14 | 15 | export default ({ ...extraProps }) => { 16 | return ( 17 | 20 | 22 | 24 | 25 | 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | Before executing this example, you must create a `.env` file within this directory with the following contents: 3 | 4 | ``` 5 | URL=https://ropsten.infura.io/v3/ 6 | ``` 7 | 8 | The `URL` must be a [Ropsten](https://ropsten.etherscan.io/) test network API URL. 9 | 10 | You can create an API key for the Ropsten test network [here](https://ropsten.etherscan.io/apis). 11 | 12 | Once this is done, go ahead and execute `yarn android` or `yarn ios` to start experimenting. 13 | -------------------------------------------------------------------------------- /example/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /example/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.example", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.example", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" 3 | 4 | import com.android.build.OutputFile 5 | 6 | /** 7 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 8 | * and bundleReleaseJsAndAssets). 9 | * These basically call `react-native bundle` with the correct arguments during the Android build 10 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 11 | * bundle directly from the development server. Below you can see all the possible configurations 12 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 13 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 14 | * 15 | * project.ext.react = [ 16 | * // the name of the generated asset file containing your JS bundle 17 | * bundleAssetName: "index.android.bundle", 18 | * 19 | * // the entry file for bundle generation. If none specified and 20 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is 21 | * // default. Can be overridden with ENTRY_FILE environment variable. 22 | * entryFile: "index.android.js", 23 | * 24 | * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format 25 | * bundleCommand: "ram-bundle", 26 | * 27 | * // whether to bundle JS and assets in debug mode 28 | * bundleInDebug: false, 29 | * 30 | * // whether to bundle JS and assets in release mode 31 | * bundleInRelease: true, 32 | * 33 | * // whether to bundle JS and assets in another build variant (if configured). 34 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 35 | * // The configuration property can be in the following formats 36 | * // 'bundleIn${productFlavor}${buildType}' 37 | * // 'bundleIn${buildType}' 38 | * // bundleInFreeDebug: true, 39 | * // bundleInPaidRelease: true, 40 | * // bundleInBeta: true, 41 | * 42 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 43 | * // for example: to disable dev mode in the staging build type (if configured) 44 | * devDisabledInStaging: true, 45 | * // The configuration property can be in the following formats 46 | * // 'devDisabledIn${productFlavor}${buildType}' 47 | * // 'devDisabledIn${buildType}' 48 | * 49 | * // the root of your project, i.e. where "package.json" lives 50 | * root: "../../", 51 | * 52 | * // where to put the JS bundle asset in debug mode 53 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 54 | * 55 | * // where to put the JS bundle asset in release mode 56 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 57 | * 58 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 59 | * // require('./image.png')), in debug mode 60 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 61 | * 62 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 63 | * // require('./image.png')), in release mode 64 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 65 | * 66 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 67 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 68 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 69 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 70 | * // for example, you might want to remove it from here. 71 | * inputExcludes: ["android/**", "ios/**"], 72 | * 73 | * // override which node gets called and with what additional arguments 74 | * nodeExecutableAndArgs: ["node"], 75 | * 76 | * // supply additional arguments to the packager 77 | * extraPackagerArgs: [] 78 | * ] 79 | */ 80 | 81 | project.ext.react = [ 82 | enableHermes: false, // clean and rebuild if changing 83 | ] 84 | 85 | apply from: "../../node_modules/react-native/react.gradle" 86 | 87 | /** 88 | * Set this to true to create two separate APKs instead of one: 89 | * - An APK that only works on ARM devices 90 | * - An APK that only works on x86 devices 91 | * The advantage is the size of the APK is reduced by about 4MB. 92 | * Upload all the APKs to the Play Store and people will download 93 | * the correct one based on the CPU architecture of their device. 94 | */ 95 | def enableSeparateBuildPerCPUArchitecture = false 96 | 97 | /** 98 | * Run Proguard to shrink the Java bytecode in release builds. 99 | */ 100 | def enableProguardInReleaseBuilds = false 101 | 102 | /** 103 | * The preferred build flavor of JavaScriptCore. 104 | * 105 | * For example, to use the international variant, you can use: 106 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 107 | * 108 | * The international variant includes ICU i18n library and necessary data 109 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 110 | * give correct results when using with locales other than en-US. Note that 111 | * this variant is about 6MiB larger per architecture than default. 112 | */ 113 | def jscFlavor = 'org.webkit:android-jsc:+' 114 | 115 | /** 116 | * Whether to enable the Hermes VM. 117 | * 118 | * This should be set on project.ext.react and mirrored here. If it is not set 119 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 120 | * and the benefits of using Hermes will therefore be sharply reduced. 121 | */ 122 | def enableHermes = project.ext.react.get("enableHermes", false); 123 | 124 | android { 125 | compileSdkVersion rootProject.ext.compileSdkVersion 126 | 127 | compileOptions { 128 | sourceCompatibility JavaVersion.VERSION_1_8 129 | targetCompatibility JavaVersion.VERSION_1_8 130 | } 131 | 132 | defaultConfig { 133 | applicationId "com.example" 134 | minSdkVersion rootProject.ext.minSdkVersion 135 | targetSdkVersion rootProject.ext.targetSdkVersion 136 | versionCode 1 137 | versionName "1.0" 138 | multiDexEnabled true 139 | } 140 | splits { 141 | abi { 142 | reset() 143 | enable enableSeparateBuildPerCPUArchitecture 144 | universalApk false // If true, also generate a universal APK 145 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 146 | } 147 | } 148 | signingConfigs { 149 | debug { 150 | storeFile file('debug.keystore') 151 | storePassword 'android' 152 | keyAlias 'androiddebugkey' 153 | keyPassword 'android' 154 | } 155 | } 156 | buildTypes { 157 | debug { 158 | signingConfig signingConfigs.debug 159 | } 160 | release { 161 | // Caution! In production, you need to generate your own keystore file. 162 | // see https://facebook.github.io/react-native/docs/signed-apk-android. 163 | signingConfig signingConfigs.debug 164 | minifyEnabled enableProguardInReleaseBuilds 165 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 166 | } 167 | } 168 | 169 | packagingOptions { 170 | pickFirst "lib/armeabi-v7a/libc++_shared.so" 171 | pickFirst "lib/arm64-v8a/libc++_shared.so" 172 | pickFirst "lib/x86/libc++_shared.so" 173 | pickFirst "lib/x86_64/libc++_shared.so" 174 | } 175 | 176 | // applicationVariants are e.g. debug, release 177 | applicationVariants.all { variant -> 178 | variant.outputs.each { output -> 179 | // For each separate APK per architecture, set a unique version code as described here: 180 | // https://developer.android.com/studio/build/configure-apk-splits.html 181 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 182 | def abi = output.getFilter(OutputFile.ABI) 183 | if (abi != null) { // null for the universal-debug, universal-release variants 184 | output.versionCodeOverride = 185 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 186 | } 187 | 188 | } 189 | } 190 | } 191 | 192 | dependencies { 193 | implementation fileTree(dir: "libs", include: ["*.jar"]) 194 | //noinspection GradleDynamicVersion 195 | implementation "com.facebook.react:react-native:+" // From node_modules 196 | 197 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" 198 | 199 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { 200 | exclude group:'com.facebook.fbjni' 201 | } 202 | 203 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 204 | exclude group:'com.facebook.flipper' 205 | } 206 | 207 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { 208 | exclude group:'com.facebook.flipper' 209 | } 210 | 211 | if (enableHermes) { 212 | def hermesPath = "../../node_modules/hermes-engine/android/"; 213 | debugImplementation files(hermesPath + "hermes-debug.aar") 214 | releaseImplementation files(hermesPath + "hermes-release.aar") 215 | } else { 216 | implementation jscFlavor 217 | } 218 | } 219 | 220 | // Run this once to be able to run the application with BUCK 221 | // puts all compile dependencies into folder libs for BUCK to use 222 | task copyDownloadableDepsToLibs(type: Copy) { 223 | from configurations.compile 224 | into 'libs' 225 | } 226 | 227 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 228 | -------------------------------------------------------------------------------- /example/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/debug/java/com/example/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.example; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin; 21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | public class ReactNativeFlipper { 28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 29 | if (FlipperUtils.shouldEnableFlipper(context)) { 30 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 31 | 32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 33 | client.addPlugin(new ReactFlipperPlugin()); 34 | client.addPlugin(new DatabasesFlipperPlugin(context)); 35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 36 | client.addPlugin(CrashReporterPlugin.getInstance()); 37 | 38 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 39 | NetworkingModule.setCustomClientBuilder( 40 | new NetworkingModule.CustomClientBuilder() { 41 | @Override 42 | public void apply(OkHttpClient.Builder builder) { 43 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 44 | } 45 | }); 46 | client.addPlugin(networkFlipperPlugin); 47 | client.start(); 48 | 49 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 50 | // Hence we run if after all native modules have been initialized 51 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 52 | if (reactContext == null) { 53 | reactInstanceManager.addReactInstanceEventListener( 54 | new ReactInstanceManager.ReactInstanceEventListener() { 55 | @Override 56 | public void onReactContextInitialized(ReactContext reactContext) { 57 | reactInstanceManager.removeReactInstanceEventListener(this); 58 | reactContext.runOnNativeModulesQueueThread( 59 | new Runnable() { 60 | @Override 61 | public void run() { 62 | client.addPlugin(new FrescoFlipperPlugin()); 63 | } 64 | }); 65 | } 66 | }); 67 | } else { 68 | client.addPlugin(new FrescoFlipperPlugin()); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. This is used to schedule 9 | * rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "example"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactInstanceManager; 8 | import com.facebook.react.ReactNativeHost; 9 | import com.facebook.react.ReactPackage; 10 | import com.facebook.soloader.SoLoader; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.util.List; 13 | 14 | public class MainApplication extends Application implements ReactApplication { 15 | 16 | private final ReactNativeHost mReactNativeHost = 17 | new ReactNativeHost(this) { 18 | @Override 19 | public boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | @SuppressWarnings("UnnecessaryLocalVariable") 26 | List packages = new PackageList(this).getPackages(); 27 | // Packages that cannot be autolinked yet can be added manually here, for example: 28 | // packages.add(new MyReactNativePackage()); 29 | return packages; 30 | } 31 | 32 | @Override 33 | protected String getJSMainModuleName() { 34 | return "index"; 35 | } 36 | }; 37 | 38 | @Override 39 | public ReactNativeHost getReactNativeHost() { 40 | return mReactNativeHost; 41 | } 42 | 43 | @Override 44 | public void onCreate() { 45 | super.onCreate(); 46 | SoLoader.init(this, /* native exopackage */ false); 47 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 48 | } 49 | 50 | /** 51 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 52 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 53 | * 54 | * @param context 55 | * @param reactInstanceManager 56 | */ 57 | private static void initializeFlipper( 58 | Context context, ReactInstanceManager reactInstanceManager) { 59 | if (BuildConfig.DEBUG) { 60 | try { 61 | /* 62 | We use reflection here to pick up the class that initializes Flipper, 63 | since Flipper library is not available in release mode 64 | */ 65 | Class aClass = Class.forName("com.example.ReactNativeFlipper"); 66 | aClass 67 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 68 | .invoke(null, context, reactInstanceManager); 69 | } catch (ClassNotFoundException e) { 70 | e.printStackTrace(); 71 | } catch (NoSuchMethodException e) { 72 | e.printStackTrace(); 73 | } catch (IllegalAccessException e) { 74 | e.printStackTrace(); 75 | } catch (InvocationTargetException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | example 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "28.0.3" 6 | minSdkVersion = 16 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | } 10 | repositories { 11 | google() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle:3.5.2") 16 | 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | mavenLocal() 25 | maven { 26 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 27 | url("$rootDir/../node_modules/react-native/android") 28 | } 29 | maven { 30 | // Android JSC is installed from npm 31 | url("$rootDir/../node_modules/jsc-android/dist") 32 | } 33 | 34 | google() 35 | jcenter() 36 | maven { url 'https://www.jitpack.io' } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.33.1 29 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'example' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "displayName": "example" 4 | } 5 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset', 'module:react-native-dotenv'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | def add_flipper_pods!(versions = {}) 5 | versions['Flipper'] ||= '~> 0.33.1' 6 | versions['DoubleConversion'] ||= '1.1.7' 7 | versions['Flipper-Folly'] ||= '~> 2.1' 8 | versions['Flipper-Glog'] ||= '0.3.6' 9 | versions['Flipper-PeerTalk'] ||= '~> 0.0.4' 10 | versions['Flipper-RSocket'] ||= '~> 1.0' 11 | 12 | pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug' 13 | pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug' 14 | pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug' 15 | pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug' 16 | pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug' 17 | 18 | # List all transitive dependencies for FlipperKit pods 19 | # to avoid them being linked in Release builds 20 | pod 'Flipper', versions['Flipper'], :configuration => 'Debug' 21 | pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug' 22 | pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug' 23 | pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug' 24 | pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug' 25 | pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug' 26 | pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug' 27 | pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug' 28 | pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug' 29 | pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug' 30 | pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug' 31 | pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug' 32 | pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug' 33 | pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug' 34 | end 35 | 36 | # Post Install processing for Flipper 37 | def flipper_post_install(installer) 38 | installer.pods_project.targets.each do |target| 39 | if target.name == 'YogaKit' 40 | target.build_configurations.each do |config| 41 | config.build_settings['SWIFT_VERSION'] = '4.1' 42 | end 43 | end 44 | end 45 | end 46 | 47 | target 'example' do 48 | 49 | # Pods for example 50 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" 51 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" 52 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" 53 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" 54 | pod 'React', :path => '../node_modules/react-native/' 55 | pod 'React-Core', :path => '../node_modules/react-native/' 56 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' 57 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' 58 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 59 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 60 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 61 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 62 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 63 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 64 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 65 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 66 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 67 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' 68 | 69 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 70 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 71 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 72 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 73 | pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon" 74 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" 75 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true 76 | 77 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 78 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 79 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 80 | 81 | # web3-react-native 82 | pod 'secp256k1.c', '0.1.2', :modular_headers => true 83 | pod 'web3swift', '2.2.1', :modular_headers => true 84 | 85 | target 'exampleTests' do 86 | inherit! :complete 87 | # Pods for testing 88 | end 89 | 90 | use_native_modules! 91 | 92 | # Enables Flipper. 93 | # 94 | # Note that if you have use_frameworks! enabled, Flipper will not work and 95 | # you should disable these next few lines. 96 | add_flipper_pods! 97 | post_install do |installer| 98 | flipper_post_install(installer) 99 | end 100 | end 101 | 102 | target 'example-tvOS' do 103 | # Pods for example-tvOS 104 | 105 | target 'example-tvOSTests' do 106 | inherit! :search_paths 107 | # Pods for testing 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /example/ios/example-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /example/ios/example-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/example.xcodeproj/xcshareddata/xcschemes/example-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /example/ios/example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /example/ios/example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | 7 | #if DEBUG 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | 15 | static void InitializeFlipper(UIApplication *application) { 16 | FlipperClient *client = [FlipperClient sharedClient]; 17 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; 18 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; 19 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 20 | [client addPlugin:[FlipperKitReactPlugin new]]; 21 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 22 | [client start]; 23 | } 24 | #endif 25 | 26 | @implementation AppDelegate 27 | 28 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 29 | { 30 | #if DEBUG 31 | InitializeFlipper(application); 32 | #endif 33 | 34 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 35 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 36 | moduleName:@"example" 37 | initialProperties:nil]; 38 | 39 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 40 | 41 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 42 | UIViewController *rootViewController = [UIViewController new]; 43 | rootViewController.view = rootView; 44 | self.window.rootViewController = rootViewController; 45 | [self.window makeKeyAndVisible]; 46 | return YES; 47 | } 48 | 49 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 50 | { 51 | #if DEBUG 52 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 53 | #else 54 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 55 | #endif 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /example/ios/example/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UIAppFonts 43 | 44 | MaterialIcons.ttf 45 | Ionicons.ttf 46 | 47 | UILaunchStoryboardName 48 | LaunchScreen 49 | UIRequiredDeviceCapabilities 50 | 51 | armv7 52 | 53 | UISupportedInterfaceOrientations 54 | 55 | UIInterfaceOrientationPortrait 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | UIViewControllerBasedStatusBarAppearance 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /example/ios/example/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/ios/exampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/exampleTests/exampleTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface exampleTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation exampleTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 38 | if (level >= RCTLogLevelError) { 39 | redboxError = message; 40 | } 41 | }); 42 | #endif 43 | 44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | 48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 50 | return YES; 51 | } 52 | return NO; 53 | }]; 54 | } 55 | 56 | #ifdef DEBUG 57 | RCTSetLogFunction(RCTDefaultLogFunction); 58 | #endif 59 | 60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | // metro.config.js 2 | // 3 | // with multiple workarounds for this issue with symlinks: 4 | // https://github.com/facebook/metro/issues/1 5 | // 6 | // with thanks to @johnryan () 7 | // for the pointers to multiple workaround solutions here: 8 | // https://github.com/facebook/metro/issues/1#issuecomment-541642857 9 | // 10 | // see also this discussion: 11 | // https://github.com/brodybits/create-react-native-module/issues/232 12 | 13 | const path = require('path') 14 | 15 | module.exports = { 16 | // workaround for an issue with symlinks encountered starting with 17 | // metro@0.55 / React Native 0.61 18 | // (not needed with React Native 0.60 / metro@0.54) 19 | resolver: { 20 | extraNodeModules: new Proxy( 21 | {}, 22 | { get: (_, name) => path.resolve('.', 'node_modules', name) } 23 | ) 24 | }, 25 | 26 | // quick workaround for another issue with symlinks 27 | watchFolders: ['.', '..'] 28 | } 29 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "cd .. ; yarn ; yarn build ; rm -rf node_modules ; cd example ; rm -rf node_modules ; yarn ; cd android ; ./gradlew clean ; cd .. ; react-native run-android", 7 | "ios": "cd .. ; yarn ; yarn build ; rm -rf node_modules ; cd example ; rm -rf node_modules ; yarn ; cd ios ; rm Podfile.lock ; pod install ; cd .. ;react-native run-ios", 8 | "start": "react-native start", 9 | "test": "jest", 10 | "lint": "eslint ." 11 | }, 12 | "dependencies": { 13 | "@react-native-community/masked-view": "^0.1.10", 14 | "@react-navigation/compat": "^5.1.9", 15 | "@react-navigation/native": "^5.1.6", 16 | "@react-navigation/stack": "^5.2.13", 17 | "immutable": "^4.0.0-rc.12", 18 | "nanoid": "^3.1.3", 19 | "native-base": "^2.13.12", 20 | "react": "16.11.0", 21 | "react-native": "0.62.2", 22 | "react-native-dotenv": "^0.2.0", 23 | "react-native-gesture-handler": "^1.6.1", 24 | "react-native-reanimated": "^1.8.0", 25 | "react-native-safe-area-context": "^0.7.3", 26 | "react-native-screens": "^2.7.0", 27 | "react-native-snap-carousel": "^3.9.0", 28 | "react-native-vector-icons": "^6.6.0", 29 | "react-redux": "^7.2.0", 30 | "redux": "^4.0.5", 31 | "redux-thunk": "^2.3.0", 32 | "type-check": "^0.4.0", 33 | "web3-react-native": "link:../" 34 | }, 35 | "devDependencies": { 36 | "@babel/core": "^7.9.0", 37 | "@babel/runtime": "^7.9.2", 38 | "@react-native-community/eslint-config": "^1.1.0", 39 | "babel-jest": "^25.4.0", 40 | "eslint": "^6.8.0", 41 | "jest": "^25.4.0", 42 | "metro-react-native-babel-preset": "^0.59.0", 43 | "react-test-renderer": "16.11.0" 44 | }, 45 | "jest": { 46 | "preset": "react-native" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/src/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, combineReducers } from "redux"; 2 | import thunkMiddleware from "redux-thunk"; 3 | 4 | import { reducer as network } from "./network"; 5 | import { reducer as routes } from "./routes"; 6 | import { reducer as transaction } from "./transaction"; 7 | import { reducer as wallet } from "./wallet"; 8 | 9 | export default () => createStore( 10 | combineReducers( 11 | { 12 | network, 13 | routes, 14 | transaction, 15 | wallet, 16 | }, 17 | ), 18 | applyMiddleware(thunkMiddleware), 19 | ); 20 | -------------------------------------------------------------------------------- /example/src/dashboard/actionTypes.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/src/dashboard/actionTypes.js -------------------------------------------------------------------------------- /example/src/dashboard/actions.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/src/dashboard/actions.js -------------------------------------------------------------------------------- /example/src/dashboard/components/Dashboard.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { Dimensions, SafeAreaView, ScrollView, View, StyleSheet, Image } from "react-native"; 4 | 5 | import { Wallets, AddWalletButton } from "../../wallet"; 6 | import { Transactions } from "../../transaction"; 7 | 8 | const styles = StyleSheet.create({ 9 | flex: { flex: 1 }, 10 | spacing: { height: 50 }, 11 | logoContainer: { width: '100%', alignItems: 'center', justifyContent: 'center', marginBottom: 50 }, 12 | logo: { width: 212, height: 212 }, 13 | floating: { position: 'absolute', top: 50, right: 15 }, 14 | header: { paddingHorizontal: 15 }, 15 | }); 16 | 17 | const Dashboard = ({ ...extraProps }) => { 18 | const { width } = Dimensions.get('window'); 19 | return ( 20 | 23 | 28 | 31 | 34 | 36 | 37 | 38 | 41 | 45 | 46 | 49 | 50 | 53 | 54 | 55 | 56 | 57 | 60 | 61 | ); 62 | }; 63 | 64 | Dashboard.propTypes = {}; 65 | Dashboard.defaultProps = {}; 66 | 67 | export default Dashboard; 68 | -------------------------------------------------------------------------------- /example/src/dashboard/containers/Dashboard.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | 3 | import Dashboard from "../components/Dashboard"; 4 | 5 | const mapStateToProps = (state, ownProps) => ({}); 6 | const mapDispatchToProps = (dispatch, ownProps) => ({}); 7 | 8 | export default connect(mapStateToProps, mapDispatchToProps)(Dashboard); 9 | -------------------------------------------------------------------------------- /example/src/dashboard/index.js: -------------------------------------------------------------------------------- 1 | export { default as reducer } from "./reducer"; 2 | export { default as Dashboard } from "./containers/Dashboard"; 3 | -------------------------------------------------------------------------------- /example/src/dashboard/model.js: -------------------------------------------------------------------------------- 1 | import { Map } from "immutable"; 2 | 3 | export default Map(); 4 | -------------------------------------------------------------------------------- /example/src/dashboard/reducer.js: -------------------------------------------------------------------------------- 1 | import initialState from "./model"; 2 | 3 | export default (state = initialState, { type, ...extras }) => { 4 | switch (type) { 5 | default: 6 | return state; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /example/src/network/actionTypes.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/src/network/actionTypes.js -------------------------------------------------------------------------------- /example/src/network/actions.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/src/network/actions.js -------------------------------------------------------------------------------- /example/src/network/index.js: -------------------------------------------------------------------------------- 1 | export { default as reducer } from "./reducer"; 2 | -------------------------------------------------------------------------------- /example/src/network/model.js: -------------------------------------------------------------------------------- 1 | import { Map } from "immutable"; 2 | import { URL } from "react-native-dotenv"; 3 | 4 | export default Map( 5 | { 6 | url: URL, 7 | Web3: null, 8 | }, 9 | ); 10 | -------------------------------------------------------------------------------- /example/src/network/reducer.js: -------------------------------------------------------------------------------- 1 | import initialState from "./model"; 2 | 3 | export default (state = initialState, { type, ...extras }) => { 4 | switch (type) { 5 | default: 6 | return state; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /example/src/routes/actionTypes.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/src/routes/actionTypes.js -------------------------------------------------------------------------------- /example/src/routes/actions.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/example/src/routes/actions.js -------------------------------------------------------------------------------- /example/src/routes/components/Routes.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { createStackNavigator } from '@react-navigation/stack'; 4 | 5 | import { Dashboard } from "../../dashboard"; 6 | import { MakeTransaction } from "../../transaction"; 7 | 8 | const Stack = createStackNavigator(); 9 | 10 | const Routes = ({ ...extraProps }) => { 11 | return ( 12 | 13 | 21 | 28 | 29 | ); 30 | }; 31 | 32 | Routes.propTypes = {}; 33 | Routes.defaultProps = {}; 34 | 35 | export default Routes; 36 | -------------------------------------------------------------------------------- /example/src/routes/containers/Routes.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | 3 | import Routes from "../components/Routes"; 4 | 5 | const mapStateToProps = (state, ownProps) => ({}); 6 | const mapDispatchToProps = (dispatch, ownProps) => ({}); 7 | 8 | export default connect(mapStateToProps, mapDispatchToProps)(Routes); 9 | -------------------------------------------------------------------------------- /example/src/routes/index.js: -------------------------------------------------------------------------------- 1 | export { default as reducer } from "./reducer"; 2 | export { default as Routes } from "./containers/Routes"; 3 | -------------------------------------------------------------------------------- /example/src/routes/model.js: -------------------------------------------------------------------------------- 1 | import { Map } from "immutable"; 2 | 3 | export default Map(); 4 | -------------------------------------------------------------------------------- /example/src/routes/reducer.js: -------------------------------------------------------------------------------- 1 | import initialState from "./model"; 2 | 3 | export default (state = initialState, { type, ...extras }) => { 4 | switch (type) { 5 | default: 6 | return state; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /example/src/transaction/actionTypes.js: -------------------------------------------------------------------------------- 1 | export const RECEIVE_TRANSACTION = 'transaction/receive_transaction'; 2 | -------------------------------------------------------------------------------- /example/src/transaction/actions.js: -------------------------------------------------------------------------------- 1 | import { RECEIVE_TRANSACTION } from "./actionTypes"; 2 | 3 | export const receiveTransaction = transaction => ({ 4 | type: RECEIVE_TRANSACTION, 5 | transaction, 6 | }); 7 | -------------------------------------------------------------------------------- /example/src/transaction/components/MakeTransaction.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import PropTypes from "prop-types"; 3 | import { View, StyleSheet } from "react-native"; 4 | import { Button, Container, Header, Content, Form, Item, Input, Text, Label, Spinner, Picker } from 'native-base'; 5 | 6 | const styles = StyleSheet.create({ 7 | buttonContainer: { 8 | paddingHorizontal: 15, 9 | }, 10 | button: { 11 | alignItems: 'center', 12 | justifyContent: 'center', 13 | }, 14 | errorContainer: { 15 | margin: 15, 16 | }, 17 | error: { 18 | color: 'red', 19 | }, 20 | }); 21 | 22 | const MakeTransaction = ({ onPressSubmit, ...extraProps }) => { 23 | const [toAddress, setToAddress] = useState("0x19e03255f667bdfd50a32722df860b1eeaf4d635"); 24 | const [amount, setAmount] = useState("1"); 25 | const [units, setUnits] = useState("wei"); 26 | const [loading, setLoading] = useState(false); 27 | const [error, setError] = useState(null); 28 | return ( 29 | 30 | 31 |

32 | 33 | 41 | 43 | 51 | 54 | 69 |
70 | 73 | {(!!error) && ( 74 | 78 | )} 79 | 80 | 83 | 111 | 112 | 113 | 114 | ); 115 | }; 116 | 117 | MakeTransaction.propTypes = { 118 | onPressSubmit: PropTypes.func.isRequired, 119 | }; 120 | MakeTransaction.defaultProps = {}; 121 | 122 | export default MakeTransaction; 123 | -------------------------------------------------------------------------------- /example/src/transaction/components/Transaction.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { View, StyleSheet } from "react-native"; 4 | 5 | import { Icon, Button, Card, CardItem, Text, H2, H3, Body } from "native-base"; 6 | 7 | const styles = StyleSheet.create({ 8 | details: { flex: 1 }, 9 | buttons: { flexDirection: 'row' }, 10 | buttonContainer: { flex: 1, alignItems: 'center', justifyContent: 'center' }, 11 | }); 12 | 13 | const Transaction = ({ transaction, onRequestViewTransaction, ...extraProps }) => { 14 | return ( 15 | 17 | 21 | 24 | 25 | 26 | 29 | 30 | 34 | 35 | 37 | 40 | 43 | 52 | 53 | 54 | 55 | 56 | ); 57 | }; 58 | 59 | Transaction.propTypes = { 60 | onRequestViewTransaction: PropTypes.func.isRequired, 61 | transaction: PropTypes.shape({}).isRequired, 62 | }; 63 | 64 | Transaction.defaultProps = {}; 65 | 66 | export default Transaction; 67 | -------------------------------------------------------------------------------- /example/src/transaction/components/Transactions.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { View, StyleSheet } from "react-native"; 4 | import { H1, Text } from 'native-base'; 5 | import Carousel from 'react-native-snap-carousel'; 6 | 7 | import Transaction from "../containers/Transaction"; 8 | 9 | const styles = StyleSheet.create({ 10 | text: { marginLeft: 15, color: 'white', marginBottom: 15 }, 11 | }); 12 | 13 | const Transactions = ({ transactions, width, ...extraProps }) => { 14 | const numTransactions = transactions.toJS().length; 15 | const hasTransactions = numTransactions > 0; 16 | return ( 17 | 19 |

23 | {(!hasTransactions) && ( 24 | 28 | )} 29 | {(!!hasTransactions) && ( 30 | ( 33 | 37 | )} 38 | sliderWidth={width} 39 | itemWidth={width * 0.8} 40 | /> 41 | )} 42 | 43 | ); 44 | }; 45 | 46 | Transactions.propTypes = { 47 | width: PropTypes.number.isRequired, 48 | transactions: PropTypes.shape({}).isRequired, 49 | }; 50 | 51 | Transactions.defaultProps = {}; 52 | 53 | export default Transactions; 54 | 55 | -------------------------------------------------------------------------------- /example/src/transaction/containers/MakeTransaction.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | import { withNavigation } from "@react-navigation/compat"; 3 | 4 | import MakeTransaction from "../components/MakeTransaction"; 5 | 6 | import { receiveTransaction } from "../actions"; 7 | 8 | const onPressSubmit = (e, navigation, wallet, toAddress, amount, units) => (dispatch, getState) => Promise 9 | .resolve() 10 | .then( 11 | () => { 12 | console.warn('sending...'); 13 | const { sendFunds } = wallet; 14 | return sendFunds( 15 | toAddress, 16 | amount, 17 | units, 18 | ); 19 | }, 20 | ) 21 | .then(e => dispatch(receiveTransaction(e))) 22 | .then(() => navigation.goBack()); 23 | 24 | const mapStateToProps = (state, ownProps) => { 25 | const { route: { params } } = ownProps; 26 | return {}; 27 | }; 28 | 29 | const mapDispatchToProps = (dispatch, ownProps) => { 30 | const { navigation } = ownProps; 31 | const { route: { params: wallet } } = ownProps; 32 | return { 33 | onPressSubmit: (e, toAddress, amount, units) => dispatch( 34 | onPressSubmit(e, navigation, wallet, toAddress, amount, units), 35 | ), 36 | }; 37 | }; 38 | 39 | export default withNavigation(connect(mapStateToProps, mapDispatchToProps)(MakeTransaction)); 40 | -------------------------------------------------------------------------------- /example/src/transaction/containers/Transaction.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | import { typeCheck } from "type-check"; 3 | import { Linking } from "react-native"; 4 | 5 | import Transaction from "../components/Transaction"; 6 | 7 | const onRequestViewTransaction = (e, transaction) => (dispatch, getState) => Promise 8 | .resolve() 9 | .then( 10 | () => { 11 | if (typeCheck("{transactionHash:String,...}", transaction)) { 12 | const { transactionHash } = transaction; 13 | return Linking.openURL(`https://ropsten.etherscan.io/tx/${transactionHash}`); 14 | } 15 | return Promise.reject(new Error(`Expected transaction object, encountered ${transaction}.`)); 16 | }, 17 | ); 18 | 19 | const mapStateToProps = (state, ownProps) => ({}); 20 | 21 | const mapDispatchToProps = (dispatch, ownProps) => { 22 | const { transaction } = ownProps; 23 | return { 24 | onRequestViewTransaction: e => dispatch(onRequestViewTransaction(e, transaction)), 25 | }; 26 | }; 27 | 28 | export default connect(mapStateToProps, mapDispatchToProps)(Transaction); 29 | -------------------------------------------------------------------------------- /example/src/transaction/containers/Transactions.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | 3 | import Transactions from "../components/Transactions"; 4 | 5 | const mapStateToProps = (state, ownProps) => { 6 | return { 7 | transactions: state.transaction.get('transactions'), 8 | }; 9 | }; 10 | 11 | const mapDispatchToProps = (dispatch, ownProps) => ({}); 12 | 13 | export default connect(mapStateToProps, mapDispatchToProps)(Transactions); 14 | -------------------------------------------------------------------------------- /example/src/transaction/index.js: -------------------------------------------------------------------------------- 1 | export { default as reducer } from "./reducer"; 2 | export { default as Transactions } from "./containers/Transactions"; 3 | export { default as MakeTransaction } from "./containers/MakeTransaction"; 4 | -------------------------------------------------------------------------------- /example/src/transaction/model.js: -------------------------------------------------------------------------------- 1 | import { Map, List } from "immutable"; 2 | 3 | export default Map({ 4 | transactions: List(), 5 | }); 6 | -------------------------------------------------------------------------------- /example/src/transaction/reducer.js: -------------------------------------------------------------------------------- 1 | import initialState from "./model"; 2 | import { RECEIVE_TRANSACTION } from "./actionTypes"; 3 | 4 | export default (state = initialState, { type, ...extras }) => { 5 | switch (type) { 6 | case RECEIVE_TRANSACTION: 7 | const { transaction } = extras; 8 | return state 9 | .set( 10 | 'transactions', 11 | state 12 | .get('transactions') 13 | .push(transaction), 14 | ); 15 | default: 16 | return state; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /example/src/wallet/actionTypes.js: -------------------------------------------------------------------------------- 1 | export const RECEIVE_WALLET = 'wallet/receive_wallet'; 2 | -------------------------------------------------------------------------------- /example/src/wallet/actions.js: -------------------------------------------------------------------------------- 1 | import { Web3 } from 'web3-react-native'; 2 | 3 | import { nanoid } from 'nanoid/non-secure'; 4 | 5 | import { RECEIVE_WALLET } from "./actionTypes"; 6 | 7 | const receiveWallet = wallet => ({ 8 | type: RECEIVE_WALLET, 9 | wallet, 10 | }); 11 | 12 | export const createWallet = (password = nanoid()) => (dispatch, getState) => Promise 13 | .resolve() 14 | .then( 15 | () => { 16 | const { network } = getState(); 17 | const url = network.get('url'); 18 | return Web3(url); 19 | }, 20 | ) 21 | .then( 22 | ({ Keystore, Wallet }) => Keystore.create( 23 | password, 24 | ) 25 | .then( 26 | keystore => Wallet.load( 27 | keystore, 28 | password, 29 | ), 30 | ), 31 | ) 32 | .then( 33 | wallet => dispatch( 34 | receiveWallet(wallet), 35 | ), 36 | ); 37 | -------------------------------------------------------------------------------- /example/src/wallet/components/AddWalletButton.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { View, TouchableOpacity } from "react-native"; 4 | import MaterialIcon from "react-native-vector-icons/MaterialIcons"; 5 | 6 | const AddWalletButton = ({ style, onPress, ...extraProps }) => ( 7 | 10 | 13 | 18 | 19 | 20 | ); 21 | 22 | AddWalletButton.propTypes = { 23 | onPress: PropTypes.func.isRequired, 24 | }; 25 | 26 | AddWalletButton.defaultProps = {}; 27 | 28 | export default AddWalletButton; 29 | -------------------------------------------------------------------------------- /example/src/wallet/components/Wallet.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { View, StyleSheet } from "react-native"; 4 | 5 | import { Icon, Button, Card, CardItem, Text, H2, H3, Body } from "native-base"; 6 | 7 | const styles = StyleSheet.create({ 8 | details: { flex: 1 }, 9 | buttons: { flexDirection: 'row' }, 10 | buttonContainer: { flex: 1, alignItems: 'center', justifyContent: 'center' }, 11 | }); 12 | 13 | const Wallet = ({ wallet, onRequestAddFunds, onRequestMakeTransaction, ...extraProps }) => { 14 | return ( 15 | 17 | 21 | 24 | 25 | 26 | 29 | 30 | 34 | 35 | 37 | 40 | 43 | 52 | 53 | 56 | 65 | 66 | 67 | 68 | 69 | ); 70 | }; 71 | 72 | Wallet.propTypes = { 73 | wallet: PropTypes.shape({}).isRequired, 74 | onRequestAddFunds: PropTypes.func.isRequired, 75 | onRequestMakeTransaction: PropTypes.func.isRequired, 76 | }; 77 | 78 | Wallet.defaultProps = {}; 79 | 80 | export default Wallet; 81 | -------------------------------------------------------------------------------- /example/src/wallet/components/Wallets.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { View, StyleSheet } from "react-native"; 4 | import { H1, Text } from 'native-base'; 5 | import Carousel from 'react-native-snap-carousel'; 6 | 7 | import Wallet from "../containers/Wallet"; 8 | 9 | const styles = StyleSheet.create({ 10 | text: { marginLeft: 15, color: 'white', marginBottom: 15 }, 11 | }); 12 | 13 | const Wallets = ({ wallets, width, ...extraProps }) => { 14 | const numWallets = wallets.toJS().length; 15 | const hasWallets = numWallets > 0; 16 | return ( 17 | 19 |

23 | {(!hasWallets) && ( 24 | 28 | )} 29 | {(!!hasWallets) && ( 30 | ( 33 | 37 | )} 38 | sliderWidth={width} 39 | itemWidth={width * 0.8} 40 | /> 41 | )} 42 | 43 | ); 44 | }; 45 | 46 | Wallets.propTypes = { 47 | width: PropTypes.number.isRequired, 48 | wallets: PropTypes.shape({}).isRequired, 49 | }; 50 | 51 | Wallets.defaultProps = {}; 52 | 53 | export default Wallets; 54 | -------------------------------------------------------------------------------- /example/src/wallet/containers/AddWalletButton.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | 3 | import AddWalletButton from "../components/AddWalletButton"; 4 | 5 | import { createWallet } from "../actions"; 6 | 7 | const onPress = e => (dispatch, getState) => Promise 8 | .resolve() 9 | .then( 10 | () => dispatch(createWallet()), 11 | ); 12 | 13 | const mapStateToProps = (state, ownProps) => ({}); 14 | 15 | const mapDispatchToProps = (dispatch, ownProps) => ({ 16 | onPress: e => dispatch(onPress(e)), 17 | }); 18 | 19 | export default connect(mapStateToProps, mapDispatchToProps)(AddWalletButton); 20 | -------------------------------------------------------------------------------- /example/src/wallet/containers/Wallet.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | import { typeCheck } from "type-check"; 3 | import { Linking, Clipboard } from "react-native"; 4 | import { withNavigation } from '@react-navigation/compat'; 5 | 6 | import Wallet from "../components/Wallet"; 7 | 8 | const onRequestAddFunds = (e, wallet) => (dispatch, getState) => Promise 9 | .resolve() 10 | .then( 11 | () => { 12 | const { address } = wallet; 13 | if (typeCheck("String", address)) { 14 | Clipboard.setString(address); 15 | return Linking.openURL('https://faucet.ropsten.be/'); 16 | } 17 | return Promise.reject(new Error(`Expected String address, encountered ${address}.`)); 18 | }, 19 | ); 20 | 21 | const onRequestMakeTransaction = (e, navigation, wallet) => (dispatch, getState) => Promise 22 | .resolve() 23 | .then( 24 | () => navigation.navigate('makeTransaction', wallet), 25 | ); 26 | 27 | const mapStateToProps = (state, ownProps) => { 28 | return {}; 29 | }; 30 | 31 | const mapDispatchToProps = (dispatch, ownProps) => { 32 | const { wallet, navigation } = ownProps; 33 | return { 34 | onRequestAddFunds: e => dispatch(onRequestAddFunds(e, wallet)), 35 | onRequestMakeTransaction: e => dispatch(onRequestMakeTransaction(e, navigation, wallet)), 36 | }; 37 | }; 38 | 39 | export default withNavigation(connect(mapStateToProps, mapDispatchToProps)(Wallet)); 40 | -------------------------------------------------------------------------------- /example/src/wallet/containers/Wallets.js: -------------------------------------------------------------------------------- 1 | import { connect } from "react-redux"; 2 | 3 | import Wallets from "../components/Wallets"; 4 | 5 | const mapStateToProps = (state, ownProps) => { 6 | const { wallet } = state; 7 | const wallets = wallet.get('wallets'); 8 | return { 9 | wallets, 10 | }; 11 | }; 12 | 13 | const mapDispatchToProps = (dispatch, ownProps) => ({}); 14 | 15 | export default connect(mapStateToProps, mapDispatchToProps)(Wallets); 16 | -------------------------------------------------------------------------------- /example/src/wallet/index.js: -------------------------------------------------------------------------------- 1 | export { default as reducer } from "./reducer"; 2 | export { default as Wallets } from "./containers/Wallets"; 3 | export { default as AddWalletButton } from "./containers/AddWalletButton"; 4 | -------------------------------------------------------------------------------- /example/src/wallet/model.js: -------------------------------------------------------------------------------- 1 | import { Map, List } from "immutable"; 2 | 3 | export default Map( 4 | { 5 | wallets: List(), 6 | }, 7 | ); 8 | -------------------------------------------------------------------------------- /example/src/wallet/reducer.js: -------------------------------------------------------------------------------- 1 | import initialState from "./model"; 2 | 3 | import { RECEIVE_WALLET } from "./actionTypes"; 4 | 5 | export default (state = initialState, { type, ...extras }) => { 6 | switch (type) { 7 | case RECEIVE_WALLET: 8 | const { wallet } = extras; 9 | return state 10 | .set( 11 | 'wallets', 12 | state 13 | .get('wallets') 14 | .push(wallet), 15 | ); 16 | default: 17 | return state; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /ios/RNWeb3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RNWeb3.swift 3 | // RNWeb3 4 | // 5 | // Created by Alex Thomas on 23/04/2020. 6 | // Copyright © 2020 Facebook. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import web3swift 11 | 12 | enum Web3Error: Error { 13 | case runtimeError(String) 14 | } 15 | 16 | @objc(RNWeb3) 17 | class RNWeb3: NSObject { 18 | var creds : [String : EthereumKeystoreV3] = [:]; 19 | 20 | func unitsFor(_ units: String) throws -> web3swift.Web3.Utils.Units { 21 | switch (units) { 22 | case "WEI": return Web3.Utils.Units.wei; 23 | case "KWEI": return Web3.Utils.Units.Kwei; 24 | case "MWEI": return Web3.Utils.Units.Mwei; 25 | case "GWEI": return Web3.Utils.Units.Gwei; 26 | case "FINNEY": return Web3.Utils.Units.Finney; 27 | case "ETHER": return Web3.Utils.Units.eth; 28 | default: 29 | throw Web3Error.runtimeError("some message"); 30 | } 31 | } 32 | 33 | @objc 34 | func loadWallet( 35 | _ 36 | keystore: NSDictionary, 37 | password: NSString, 38 | resolve: RCTPromiseResolveBlock, 39 | reject: RCTPromiseRejectBlock 40 | ) -> Void { 41 | do { 42 | let data = try JSONSerialization.data(withJSONObject: keystore, options: []); 43 | let jsonStr = String(data: data, encoding: .ascii); 44 | let ks : EthereumKeystoreV3 = EthereumKeystoreV3.init(jsonStr!)!; 45 | let address : String = ks.getAddress()!.address; 46 | 47 | creds[address] = ks; 48 | resolve(["address": address]); 49 | } catch { 50 | reject("E_KEYSTORE", "\(error)", error); 51 | } 52 | } 53 | 54 | @objc 55 | func createKeystore( 56 | _ 57 | password: NSString, 58 | resolve: RCTPromiseResolveBlock, 59 | reject: RCTPromiseRejectBlock 60 | ) -> Void { 61 | do { 62 | let keystore = try! EthereumKeystoreV3(password: (password as String))! 63 | let data = try! keystore.serialize(); 64 | let d2 = (try! JSONSerialization.jsonObject(with: data!)); 65 | resolve(d2); 66 | } catch { 67 | reject("E_CREATEW", "\(error)", error); 68 | } 69 | } 70 | 71 | @objc 72 | func sendFunds( 73 | _ 74 | wallet: NSDictionary, 75 | url: NSString, 76 | password: NSString, 77 | toAddress: NSString, 78 | amount: NSString, 79 | units: NSString, 80 | resolve: RCTPromiseResolveBlock, 81 | reject: RCTPromiseRejectBlock 82 | ) -> Void { 83 | do { 84 | let address = (wallet["address"] as? String)!; 85 | 86 | let ks = creds[address]; 87 | let w = web3(provider: Web3HttpProvider(URL(string: (url as String))!)!); 88 | let keystoreManager = KeystoreManager([ks!]); 89 | w.addKeystoreManager(keystoreManager); 90 | 91 | let walletAddress = EthereumAddress(address)!; 92 | let at = EthereumAddress((toAddress as String)); 93 | 94 | let contract = w.contract(Web3.Utils.coldWalletABI, at: at, abiVersion: 2); 95 | let value = try Web3.Utils.parseToBigUInt((amount as String), units: self.unitsFor(units as String)); 96 | 97 | var options = TransactionOptions.defaultOptions; 98 | options.value = value; 99 | options.from = walletAddress; 100 | options.gasPrice = .automatic; 101 | options.gasLimit = .automatic; 102 | 103 | let tx = contract!.write("fallback", parameters: [AnyObject](), extraData: Data(), transactionOptions: options)! 104 | 105 | let res = try tx.send(password: (password as String)); 106 | 107 | resolve(["transactionHash": res.hash]); 108 | } catch { 109 | reject("E_SENDFUNDS", "\(error)", error); 110 | } 111 | } 112 | 113 | @objc 114 | static func requiresMainQueueSetup() -> Bool { 115 | return true 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /ios/Web3-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "React/RCTBridgeModule.h" 6 | -------------------------------------------------------------------------------- /ios/Web3.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface Web3 : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /ios/Web3.m: -------------------------------------------------------------------------------- 1 | #import "React/RCTBridgeModule.h" 2 | 3 | @interface RCT_EXTERN_REMAP_MODULE(Web3, RNWeb3, NSObject) 4 | 5 | RCT_EXTERN_METHOD( 6 | createKeystore: (NSString)password 7 | resolve: (RCTPromiseResolveBlock)resolve 8 | reject: (RCTPromiseRejectBlock)reject 9 | ) 10 | 11 | RCT_EXTERN_METHOD( 12 | loadWallet: (NSDictionary)keystore 13 | password: (NSString)password 14 | resolve: (RCTPromiseResolveBlock)resolve 15 | reject: (RCTPromiseRejectBlock)reject 16 | ) 17 | 18 | RCT_EXTERN_METHOD( 19 | sendFunds: (NSDictionary)wallet 20 | url: (NSString)url 21 | password: (NSString)password 22 | toAddress: (NSString)toAddress 23 | amount: (NSString)amount 24 | units: (NSString)units 25 | resolve: (RCTPromiseResolveBlock)resolve 26 | reject: (RCTPromiseRejectBlock)reject 27 | ) 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ios/Web3.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B3E7B58A1CC2AC0600A0062D /* Web3.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* Web3.m */; }; 11 | C05CDBF62451C732009E589F /* RNWeb3.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05CDBF52451C732009E589F /* RNWeb3.swift */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = "include/$(PRODUCT_NAME)"; 19 | dstSubfolderSpec = 16; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 0; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 134814201AA4EA6300B7C361 /* libWeb3.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWeb3.a; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | B3E7B5881CC2AC0600A0062D /* Web3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Web3.h; sourceTree = ""; }; 29 | B3E7B5891CC2AC0600A0062D /* Web3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Web3.m; sourceTree = ""; }; 30 | C05CDBF42451C731009E589F /* Web3-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Web3-Bridging-Header.h"; sourceTree = ""; }; 31 | C05CDBF52451C732009E589F /* RNWeb3.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNWeb3.swift; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 134814211AA4EA7D00B7C361 /* Products */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | 134814201AA4EA6300B7C361 /* libWeb3.a */, 49 | ); 50 | name = Products; 51 | sourceTree = ""; 52 | }; 53 | 58B511D21A9E6C8500147676 = { 54 | isa = PBXGroup; 55 | children = ( 56 | C05CDBF52451C732009E589F /* RNWeb3.swift */, 57 | B3E7B5881CC2AC0600A0062D /* Web3.h */, 58 | B3E7B5891CC2AC0600A0062D /* Web3.m */, 59 | 134814211AA4EA7D00B7C361 /* Products */, 60 | C05CDBF42451C731009E589F /* Web3-Bridging-Header.h */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | /* End PBXGroup section */ 65 | 66 | /* Begin PBXNativeTarget section */ 67 | 58B511DA1A9E6C8500147676 /* Web3 */ = { 68 | isa = PBXNativeTarget; 69 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "Web3" */; 70 | buildPhases = ( 71 | 58B511D71A9E6C8500147676 /* Sources */, 72 | 58B511D81A9E6C8500147676 /* Frameworks */, 73 | 58B511D91A9E6C8500147676 /* CopyFiles */, 74 | ); 75 | buildRules = ( 76 | ); 77 | dependencies = ( 78 | ); 79 | name = Web3; 80 | productName = RCTDataManager; 81 | productReference = 134814201AA4EA6300B7C361 /* libWeb3.a */; 82 | productType = "com.apple.product-type.library.static"; 83 | }; 84 | /* End PBXNativeTarget section */ 85 | 86 | /* Begin PBXProject section */ 87 | 58B511D31A9E6C8500147676 /* Project object */ = { 88 | isa = PBXProject; 89 | attributes = { 90 | LastUpgradeCheck = 0920; 91 | ORGANIZATIONNAME = Facebook; 92 | TargetAttributes = { 93 | 58B511DA1A9E6C8500147676 = { 94 | CreatedOnToolsVersion = 6.1.1; 95 | LastSwiftMigration = 1130; 96 | }; 97 | }; 98 | }; 99 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "Web3" */; 100 | compatibilityVersion = "Xcode 3.2"; 101 | developmentRegion = English; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | English, 105 | en, 106 | ); 107 | mainGroup = 58B511D21A9E6C8500147676; 108 | productRefGroup = 58B511D21A9E6C8500147676; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | 58B511DA1A9E6C8500147676 /* Web3 */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | 58B511D71A9E6C8500147676 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | C05CDBF62451C732009E589F /* RNWeb3.swift in Sources */, 123 | B3E7B58A1CC2AC0600A0062D /* Web3.m in Sources */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXSourcesBuildPhase section */ 128 | 129 | /* Begin XCBuildConfiguration section */ 130 | 58B511ED1A9E6C8500147676 /* Debug */ = { 131 | isa = XCBuildConfiguration; 132 | buildSettings = { 133 | ALWAYS_SEARCH_USER_PATHS = NO; 134 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 135 | CLANG_CXX_LIBRARY = "libc++"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 139 | CLANG_WARN_BOOL_CONVERSION = YES; 140 | CLANG_WARN_COMMA = YES; 141 | CLANG_WARN_CONSTANT_CONVERSION = YES; 142 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 143 | CLANG_WARN_EMPTY_BODY = YES; 144 | CLANG_WARN_ENUM_CONVERSION = YES; 145 | CLANG_WARN_INFINITE_RECURSION = YES; 146 | CLANG_WARN_INT_CONVERSION = YES; 147 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 148 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 149 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 150 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 151 | CLANG_WARN_STRICT_PROTOTYPES = YES; 152 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 153 | CLANG_WARN_UNREACHABLE_CODE = YES; 154 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 155 | COPY_PHASE_STRIP = NO; 156 | ENABLE_STRICT_OBJC_MSGSEND = YES; 157 | ENABLE_TESTABILITY = YES; 158 | GCC_C_LANGUAGE_STANDARD = gnu99; 159 | GCC_DYNAMIC_NO_PIC = NO; 160 | GCC_NO_COMMON_BLOCKS = YES; 161 | GCC_OPTIMIZATION_LEVEL = 0; 162 | GCC_PREPROCESSOR_DEFINITIONS = ( 163 | "DEBUG=1", 164 | "$(inherited)", 165 | ); 166 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 167 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 168 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 169 | GCC_WARN_UNDECLARED_SELECTOR = YES; 170 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 171 | GCC_WARN_UNUSED_FUNCTION = YES; 172 | GCC_WARN_UNUSED_VARIABLE = YES; 173 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 174 | MTL_ENABLE_DEBUG_INFO = YES; 175 | ONLY_ACTIVE_ARCH = YES; 176 | SDKROOT = iphoneos; 177 | }; 178 | name = Debug; 179 | }; 180 | 58B511EE1A9E6C8500147676 /* Release */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 185 | CLANG_CXX_LIBRARY = "libc++"; 186 | CLANG_ENABLE_MODULES = YES; 187 | CLANG_ENABLE_OBJC_ARC = YES; 188 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 189 | CLANG_WARN_BOOL_CONVERSION = YES; 190 | CLANG_WARN_COMMA = YES; 191 | CLANG_WARN_CONSTANT_CONVERSION = YES; 192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 193 | CLANG_WARN_EMPTY_BODY = YES; 194 | CLANG_WARN_ENUM_CONVERSION = YES; 195 | CLANG_WARN_INFINITE_RECURSION = YES; 196 | CLANG_WARN_INT_CONVERSION = YES; 197 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 198 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 199 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 200 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 201 | CLANG_WARN_STRICT_PROTOTYPES = YES; 202 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 203 | CLANG_WARN_UNREACHABLE_CODE = YES; 204 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 205 | COPY_PHASE_STRIP = YES; 206 | ENABLE_NS_ASSERTIONS = NO; 207 | ENABLE_STRICT_OBJC_MSGSEND = YES; 208 | GCC_C_LANGUAGE_STANDARD = gnu99; 209 | GCC_NO_COMMON_BLOCKS = YES; 210 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 211 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 212 | GCC_WARN_UNDECLARED_SELECTOR = YES; 213 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 214 | GCC_WARN_UNUSED_FUNCTION = YES; 215 | GCC_WARN_UNUSED_VARIABLE = YES; 216 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 217 | MTL_ENABLE_DEBUG_INFO = NO; 218 | SDKROOT = iphoneos; 219 | VALIDATE_PRODUCT = YES; 220 | }; 221 | name = Release; 222 | }; 223 | 58B511F01A9E6C8500147676 /* Debug */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | CLANG_ENABLE_MODULES = YES; 227 | HEADER_SEARCH_PATHS = ( 228 | "$(inherited)", 229 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 230 | "$(SRCROOT)/../../../React/**", 231 | "$(SRCROOT)/../../react-native/React/**", 232 | ); 233 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 234 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 235 | OTHER_LDFLAGS = "-ObjC"; 236 | PRODUCT_NAME = Web3; 237 | SKIP_INSTALL = YES; 238 | SWIFT_OBJC_BRIDGING_HEADER = "Web3-Bridging-Header.h"; 239 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 240 | SWIFT_VERSION = 5.0; 241 | }; 242 | name = Debug; 243 | }; 244 | 58B511F11A9E6C8500147676 /* Release */ = { 245 | isa = XCBuildConfiguration; 246 | buildSettings = { 247 | CLANG_ENABLE_MODULES = YES; 248 | HEADER_SEARCH_PATHS = ( 249 | "$(inherited)", 250 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 251 | "$(SRCROOT)/../../../React/**", 252 | "$(SRCROOT)/../../react-native/React/**", 253 | ); 254 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 255 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 256 | OTHER_LDFLAGS = "-ObjC"; 257 | PRODUCT_NAME = Web3; 258 | SKIP_INSTALL = YES; 259 | SWIFT_OBJC_BRIDGING_HEADER = "Web3-Bridging-Header.h"; 260 | SWIFT_VERSION = 5.0; 261 | }; 262 | name = Release; 263 | }; 264 | /* End XCBuildConfiguration section */ 265 | 266 | /* Begin XCConfigurationList section */ 267 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "Web3" */ = { 268 | isa = XCConfigurationList; 269 | buildConfigurations = ( 270 | 58B511ED1A9E6C8500147676 /* Debug */, 271 | 58B511EE1A9E6C8500147676 /* Release */, 272 | ); 273 | defaultConfigurationIsVisible = 0; 274 | defaultConfigurationName = Release; 275 | }; 276 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "Web3" */ = { 277 | isa = XCConfigurationList; 278 | buildConfigurations = ( 279 | 58B511F01A9E6C8500147676 /* Debug */, 280 | 58B511F11A9E6C8500147676 /* Release */, 281 | ); 282 | defaultConfigurationIsVisible = 0; 283 | defaultConfigurationName = Release; 284 | }; 285 | /* End XCConfigurationList section */ 286 | }; 287 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 288 | } 289 | -------------------------------------------------------------------------------- /ios/Web3.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Web3.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web3-react-native", 3 | "version": "0.1.1", 4 | "description": "⚛️ Web3 Native Modules for React Native.", 5 | "main": "dist", 6 | "scripts": { 7 | "build": "babel src --out-dir dist", 8 | "prettify": "yarn prettier --write \"**/*.js\"", 9 | "test": "jest" 10 | }, 11 | "private": false, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/cawfree/web3-react-native.git", 15 | "baseUrl": "https://github.com/cawfree/web3-react-native" 16 | }, 17 | "keywords": [ 18 | "react-native", 19 | "ethereum", 20 | "web3" 21 | ], 22 | "author": { 23 | "name": "Alex Thomas (@cawfree) ", 24 | "email": "hello@cawfree.com" 25 | }, 26 | "license": "MIT", 27 | "licenseFilename": "LICENSE", 28 | "readmeFilename": "README.md", 29 | "peerDependencies": { 30 | "react": "^16.8.1", 31 | "react-native": ">=0.60.0-rc.0 <1.0.x" 32 | }, 33 | "devDependencies": { 34 | "@babel/cli": "^7.8.4", 35 | "@babel/core": "^7.9.0", 36 | "@babel/polyfill": "^7.8.7", 37 | "@babel/preset-env": "^7.9.5", 38 | "@babel/preset-react": "^7.9.4", 39 | "husky": "^4.2.5", 40 | "jest": "^25.4.0", 41 | "prettier": "^2.0.5", 42 | "react": "^16.9.0", 43 | "react-native": "^0.61.5" 44 | }, 45 | "dependencies": { 46 | "type-check": "^0.4.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cawfree/web3-react-native/744e8528f3349c5265e2f4b24574e27fce77676b/public/logo.png -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { NativeModules, Platform } from 'react-native'; 2 | import { typeCheck } from 'type-check'; 3 | 4 | const { Web3: RNWeb3 } = NativeModules; 5 | 6 | const sanitizeKeystore = (k) => { 7 | if (typeCheck("Object", k)) { 8 | return k; 9 | } else if (typeCheck("String", k)) { 10 | return JSON.parse(k); 11 | } 12 | throw new Error(`Expected Object|String keystore, encountered ${keystore}.`); 13 | }; 14 | 15 | const sanitizePassword = (p) => { 16 | if (typeCheck("String", p) && p.length > 0) { 17 | return p; 18 | } 19 | throw new Error(`Expected non-null non-empty String password, encountered ${typeof p}.`); 20 | }; 21 | 22 | const ethUnits = Object.freeze( 23 | { 24 | wei: 'WEI', 25 | kwei: 'KWEI', 26 | mwei: 'MWEI', 27 | gwei: 'GWEI', 28 | finney: 'FINNEY', 29 | eth: 'ETHER', 30 | }, 31 | ); 32 | 33 | const sanitizeUnits = (units) => { 34 | const { [units]: u } = ethUnits; 35 | if (typeCheck("String", u)) { 36 | return u; 37 | } 38 | throw new Error(`Unsupported unit of eth, \"${units}\".`); 39 | }; 40 | 41 | const sanitizeUrl = (url) => { 42 | if (typeCheck("String", url) && url.length > 0) { 43 | return url; 44 | } 45 | throw new Error(`Expected non-null, non-empty String, encountered ${url}.`); 46 | }; 47 | 48 | const createWallet = ({ ...wallet }, url, password) => Object.freeze({ 49 | ...wallet, 50 | sendFunds: (toAddress, amount, units) => RNWeb3 51 | .sendFunds( 52 | wallet, 53 | url, 54 | password, 55 | toAddress, 56 | amount, 57 | sanitizeUnits(units), 58 | ), 59 | }); 60 | 61 | export const Web3 = url => Promise 62 | .resolve() 63 | // TODO: Could attempt to cache the associated HttpService here. 64 | .then(() => sanitizeUrl(url)) 65 | .then( 66 | url => Object.freeze( 67 | { 68 | Keystore: Object.freeze({ 69 | create: (p) => Promise 70 | .resolve([sanitizePassword(p)]) 71 | .then( 72 | ([p]) => RNWeb3.createKeystore( 73 | p, 74 | ), 75 | ), 76 | }), 77 | Wallet: Object.freeze({ 78 | load: (k, p) => Promise 79 | .resolve([sanitizeKeystore(k), sanitizePassword(p)]) 80 | .then( 81 | ([k, p]) => RNWeb3.loadWallet( 82 | k, 83 | p, 84 | ) 85 | .then(wallet => createWallet(wallet, url, p)), 86 | ), 87 | }) 88 | }, 89 | ), 90 | ); 91 | -------------------------------------------------------------------------------- /web3-react-native.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = "web3-react-native" 7 | s.version = package["version"] 8 | s.summary = package["description"] 9 | s.description = <<-DESC 10 | web3-react-native 11 | DESC 12 | s.homepage = "https://github.com/cawfree/web3-react-native" 13 | # brief license entry: 14 | s.license = "MIT" 15 | # optional - use expanded license entry instead: 16 | # s.license = { :type => "MIT", :file => "LICENSE" } 17 | s.authors = { "Alex Thomas (@cawfree) " => "hello@cawfree.com" } 18 | s.platforms = { :ios => "9.0" } 19 | s.source = { :git => "https://github.com/cawfree/web3-react-native.git", :tag => "#{s.version}" } 20 | 21 | s.source_files = "ios/**/*.{h,m,swift}" 22 | s.requires_arc = true 23 | 24 | s.dependency "React" 25 | 26 | # TODO: We need some way to import web3swift as a header without 27 | # triggering compilation errors. As a workaround, we 28 | # manually define these in the app's Podspec. 29 | 30 | s.dependency 'secp256k1.c', '0.1.2' 31 | s.dependency 'web3swift', '2.2.1' 32 | 33 | end 34 | 35 | --------------------------------------------------------------------------------