├── .buildkite
└── pipeline.yml
├── .gitignore
├── .scripts
└── artifactory.sh
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── one
│ │ └── block
│ │ └── androidexampleapp
│ │ ├── AbiEosInstrumentedTest.java
│ │ ├── EosioRpcProviderInstrumentedTest.java
│ │ ├── ExampleInstrumentedTest.java
│ │ └── TransactionInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── one
│ │ │ └── block
│ │ │ └── androidexampleapp
│ │ │ ├── CheckBalanceTask.java
│ │ │ ├── ErrorUtils.java
│ │ │ ├── MainActivity.java
│ │ │ └── TransactionTask.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── 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
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── one
│ └── block
│ └── androidexampleapp
│ └── ExampleUnitTest.java
├── build.gradle
├── eosio.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── img
├── Android_Robot.png
├── java-logo.png
└── screenshot.png
└── settings.gradle
/.buildkite/pipeline.yml:
--------------------------------------------------------------------------------
1 | steps:
2 |
3 | - command: |
4 | bash .scripts/artifactory.sh
5 | gradle build
6 | label: "Build Library"
7 | agents:
8 | - "queue=automation-android-builder-fleet"
9 |
10 | - command: |
11 | bash .scripts/artifactory.sh
12 | gradle test
13 | label: "Run Tests"
14 | agents:
15 | - "queue=automation-android-builder-fleet"
16 | - wait
17 |
18 | - command: "echo 'Success!!'"
19 | label: ":trophy: Success"
20 | agents:
21 | - "queue=automation-android-builder-fleet"
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 | .idea/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 | gradle.properties
24 |
25 | # Proguard folder generated by Eclipse
26 | proguard/
27 |
28 | # Log Files
29 | *.log
30 |
31 | # Android Studio Navigation editor temp files
32 | .navigation/
33 |
34 | # Android Studio captures folder
35 | captures/
36 |
37 | # Keystore files
38 | # Uncomment the following line if you do not want to check your keystore files in.
39 | #*.jks
40 |
41 | # External native build folder generated in Android Studio 2.2 and later
42 | .externalNativeBuild
43 |
44 | # Google Services (e.g. APIs or Firebase)
45 | google-services.json
46 |
47 | # Freeline
48 | freeline.py
49 | freeline/
50 | freeline_project_description.json
51 |
52 | # fastlane
53 | fastlane/report.xml
54 | fastlane/Preview.html
55 | fastlane/screenshots
56 | fastlane/test_output
57 | fastlane/readme.md
58 |
59 | # Implementtation
60 | *.iml
--------------------------------------------------------------------------------
/.scripts/artifactory.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -eu -o pipefail
3 |
4 | GRADLE_PROPERTIES="/var/lib/buildkite-agent/builds/automation-android-builder-fleet/EOSIO/eosio-java-android-example-app/gradle.properties"
5 | export GRADLE_PROPERTIES
6 | echo "Gradle Properties should exist at $GRADLE_PROPERTIES"
7 | echo "Gradle Properties does not exist"
8 | echo "Creating Gradle Properties file..."
9 | touch $GRADLE_PROPERTIES
10 | echo "Writing Secrets to gradle.properties..."
11 | echo "artifactory_username=$(cat /var/lib/buildkite-agent/.artifactory-username)" >> $GRADLE_PROPERTIES
12 | echo "artifactory_password=$(cat /var/lib/buildkite-agent/.artifactory-password)" >> $GRADLE_PROPERTIES
13 | #echo "artifactory_password=testest" >> $GRADLE_PROPERTIES
14 | echo "artifactory_contextURL=https://blockone.jfrog.io/blockone" >> $GRADLE_PROPERTIES
15 | echo "artifactory_repo=android-libs-dev" >> $GRADLE_PROPERTIES
16 | echo "artifactory_path_android_libraries=https://blockone.jfrog.io/blockone/android-libs" >> $GRADLE_PROPERTIES
17 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | jdk: oraclejdk8
3 | env:
4 | global:
5 | - ANDROID_API=28
6 | - EMULATOR_API=28
7 | - ANDROID_BUILD_TOOLS=28.0.3
8 | - ABI=x86_64
9 | - EMU_FLAVOR=default # use google_apis flavor if no default flavor emulator
10 | - ADB_INSTALL_TIMEOUT=10 # minutes
11 | - ANDROID_HOME=/usr/local/android-sdk
12 | - TOOLS=${ANDROID_HOME}/tools
13 | - PATH=${ANDROID_HOME}:${ANDROID_HOME}/emulator:${TOOLS}:${TOOLS}/bin:${ANDROID_HOME}/platform-tools:${PATH}
14 | - VERACODE_APP_NAME=eosio-java-android-example-app
15 | dist: trusty
16 | android:
17 | components:
18 | - tools
19 | - extra-google-google_play_services
20 | - extra-google-m2repository
21 | - extra-android-m2repository
22 |
23 | licenses:
24 | - 'android-sdk-preview-license-.+'
25 | - 'android-sdk-license-.+'
26 | - 'google-gdk-license-.+'
27 |
28 | install:
29 | - touch $HOME/.android/repositories.cfg
30 | - yes | sdkmanager "platform-tools" >/dev/null
31 | - yes | sdkmanager "build-tools;$ANDROID_BUILD_TOOLS" >/dev/null
32 | - yes | sdkmanager "tools" >/dev/null
33 | - yes | sdkmanager "platforms;android-$ANDROID_API" >/dev/null
34 | - yes | sdkmanager "platforms;android-$EMULATOR_API" >/dev/null #for matrix builds, we want to also install the matrix version.
35 | - yes | sdkmanager "system-images;android-$EMULATOR_API;$EMU_FLAVOR;$ABI" >/dev/null
36 |
37 |
38 | before_cache:
39 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
40 | cache:
41 | directories:
42 | - $HOME/.gradle/caches/
43 | - $HOME/.gradle/wrapper/
44 | - $HOME/.android/build-cache
45 |
46 | before_script:
47 | - echo no | $ANDROID_HOME/tools/bin/avdmanager create avd --force -n test -k "system-images;android-$EMULATOR_API;$EMU_FLAVOR;$ABI" -c 10M
48 | - emulator -verbose -avd test -no-accel -no-snapshot -no-window $AUDIO -camera-back none -camera-front none -selinux permissive -qemu -m 2048 &
49 | - android-wait-for-emulator
50 | - adb shell input keyevent 82 &
51 | script:
52 | - "./gradlew clean build --stacktrace"
53 | - "./gradlew clean build connectedCheck --stacktrace"
54 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to EOSIO SDK for Java: Android Example App
2 |
3 | Interested in contributing? That's awesome! Here are some guidelines to get started quickly and easily:
4 |
5 | - [Reporting An Issue](#reporting-an-issue)
6 | - [Bug Reports](#bug-reports)
7 | - [Feature Requests](#feature-requests)
8 | - [Change Requests](#change-requests)
9 | - [Working on Android Example App](#working-on-android-example-app)
10 | - [Feature Branches](#feature-branches)
11 | - [Submitting Pull Requests](#submitting-pull-requests)
12 | - [Testing and Quality Assurance](#testing-and-quality-assurance)
13 | - [Conduct](#conduct)
14 | - [Contributor License & Acknowledgments](#contributor-license--acknowledgments)
15 | - [References](#references)
16 |
17 | ## Reporting An Issue
18 |
19 | If you're about to raise an issue because you think you've found a problem with Android Example App, or you'd like to make a request for a new feature in the codebase, or any other reason… please read this first.
20 |
21 | The GitHub issue tracker is the preferred channel for [bug reports](#bug-reports), [feature requests](#feature-requests), and [submitting pull requests](#submitting-pull-requests), but please respect the following restrictions:
22 |
23 | * Please **search for existing issues**. Help us keep duplicate issues to a minimum by checking to see if someone has already reported your problem or requested your idea.
24 |
25 | * Please **be civil**. Keep the discussion on topic and respect the opinions of others. See also our [Contributor Code of Conduct](#conduct).
26 |
27 | ### Bug Reports
28 |
29 | A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you!
30 |
31 | Guidelines for bug reports:
32 |
33 | 1. **Use the GitHub issue search** — check if the issue has already been
34 | reported.
35 |
36 | 1. **Check if the issue has been fixed** — look for [closed issues in the
37 | current milestone](/../../issues?q=is%3Aissue+is%3Aclosed) or try to reproduce it
38 | using the latest `develop` branch.
39 |
40 | A good bug report shouldn't leave others needing to chase you up for more information. Be sure to include the details of your environment and relevant tests that demonstrate the failure.
41 |
42 | [Report a bug](/../../issues/new?title=Bug%3A)
43 |
44 | ### Feature Requests
45 |
46 | Feature requests are welcome. Before you submit one be sure to have:
47 |
48 | 1. **Use the GitHub search** and check the feature hasn't already been requested.
49 | 1. Take a moment to think about whether your idea fits with the scope and aims of the project.
50 | 1. Remember, it's up to *you* to make a strong case to convince the project's leaders of the merits of this feature. Please provide as much detail and context as possible, this means explaining the use case and why it is likely to be common.
51 |
52 | ### Change Requests
53 |
54 | Change requests cover both architectural and functional changes to how Android Example App works. If you have an idea for a new or different dependency, a refactor, or an improvement to a feature, etc - please be sure to:
55 |
56 | 1. **Use the GitHub search** and check someone else didn't get there first
57 | 1. Take a moment to think about the best way to make a case for, and explain what you're thinking. Are you sure this shouldn't really be
58 | a [bug report](#bug-reports) or a [feature request](#feature-requests)? Is it really one idea or is it many? What's the context? What problem are you solving? Why is what you are suggesting better than what's already there?
59 |
60 | ## Working on Android Example App
61 |
62 | Code contributions are welcome and encouraged! If you are looking for a good place to start, check out the [good first issue](/../../labels/good%20first%20issue) label in GitHub issues.
63 |
64 | Also, please follow these guidelines when submitting code:
65 |
66 | ### Feature Branches
67 |
68 | To get it out of the way:
69 |
70 | - **[develop](/../../tree/develop)** is the development branch. All work on the next release happens here so you should generally branch off `develop`. Do **NOT** use this branch for a production site.
71 | - **[master](/../../tree/master)** contains the latest release of Android Example App}. This branch may be used in production. Do **NOT** use this branch to work on Android Example App's source.
72 |
73 | ### Submitting Pull Requests
74 |
75 | Pull requests are awesome. If you're looking to raise a PR for something which doesn't have an open issue, please think carefully about [raising an issue](#reporting-an-issue) which your PR can close, especially if you're fixing a bug. This makes it more likely that there will be enough information available for your PR to be properly tested and merged.
76 |
77 | ### Testing and Quality Assurance
78 |
79 | Never underestimate just how useful quality assurance is. If you're looking to get involved with the code base and don't know where to start, checking out and testing a pull request is one of the most useful things you could do.
80 |
81 | Essentially, [check out the latest develop branch](#working-on-android-example-app), take it for a spin, and if you find anything odd, please follow the [bug report guidelines](#bug-reports) and let us know!
82 |
83 | ## Conduct
84 |
85 | While contributing, please be respectful and constructive, so that participation in our project is a positive experience for everyone.
86 |
87 | Examples of behavior that contributes to creating a positive environment include:
88 | - Using welcoming and inclusive language
89 | - Being respectful of differing viewpoints and experiences
90 | - Gracefully accepting constructive criticism
91 | - Focusing on what is best for the community
92 | - Showing empathy towards other community members
93 |
94 | Examples of unacceptable behavior include:
95 | - The use of sexualized language or imagery and unwelcome sexual attention or advances
96 | - Trolling, insulting/derogatory comments, and personal or political attacks
97 | - Public or private harassment
98 | - Publishing others’ private information, such as a physical or electronic address, without explicit permission
99 | - Other conduct which could reasonably be considered inappropriate in a professional setting
100 |
101 | ## Contributor License & Acknowledgments
102 |
103 | Whenever you make a contribution to this project, you license your contribution under the same terms as set out in LICENSE, and you represent and warrant that you have the right to license your contribution under those terms. Whenever you make a contribution to this project, you also certify in the terms of the Developer’s Certificate of Origin set out below:
104 |
105 | ```
106 | Developer Certificate of Origin
107 | Version 1.1
108 |
109 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
110 | 1 Letterman Drive
111 | Suite D4700
112 | San Francisco, CA, 94129
113 |
114 | Everyone is permitted to copy and distribute verbatim copies of this
115 | license document, but changing it is not allowed.
116 |
117 |
118 | Developer's Certificate of Origin 1.1
119 |
120 | By making a contribution to this project, I certify that:
121 |
122 | (a) The contribution was created in whole or in part by me and I
123 | have the right to submit it under the open source license
124 | indicated in the file; or
125 |
126 | (b) The contribution is based upon previous work that, to the best
127 | of my knowledge, is covered under an appropriate open source
128 | license and I have the right under that license to submit that
129 | work with modifications, whether created in whole or in part
130 | by me, under the same open source license (unless I am
131 | permitted to submit under a different license), as indicated
132 | in the file; or
133 |
134 | (c) The contribution was provided directly to me by some other
135 | person who certified (a), (b) or (c) and I have not modified
136 | it.
137 |
138 | (d) I understand and agree that this project and the contribution
139 | are public and that a record of the contribution (including all
140 | personal information I submit with it, including my sign-off) is
141 | maintained indefinitely and may be redistributed consistent with
142 | this project or the open source license(s) involved.
143 | ```
144 |
145 | ## References
146 |
147 | * Overall CONTRIB adapted from https://github.com/mathjax/MathJax/blob/master/CONTRIBUTING.md
148 | * Conduct section adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
149 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017-2019 block.one and its contributors. All rights reserved.
2 |
3 | The MIT License
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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | # EOSIO SDK for Java: Android Example App
3 | [](/./LICENSE)
4 | 
5 | 
6 |
7 | The EOSIO SDK for Java: Android Example App is a simple application demonstrating how to integrate with EOSIO-based blockchains using [EOSIO SDK for Java](https://github.com/EOSIO/eosio-java). The application does two things: fetches your account token balance and pushes a transfer action.
8 |
9 | *All product and company names are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.*
10 |
11 | *The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.*
12 |
13 |
14 |
15 |
16 |
17 | ## Contents
18 |
19 | - [Requirements](#requirements)
20 | - [Installation](#installation)
21 | - [About the App](#about-the-app)
22 | - [How to Transact](#how-to-transact)
23 | - [Want to Help?](#want-to-help)
24 | - [License & Legal](#license)
25 |
26 | ## Requirements
27 |
28 | * Android SDK 6.0+
29 | * Android Studio 3.0+
30 | * JDK 1.7
31 |
32 | ## Installation
33 |
34 | To get the example application up and running:
35 |
36 | 1. Clone this repo: `git clone https://github.com/EOSIO/eosio-java-android-example-app.git`
37 | 1. Open the project with Android Studio.
38 | 1. Modify `eosio.properties` file:
39 |
40 | ```java
41 | node_url=[your node endpoint URL] //mandatory
42 | from_account=[your account name] //optional
43 | to_account=[receiver account] //optional
44 | from_account_private_key=[your private key] //optional
45 | amount=[amount to transfer] //optional; e.g., 1.1234 EOS
46 | memo=[transfer memo] //optional
47 | private_keys=[for multiple key tests in instrumentation test] //optional
48 | ```
49 |
50 | `from_account`, `to_account`, `from_account_private_key`, `amount`, `memo` and `private_keys` are optional convenience properties which will prefill the app's form. `node_url` is required.
51 |
52 | 1. Run the app.
53 |
54 | ## About the App
55 |
56 | The app demonstrates how to:
57 | - use the [Java RPC Provider implementation](https://github.com/EOSIO/eosio-java-rpc-provider) to query the chain for an account's token balance,
58 | - get a new transaction from [`TransactionSession`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionSession.java),
59 | - create an action and add it to a transaction,
60 | - and sign and broadcast the transaction.
61 |
62 | To do this we are using a few libraries and providers, in concert:
63 |
64 | * [EOSIO SDK for Java](https://github.com/EOSIO/eosio-java): The core EOSIO SDK for Java library
65 | * [Java RPC Provider](https://github.com/EOSIO/eosio-java-rpc-provider): An RPC provider implementation for Java (including Android)
66 | * [ABIEOS Serialization Provider for Android](https://github.com/EOSIO/eosio-java-android-abieos-serialization-provider): A pluggable serialization provider for EOSIO SDK for Java using ABIEOS (for transaction and action conversion between JSON and binary data representations)
67 | * [Softkey Signature Provider](https://github.com/EOSIO/eosio-java-softkey-signature-provider): An example pluggable signature provider for EOSIO SDK for Java for signing transactions using in-memory keys (not for production use)
68 |
69 | **WARNING**: [Android 9 disables clear text traffic support by default](https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted) so `android:usesCleartextTraffic` setting in [AndroidManifest.xml](https://github.com/EOSIO/eosio-java-android-example-app/blob/master/app/src/main/AndroidManifest.xml) is used to enable/disable the support depending on the build variant you use.
70 |
71 | ## How to Transact
72 |
73 | [`TransactionTask.java`](app/src/main/java/one/block/androidexampleapp/TransactionTask.java) contains basic sample code for constructing, signing and broadcasting transactions using the `eosiojava` libraries.
74 |
75 | ### Set Up Your TransactionSession
76 |
77 | First, set up your [`TransactionSession`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionSession.java). This is your factory for creating new transactions:
78 |
79 | 1. Create an instance of the [`AbiEosSerializationProviderImpl`](https://github.com/EOSIO/eosio-java-android-abieos-serialization-provider/blob/develop/eosiojavaabieos/src/main/java/one/block/eosiojavaabieosserializationprovider/AbiEosSerializationProviderImpl.java) serialization provider from the [`eosiojavaandroidabieosserializationprovider`](https://github.com/EOSIO/eosio-java-android-abieos-serialization-provider) library.
80 | 1. Create an instance of the [`EosioJavaRpcProviderImpl`](https://github.com/EOSIO/eosio-java-rpc-provider/blob/master/eosiojavarpcprovider/src/main/java/one/block/eosiojavarpcprovider/implementations/EosioJavaRpcProviderImpl.java) RPC provider with an input string pointing to a nodeos RPC endpoint. You can also use `EosioJavaRpcProviderImpl(String, Boolean)` constructor to enable network debug log.
81 | 1. Create an instance of the [`ABIProviderImpl`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/implementations/ABIProviderImpl.java) ABI provider, instantiating it with the RPC and serialization provider instances.
82 | 1. Create an instance of the [` SoftKeySignatureProviderImpl`](https://github.com/EOSIO/eosio-java-softkey-signature-provider/blob/master/eosiojavasoftkeysignatureprovider/src/main/java/one/block/eosiosoftkeysignatureprovider/SoftKeySignatureProviderImpl.java) signature provider. (This particular implementation is not recommended for production use due to its simplistic management of private keys).
83 | - Import an EOS private key associated with the sender's account.
84 | 1. Create an instance of [`TransactionSession`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionSession.java), which is used for spawning [`TransactionProcessor`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java)s.
85 |
86 | ### Create, Sign and Broadcast Transactions
87 |
88 | Now you're ready to create transactions using your `TransactionSession`:
89 |
90 | 1. Create an instance of [`TransactionProcessor`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java) from the [`TransactionSession`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionSession.java) instance above by calling ` TransactionSession#getTransactionProcessor()` or `TransactionSession#getTransactionProcessor(Transaction)`.
91 | 1. Call `TransactionProcessor#prepare(List)` with a list of Actions. The method will serialize the actions, which can always be queried with `Transaction#getActions()`. The transaction now is ready to be signed and broadcast.
92 | 1. Call `TransactionProcessor#signAndBroadcast()` to sign the transaction inside [`TransactionProcessor`](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java) and broadcast it.
93 |
94 | For a more comprehensive list of available provider implementations, see [`EOSIO SDK for Java - Provider Interface Architecture`](https://github.com/EOSIO/eosio-java/tree/master#provider-interface-architecture).
95 |
96 | For more details about the complete workflow of EOSIO SDK for Java, see [`EOSIO SDK for Java - Complete workflow`](https://github.com/EOSIO/eosio-java/tree/master/documents/complete_workflow.pdf).
97 |
98 | An overview of the error model used in this library can be found in the [`EOSIO SDK for Java - Error Model`](https://github.com/EOSIO/eosio-java/tree/master/documents/error_model.pdf)
99 |
100 | ## Want to help?
101 |
102 | Interested in improving the example application? That's awesome! Here are some [Contribution Guidelines](./CONTRIBUTING.md) and the [Code of Conduct](./CONTRIBUTING.md#conduct).
103 |
104 | If you'd like to contribute to the EOSIO SDK for Java libraries themselves, please see the contribution guidelines on those individual repos.
105 |
106 | ## License
107 | [MIT licensed](./LICENSE)
108 |
109 | ## Important
110 |
111 | See LICENSE for copyright and license terms. Block.one makes its contribution on a voluntary basis as a member of the EOSIO community and is not responsible for ensuring the overall performance of the software or any related applications. We make no representation, warranty, guarantee or undertaking in respect of the software or any related documentation, whether expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall we be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or documentation or the use or other dealings in the software or documentation. Any test results or performance figures are indicative and will not reflect performance under all conditions. Any reference to any third party or third-party product, service or other resource is not an endorsement or recommendation by Block.one. We are not responsible, and disclaim any and all responsibility and liability, for your use of or reliance on any of these resources. Third-party resources may be updated, changed or terminated at any time, so the information here may be out of date or inaccurate. Any person using or offering this software in connection with providing software, goods or services to third parties shall advise such third parties of these license terms, disclaimers and exclusions of liability. Block.one, EOSIO, EOSIO Labs, EOS, the heptahedron and associated logos are trademarks of Block.one.
112 |
113 | Wallets and related components are complex software that require the highest levels of security. If incorrectly built or used, they may compromise users’ private keys and digital assets. Wallet applications and related components should undergo thorough security evaluations before being used. Only experienced developers should work with this software.
114 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 |
4 | android {
5 | compileSdkVersion 28
6 | defaultConfig {
7 | applicationId "one.block.androidexampleapp"
8 | minSdkVersion 23
9 | targetSdkVersion 28
10 | versionCode 1
11 | versionName "1.0.0"
12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 | }
14 |
15 | def Properties properties = new Properties()
16 | properties.load(project.rootProject.file("eosio.properties").newDataInputStream())
17 |
18 | buildTypes {
19 | debug {
20 | resValue "string", "node_url", properties.getProperty("node_url", "")
21 | resValue "string", "from_account", properties.getProperty("from_account", "")
22 | resValue "string", "to_account", properties.getProperty("to_account", "")
23 | resValue "string", "from_account_private_key", properties.getProperty("from_account_private_key", "")
24 | resValue "string", "amount", properties.getProperty("amount", "")
25 | resValue "string", "memo", properties.getProperty("memo", "")
26 | resValue "string", "private_keys", properties.getProperty("private_keys", "")
27 |
28 | manifestPlaceholders = [usesCleartextTraffic:"true"]
29 | }
30 | release {
31 | resValue "string", "node_url", properties.getProperty("node_url", "")
32 | resValue "string", "from_account", properties.getProperty("from_account", "")
33 | resValue "string", "to_account", properties.getProperty("to_account", "")
34 | resValue "string", "from_account_private_key", properties.getProperty("from_account_private_key", "")
35 | resValue "string", "amount", properties.getProperty("amount", "")
36 | resValue "string", "memo", properties.getProperty("memo", "")
37 | resValue "string", "private_keys", properties.getProperty("private_keys", "")
38 |
39 | manifestPlaceholders = [usesCleartextTraffic:"false"]
40 |
41 | minifyEnabled false
42 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
43 | }
44 | }
45 |
46 | // Needed to get bitcoin-j to produce a valid apk for android.
47 | packagingOptions {
48 | exclude 'lib/x86_64/darwin/libscrypt.dylib'
49 | exclude 'lib/x86_64/freebsd/libscrypt.so'
50 | exclude 'lib/x86_64/linux/libscrypt.so'
51 | }
52 |
53 | compileOptions {
54 | sourceCompatibility JavaVersion.VERSION_1_7
55 | targetCompatibility JavaVersion.VERSION_1_7
56 | }
57 |
58 | lintOptions {
59 | abortOnError false
60 | }
61 | }
62 |
63 | dependencies {
64 | implementation fileTree(include: ['*.jar'], dir: 'libs')
65 | implementation 'one.block:eosiojava:1.0.0'
66 | implementation 'one.block:eosiojavasoftkeysignatureprovider:1.0.0'
67 | implementation 'one.block:eosiojavaandroidabieosserializationprovider:1.0.0'
68 | implementation 'one.block:eosio-java-rpc-provider:1.0.0'
69 |
70 | implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
71 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
72 | testImplementation 'junit:junit:4.12'
73 | androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
74 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
75 | androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.12.1'
76 | implementation 'com.google.android.material:material:1.0.0'
77 | }
78 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/one/block/androidexampleapp/AbiEosInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import org.junit.AfterClass;
4 | import org.junit.BeforeClass;
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 |
8 | import androidx.test.runner.AndroidJUnit4;
9 | import one.block.eosiojava.error.serializationProvider.DeserializeAbiError;
10 | import one.block.eosiojava.error.serializationProvider.DeserializeError;
11 | import one.block.eosiojava.error.serializationProvider.DeserializeTransactionError;
12 | import one.block.eosiojava.error.serializationProvider.SerializationProviderError;
13 | import one.block.eosiojava.error.serializationProvider.SerializeTransactionError;
14 | import one.block.eosiojava.models.AbiEosSerializationObject;
15 | import one.block.eosiojavaabieosserializationprovider.AbiEosSerializationProviderImpl;
16 |
17 | import static org.junit.Assert.assertEquals;
18 | import static org.junit.Assert.assertNotNull;
19 | import static org.junit.Assert.fail;
20 |
21 | // At this point its not possible to run these as normal unit tests even though the context
22 | // access to pick up the abi json as resources has been removed. This is because we are
23 | // using the NDK to compile the abieos c++ code, which results in shared libraries that need
24 | // android to run.
25 |
26 | @RunWith(AndroidJUnit4.class)
27 | public class AbiEosInstrumentedTest {
28 |
29 | private static AbiEosSerializationProviderImpl abieos;
30 |
31 | @BeforeClass
32 | public static void startSetup() {
33 | try {
34 | abieos = new AbiEosSerializationProviderImpl();
35 | } catch (SerializationProviderError serializationProviderError) {
36 | serializationProviderError.printStackTrace();
37 | fail();
38 | }
39 | }
40 |
41 | @AfterClass
42 | public static void endTearDown() {
43 | abieos.destroyContext();
44 | abieos = null;
45 | }
46 |
47 | @Test
48 | public void hexToJsonAbiDef() {
49 | String hex = "0E656F73696F3A3A6162692F312E30010C6163636F756E745F6E616D65046E616D6505087472616E7366657200040466726F6D0C6163636F756E745F6E616D6502746F0C6163636F756E745F6E616D65087175616E74697479056173736574046D656D6F06737472696E67066372656174650002066973737565720C6163636F756E745F6E616D650E6D6178696D756D5F737570706C79056173736574056973737565000302746F0C6163636F756E745F6E616D65087175616E74697479056173736574046D656D6F06737472696E67076163636F756E7400010762616C616E63650561737365740E63757272656E63795F7374617473000306737570706C790561737365740A6D61785F737570706C79056173736574066973737565720C6163636F756E745F6E616D6503000000572D3CCDCD087472616E73666572BC072D2D2D0A7469746C653A20546F6B656E205472616E736665720A73756D6D6172793A205472616E7366657220746F6B656E732066726F6D206F6E65206163636F756E7420746F20616E6F746865722E0A69636F6E3A2068747470733A2F2F63646E2E746573746E65742E6465762E62316F70732E6E65742F746F6B656E2D7472616E736665722E706E6723636535316566396639656563613334333465383535303765306564343965373666666631323635343232626465643032353566333139366561353963386230630A2D2D2D0A0A2323205472616E73666572205465726D73202620436F6E646974696F6E730A0A492C207B7B66726F6D7D7D2C20636572746966792074686520666F6C6C6F77696E6720746F206265207472756520746F207468652062657374206F66206D79206B6E6F776C656467653A0A0A312E204920636572746966792074686174207B7B7175616E746974797D7D206973206E6F74207468652070726F6365656473206F66206672617564756C656E74206F722076696F6C656E7420616374697669746965732E0A322E2049206365727469667920746861742C20746F207468652062657374206F66206D79206B6E6F776C656467652C207B7B746F7D7D206973206E6F7420737570706F7274696E6720696E6974696174696F6E206F662076696F6C656E636520616761696E7374206F74686572732E0A332E2049206861766520646973636C6F73656420616E7920636F6E747261637475616C207465726D73202620636F6E646974696F6E732077697468207265737065637420746F207B7B7175616E746974797D7D20746F207B7B746F7D7D2E0A0A4920756E6465727374616E6420746861742066756E6473207472616E736665727320617265206E6F742072657665727369626C6520616674657220746865207B7B247472616E73616374696F6E2E64656C61795F7365637D7D207365636F6E6473206F72206F746865722064656C617920617320636F6E66696775726564206279207B7B66726F6D7D7D2773207065726D697373696F6E732E0A0A4966207468697320616374696F6E206661696C7320746F20626520697272657665727369626C7920636F6E6669726D656420616674657220726563656976696E6720676F6F6473206F722073657276696365732066726F6D20277B7B746F7D7D272C204920616772656520746F206569746865722072657475726E2074686520676F6F6473206F72207365727669636573206F7220726573656E64207B7B7175616E746974797D7D20696E20612074696D656C79206D616E6E65722E0000000000A531760569737375650000000000A86CD445066372656174650002000000384F4D113203693634010863757272656E6379010675696E743634076163636F756E740000000000904DC603693634010863757272656E6379010675696E7436340E63757272656E63795F737461747300000000";
50 | String jsonResult = "{\"version\":\"eosio::abi/1.0\",\"types\":[{\"new_type_name\":\"account_name\",\"type\":\"name\"}],\"structs\":[{\"name\":\"transfer\",\"base\":\"\",\"fields\":[{\"name\":\"from\",\"type\":\"account_name\"},{\"name\":\"to\",\"type\":\"account_name\"},{\"name\":\"quantity\",\"type\":\"asset\"},{\"name\":\"memo\",\"type\":\"string\"}]},{\"name\":\"create\",\"base\":\"\",\"fields\":[{\"name\":\"issuer\",\"type\":\"account_name\"},{\"name\":\"maximum_supply\",\"type\":\"asset\"}]},{\"name\":\"issue\",\"base\":\"\",\"fields\":[{\"name\":\"to\",\"type\":\"account_name\"},{\"name\":\"quantity\",\"type\":\"asset\"},{\"name\":\"memo\",\"type\":\"string\"}]},{\"name\":\"account\",\"base\":\"\",\"fields\":[{\"name\":\"balance\",\"type\":\"asset\"}]},{\"name\":\"currency_stats\",\"base\":\"\",\"fields\":[{\"name\":\"supply\",\"type\":\"asset\"},{\"name\":\"max_supply\",\"type\":\"asset\"},{\"name\":\"issuer\",\"type\":\"account_name\"}]}],\"actions\":[{\"name\":\"transfer\",\"type\":\"transfer\",\"ricardian_contract\":\"---\\u000Atitle: Token Transfer\\u000Asummary: Transfer tokens from one account to another.\\u000Aicon: https://cdn.testnet.dev.b1ops.net/token-transfer.png#ce51ef9f9eeca3434e85507e0ed49e76fff1265422bded0255f3196ea59c8b0c\\u000A---\\u000A\\u000A## Transfer Terms & Conditions\\u000A\\u000AI, {{from}}, certify the following to be true to the best of my knowledge:\\u000A\\u000A1. I certify that {{quantity}} is not the proceeds of fraudulent or violent activities.\\u000A2. I certify that, to the best of my knowledge, {{to}} is not supporting initiation of violence against others.\\u000A3. I have disclosed any contractual terms & conditions with respect to {{quantity}} to {{to}}.\\u000A\\u000AI understand that funds transfers are not reversible after the {{$transaction.delay_sec}} seconds or other delay as configured by {{from}}'s permissions.\\u000A\\u000AIf this action fails to be irreversibly confirmed after receiving goods or services from '{{to}}', I agree to either return the goods or services or resend {{quantity}} in a timely manner.\"},{\"name\":\"issue\",\"type\":\"issue\",\"ricardian_contract\":\"\"},{\"name\":\"create\",\"type\":\"create\",\"ricardian_contract\":\"\"}],\"tables\":[{\"name\":\"accounts\",\"index_type\":\"i64\",\"key_names\":[\"currency\"],\"key_types\":[\"uint64\"],\"type\":\"account\"},{\"name\":\"stat\",\"index_type\":\"i64\",\"key_names\":[\"currency\"],\"key_types\":[\"uint64\"],\"type\":\"currency_stats\"}],\"ricardian_clauses\":[],\"error_messages\":[],\"variants\":[],\"action_results\":[],\"kv_tables\":{}}";
51 |
52 | String json = null;
53 |
54 | try {
55 | json = abieos.deserializeAbi(hex);
56 | } catch (DeserializeAbiError err) {
57 | err.printStackTrace();
58 | }
59 |
60 | assertNotNull(json);
61 | assertEquals(json, jsonResult);
62 |
63 | }
64 |
65 | @Test
66 | public void hexToJsonAbiTransaction() {
67 | String hex = "AE0D635CDCAC90A6DCFA000000000100A6823403EA3055000000572D3CCDCD0100AEAA4AC15CFD4500000000A8ED32323B00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C69657320686561767900";
68 | String jsonResult = "{\"expiration\":\"2019-02-12T18:17:18.000\",\"ref_block_num\":44252,\"ref_block_prefix\":4208764560,\"max_net_usage_words\":0,\"max_cpu_usage_ms\":0,\"delay_sec\":0,\"context_free_actions\":[],\"actions\":[{\"account\":\"eosio.token\",\"name\":\"transfer\",\"authorization\":[{\"actor\":\"cryptkeeper\",\"permission\":\"active\"}],\"data\":\"00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C696573206865617679\"}],\"transaction_extensions\":[]}";
69 |
70 | String json = null;
71 |
72 | try {
73 | json = abieos.deserializeTransaction(hex);
74 | } catch (DeserializeTransactionError err) {
75 | err.printStackTrace();
76 | }
77 |
78 | assertNotNull(json);
79 | assertEquals(json, jsonResult);
80 |
81 | }
82 |
83 | @Test
84 | public void hexToJsonAbiTokenTransfer() {
85 | String hex = "00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C696573206865617679";
86 | String jsonResult = "{\"from\":\"cryptkeeper\",\"to\":\"brandon\",\"quantity\":\"42.0000 EOS\",\"memo\":\"the grasshopper lies heavy\"}";
87 | String abi = "{\"version\":\"eosio::abi/1.0\",\"types\":[{\"new_type_name\":\"account_name\",\"type\":\"name\"}],\"structs\":[{\"name\":\"transfer\",\"base\":\"\",\"fields\":[{\"name\":\"from\",\"type\":\"account_name\"},{\"name\":\"to\",\"type\":\"account_name\"},{\"name\":\"quantity\",\"type\":\"asset\"},{\"name\":\"memo\",\"type\":\"string\"}]},{\"name\":\"create\",\"base\":\"\",\"fields\":[{\"name\":\"issuer\",\"type\":\"account_name\"},{\"name\":\"maximum_supply\",\"type\":\"asset\"}]},{\"name\":\"issue\",\"base\":\"\",\"fields\":[{\"name\":\"to\",\"type\":\"account_name\"},{\"name\":\"quantity\",\"type\":\"asset\"},{\"name\":\"memo\",\"type\":\"string\"}]},{\"name\":\"account\",\"base\":\"\",\"fields\":[{\"name\":\"balance\",\"type\":\"asset\"}]},{\"name\":\"currency_stats\",\"base\":\"\",\"fields\":[{\"name\":\"supply\",\"type\":\"asset\"},{\"name\":\"max_supply\",\"type\":\"asset\"},{\"name\":\"issuer\",\"type\":\"account_name\"}]}],\"actions\":[{\"name\":\"transfer\",\"type\":\"transfer\",\"ricardian_contract\":\"---\\ntitle: Token Transfer\\nsummary: Transfer tokens from one account to another.\\nicon: https://cdn.testnet.dev.b1ops.net/token-transfer.png#ce51ef9f9eeca3434e85507e0ed49e76fff1265422bded0255f3196ea59c8b0c\\n---\\n\\n## Transfer Terms & Conditions\\n\\nI, {{from}}, certify the following to be true to the best of my knowledge:\\n\\n1. I certify that {{quantity}} is not the proceeds of fraudulent or violent activities.\\n2. I certify that, to the best of my knowledge, {{to}} is not supporting initiation of violence against others.\\n3. I have disclosed any contractual terms & conditions with respect to {{quantity}} to {{to}}.\\n\\nI understand that funds transfers are not reversible after the {{$transaction.delay_sec}} seconds or other delay as configured by {{from}}'s permissions.\\n\\nIf this action fails to be irreversibly confirmed after receiving goods or services from '{{to}}', I agree to either return the goods or services or resend {{quantity}} in a timely manner.\"},{\"name\":\"issue\",\"type\":\"issue\",\"ricardian_contract\":\"\"},{\"name\":\"create\",\"type\":\"create\",\"ricardian_contract\":\"\"}],\"tables\":[{\"name\":\"accounts\",\"index_type\":\"i64\",\"key_names\":[\"currency\"],\"key_types\":[\"uint64\"],\"type\":\"account\"},{\"name\":\"stat\",\"index_type\":\"i64\",\"key_names\":[\"currency\"],\"key_types\":[\"uint64\"],\"type\":\"currency_stats\"}],\"ricardian_clauses\":[],\"error_messages\":[],\"abi_extensions\":[],\"variants\":[]}";
88 |
89 | String json = null;
90 |
91 | try {
92 | AbiEosSerializationObject serializationObject = new AbiEosSerializationObject("eosio.token", "transfer", null, abi);
93 | serializationObject.setHex(hex);
94 | abieos.deserialize(serializationObject);
95 | json = serializationObject.getJson();
96 | } catch (DeserializeError err) {
97 | err.printStackTrace();
98 | }
99 |
100 | assertNotNull(json);
101 | assertEquals(json, jsonResult);
102 |
103 | }
104 |
105 | @Test
106 | public void jsonToHexTransaction2() {
107 | String json = "{\n" +
108 | "\"expiration\" : \"2019-02-12T20:35:38.000\",\n" +
109 | "\"ref_block_num\" : 60851,\n" +
110 | "\"ref_block_prefix\" : 1743894440,\n" +
111 | "\"max_net_usage_words\" : 0,\n" +
112 | "\"max_cpu_usage_ms\" : 0,\n" +
113 | "\"delay_sec\" : 0,\n" +
114 | "\"context_free_actions\" : [],\n" +
115 | "\"actions\" : [\n" +
116 | "{\n" +
117 | "\"account\" : \"eosio.assert\",\n" +
118 | "\"name\" : \"require\",\n" +
119 | "\"authorization\" : [],\n" +
120 | "\"data\" : \"CBDD956F52ACD910C3C958136D72F8560D1846BC7CF3157F5FBFB72D3001DE4597F4A1FDBECDA6D59C96A43009FC5E5D7B8F639B1269C77CEC718460DCC19CB30100A6823403EA3055000000572D3CCDCD0143864D5AF0FE294D44D19C612036CBE8C098414C4A12A5A7BB0BFE7DB1556248\"\n" +
121 | "},\n" +
122 | "{\n" +
123 | "\"account\" : \"eosio.token\",\n" +
124 | "\"name\" : \"transfer\",\n" +
125 | "\"authorization\" : [\n" +
126 | "{\n" +
127 | "\"actor\" : \"cryptkeeper\",\n" +
128 | "\"permission\" : \"active\"\n" +
129 | "}\n" +
130 | "],\n" +
131 | "\"data\" : \"00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C696573206865617679\"\n" +
132 | "}\n" +
133 | "]\n" +
134 | ",\n" +
135 | "\"transaction_extensions\" : []\n" +
136 | "}";
137 |
138 | String hexResult = "1A2E635CB3EDA8B7F167000000000290AFC2D800EA3055000000405DA7ADBA0072CBDD956F52ACD910C3C958136D72F8560D1846BC7CF3157F5FBFB72D3001DE4597F4A1FDBECDA6D59C96A43009FC5E5D7B8F639B1269C77CEC718460DCC19CB30100A6823403EA3055000000572D3CCDCD0143864D5AF0FE294D44D19C612036CBE8C098414C4A12A5A7BB0BFE7DB155624800A6823403EA3055000000572D3CCDCD0100AEAA4AC15CFD4500000000A8ED32323B00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C69657320686561767900";
139 |
140 | String hex = null;
141 |
142 | try {
143 | hex = abieos.serializeTransaction(json);
144 | } catch (SerializeTransactionError err) {
145 | err.printStackTrace();
146 | }
147 |
148 | assertNotNull(hex);
149 | assertEquals(hex, hexResult);
150 | }
151 |
152 | @Test
153 | public void testContextError() {
154 | try {
155 | abieos.destroyContext();
156 | String err = abieos.error();
157 | fail("Should have thrown an error because the context was null.");
158 | } catch (SerializationProviderError ace) {
159 |
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/one/block/androidexampleapp/EosioRpcProviderInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import android.os.AsyncTask;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 |
8 | import java.io.PrintWriter;
9 | import java.io.StringWriter;
10 | import java.math.BigInteger;
11 | import java.net.SocketTimeoutException;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.concurrent.CountDownLatch;
15 | import java.util.concurrent.TimeUnit;
16 |
17 | import androidx.test.runner.AndroidJUnit4;
18 | import okhttp3.mockwebserver.MockResponse;
19 | import okhttp3.mockwebserver.MockWebServer;
20 | import okhttp3.mockwebserver.SocketPolicy;
21 | import one.block.eosiojava.error.rpcProvider.GetBlockRpcError;
22 | import one.block.eosiojava.models.rpcProvider.Action;
23 | import one.block.eosiojava.models.rpcProvider.Authorization;
24 | import one.block.eosiojava.models.rpcProvider.Transaction;
25 | import one.block.eosiojava.models.rpcProvider.request.GetBlockRequest;
26 | import one.block.eosiojava.models.rpcProvider.request.GetRawAbiRequest;
27 | import one.block.eosiojava.models.rpcProvider.request.GetRequiredKeysRequest;
28 | import one.block.eosiojava.models.rpcProvider.request.PushTransactionRequest;
29 | import one.block.eosiojava.models.rpcProvider.response.GetBlockResponse;
30 | import one.block.eosiojava.models.rpcProvider.response.GetInfoResponse;
31 | import one.block.eosiojava.models.rpcProvider.response.GetRawAbiResponse;
32 | import one.block.eosiojava.models.rpcProvider.response.GetRequiredKeysResponse;
33 | import one.block.eosiojava.models.rpcProvider.response.PushTransactionResponse;
34 | import one.block.eosiojava.models.rpcProvider.response.RPCResponseError;
35 | import one.block.eosiojava.models.rpcProvider.response.RpcError;
36 | import one.block.eosiojavarpcprovider.error.EosioJavaRpcProviderCallError;
37 | import one.block.eosiojavarpcprovider.implementations.EosioJavaRpcProviderImpl;
38 |
39 | import static junit.framework.TestCase.assertEquals;
40 | import static junit.framework.TestCase.assertFalse;
41 | import static junit.framework.TestCase.assertNotNull;
42 | import static junit.framework.TestCase.fail;
43 | import static org.junit.Assert.assertTrue;
44 |
45 | /**
46 | * Instrumented test, which will execute on an Android device.
47 | *
48 | * @see Testing documentation
49 | */
50 | @RunWith(AndroidJUnit4.class)
51 | public class EosioRpcProviderInstrumentedTest {
52 |
53 | @Test
54 | public void getInfoTest() {
55 |
56 | MockWebServer server = new MockWebServer();
57 | server.enqueue(new MockResponse().setResponseCode(200).setBody(GET_INFO_RESPONSE));
58 |
59 | try {
60 | server.start();
61 | String baseUrl = server.url("/").toString();
62 |
63 | EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
64 | baseUrl);
65 | GetInfoResponse response = rpcProvider.getInfo();
66 | assertNotNull(response);
67 | assertEquals("687fa513e18843ad3e820744f4ffcf93b1354036d80737db8dc444fe4b15ad17",
68 | response.getChainId());
69 | assertEquals("0f6695cb", response.getServerVersion());
70 | assertEquals("v1.3.0", response.getServerVersionString());
71 | } catch (Exception ex) {
72 | fail("Should not get exception when calling getInfo(): " + "\n" + getStackTraceString(ex));
73 | } finally {
74 | try {
75 | server.shutdown();
76 | } catch (Exception ex) {
77 | // No need for anything here.
78 | }
79 | }
80 |
81 | }
82 |
83 | @Test
84 | public void getBlockTest() {
85 |
86 | MockWebServer server = new MockWebServer();
87 | server.enqueue(new MockResponse().setResponseCode(200).setBody(GET_BLOCK_RESPONSE));
88 |
89 | try {
90 | server.start();
91 | String baseUrl = server.url("/").toString();
92 |
93 | EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
94 | baseUrl);
95 | GetBlockRequest request = new GetBlockRequest("25260032");
96 | GetBlockResponse response = rpcProvider.getBlock(request);
97 | assertNotNull(response);
98 | assertEquals("0181700002e623f2bf291b86a10a5cec4caab4954d4231f31f050f4f86f26116",
99 | response.getId());
100 | assertEquals(new BigInteger("2249927103"), response.getRefBlockPrefix());
101 | assertEquals("de5493939e3abdca80deeab2fc9389cc43dc1982708653cfe6b225eb788d6659",
102 | response.getActionMroot());
103 | } catch (Exception ex) {
104 | fail("Should not get exception when calling getBlock(): " + ex.getLocalizedMessage()
105 | + "\n" + getStackTraceString(ex));
106 | } finally {
107 | try {
108 | server.shutdown();
109 | } catch (Exception ex) {
110 | // No need for anything here.
111 | }
112 | }
113 |
114 | }
115 |
116 | @Test
117 | public void getRawAbiTest() {
118 |
119 | MockWebServer server = new MockWebServer();
120 | server.enqueue(new MockResponse().setResponseCode(200).setBody(GET_RAW_EOSIO_TOKEN_ABI_RESPONSE));
121 |
122 | try {
123 | server.start();
124 | String baseUrl = server.url("/").toString();
125 |
126 | EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
127 | baseUrl);
128 | GetRawAbiRequest request = new GetRawAbiRequest("eosio.token");
129 | GetRawAbiResponse response = rpcProvider.getRawAbi(request);
130 | assertNotNull(response);
131 | assertEquals("eosio.token", response.getAccountName());
132 | assertEquals("43864d5af0fe294d44d19c612036cbe8c098414c4a12a5a7bb0bfe7db1556248", response.getAbiHash());
133 | assertEquals("DmVvc2lvOjphYmkvMS4wAQxhY2NvdW50X25hbWUEbmFtZQUIdHJhbnNmZXIABARmcm9tDGFjY291bnRfbmFtZQJ0bwxhY2NvdW50X25hbWUIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcGY3JlYXRlAAIGaXNzdWVyDGFjY291bnRfbmFtZQ5tYXhpbXVtX3N1cHBseQVhc3NldAVpc3N1ZQADAnRvDGFjY291bnRfbmFtZQhxdWFudGl0eQVhc3NldARtZW1vBnN0cmluZwdhY2NvdW50AAEHYmFsYW5jZQVhc3NldA5jdXJyZW5jeV9zdGF0cwADBnN1cHBseQVhc3NldAptYXhfc3VwcGx5BWFzc2V0Bmlzc3VlcgxhY2NvdW50X25hbWUDAAAAVy08zc0IdHJhbnNmZXK8By0tLQp0aXRsZTogVG9rZW4gVHJhbnNmZXIKc3VtbWFyeTogVHJhbnNmZXIgdG9rZW5zIGZyb20gb25lIGFjY291bnQgdG8gYW5vdGhlci4KaWNvbjogaHR0cHM6Ly9jZG4udGVzdG5ldC5kZXYuYjFvcHMubmV0L3Rva2VuLXRyYW5zZmVyLnBuZyNjZTUxZWY5ZjllZWNhMzQzNGU4NTUwN2UwZWQ0OWU3NmZmZjEyNjU0MjJiZGVkMDI1NWYzMTk2ZWE1OWM4YjBjCi0tLQoKIyMgVHJhbnNmZXIgVGVybXMgJiBDb25kaXRpb25zCgpJLCB7e2Zyb219fSwgY2VydGlmeSB0aGUgZm9sbG93aW5nIHRvIGJlIHRydWUgdG8gdGhlIGJlc3Qgb2YgbXkga25vd2xlZGdlOgoKMS4gSSBjZXJ0aWZ5IHRoYXQge3txdWFudGl0eX19IGlzIG5vdCB0aGUgcHJvY2VlZHMgb2YgZnJhdWR1bGVudCBvciB2aW9sZW50IGFjdGl2aXRpZXMuCjIuIEkgY2VydGlmeSB0aGF0LCB0byB0aGUgYmVzdCBvZiBteSBrbm93bGVkZ2UsIHt7dG99fSBpcyBub3Qgc3VwcG9ydGluZyBpbml0aWF0aW9uIG9mIHZpb2xlbmNlIGFnYWluc3Qgb3RoZXJzLgozLiBJIGhhdmUgZGlzY2xvc2VkIGFueSBjb250cmFjdHVhbCB0ZXJtcyAmIGNvbmRpdGlvbnMgd2l0aCByZXNwZWN0IHRvIHt7cXVhbnRpdHl9fSB0byB7e3RvfX0uCgpJIHVuZGVyc3RhbmQgdGhhdCBmdW5kcyB0cmFuc2ZlcnMgYXJlIG5vdCByZXZlcnNpYmxlIGFmdGVyIHRoZSB7eyR0cmFuc2FjdGlvbi5kZWxheV9zZWN9fSBzZWNvbmRzIG9yIG90aGVyIGRlbGF5IGFzIGNvbmZpZ3VyZWQgYnkge3tmcm9tfX0ncyBwZXJtaXNzaW9ucy4KCklmIHRoaXMgYWN0aW9uIGZhaWxzIHRvIGJlIGlycmV2ZXJzaWJseSBjb25maXJtZWQgYWZ0ZXIgcmVjZWl2aW5nIGdvb2RzIG9yIHNlcnZpY2VzIGZyb20gJ3t7dG99fScsIEkgYWdyZWUgdG8gZWl0aGVyIHJldHVybiB0aGUgZ29vZHMgb3Igc2VydmljZXMgb3IgcmVzZW5kIHt7cXVhbnRpdHl9fSBpbiBhIHRpbWVseSBtYW5uZXIuAAAAAAClMXYFaXNzdWUAAAAAAKhs1EUGY3JlYXRlAAIAAAA4T00RMgNpNjQBCGN1cnJlbmN5AQZ1aW50NjQHYWNjb3VudAAAAAAAkE3GA2k2NAEIY3VycmVuY3kBBnVpbnQ2NA5jdXJyZW5jeV9zdGF0cwAAAAA==",
134 | response.getAbi());
135 | } catch (Exception ex) {
136 | fail("Should not get exception when calling getRawAbi(): " + ex.getLocalizedMessage()
137 | + "\n" + getStackTraceString(ex));
138 | } finally {
139 | try {
140 | server.shutdown();
141 | } catch (Exception ex) {
142 | // No need for anything here.
143 | }
144 | }
145 |
146 | }
147 |
148 | @Test
149 | public void getRequiredKeysTest() {
150 |
151 | MockWebServer server = new MockWebServer();
152 | server.enqueue(new MockResponse().setResponseCode(200).setBody(GET_REQUIRED_KEYS_RESPONSE));
153 |
154 | try {
155 | server.start();
156 | String baseUrl = server.url("/").toString();
157 |
158 | EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
159 | baseUrl);
160 |
161 | GetRequiredKeysRequest request = new GetRequiredKeysRequest(availableKeys(), transactionForRequiredKeys());
162 | GetRequiredKeysResponse response = rpcProvider.getRequiredKeys(request);
163 | assertNotNull(response);
164 | assertFalse(response.getRequiredKeys().isEmpty());
165 | assertNotNull(response.getRequiredKeys().get(0));
166 | assertEquals("EOS5j67P1W2RyBXAL8sNzYcDLox3yLpxyrxgkYy1xsXzVCvzbYpba",
167 | response.getRequiredKeys().get(0));
168 | } catch (Exception ex) {
169 | fail("Should not get exception when calling getRequiredKeys(): " + ex.getLocalizedMessage()
170 | + "\n" + getStackTraceString(ex));
171 | } finally {
172 | try {
173 | server.shutdown();
174 | } catch (Exception ex) {
175 | // No need for anything here.
176 | }
177 | }
178 |
179 | }
180 |
181 | @Test
182 | public void pushTransactionTest() {
183 |
184 | MockWebServer server = new MockWebServer();
185 | server.enqueue(new MockResponse().setResponseCode(200).setBody(PUSH_TRANSACTION_RESPONSE));
186 |
187 | try {
188 | server.start();
189 | String baseUrl = server.url("/").toString();
190 |
191 | EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
192 | baseUrl);
193 |
194 | List signatures = new ArrayList<>();
195 | signatures.add("SIG_K1_JzFA9ffefWfrTBvpwMwZi81kR6tvHF4mfsRekVXrBjLWWikg9g1FrS9WupYuoGaRew5mJhr4d39tHUjHiNCkxamtEfxi68");
196 | PushTransactionRequest request = new PushTransactionRequest(signatures,
197 | 0,
198 | "",
199 | "C62A4F5C1CEF3D6D71BD000000000290AFC2D800EA3055000000405DA7ADBA0072CBDD956F52ACD910C3C958136D72F8560D1846BC7CF3157F5FBFB72D3001DE4597F4A1FDBECDA6D59C96A43009FC5E5D7B8F639B1269C77CEC718460DCC19CB30100A6823403EA3055000000572D3CCDCD0143864D5AF0FE294D44D19C612036CBE8C098414C4A12A5A7BB0BFE7DB155624800A6823403EA3055000000572D3CCDCD0100AEAA4AC15CFD4500000000A8ED32323B00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C69657320686561767900");
200 | PushTransactionResponse response = rpcProvider.pushTransaction(request);
201 | assertNotNull(response);
202 | assertEquals("ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a",
203 | response.getTransactionId());
204 | } catch (Exception ex) {
205 | fail("Should not get exception when calling pushTransaction(): " + ex.getLocalizedMessage()
206 | + "\n" + getStackTraceString(ex));
207 | } finally {
208 | try {
209 | server.shutdown();
210 | } catch (Exception ex) {
211 | // No need for anything here.
212 | }
213 | }
214 |
215 | }
216 |
217 | @Test
218 | public void pushTransactionErrorTest() {
219 |
220 | MockWebServer server = new MockWebServer();
221 | server.enqueue(new MockResponse().setResponseCode(500).setBody(PUSH_TRANSACTION_ERROR_RESPONSE));
222 |
223 | try {
224 | server.start();
225 | String baseUrl = server.url("/").toString();
226 |
227 | EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
228 | baseUrl);
229 |
230 | List signatures = new ArrayList<>();
231 | signatures.add("SIG_K1_JzFA9ffefWfrTBvpwMwZi81kR6tvHF4mfsRekVXrBjLWWikg9g1FrS9WupYuoGaRew5mJhr4d39tHUjHiNCkxamtEfxi68");
232 | PushTransactionRequest request = new PushTransactionRequest(signatures,
233 | 0,
234 | "",
235 | "C62A4F5C1CEF3D6D71BD000000000290AFC2D800EA3055000000405DA7ADBA0072CBDD956F52ACD910C3C958136D72F8560D1846BC7CF3157F5FBFB72D3001DE4597F4A1FDBECDA6D59C96A43009FC5E5D7B8F639B1269C77CEC718460DCC19CB30100A6823403EA3055000000572D3CCDCD0143864D5AF0FE294D44D19C612036CBE8C098414C4A12A5A7BB0BFE7DB155624800A6823403EA3055000000572D3CCDCD0100AEAA4AC15CFD4500000000A8ED32323B00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C69657320686561767900");
236 | PushTransactionResponse response = rpcProvider.pushTransaction(request);
237 | fail("Push transaction should not succeed.");
238 | } catch (Exception ex) {
239 | assertEquals("Error pushing transaction.", ex.getLocalizedMessage());
240 | assertNotNull(ex.getCause());
241 | assertEquals("Bad status code: 500 (Server Error), returned from server. Additional error information: See further error information in RPCProviderError.", ex.getCause().getMessage());
242 | RPCResponseError rpcResponseError = ((EosioJavaRpcProviderCallError)ex.getCause()).getRpcResponseError();
243 | assertNotNull(rpcResponseError);
244 | assertEquals(new BigInteger("500"), rpcResponseError.getCode());
245 | assertEquals("Internal Service Error", rpcResponseError.getMessage());
246 | RpcError rpcError = rpcResponseError.getError();
247 | assertNotNull(rpcError);
248 | assertEquals(new BigInteger("3040005"), rpcError.getCode());
249 | assertEquals("Expired Transaction", rpcError.getWhat());
250 | } finally {
251 | try {
252 | server.shutdown();
253 | } catch (Exception ex) {
254 | // No need for anything here.
255 | }
256 | }
257 |
258 | }
259 |
260 | @Test
261 | public void getInfoTimeoutTest() {
262 |
263 | MockWebServer server = new MockWebServer();
264 | MockResponse mockResponse = new MockResponse().setResponseCode(200).setBody(GET_INFO_RESPONSE);
265 | // This will cause the call to time out.
266 | mockResponse.setSocketPolicy(SocketPolicy.NO_RESPONSE);
267 | server.enqueue(mockResponse);
268 |
269 | try {
270 | server.start();
271 | String baseUrl = server.url("/").toString();
272 |
273 | EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
274 | baseUrl);
275 | GetInfoResponse response = rpcProvider.getInfo();
276 | fail("Should not succeed when calling getInfo(). Should time out.");
277 | } catch (Exception ex) {
278 | assertEquals("Error retrieving chain information.", ex.getMessage());
279 | assertNotNull(ex.getCause());
280 | assertTrue(ex.getCause() instanceof SocketTimeoutException);
281 | assertEquals("timeout", ex.getCause().getMessage());
282 | } finally {
283 | try {
284 | server.shutdown();
285 | } catch (Exception ex) {
286 | // No need for anything here.
287 | }
288 | }
289 |
290 | }
291 |
292 | @Test
293 | public void getBlockAsyncTest() {
294 |
295 | // This test shows how an RPC provider call might be made asynchronously.
296 |
297 | final CountDownLatch testLock = new CountDownLatch(1);
298 |
299 | MockWebServer server = new MockWebServer();
300 | server.enqueue(new MockResponse().setResponseCode(200).setBody(GET_BLOCK_RESPONSE));
301 |
302 | try {
303 | server.start();
304 | String baseUrl = server.url("/").toString();
305 |
306 | final EosioJavaRpcProviderImpl rpcProvider = new EosioJavaRpcProviderImpl(
307 | baseUrl);
308 | GetBlockRequest[] request = { new GetBlockRequest("25260032") };
309 |
310 | AsyncTask asyncTask = new AsyncTask() {
311 | GetBlockRpcError getBlockError = null;
312 | @Override
313 | protected GetBlockResponse doInBackground(GetBlockRequest... getBlockRequests) {
314 | // Here we are on a background thread.
315 | GetBlockResponse response = null;
316 | try {
317 | response = rpcProvider.getBlock(getBlockRequests[0]);
318 | } catch (GetBlockRpcError err) {
319 | getBlockError = err;
320 | }
321 | return response;
322 | }
323 |
324 | protected void onPostExecute(GetBlockResponse response) {
325 | // Here we are back on the main thread and could update the UI.
326 | assertNotNull(response);
327 | assertEquals("0181700002e623f2bf291b86a10a5cec4caab4954d4231f31f050f4f86f26116",
328 | response.getId());
329 | assertEquals(new BigInteger("2249927103"), response.getRefBlockPrefix());
330 | assertEquals("de5493939e3abdca80deeab2fc9389cc43dc1982708653cfe6b225eb788d6659",
331 | response.getActionMroot());
332 | testLock.countDown();
333 | }
334 | }.execute(request);
335 |
336 | try {
337 | testLock.await(5000, TimeUnit.MILLISECONDS);
338 | } catch (InterruptedException interruptedException) {
339 | fail("Interrupted waiting for getBlock() to complete: " +
340 | interruptedException.getLocalizedMessage());
341 | }
342 |
343 | } catch (Exception ex) {
344 | fail("Should not get exception when calling getBlock(): " + ex.getLocalizedMessage());
345 | } finally {
346 | try {
347 | server.shutdown();
348 | } catch (Exception ex) {
349 | // No need for anything here.
350 | }
351 | }
352 |
353 | }
354 |
355 | private String getStackTraceString(Exception ex) {
356 | StringWriter stringWriter = new StringWriter();
357 | PrintWriter printWriter = new PrintWriter(stringWriter);
358 | ex.printStackTrace(printWriter);
359 | return stringWriter.toString();
360 | }
361 |
362 | private List availableKeys() {
363 |
364 | List availableKeys = new ArrayList<>();
365 | availableKeys.add("PUB_K1_5j67P1W2RyBXAL8sNzYcDLox3yLpxyrxgkYy1xsXzVCw1oi9eG");
366 | return availableKeys;
367 |
368 | }
369 |
370 | private Transaction transactionForRequiredKeys() {
371 | List authList = new ArrayList<>();
372 | authList.add(new Authorization("cryptkeeper", "active"));
373 |
374 | List actionList = new ArrayList<>();
375 | Action action = new Action("eosio.token",
376 | "transfer",
377 | authList,
378 | "00AEAA4AC15CFD4500000060D234CD3DA06806000000000004454F53000000001A746865206772617373686F70706572206C696573206865617679"
379 | );
380 | actionList.add(action);
381 |
382 | Transaction transaction = new Transaction(
383 | "2019-01-25T22:13:55",
384 | new BigInteger("44503"),
385 | new BigInteger("1776994640"),
386 | BigInteger.ZERO,
387 | BigInteger.ZERO,
388 | BigInteger.ZERO,
389 | new ArrayList(),
390 | actionList,
391 | new ArrayList()
392 | );
393 |
394 | return transaction;
395 |
396 | }
397 |
398 | private static final String GET_INFO_RESPONSE = "{\n"
399 | + " \"server_version\": \"0f6695cb\",\n"
400 | + " \"chain_id\": \"687fa513e18843ad3e820744f4ffcf93b1354036d80737db8dc444fe4b15ad17\",\n"
401 | + " \"head_block_num\": 20583056,\n"
402 | + " \"last_irreversible_block_num\": 20583039,\n"
403 | + " \"last_irreversible_block_id\": \"013a127fab9a79403a20b55914cdc7e1ac136618387325ad3c1914d27528a1f1\",\n"
404 | + " \"head_block_id\": \"013a129048f4486ce8a5ac8380870a8ce1bcbd4ff45b40fd0792503dc44c427d\",\n"
405 | + " \"head_block_time\": \"2019-01-25T16:39:38.000\",\n"
406 | + " \"head_block_producer\": \"blkproducer1\",\n"
407 | + " \"virtual_block_cpu_limit\": 200000000,\n"
408 | + " \"virtual_block_net_limit\": 1048576000,\n"
409 | + " \"block_cpu_limit\": 199900,\n"
410 | + " \"block_net_limit\": 1048576,\n"
411 | + " \"server_version_string\": \"v1.3.0\"\n"
412 | + "}";
413 |
414 | private static final String GET_BLOCK_RESPONSE = "{\n"
415 | + " \"timestamp\": \"2019-02-21T18:31:40.000\",\n"
416 | + " \"producer\": \"blkproducer2\",\n"
417 | + " \"confirmed\": 0,\n"
418 | + " \"previous\": \"01816fffa4548475add3c45d0e0620f59468a6817426137b37851c23ccafa9cc\",\n"
419 | + " \"transaction_mroot\": \"0000000000000000000000000000000000000000000000000000000000000000\",\n"
420 | + " \"action_mroot\": \"de5493939e3abdca80deeab2fc9389cc43dc1982708653cfe6b225eb788d6659\",\n"
421 | + " \"schedule_version\": 3,\n"
422 | + " \"new_producers\": null,\n"
423 | + " \"header_extensions\": [],\n"
424 | + " \"producer_signature\": \"SIG_K1_KZ3ptku7orAgcyMzd9FKW4jPC9PvjW9BGadFoyxdJFWM44VZdjW28DJgDe6wkNHAxnpqCWSzaBHB1AfbXBUn3HDzetemoA\",\n"
425 | + " \"transactions\": [],\n"
426 | + " \"block_extensions\": [],\n"
427 | + " \"id\": \"0181700002e623f2bf291b86a10a5cec4caab4954d4231f31f050f4f86f26116\",\n"
428 | + " \"block_num\": 25260032,\n"
429 | + " \"ref_block_prefix\": 2249927103\n"
430 | + "}";
431 |
432 | private static final String GET_RAW_EOSIO_TOKEN_ABI_RESPONSE = "{\n"
433 | + " \"account_name\": \"eosio.token\",\n"
434 | + " \"code_hash\": \"3e0cf4172ab025f9fff5f1db11ee8a34d44779492e1d668ae1dc2d129e865348\",\n"
435 | + " \"abi_hash\": \"43864d5af0fe294d44d19c612036cbe8c098414c4a12a5a7bb0bfe7db1556248\",\n"
436 | + " \"abi\": \"DmVvc2lvOjphYmkvMS4wAQxhY2NvdW50X25hbWUEbmFtZQUIdHJhbnNmZXIABARmcm9tDGFjY291bnRfbmFtZQJ0bwxhY2NvdW50X25hbWUIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcGY3JlYXRlAAIGaXNzdWVyDGFjY291bnRfbmFtZQ5tYXhpbXVtX3N1cHBseQVhc3NldAVpc3N1ZQADAnRvDGFjY291bnRfbmFtZQhxdWFudGl0eQVhc3NldARtZW1vBnN0cmluZwdhY2NvdW50AAEHYmFsYW5jZQVhc3NldA5jdXJyZW5jeV9zdGF0cwADBnN1cHBseQVhc3NldAptYXhfc3VwcGx5BWFzc2V0Bmlzc3VlcgxhY2NvdW50X25hbWUDAAAAVy08zc0IdHJhbnNmZXK8By0tLQp0aXRsZTogVG9rZW4gVHJhbnNmZXIKc3VtbWFyeTogVHJhbnNmZXIgdG9rZW5zIGZyb20gb25lIGFjY291bnQgdG8gYW5vdGhlci4KaWNvbjogaHR0cHM6Ly9jZG4udGVzdG5ldC5kZXYuYjFvcHMubmV0L3Rva2VuLXRyYW5zZmVyLnBuZyNjZTUxZWY5ZjllZWNhMzQzNGU4NTUwN2UwZWQ0OWU3NmZmZjEyNjU0MjJiZGVkMDI1NWYzMTk2ZWE1OWM4YjBjCi0tLQoKIyMgVHJhbnNmZXIgVGVybXMgJiBDb25kaXRpb25zCgpJLCB7e2Zyb219fSwgY2VydGlmeSB0aGUgZm9sbG93aW5nIHRvIGJlIHRydWUgdG8gdGhlIGJlc3Qgb2YgbXkga25vd2xlZGdlOgoKMS4gSSBjZXJ0aWZ5IHRoYXQge3txdWFudGl0eX19IGlzIG5vdCB0aGUgcHJvY2VlZHMgb2YgZnJhdWR1bGVudCBvciB2aW9sZW50IGFjdGl2aXRpZXMuCjIuIEkgY2VydGlmeSB0aGF0LCB0byB0aGUgYmVzdCBvZiBteSBrbm93bGVkZ2UsIHt7dG99fSBpcyBub3Qgc3VwcG9ydGluZyBpbml0aWF0aW9uIG9mIHZpb2xlbmNlIGFnYWluc3Qgb3RoZXJzLgozLiBJIGhhdmUgZGlzY2xvc2VkIGFueSBjb250cmFjdHVhbCB0ZXJtcyAmIGNvbmRpdGlvbnMgd2l0aCByZXNwZWN0IHRvIHt7cXVhbnRpdHl9fSB0byB7e3RvfX0uCgpJIHVuZGVyc3RhbmQgdGhhdCBmdW5kcyB0cmFuc2ZlcnMgYXJlIG5vdCByZXZlcnNpYmxlIGFmdGVyIHRoZSB7eyR0cmFuc2FjdGlvbi5kZWxheV9zZWN9fSBzZWNvbmRzIG9yIG90aGVyIGRlbGF5IGFzIGNvbmZpZ3VyZWQgYnkge3tmcm9tfX0ncyBwZXJtaXNzaW9ucy4KCklmIHRoaXMgYWN0aW9uIGZhaWxzIHRvIGJlIGlycmV2ZXJzaWJseSBjb25maXJtZWQgYWZ0ZXIgcmVjZWl2aW5nIGdvb2RzIG9yIHNlcnZpY2VzIGZyb20gJ3t7dG99fScsIEkgYWdyZWUgdG8gZWl0aGVyIHJldHVybiB0aGUgZ29vZHMgb3Igc2VydmljZXMgb3IgcmVzZW5kIHt7cXVhbnRpdHl9fSBpbiBhIHRpbWVseSBtYW5uZXIuAAAAAAClMXYFaXNzdWUAAAAAAKhs1EUGY3JlYXRlAAIAAAA4T00RMgNpNjQBCGN1cnJlbmN5AQZ1aW50NjQHYWNjb3VudAAAAAAAkE3GA2k2NAEIY3VycmVuY3kBBnVpbnQ2NA5jdXJyZW5jeV9zdGF0cwAAAAA==\"\n"
437 | + "}";
438 |
439 |
440 | private static final String GET_REQUIRED_KEYS_RESPONSE = "{\n"
441 | + " \"required_keys\": [\n"
442 | + " \"EOS5j67P1W2RyBXAL8sNzYcDLox3yLpxyrxgkYy1xsXzVCvzbYpba\"\n"
443 | + " ]\n"
444 | + "}";
445 |
446 | private static final String PUSH_TRANSACTION_RESPONSE = "{\n"
447 | + " \"transaction_id\": \"ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a\",\n"
448 | + " \"processed\": {\n"
449 | + " \"id\": \"ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a\",\n"
450 | + " \"block_num\": 21098575,\n"
451 | + " \"block_time\": \"2019-01-28T16:15:37.500\",\n"
452 | + " \"producer_block_id\": null,\n"
453 | + " \"receipt\": {\n"
454 | + " \"status\": \"executed\",\n"
455 | + " \"cpu_usage_us\": 3837,\n"
456 | + " \"net_usage_words\": 36\n"
457 | + " },\n"
458 | + " \"elapsed\": 3837,\n"
459 | + " \"net_usage\": 288,\n"
460 | + " \"scheduled\": false,\n"
461 | + " \"action_traces\": [\n"
462 | + " {\n"
463 | + " \"receipt\": {\n"
464 | + " \"receiver\": \"eosio.assert\",\n"
465 | + " \"act_digest\": \"a4caeedd5e5824dd916c1aaabc84f0a114ddbda83728c8c23ba859d4a8a93721\",\n"
466 | + " \"global_sequence\": 21103875,\n"
467 | + " \"recv_sequence\": 332,\n"
468 | + " \"auth_sequence\": [],\n"
469 | + " \"code_sequence\": 1,\n"
470 | + " \"abi_sequence\": 1\n"
471 | + " },\n"
472 | + " \"act\": {\n"
473 | + " \"account\": \"eosio.assert\",\n"
474 | + " \"name\": \"require\",\n"
475 | + " \"authorization\": [],\n"
476 | + " \"data\": {\n"
477 | + " \"chain_params_hash\": \"cbdd956f52acd910c3c958136d72f8560d1846bc7cf3157f5fbfb72d3001de45\",\n"
478 | + " \"manifest_id\": \"97f4a1fdbecda6d59c96a43009fc5e5d7b8f639b1269c77cec718460dcc19cb3\",\n"
479 | + " \"actions\": [\n"
480 | + " {\n"
481 | + " \"contract\": \"eosio.token\",\n"
482 | + " \"action\": \"transfer\"\n"
483 | + " }\n"
484 | + " ],\n"
485 | + " \"abi_hashes\": [\n"
486 | + " \"43864d5af0fe294d44d19c612036cbe8c098414c4a12a5a7bb0bfe7db1556248\"\n"
487 | + " ]\n"
488 | + " },\n"
489 | + " \"hex_data\": \"cbdd956f52acd910c3c958136d72f8560d1846bc7cf3157f5fbfb72d3001de4597f4a1fdbecda6d59c96a43009fc5e5d7b8f639b1269c77cec718460dcc19cb30100a6823403ea3055000000572d3ccdcd0143864d5af0fe294d44d19c612036cbe8c098414c4a12a5a7bb0bfe7db1556248\"\n"
490 | + " },\n"
491 | + " \"context_free\": false,\n"
492 | + " \"elapsed\": 1264,\n"
493 | + " \"cpu_usage\": 0,\n"
494 | + " \"console\": \"\",\n"
495 | + " \"total_cpu_usage\": 0,\n"
496 | + " \"trx_id\": \"ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a\",\n"
497 | + " \"block_num\": 21098575,\n"
498 | + " \"block_time\": \"2019-01-28T16:15:37.500\",\n"
499 | + " \"producer_block_id\": null,\n"
500 | + " \"account_ram_deltas\": [],\n"
501 | + " \"inline_traces\": []\n"
502 | + " },\n"
503 | + " {\n"
504 | + " \"receipt\": {\n"
505 | + " \"receiver\": \"eosio.token\",\n"
506 | + " \"act_digest\": \"9eab239d66d13c34b9cc35a6f79fb2f6d61a2d9df9a484075c82e65d73a0cbc8\",\n"
507 | + " \"global_sequence\": 21103876,\n"
508 | + " \"recv_sequence\": 1366,\n"
509 | + " \"auth_sequence\": [\n"
510 | + " [\n"
511 | + " \"cryptkeeper\",\n"
512 | + " 875\n"
513 | + " ]\n"
514 | + " ],\n"
515 | + " \"code_sequence\": 1,\n"
516 | + " \"abi_sequence\": 4\n"
517 | + " },\n"
518 | + " \"act\": {\n"
519 | + " \"account\": \"eosio.token\",\n"
520 | + " \"name\": \"transfer\",\n"
521 | + " \"authorization\": [\n"
522 | + " {\n"
523 | + " \"actor\": \"cryptkeeper\",\n"
524 | + " \"permission\": \"active\"\n"
525 | + " }\n"
526 | + " ],\n"
527 | + " \"data\": {\n"
528 | + " \"from\": \"cryptkeeper\",\n"
529 | + " \"to\": \"brandon\",\n"
530 | + " \"quantity\": \"42.0000 EOS\",\n"
531 | + " \"memo\": \"the grasshopper lies heavy\"\n"
532 | + " },\n"
533 | + " \"hex_data\": \"00aeaa4ac15cfd4500000060d234cd3da06806000000000004454f53000000001a746865206772617373686f70706572206c696573206865617679\"\n"
534 | + " },\n"
535 | + " \"context_free\": false,\n"
536 | + " \"elapsed\": 2197,\n"
537 | + " \"cpu_usage\": 0,\n"
538 | + " \"console\": \"\",\n"
539 | + " \"total_cpu_usage\": 0,\n"
540 | + " \"trx_id\": \"ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a\",\n"
541 | + " \"block_num\": 21098575,\n"
542 | + " \"block_time\": \"2019-01-28T16:15:37.500\",\n"
543 | + " \"producer_block_id\": null,\n"
544 | + " \"account_ram_deltas\": [],\n"
545 | + " \"inline_traces\": [\n"
546 | + " {\n"
547 | + " \"receipt\": {\n"
548 | + " \"receiver\": \"cryptkeeper\",\n"
549 | + " \"act_digest\": \"9eab239d66d13c34b9cc35a6f79fb2f6d61a2d9df9a484075c82e65d73a0cbc8\",\n"
550 | + " \"global_sequence\": 21103877,\n"
551 | + " \"recv_sequence\": 496,\n"
552 | + " \"auth_sequence\": [\n"
553 | + " [\n"
554 | + " \"cryptkeeper\",\n"
555 | + " 876\n"
556 | + " ]\n"
557 | + " ],\n"
558 | + " \"code_sequence\": 1,\n"
559 | + " \"abi_sequence\": 4\n"
560 | + " },\n"
561 | + " \"act\": {\n"
562 | + " \"account\": \"eosio.token\",\n"
563 | + " \"name\": \"transfer\",\n"
564 | + " \"authorization\": [\n"
565 | + " {\n"
566 | + " \"actor\": \"cryptkeeper\",\n"
567 | + " \"permission\": \"active\"\n"
568 | + " }\n"
569 | + " ],\n"
570 | + " \"data\": {\n"
571 | + " \"from\": \"cryptkeeper\",\n"
572 | + " \"to\": \"brandon\",\n"
573 | + " \"quantity\": \"42.0000 EOS\",\n"
574 | + " \"memo\": \"the grasshopper lies heavy\"\n"
575 | + " },\n"
576 | + " \"hex_data\": \"00aeaa4ac15cfd4500000060d234cd3da06806000000000004454f53000000001a746865206772617373686f70706572206c696573206865617679\"\n"
577 | + " },\n"
578 | + " \"context_free\": false,\n"
579 | + " \"elapsed\": 6,\n"
580 | + " \"cpu_usage\": 0,\n"
581 | + " \"console\": \"\",\n"
582 | + " \"total_cpu_usage\": 0,\n"
583 | + " \"trx_id\": \"ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a\",\n"
584 | + " \"block_num\": 21098575,\n"
585 | + " \"block_time\": \"2019-01-28T16:15:37.500\",\n"
586 | + " \"producer_block_id\": null,\n"
587 | + " \"account_ram_deltas\": [],\n"
588 | + " \"inline_traces\": []\n"
589 | + " },\n"
590 | + " {\n"
591 | + " \"receipt\": {\n"
592 | + " \"receiver\": \"brandon\",\n"
593 | + " \"act_digest\": \"9eab239d66d13c34b9cc35a6f79fb2f6d61a2d9df9a484075c82e65d73a0cbc8\",\n"
594 | + " \"global_sequence\": 21103878,\n"
595 | + " \"recv_sequence\": 582,\n"
596 | + " \"auth_sequence\": [\n"
597 | + " [\n"
598 | + " \"cryptkeeper\",\n"
599 | + " 877\n"
600 | + " ]\n"
601 | + " ],\n"
602 | + " \"code_sequence\": 1,\n"
603 | + " \"abi_sequence\": 4\n"
604 | + " },\n"
605 | + " \"act\": {\n"
606 | + " \"account\": \"eosio.token\",\n"
607 | + " \"name\": \"transfer\",\n"
608 | + " \"authorization\": [\n"
609 | + " {\n"
610 | + " \"actor\": \"cryptkeeper\",\n"
611 | + " \"permission\": \"active\"\n"
612 | + " }\n"
613 | + " ],\n"
614 | + " \"data\": {\n"
615 | + " \"from\": \"cryptkeeper\",\n"
616 | + " \"to\": \"brandon\",\n"
617 | + " \"quantity\": \"42.0000 EOS\",\n"
618 | + " \"memo\": \"the grasshopper lies heavy\"\n"
619 | + " },\n"
620 | + " \"hex_data\": \"00aeaa4ac15cfd4500000060d234cd3da06806000000000004454f53000000001a746865206772617373686f70706572206c696573206865617679\"\n"
621 | + " },\n"
622 | + " \"context_free\": false,\n"
623 | + " \"elapsed\": 5,\n"
624 | + " \"cpu_usage\": 0,\n"
625 | + " \"console\": \"\",\n"
626 | + " \"total_cpu_usage\": 0,\n"
627 | + " \"trx_id\": \"ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a\",\n"
628 | + " \"block_num\": 21098575,\n"
629 | + " \"block_time\": \"2019-01-28T16:15:37.500\",\n"
630 | + " \"producer_block_id\": null,\n"
631 | + " \"account_ram_deltas\": [],\n"
632 | + " \"inline_traces\": []\n"
633 | + " }\n"
634 | + " ]\n"
635 | + " }\n"
636 | + " ],\n"
637 | + " \"except\": null\n"
638 | + " }\n"
639 | + "}";
640 |
641 | private static final String PUSH_TRANSACTION_ERROR_RESPONSE = "{\n"
642 | + " \"code\": 500,\n"
643 | + " \"message\": \"Internal Service Error\",\n"
644 | + " \"error\": {\n"
645 | + " \"code\": 3040005,\n"
646 | + " \"name\": \"expired_tx_exception\",\n"
647 | + " \"what\": \"Expired Transaction\",\n"
648 | + " \"details\": [\n"
649 | + " {\n"
650 | + " \"message\": \"expired transaction ae735820e26a7b771e1b522186294d7cbba035d0c31ca88237559d6c0a3bf00a\",\n"
651 | + " \"file\": \"producer_plugin.cpp\",\n"
652 | + " \"line_number\": 378,\n"
653 | + " \"method\": \"on_incoming_transaction_async\"\n"
654 | + " }\n"
655 | + " ]\n"
656 | + " }\n"
657 | + "}";
658 | }
659 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/one/block/androidexampleapp/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.InstrumentationRegistry;
6 | import androidx.test.runner.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getTargetContext();
24 |
25 | assertEquals("one.block.androidexampleapp", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/one/block/androidexampleapp/TransactionInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.InstrumentationRegistry;
6 | import androidx.test.runner.AndroidJUnit4;
7 |
8 | import org.json.JSONArray;
9 | import org.json.JSONException;
10 | import org.junit.Test;
11 | import org.junit.runner.RunWith;
12 |
13 | import java.util.concurrent.CountDownLatch;
14 | import java.util.concurrent.TimeUnit;
15 |
16 | import static org.junit.Assert.assertTrue;
17 |
18 | @RunWith(AndroidJUnit4.class)
19 | public class TransactionInstrumentedTest {
20 |
21 | @Test
22 | public void testSubmitTransaction() throws JSONException, InterruptedException {
23 | Context appContext = InstrumentationRegistry.getTargetContext();
24 | String nodeURL = appContext.getString(R.string.node_url);
25 |
26 | String fromAccount = appContext.getString(R.string.from_account);
27 | String toAccount = appContext.getString(R.string.to_account);
28 | String amount = appContext.getString(R.string.amount);
29 | String memo = appContext.getString(R.string.memo);
30 |
31 | JSONArray privateKeysJSON = new JSONArray(appContext.getString(R.string.private_keys));
32 |
33 | for (int i = 0; i < privateKeysJSON.length(); i++) {
34 | testSubmitTransactionByMultipleKey(fromAccount, toAccount, amount, memo, privateKeysJSON.getString(i), nodeURL);
35 | Thread.sleep(1000);
36 | }
37 | }
38 |
39 | private void testSubmitTransactionByMultipleKey(
40 | String fromAccount,
41 | String toAccount,
42 | String amount,
43 | String memo,
44 | final String privateKey,
45 | String url) throws InterruptedException {
46 |
47 | final CountDownLatch signal = new CountDownLatch(1);
48 |
49 | new TransactionTask(new TransactionTask.TransactionTaskCallback() {
50 | @Override
51 | public void update(String updateContent) {
52 |
53 | }
54 |
55 | @Override
56 | public void finish(boolean success, String updateContent) {
57 | System.out.println("Finish Transaction " + updateContent + " - key " + privateKey);
58 | assertTrue(success);
59 | signal.countDown();
60 | }
61 | }).execute(url, fromAccount, toAccount, privateKey, amount, memo);
62 |
63 | signal.await(5000, TimeUnit.MILLISECONDS);
64 | assertTrue(true);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/one/block/androidexampleapp/CheckBalanceTask.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import android.os.AsyncTask;
4 |
5 | import org.json.JSONArray;
6 | import org.json.JSONException;
7 |
8 | import okhttp3.RequestBody;
9 | import one.block.eosiojava.error.rpcProvider.RpcProviderError;
10 | import one.block.eosiojava.models.rpcProvider.response.RPCResponseError;
11 | import one.block.eosiojavarpcprovider.error.EosioJavaRpcProviderInitializerError;
12 | import one.block.eosiojavarpcprovider.implementations.EosioJavaRpcProviderImpl;
13 |
14 | public class CheckBalanceTask extends AsyncTask {
15 |
16 | /**
17 | * Whether the network logs will be enabled for RPC provider
18 | */
19 | private static final boolean ENABLE_NETWORK_LOG = true;
20 |
21 | private CheckBalanceTaskCallback callback;
22 |
23 | public CheckBalanceTask(CheckBalanceTaskCallback callback) {
24 | this.callback = callback;
25 | }
26 |
27 | @Override
28 | protected void onProgressUpdate(String... values) {
29 | super.onProgressUpdate(values);
30 | // Send back statuses to caller for progress update or finishing task with failure or success.
31 | if (values.length == 1) {
32 | // Updating case
33 | String message = values[0];
34 | this.callback.update(message);
35 | } else if (values.length == 2) {
36 | // Failing case
37 | boolean isSuccess = Boolean.parseBoolean(values[0]);
38 | String message = values[1];
39 | this.callback.finish(isSuccess, message, null);
40 | } else if (values.length == 3) {
41 | // Successful case
42 | boolean isSuccess = Boolean.parseBoolean(values[0]);
43 | String message = values[1];
44 | String balance = values[2];
45 | this.callback.finish(isSuccess, message, balance);
46 | }
47 | }
48 |
49 | @Override
50 | protected Void doInBackground(String... params) {
51 | String nodeUrl = params[0];
52 | String fromAccount = params[1];
53 |
54 | EosioJavaRpcProviderImpl rpcProvider;
55 | try {
56 | this.publishProgress("Checking Account Balance...");
57 | rpcProvider = new EosioJavaRpcProviderImpl(nodeUrl, ENABLE_NETWORK_LOG);
58 | String getCurrentBalanceRequestJSON = "{\n" +
59 | "\t\"code\" : \"eosio.token\"\n" +
60 | "\t\"account\" : \"" + fromAccount + "\"\n" +
61 | "}";
62 |
63 | RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), getCurrentBalanceRequestJSON);
64 | String responseJSON = rpcProvider.getCurrencyBalance(requestBody);
65 |
66 | this.publishProgress("Account Balance Check Successful!");
67 |
68 | JSONArray jsonArray = new JSONArray(responseJSON);
69 | if (jsonArray.length() == 0) {
70 | this.publishProgress(Boolean.toString(false), "Invalid Account!");
71 | return null;
72 | }
73 |
74 | String accountBalance = jsonArray.getString(0);
75 |
76 | this.publishProgress(Boolean.toString(true), "Current Account Balance: " + accountBalance, accountBalance);
77 | } catch (EosioJavaRpcProviderInitializerError eosioJavaRpcProviderInitializerError) {
78 | // Happens if creating EosioJavaRpcProviderImpl unsuccessful
79 | eosioJavaRpcProviderInitializerError.printStackTrace();
80 |
81 | this.publishProgress(Boolean.toString(false), eosioJavaRpcProviderInitializerError.asJsonString());
82 | } catch (RpcProviderError rpcProviderError) {
83 | // Happens if calling getCurrentBalance unsuccessful
84 | rpcProviderError.printStackTrace();
85 |
86 | // try to get response from backend if the process fail from backend
87 | RPCResponseError rpcResponseError = ErrorUtils.getBackendError(rpcProviderError);
88 | if (rpcResponseError != null) {
89 | String backendErrorMessage = ErrorUtils.getBackendErrorMessageFromResponse(rpcResponseError);
90 | this.publishProgress(Boolean.toString(false), backendErrorMessage);
91 | return null;
92 | }
93 |
94 | this.publishProgress(Boolean.toString(false), rpcProviderError.getMessage());
95 | } catch (JSONException e) {
96 | // Happens if parsing JSON response unsuccessful
97 | e.printStackTrace();
98 | this.publishProgress(Boolean.toString(false), e.getMessage());
99 | }
100 |
101 | return null;
102 | }
103 |
104 | public interface CheckBalanceTaskCallback {
105 | void update(String updateContent);
106 |
107 | void finish(boolean success, String updateContent, String balance);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/app/src/main/java/one/block/androidexampleapp/ErrorUtils.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import one.block.eosiojava.error.EosioError;
6 | import one.block.eosiojava.models.rpcProvider.response.Detail;
7 | import one.block.eosiojava.models.rpcProvider.response.RPCResponseError;
8 | import one.block.eosiojavarpcprovider.error.EosioJavaRpcProviderCallError;
9 |
10 | public class ErrorUtils {
11 |
12 | /**
13 | * Recursively look for a specific error inside causes loop of an EosioError
14 | *
15 | * @param errorClass - the error class to find
16 | * @param error - the error object to search
17 | * @param - the generic class which extends from EosioError
18 | * @return the error which class is specified by input. Return null if could not find the specific class.
19 | */
20 | @Nullable
21 | public static T getErrorObject(Class errorClass, Exception error) {
22 | if (error.getClass() == errorClass) {
23 | return (T) error;
24 | }
25 |
26 | if (error.getCause() == null) {
27 | return null;
28 | }
29 |
30 | // Recursively look deeper
31 | return getErrorObject(errorClass, (Exception) error.getCause());
32 | }
33 |
34 | /**
35 | * Recursively look for the error message of a specific error inside causes loop of an EosioError
36 | *
37 | * @param errorClass - the error class to get the message
38 | * @param error - the error object to search
39 | * @return the error message which class is specified by input. Return the root cause message if could not find the specific class.
40 | */
41 | public static String getError(Class errorClass, EosioError error) {
42 | if (error.getClass() == errorClass || error.getCause() == null) {
43 | return error.getMessage();
44 | }
45 |
46 | return getError(errorClass, (EosioError) error.getCause());
47 | }
48 |
49 | /**
50 | * Get backend error class {@link RPCResponseError} if an backend error is available
51 | *
52 | * @param error the error class to get the backend error
53 | * @return {@link RPCResponseError} object. Return null if input error does not contain any backend error.
54 | */
55 | @Nullable
56 | public static RPCResponseError getBackendError(EosioError error) {
57 | EosioJavaRpcProviderCallError rpcError = ErrorUtils.getErrorObject(EosioJavaRpcProviderCallError.class, error);
58 | if (rpcError != null) {
59 | return rpcError.getRpcResponseError();
60 | }
61 |
62 | return null;
63 | }
64 |
65 | /**
66 | * Format and return a back end error message from a {@link RPCResponseError} object
67 | *
68 | * @param error the backend error
69 | * @return Formatted backend error message from input
70 | */
71 | public static String getBackendErrorMessageFromResponse(@NonNull RPCResponseError error) {
72 | StringBuilder detail = new StringBuilder();
73 | if (!error.getError().getDetails().isEmpty()) {
74 | for (Detail errorDetail : error.getError().getDetails()) {
75 | detail.append(errorDetail.getMessage()).append(" - ");
76 | }
77 | }
78 |
79 | return error.getMessage() + " - Code: " + error.getError().getCode() + " - What " + error.getError().getCode() + " - detail: " + detail.toString();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/one/block/androidexampleapp/MainActivity.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.os.Bundle;
6 | import android.text.Html;
7 | import android.text.method.ScrollingMovementMethod;
8 | import android.view.View;
9 | import android.widget.Button;
10 | import android.widget.EditText;
11 | import android.widget.TextView;
12 |
13 | import com.google.android.material.textfield.TextInputEditText;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | public class MainActivity extends AppCompatActivity {
19 |
20 | private TextView tvStatus;
21 | private Button btnTransfer;
22 | private Button btnCheckBalance;
23 | private TextView tvBalanceStatus;
24 | private List logs = new ArrayList<>();
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_main);
30 |
31 | final String nodeUrl = this.getString(R.string.node_url);
32 |
33 | this.tvStatus = findViewById(R.id.tv_status);
34 | this.tvStatus.setMovementMethod(new ScrollingMovementMethod());
35 |
36 | this.btnCheckBalance = findViewById(R.id.btn_check_balance);
37 | this.btnTransfer = findViewById(R.id.btn_transfer);
38 | this.tvBalanceStatus = findViewById(R.id.tv_balance);
39 |
40 | this.btnTransfer.setOnClickListener(new View.OnClickListener() {
41 | @Override
42 | public void onClick(View v) {
43 | executeTransaction(nodeUrl);
44 | }
45 | });
46 |
47 | this.btnCheckBalance.setOnClickListener(new View.OnClickListener() {
48 | @Override
49 | public void onClick(View v) {
50 | executeCheckBalance(nodeUrl);
51 | }
52 | });
53 |
54 | findViewById(R.id.btn_clear_log).setOnClickListener(new View.OnClickListener() {
55 | @Override
56 | public void onClick(View v) {
57 | logs.clear();
58 | tvStatus.setText("");
59 | }
60 | });
61 | }
62 |
63 | private void update() {
64 | StringBuilder updateContentBuilder = new StringBuilder();
65 | for (String log : this.logs) {
66 | updateContentBuilder.append(log);
67 | }
68 |
69 | this.tvStatus.setText(Html.fromHtml(updateContentBuilder.toString()));
70 | }
71 |
72 | private void executeTransaction(final String nodeUrl) {
73 | // Collecting necessary data to send transaction
74 | final String fromAccount = ((TextInputEditText) this.findViewById(R.id.edt_from_account)).getText().toString();
75 | final String toAccount = ((TextInputEditText) this.findViewById(R.id.edt_to_account)).getText().toString();
76 | final String privateKey = ((TextInputEditText) this.findViewById(R.id.edt_private_key)).getText().toString();
77 | final String amount = ((TextInputEditText) this.findViewById(R.id.edt_amount)).getText().toString();
78 | final String memo = ((TextInputEditText) this.findViewById(R.id.edt_memo)).getText().toString();
79 |
80 | this.btnTransfer.setEnabled(false);
81 | new TransactionTask(new TransactionTask.TransactionTaskCallback() {
82 | @Override
83 | public void update(String updateContent) {
84 | logs.add("
35 | * - Create serialization provider as an instant of {@link AbiEosSerializationProviderImpl} from [eosiojavaandroidabieosserializationprovider] library
36 | *
37 | * - Create RPC provider as an instant of {@link EosioJavaRpcProviderImpl} with an input string point to a node backend.
38 | *
39 | * - Create ABI provider as an instant of {@link ABIProviderImpl} with instants of Rpc provider and serialization provider.
40 | *
41 | * - Create Signature provider as an instant of {@link SoftKeySignatureProviderImpl} which is not recommended for production because of its simple key management.
42 | *
43 | * - Import an EOS private key which associate with sender's account which will be used to sign the transaction.
44 | *
45 | * - Create an instant of {@link TransactionSession} which is used for spawning/factory {@link TransactionProcessor}
46 | *
47 | * - Create an instant of {@link TransactionProcessor} from the instant of {@link TransactionSession} above by calling {@link TransactionSession#getTransactionProcessor()} or {@link TransactionSession#getTransactionProcessor(Transaction)} if desire to use a preset {@link Transaction} object.
48 | *
49 | * - Call {@link TransactionProcessor#prepare(List)} with a list of Actions which is desired to be sent to backend. The method will serialize the list of action to list of hex and keep them inside
50 | * the list of {@link Transaction#getActions()}. The transaction now is ready to be signed and broadcast.
51 | *
52 | * - Call {@link TransactionProcessor#signAndBroadcast()} to sign the transaction inside {@link TransactionProcessor} and broadcast it to backend.
53 | */
54 | public class TransactionTask extends AsyncTask {
55 |
56 | /**
57 | * Whether the network logs will be enabled for RPC provider
58 | */
59 | private static final boolean ENABLE_NETWORK_LOG = true;
60 |
61 | private TransactionTaskCallback callback;
62 |
63 | public TransactionTask(@NonNull TransactionTaskCallback callback) {
64 | this.callback = callback;
65 | }
66 |
67 | @Override
68 | protected void onProgressUpdate(String... values) {
69 | super.onProgressUpdate(values);
70 | if (values.length == 1) {
71 | String message = values[0];
72 | this.callback.update(message);
73 | } else if (values.length == 2) {
74 | boolean isSuccess = Boolean.parseBoolean(values[0]);
75 | String message = values[1];
76 | this.callback.finish(isSuccess, message);
77 | }
78 | }
79 |
80 | @Override
81 | protected Void doInBackground(String... params) {
82 | String nodeUrl = params[0];
83 | String fromAccount = params[1];
84 | String toAccount = params[2];
85 | String privateKey = params[3];
86 | String amount = params[4];
87 | String memo = params[5];
88 |
89 | this.publishProgress("Transferring " + amount + " to " + toAccount);
90 |
91 | // Creating serialization provider
92 | ISerializationProvider serializationProvider;
93 | try {
94 | serializationProvider = new AbiEosSerializationProviderImpl();
95 | } catch (SerializationProviderError serializationProviderError) {
96 | serializationProviderError.printStackTrace();
97 | return null;
98 | }
99 |
100 | // Creating RPC Provider
101 | IRPCProvider rpcProvider;
102 | try {
103 | rpcProvider = new EosioJavaRpcProviderImpl(nodeUrl, ENABLE_NETWORK_LOG);
104 | } catch (EosioJavaRpcProviderInitializerError eosioJavaRpcProviderInitializerError) {
105 | eosioJavaRpcProviderInitializerError.printStackTrace();
106 | this.publishProgress(Boolean.toString(false), eosioJavaRpcProviderInitializerError.getMessage());
107 | return null;
108 | }
109 |
110 | // Creating ABI provider
111 | IABIProvider abiProvider = new ABIProviderImpl(rpcProvider, serializationProvider);
112 |
113 | // Creating Signature provider
114 | ISignatureProvider signatureProvider = new SoftKeySignatureProviderImpl();
115 |
116 | try {
117 | ((SoftKeySignatureProviderImpl) signatureProvider).importKey(privateKey);
118 | } catch (ImportKeyError importKeyError) {
119 | importKeyError.printStackTrace();
120 | this.publishProgress(Boolean.toString(false), importKeyError.getMessage());
121 | return null;
122 | }
123 |
124 | // Creating TransactionProcess
125 | TransactionSession session = new TransactionSession(serializationProvider, rpcProvider, abiProvider, signatureProvider);
126 | TransactionProcessor processor = session.getTransactionProcessor();
127 |
128 | // Apply transaction data to Action's data
129 | String jsonData = "{\n" +
130 | "\"from\": \"" + fromAccount + "\",\n" +
131 | "\"to\": \"" + toAccount + "\",\n" +
132 | "\"quantity\": \"" + amount + "\",\n" +
133 | "\"memo\" : \"" + memo + "\"\n" +
134 | "}";
135 |
136 | // Creating action with action's data, eosio.token contract and transfer action.
137 | Action action = new Action("eosio.token", "transfer", Collections.singletonList(new Authorization(fromAccount, "active")), jsonData);
138 | try {
139 |
140 | // Prepare transaction with above action. A transaction can be executed with multiple action.
141 | this.publishProgress("Preparing Transaction...");
142 | processor.prepare(Collections.singletonList(action));
143 |
144 | // Sign and broadcast the transaction.
145 | this.publishProgress("Signing and Broadcasting Transaction...");
146 | SendTransactionResponse response = processor.signAndBroadcast();
147 |
148 | this.publishProgress(Boolean.toString(true), "Finished! Your transaction id is: " + response.getTransactionId());
149 | } catch (TransactionPrepareError transactionPrepareError) {
150 | // Happens if preparing transaction unsuccessful
151 | transactionPrepareError.printStackTrace();
152 | this.publishProgress(Boolean.toString(false), transactionPrepareError.getLocalizedMessage());
153 | } catch (TransactionSignAndBroadCastError transactionSignAndBroadCastError) {
154 | // Happens if Sign transaction or broadcast transaction unsuccessful.
155 | transactionSignAndBroadCastError.printStackTrace();
156 |
157 | // try to get backend error if the error come from backend
158 | RPCResponseError rpcResponseError = ErrorUtils.getBackendError(transactionSignAndBroadCastError);
159 | if (rpcResponseError != null) {
160 | String backendErrorMessage = ErrorUtils.getBackendErrorMessageFromResponse(rpcResponseError);
161 | this.publishProgress(Boolean.toString(false), backendErrorMessage);
162 | return null;
163 | }
164 |
165 | this.publishProgress(Boolean.toString(false), transactionSignAndBroadCastError.getMessage());
166 | }
167 |
168 | return null;
169 | }
170 |
171 | public interface TransactionTaskCallback {
172 | void update(String updateContent);
173 |
174 | void finish(boolean success, String updateContent);
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
24 |
25 |
26 |
27 |
41 |
42 |
48 |
49 |
55 |
56 |
64 |
65 |
72 |
73 |
74 |
75 |
83 |
84 |
91 |
92 |
93 |
94 |
102 |
103 |
110 |
111 |
112 |
113 |
121 |
122 |
129 |
130 |
131 |
132 |
138 |
139 |
145 |
146 |
152 |
153 |
166 |
167 |
176 |
177 |
186 |
187 |
196 |
197 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 | #2A2A2A
7 | #808080
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Example App
3 | Account\'s balance :
4 | Your account name
5 | Receiver account name
6 | Transfer Amount
7 | Memo
8 | Private key
9 | Account balance %s
10 | CHECK
11 | TRANSFER
12 | Clear
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/one/block/androidexampleapp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package one.block.androidexampleapp;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 |
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.4.0'
11 |
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | jcenter()
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/eosio.properties:
--------------------------------------------------------------------------------
1 | node_url=
2 | from_account =
3 | to_account =
4 | from_account_private_key =
5 | amount =
6 | memo =
7 | private_keys=[]
8 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu May 09 15:50:52 EDT 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/img/Android_Robot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/img/Android_Robot.png
--------------------------------------------------------------------------------
/img/java-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/img/java-logo.png
--------------------------------------------------------------------------------
/img/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-android-example-app/89d9aa9b9eac8a133c4bc93a4f1470a1baf861ac/img/screenshot.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
--------------------------------------------------------------------------------