├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradlew ├── graphenej ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── maven-push.gradle └── src │ ├── androidTest │ └── java │ │ └── cy │ │ └── agorise │ │ └── graphenej │ │ └── NodeLatencyVerifierTest.java │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── cy │ │ └── agorise │ │ └── graphenej │ │ ├── AccountOptions.java │ │ ├── Address.java │ │ ├── Asset.java │ │ ├── AssetAmount.java │ │ ├── AssetOptions.java │ │ ├── Authority.java │ │ ├── AuthorityType.java │ │ ├── BIP39.java │ │ ├── BaseOperation.java │ │ ├── BlockData.java │ │ ├── BrainKey.java │ │ ├── Chains.java │ │ ├── Converter.java │ │ ├── Extensions.java │ │ ├── FileBin.java │ │ ├── GrapheneObject.java │ │ ├── Invoice.java │ │ ├── LimitOrder.java │ │ ├── LineItem.java │ │ ├── MarketTrade.java │ │ ├── Memo.java │ │ ├── ObjectType.java │ │ ├── OperationType.java │ │ ├── Optional.java │ │ ├── OrderBook.java │ │ ├── Price.java │ │ ├── PublicKey.java │ │ ├── RPC.java │ │ ├── Transaction.java │ │ ├── UserAccount.java │ │ ├── Util.java │ │ ├── Varint.java │ │ ├── Vote.java │ │ ├── api │ │ ├── ApiAccess.java │ │ ├── BaseGrapheneHandler.java │ │ ├── ConnectionStatusUpdate.java │ │ ├── GetAccountBalances.java │ │ ├── GetAccountByName.java │ │ ├── GetAccountHistory.java │ │ ├── GetAccounts.java │ │ ├── GetAllAssetHolders.java │ │ ├── GetBlock.java │ │ ├── GetBlockHeader.java │ │ ├── GetKeyReferences.java │ │ ├── GetLimitOrders.java │ │ ├── GetMarketHistory.java │ │ ├── GetObjects.java │ │ ├── GetRelativeAccountHistory.java │ │ ├── GetRequiredFees.java │ │ ├── GetTradeHistory.java │ │ ├── ListAssets.java │ │ ├── LookupAccounts.java │ │ ├── LookupAssetSymbols.java │ │ ├── SubscriptionMessagesHub.java │ │ ├── TransactionBroadcastSequence.java │ │ ├── android │ │ │ ├── DeserializationMap.java │ │ │ ├── NetworkService.java │ │ │ ├── NetworkServiceManager.java │ │ │ ├── NodeConnection.java │ │ │ ├── RxBus.java │ │ │ └── WebsocketWorkerThread.java │ │ ├── bitshares │ │ │ └── Nodes.java │ │ └── calls │ │ │ ├── ApiCallable.java │ │ │ ├── CancelAllSubscriptions.java │ │ │ ├── GetAccountByName.java │ │ │ ├── GetAccountHistory.java │ │ │ ├── GetAccountHistoryByOperations.java │ │ │ ├── GetAccounts.java │ │ │ ├── GetBlock.java │ │ │ ├── GetBlockHeader.java │ │ │ ├── GetDynamicGlobalProperties.java │ │ │ ├── GetFullAccounts.java │ │ │ ├── GetKeyReferences.java │ │ │ ├── GetLimitOrders.java │ │ │ ├── GetMarketHistory.java │ │ │ ├── GetObjects.java │ │ │ ├── GetRelativeAccountHistory.java │ │ │ ├── GetRequiredFees.java │ │ │ ├── ListAssets.java │ │ │ ├── LookupAssetSymbols.java │ │ │ └── SetSubscribeCallback.java │ │ ├── brainkeydict.txt │ │ ├── crypto │ │ ├── AndroidRandomSource.java │ │ ├── EntropySource.java │ │ ├── RandomSource.java │ │ ├── SecureRandomGenerator.java │ │ └── SecureRandomStrengthener.java │ │ ├── errors │ │ ├── ChecksumException.java │ │ ├── IncompatibleOperation.java │ │ ├── IncompleteAssetError.java │ │ ├── MalformedAddressException.java │ │ ├── MalformedOperationException.java │ │ ├── MalformedTransactionException.java │ │ └── RepeatedRequestIdException.java │ │ ├── interfaces │ │ ├── ByteSerializable.java │ │ ├── GrapheneSerializable.java │ │ ├── JsonSerializable.java │ │ ├── NodeErrorListener.java │ │ ├── SubscriptionHub.java │ │ ├── SubscriptionListener.java │ │ └── WitnessResponseListener.java │ │ ├── models │ │ ├── AccountBalanceUpdate.java │ │ ├── AccountProperties.java │ │ ├── ApiCall.java │ │ ├── AssetFeed.java │ │ ├── AssetHolderCount.java │ │ ├── BaseResponse.java │ │ ├── BitAssetData.java │ │ ├── Block.java │ │ ├── BlockHeader.java │ │ ├── BroadcastedTransaction.java │ │ ├── BucketObject.java │ │ ├── DynamicGlobalProperties.java │ │ ├── FullAccountDetails.java │ │ ├── HistoryOperationDetail.java │ │ ├── JsonRpcNotification.java │ │ ├── JsonRpcResponse.java │ │ ├── OperationHistory.java │ │ ├── Options.java │ │ ├── ReportedAssetFeed.java │ │ ├── SubscriptionResponse.java │ │ ├── WitnessResponse.java │ │ └── backup │ │ │ ├── LinkedAccount.java │ │ │ ├── PrivateKeyBackup.java │ │ │ ├── Wallet.java │ │ │ └── WalletBackup.java │ │ ├── network │ │ ├── FullNode.java │ │ ├── LatencyNodeProvider.java │ │ ├── NodeLatencyVerifier.java │ │ └── NodeProvider.java │ │ ├── operations │ │ ├── AccountUpdateOperation.java │ │ ├── AccountUpdateOperationBuilder.java │ │ ├── AccountUpgradeOperation.java │ │ ├── AccountUpgradeOperationBuilder.java │ │ ├── BaseOperationBuilder.java │ │ ├── CustomOperation.java │ │ ├── LimitOrderCancelOperation.java │ │ ├── LimitOrderCreateOperation.java │ │ ├── TransferOperation.java │ │ └── TransferOperationBuilder.java │ │ ├── stats │ │ └── ExponentialMovingAverage.java │ │ └── test │ │ └── NaiveSSLContext.java │ └── test │ └── java │ └── cy │ └── agorise │ └── graphenej │ ├── AssetAmountTest.java │ ├── AssetTest.java │ ├── AuthorityTest.java │ ├── BrainKeyTest.java │ ├── KeyTest.java │ ├── ObjectTypeTest.java │ ├── OrderBookTest.java │ ├── PublicKeyTest.java │ ├── TestAccounts.java │ ├── TransactionTest.java │ ├── UserAccountTest.java │ ├── UtilTest.java │ ├── api │ ├── BaseApiTest.java │ ├── GetAccountsTest.java │ ├── GetBlockTest.java │ ├── GetKeyReferencesTest.java │ ├── GetLimitOrdersTest.java │ ├── GetObjectsTest.java │ ├── GetRelativeAccountHistoryTest.java │ ├── LookupAssetSymbolsTest.java │ ├── SubscriptionMessagesHubTest.java │ ├── android │ │ └── NodeConnectionTest.java │ └── calls │ │ └── GetAccountHistoryTest.java │ ├── models │ ├── FullAccountDetailsTest.java │ ├── HistoryOperationDetailsTest.java │ ├── JsonRpcNotificationTest.java │ └── JsonRpcResponseTest.java │ ├── network │ ├── FullNodeTest.java │ └── LatencyNodeProviderTest.java │ ├── objects │ └── MemoTest.java │ └── operations │ ├── AccountUpdateOperationTest.java │ ├── AccountUpgradeOperationTest.java │ ├── CustomOperationTest.java │ ├── LimitOrderCancelOperationTest.java │ └── LimitOrderCreateOperationTest.java ├── sample ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cy │ │ └── sample │ │ └── labs │ │ └── sample │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cy │ │ │ └── agorise │ │ │ └── labs │ │ │ └── sample │ │ │ ├── CallsActivity.java │ │ │ ├── ConnectedActivity.java │ │ │ ├── Constants.java │ │ │ ├── PerformCallActivity.java │ │ │ ├── SampleApplication.java │ │ │ └── SubscriptionActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_calls.xml │ │ ├── activity_perform_call.xml │ │ ├── activity_second.xml │ │ └── item_call.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 │ └── cy │ └── sample │ └── labs │ └── sample │ └── ExampleUnitTest.java └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Declare files that will always have LF line endings on checkout. 5 | *.java text eol=lf 6 | 7 | # Denote all files that are truly binary and should not be modified. 8 | *.png binary 9 | *.jpg binary 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Java compilation 2 | *.class 3 | 4 | # Mac OS X file 5 | .DS_Store 6 | 7 | # Gradle 8 | # ------ 9 | .gradle 10 | gradlew.bat 11 | gradle 12 | graphenej/build 13 | /build 14 | /buildSrc/build 15 | /subprojects/*/build 16 | /subprojects/docs/src/samples/*/*/build 17 | /subprojects/internal-android-performance-testing/build-android-libs 18 | 19 | # IDEA 20 | # ---- 21 | .idea 22 | .shelf 23 | *.iml 24 | *.ipr 25 | *.iws 26 | /buildSrc/*.iml 27 | /buildSrc/*.ipr 28 | /buildSrc/*.iws 29 | /buildSrc/out 30 | /out 31 | /subprojects/*/*.iml 32 | /subprojects/*/out 33 | 34 | # Eclipse 35 | # ------- 36 | *.classpath 37 | *.project 38 | *.settings 39 | /bin 40 | /subprojects/*/bin 41 | atlassian-ide-plugin.xml 42 | 43 | # NetBeans 44 | # -------- 45 | .nb-gradle 46 | .nb-gradle-properties 47 | 48 | # Vim 49 | # --- 50 | *.sw[op] 51 | 52 | # Emacs 53 | # ----- 54 | *~ 55 | 56 | # Textmate 57 | # -------- 58 | .textmate 59 | 60 | # Sublime Text 61 | # ------------ 62 | *.sublime-* 63 | 64 | # jEnv 65 | # ---- 66 | .java-version 67 | 68 | # OS X 69 | # ---- 70 | .DS_Store 71 | 72 | # HPROF 73 | # ----- 74 | *.hprof 75 | 76 | # Work dirs 77 | # --------- 78 | /incoming-distributions 79 | /intTestHomeDir 80 | 81 | # Logs 82 | # ---- 83 | /*.log 84 | 85 | # Ignore bin backups 86 | *.bin 87 | 88 | # [Maven] 89 | # ------- 90 | target/ 91 | pom.xml.tag 92 | pom.xml.releaseBackup 93 | pom.xml.versionsBackup 94 | pom.xml.next 95 | release.properties 96 | 97 | # Package Files # 98 | *.jar 99 | *.war 100 | *.ear 101 | 102 | # Build dir 103 | graphenej/build 104 | 105 | local.properties 106 | 107 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 AGORISE, LTD. 4 | An International Business Company, Cyprus Reg# ΗΕ375959 5 | 6 | Contains works from BitShares Munich IVS 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # graphenej 2 | A Java library for mobile app Developers; Graphene/Bitshares blockchain. 3 | 4 | ## Usage 5 | 6 | In your root build.gradle, add this if you don't already have it. 7 | 8 | ```Groovy 9 | allprojects { 10 | repositories { 11 | jcenter() 12 | } 13 | } 14 | ``` 15 | 16 | In yout app module, add the following dependency: 17 | 18 | ```Groovy 19 | dependencies { 20 | compile 'com.github.bilthon:graphenej:0.4.2' 21 | } 22 | ``` 23 | 24 | ## Example 25 | 26 | ### Very simple funds transfer 27 | 28 | This is a simple transfer operation of 1 BTS from account **bilthon-15** to **bilthon-5** 29 | ```java 30 | // Creating a transfer operation 31 | TransferOperation transferOperation = new TransferOperationBuilder() 32 | .setTransferAmount(new AssetAmount(UnsignedLong.valueOf(100000), new Asset("1.3.0"))) 33 | .setSource(new UserAccount("1.2.143563")) // bilthon-15 34 | .setDestination(new UserAccount("1.2.139313")) // bilthon-5 35 | .setFee(new AssetAmount(UnsignedLong.valueOf(264174), new Asset("1.3.0"))) 36 | .build(); 37 | 38 | // Adding operations to the operation list 39 | ArrayList operationList = new ArrayList<>(); 40 | operationList.add(transferOperation); 41 | 42 | // Creating a transaction instance 43 | Transaction transaction = new Transaction(sourcePrivateKey, null, operationList); 44 | ``` 45 | 46 | From here on, it is just a matter of creating a websocket connection and using a custom handler called 47 | ```TransactionBroadcastSequence``` in order to broadcast it to the witness node. 48 | 49 | ```java 50 | // Setting up a secure websocket connection. 51 | SSLContext context = null; 52 | context = NaiveSSLContext.getInstance("TLS"); 53 | WebSocketFactory factory = new WebSocketFactory(); 54 | factory.setSSLContext(context); 55 | 56 | WebSocket mWebSocket = factory.createSocket(FULL_NODE_URL); 57 | 58 | mWebSocket.addListener(new TransactionBroadcastSequence(transaction, new Asset("1.3.0"), listener)); 59 | mWebSocket.connect(); 60 | ``` 61 | 62 | The provided ```listener``` is an instance of the class ```WitnessResponseListener```. 63 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | subprojects { 2 | repositories { 3 | mavenCentral() 4 | } 5 | } 6 | allprojects { 7 | repositories { 8 | mavenCentral() 9 | jcenter() 10 | maven { 11 | url "https://maven.google.com" 12 | } 13 | } 14 | } 15 | buildscript { 16 | repositories { 17 | mavenCentral() 18 | maven { 19 | url 'https://maven.google.com/' 20 | name 'Google' 21 | } 22 | google() 23 | } 24 | dependencies { 25 | classpath 'com.android.tools.build:gradle:3.2.0' 26 | } 27 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | VERSION_NAME=0.4.7-alpha3 21 | VERSION_CODE=12 22 | GROUP=com.github.bilthon 23 | 24 | POM_DESCRIPTION=A Java library for mobile app Developers; Graphene/Bitshares blockchain. 25 | POM_URL=https://github.com/bilthon/graphenej 26 | POM_SCM_URL=https://github.com/bilthon/graphenej 27 | POM_SCM_CONNECTION=scm:git@github.com:bilthon/graphenej.git 28 | POM_SCM_DEV_CONNECTION=scm:git@github.com:bilthon/graphenej.git 29 | POM_LICENCE_NAME=MIT License 30 | POM_LICENCE_URL=https://github.com/bilthon/graphenej/blob/master/LICENSE 31 | POM_LICENCE_DIST=repo 32 | POM_DEVELOPER_ID=bilthon 33 | POM_DEVELOPER_NAME=bilthon -------------------------------------------------------------------------------- /graphenej/build.gradle: -------------------------------------------------------------------------------- 1 | group 'cy.agorise' 2 | version '0.4.7-alpha2' 3 | 4 | apply plugin: 'com.android.library' 5 | //apply from: 'maven-push.gradle' 6 | 7 | android { 8 | compileSdkVersion 24 9 | buildToolsVersion '28.0.2' 10 | 11 | defaultConfig { 12 | minSdkVersion 14 13 | targetSdkVersion 24 14 | versionCode 12 15 | versionName "0.4.7-alpha3" 16 | vectorDrawables.useSupportLibrary = true 17 | } 18 | buildTypes { 19 | debug{} 20 | preRelease{} 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 24 | } 25 | } 26 | defaultConfig { 27 | multiDexEnabled true 28 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 29 | } 30 | } 31 | 32 | dependencies { 33 | testImplementation group: 'junit', name: 'junit', version: '4.12' 34 | implementation 'com.neovisionaries:nv-websocket-client:1.30' 35 | implementation 'org.bitcoinj:bitcoinj-core:0.14.3' 36 | implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.0' 37 | implementation group: "org.tukaani", name: "xz", version: "1.6" 38 | 39 | androidTestImplementation 'com.android.support:support-annotations:27.1.1' 40 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 41 | androidTestImplementation 'com.android.support.test:rules:1.0.2' 42 | 43 | // Rx dependencies 44 | api 'io.reactivex.rxjava2:rxandroid:2.0.2' 45 | api 'io.reactivex.rxjava2:rxjava:2.1.16' 46 | api 'com.jakewharton.rxrelay2:rxrelay:2.0.0' 47 | api 'com.squareup.okhttp3:okhttp:3.5.0' 48 | } -------------------------------------------------------------------------------- /graphenej/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_NAME=Graphenej 2 | POM_ARTIFACT_ID=graphenej 3 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /graphenej/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/computationalcore/graphenej/de9e4801d093ce4e23330235ef9a54bb92935660/graphenej/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /graphenej/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Nov 21 11:33:11 PET 2016 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-2.13-all.zip 7 | -------------------------------------------------------------------------------- /graphenej/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 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /graphenej/src/androidTest/java/cy/agorise/graphenej/NodeLatencyVerifierTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import android.support.test.runner.AndroidJUnit4; 4 | import android.util.Log; 5 | 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import cy.agorise.graphenej.api.bitshares.Nodes; 13 | import cy.agorise.graphenej.network.FullNode; 14 | import cy.agorise.graphenej.network.LatencyNodeProvider; 15 | import cy.agorise.graphenej.network.NodeLatencyVerifier; 16 | import cy.agorise.graphenej.network.NodeProvider; 17 | import io.reactivex.Observer; 18 | import io.reactivex.disposables.Disposable; 19 | import io.reactivex.subjects.PublishSubject; 20 | 21 | @RunWith(AndroidJUnit4.class) 22 | public class NodeLatencyVerifierTest { 23 | private final String TAG = this.getClass().getName(); 24 | 25 | @Test 26 | public void testNodeLatencyTest() throws Exception { 27 | ArrayList nodeList = new ArrayList<>(); 28 | nodeList.add(new FullNode(Nodes.NODE_URLS[0])); 29 | nodeList.add(new FullNode(Nodes.NODE_URLS[1])); 30 | nodeList.add(new FullNode(Nodes.NODE_URLS[2])); 31 | final NodeLatencyVerifier nodeLatencyVerifier = new NodeLatencyVerifier(nodeList); 32 | PublishSubject subject = nodeLatencyVerifier.start(); 33 | final NodeProvider nodeProvider = new LatencyNodeProvider(); 34 | subject.subscribe(new Observer() { 35 | int counter = 0; 36 | 37 | @Override 38 | public void onSubscribe(Disposable d) {} 39 | 40 | @Override 41 | public void onNext(FullNode fullNode) { 42 | Log.i(TAG,String.format("Avg latency: %.2f, url: %s", fullNode.getLatencyValue(), fullNode.getUrl())); 43 | 44 | // Updating node provider 45 | nodeProvider.updateNode(fullNode); 46 | List sortedNodes = nodeProvider.getSortedNodes(); 47 | for(FullNode node : sortedNodes){ 48 | Log.d(TAG,String.format("> %.2f, url: %s", node.getLatencyValue(), node.getUrl())); 49 | } 50 | 51 | // Finish test after certain amount of rounds 52 | if(counter > 3){ 53 | synchronized (NodeLatencyVerifierTest.this){ 54 | nodeLatencyVerifier.stop(); 55 | NodeLatencyVerifierTest.this.notifyAll(); 56 | } 57 | } 58 | 59 | counter++; 60 | } 61 | 62 | @Override 63 | public void onError(Throwable e) { 64 | Log.e(TAG,"onError.Msg: "+e.getMessage()); 65 | synchronized (NodeLatencyVerifierTest.this){ 66 | NodeLatencyVerifierTest.this.notifyAll(); 67 | } 68 | } 69 | 70 | @Override 71 | public void onComplete() { 72 | Log.d(TAG,"onComplete"); 73 | } 74 | }); 75 | try { 76 | synchronized(this) { 77 | wait(); 78 | } 79 | } catch (InterruptedException e) { 80 | e.printStackTrace(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /graphenej/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/Address.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.common.primitives.Bytes; 4 | import cy.agorise.graphenej.errors.MalformedAddressException; 5 | import org.bitcoinj.core.Base58; 6 | import org.bitcoinj.core.ECKey; 7 | import org.spongycastle.crypto.digests.RIPEMD160Digest; 8 | 9 | import java.util.Arrays; 10 | 11 | /** 12 | * Class used to encapsulate address-related operations. 13 | */ 14 | public class Address { 15 | 16 | public final static String BITSHARES_PREFIX = "BTS"; 17 | 18 | private PublicKey publicKey; 19 | private String prefix; 20 | 21 | public Address(ECKey key) { 22 | this.publicKey = new PublicKey(key); 23 | this.prefix = BITSHARES_PREFIX; 24 | } 25 | 26 | public Address(ECKey key, String prefix) { 27 | this.publicKey = new PublicKey(key); 28 | this.prefix = prefix; 29 | } 30 | 31 | public Address(String address) throws MalformedAddressException { 32 | this.prefix = address.substring(0, 3); 33 | byte[] decoded = Base58.decode(address.substring(3, address.length())); 34 | byte[] pubKey = Arrays.copyOfRange(decoded, 0, decoded.length - 4); 35 | byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length); 36 | publicKey = new PublicKey(ECKey.fromPublicOnly(pubKey)); 37 | byte[] calculatedChecksum = calculateChecksum(pubKey); 38 | for(int i = 0; i < calculatedChecksum.length; i++){ 39 | if(checksum[i] != calculatedChecksum[i]){ 40 | throw new MalformedAddressException("Checksum error"); 41 | } 42 | } 43 | } 44 | 45 | public PublicKey getPublicKey(){ 46 | return this.publicKey; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | byte[] pubKey = this.publicKey.toBytes(); 52 | byte[] checksum = calculateChecksum(pubKey); 53 | byte[] pubKeyChecksummed = Bytes.concat(pubKey, checksum); 54 | return this.prefix + Base58.encode(pubKeyChecksummed); 55 | } 56 | 57 | private byte[] calculateChecksum(byte[] data){ 58 | byte[] checksum = new byte[160 / 8]; 59 | RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest(); 60 | ripemd160Digest.update(data, 0, data.length); 61 | ripemd160Digest.doFinal(checksum, 0); 62 | return Arrays.copyOfRange(checksum, 0, 4); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/AssetOptions.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.common.primitives.UnsignedLong; 4 | 5 | /** 6 | * Created by nelson on 12/13/16. 7 | */ 8 | public class AssetOptions { 9 | // TODO: Use these constants instead of using cryptic constants like 128 and 511 10 | public static final int CHARGE_MARKET_FEE = 0x01; 11 | public static final int WHITE_LIST = 0x02; 12 | public static final int OVERRIDE_AUTHORITY = 0x04; 13 | public static final int TRANSFER_RESTRICTED = 0x08; 14 | public static final int DISABLE_FORCE_SETTLE = 0x10; 15 | public static final int GLOBAL_SETTLE = 0x20; 16 | public static final int DISABLE_CONFIDENTIAL = 0x40; 17 | public static final int WITNESS_FED_ASSET = 0x80; 18 | public static final int COMITEE_FED_ASSET = 0x100; 19 | 20 | private UnsignedLong max_supply; 21 | private float market_fee_percent; 22 | private UnsignedLong max_market_fee; 23 | private long issuer_permissions; 24 | private int flags; 25 | private Price core_exchange_rate; 26 | //TODO: Implement whitelist_authorities, blacklist_authorities, whitelist_markets, blacklist_markets and extensions 27 | private String description; 28 | 29 | public UnsignedLong getMaxSupply() { 30 | return max_supply; 31 | } 32 | 33 | public void setMaxSupply(UnsignedLong max_supply) { 34 | this.max_supply = max_supply; 35 | } 36 | 37 | public float getMarketFeePercent() { 38 | return market_fee_percent; 39 | } 40 | 41 | public void setMarketFeePercent(float market_fee_percent) { 42 | this.market_fee_percent = market_fee_percent; 43 | } 44 | 45 | public UnsignedLong getMaxMarketFee() { 46 | return max_market_fee; 47 | } 48 | 49 | public void setMaxMarketFee(UnsignedLong max_market_fee) { 50 | this.max_market_fee = max_market_fee; 51 | } 52 | 53 | public long getIssuerPermissions() { 54 | return issuer_permissions; 55 | } 56 | 57 | public void setIssuerPermissions(long issuer_permissions) { 58 | this.issuer_permissions = issuer_permissions; 59 | } 60 | 61 | public int getFlags() { 62 | return flags; 63 | } 64 | 65 | public void setFlags(int flags) { 66 | this.flags = flags; 67 | } 68 | 69 | public Price getCoreExchangeRate() { 70 | return core_exchange_rate; 71 | } 72 | 73 | public void setCoreExchangeRate(Price core_exchange_rate) { 74 | this.core_exchange_rate = core_exchange_rate; 75 | } 76 | 77 | public String getDescription() { 78 | return description; 79 | } 80 | 81 | public void setDescription(String description) { 82 | this.description = description; 83 | } 84 | } -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/AuthorityType.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * Enum-type used to specify the different roles of an authority. 5 | * 6 | * @see Authority 7 | */ 8 | 9 | public enum AuthorityType { 10 | OWNER, 11 | ACTIVE, 12 | MEMO; 13 | 14 | @Override 15 | public String toString() { 16 | return String.format("%d", this.ordinal()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/BIP39.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import java.util.Arrays; 4 | import org.bitcoinj.core.Base58; 5 | import org.bitcoinj.core.ECKey; 6 | import org.bitcoinj.crypto.HDKeyDerivation; 7 | import org.bitcoinj.crypto.MnemonicCode; 8 | import org.spongycastle.crypto.digests.RIPEMD160Digest; 9 | import org.spongycastle.crypto.digests.SHA512Digest; 10 | 11 | /** 12 | * 13 | * @author hvarona 14 | */ 15 | public class BIP39 { 16 | 17 | private final ECKey mPrivateKey; 18 | 19 | public BIP39(String words, String passphrase) { 20 | 21 | byte[] seed = MnemonicCode.toSeed(Arrays.asList(words.split(" ")), passphrase); 22 | mPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed); 23 | 24 | } 25 | 26 | public String getUncompressedAddress() { 27 | RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest(); 28 | SHA512Digest sha512Digest = new SHA512Digest(); 29 | sha512Digest.update(mPrivateKey.decompress().getPubKey(), 0, mPrivateKey.decompress().getPubKey().length); 30 | byte[] intermediate = new byte[512 / 8]; 31 | sha512Digest.doFinal(intermediate, 0); 32 | ripemd160Digest.update(intermediate, 0, intermediate.length); 33 | byte[] output = new byte[160 / 8]; 34 | ripemd160Digest.doFinal(output, 0); 35 | String encoded = Base58.encode(output); 36 | byte[] checksum = new byte[(160 / 8) + 4]; 37 | System.arraycopy(calculateChecksum(output), 0, checksum, checksum.length - 4, 4); 38 | System.arraycopy(output, 0, checksum, 0, output.length); 39 | 40 | return ("BTS" + Base58.encode(checksum)); 41 | } 42 | 43 | public String getAddress() { 44 | RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest(); 45 | SHA512Digest sha512Digest = new SHA512Digest(); 46 | sha512Digest.update(mPrivateKey.getPubKey(), 0, mPrivateKey.getPubKey().length); 47 | byte[] intermediate = new byte[512 / 8]; 48 | sha512Digest.doFinal(intermediate, 0); 49 | ripemd160Digest.update(intermediate, 0, intermediate.length); 50 | byte[] output = new byte[160 / 8]; 51 | ripemd160Digest.doFinal(output, 0); 52 | String encoded = Base58.encode(output); 53 | byte[] checksum = new byte[(160 / 8) + 4]; 54 | System.arraycopy(calculateChecksum(output), 0, checksum, checksum.length - 4, 4); 55 | System.arraycopy(output, 0, checksum, 0, output.length); 56 | 57 | return ("BTS" + Base58.encode(checksum)); 58 | } 59 | 60 | public byte[] calculateChecksum(byte[] input) { 61 | byte[] answer = new byte[4]; 62 | RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest(); 63 | ripemd160Digest.update(input, 0, input.length); 64 | byte[] output = new byte[160 / 8]; 65 | ripemd160Digest.doFinal(output, 0); 66 | System.arraycopy(output, 0, answer, 0, 4); 67 | return answer; 68 | } 69 | 70 | public byte[] getPublicKey() { 71 | return mPrivateKey.getPubKey(); 72 | } 73 | 74 | public ECKey getPrivateKey() { 75 | return mPrivateKey; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/BaseOperation.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonDeserializationContext; 5 | import com.google.gson.JsonDeserializer; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonParseException; 8 | 9 | import java.lang.reflect.Type; 10 | 11 | import cy.agorise.graphenej.interfaces.ByteSerializable; 12 | import cy.agorise.graphenej.interfaces.JsonSerializable; 13 | import cy.agorise.graphenej.operations.TransferOperation; 14 | 15 | /** 16 | * Base class that represents a generic operation 17 | */ 18 | public abstract class BaseOperation implements ByteSerializable, JsonSerializable { 19 | 20 | public static final String KEY_FEE = "fee"; 21 | public static final String KEY_EXTENSIONS = "extensions"; 22 | 23 | protected OperationType type; 24 | protected Extensions extensions; 25 | 26 | public BaseOperation(OperationType type){ 27 | this.type = type; 28 | this.extensions = new Extensions(); 29 | } 30 | 31 | public byte getId() { 32 | return (byte) this.type.ordinal(); 33 | } 34 | 35 | public abstract void setFee(AssetAmount assetAmount); 36 | 37 | public JsonElement toJsonObject(){ 38 | JsonArray array = new JsonArray(); 39 | array.add(this.getId()); 40 | return array; 41 | } 42 | 43 | /** 44 | *

45 | * De-serializer used to unpack data from a generic operation. The general format used in the 46 | * JSON-RPC blockchain API is the following: 47 | *

48 | * 49 | * [OPERATION_ID, OPERATION_OBJECT]
50 | * 51 | *

52 | * Where OPERATION_ID is one of the operations defined in {@link cy.agorise.graphenej.OperationType} 53 | * and OPERATION_OBJECT is the actual operation serialized in the JSON format. 54 | *

55 | * Here's an example of this serialized form for a transfer operation:

56 | *
57 |      *[
58 |      *   0,
59 |      *   {
60 |      *       "fee": {
61 |      *           "amount": 264174,
62 |      *           "asset_id": "1.3.0"
63 |      *       },
64 |      *       "from": "1.2.138632",
65 |      *       "to": "1.2.129848",
66 |      *       "amount": {
67 |      *           "amount": 100,
68 |      *           "asset_id": "1.3.0"
69 |      *       },
70 |      *       "extensions": []
71 |      *   }
72 |      *]
73 |      *

74 | * If this class is used, this serialized data will be translated to a TransferOperation object instance.
75 | * 76 | * TODO: Add support for operations other than the 'transfer' 77 | */ 78 | public static class OperationDeserializer implements JsonDeserializer { 79 | 80 | @Override 81 | public BaseOperation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 82 | BaseOperation operation = null; 83 | if(json.isJsonArray()){ 84 | JsonArray array = json.getAsJsonArray(); 85 | if(array.get(0).getAsLong() == OperationType.TRANSFER_OPERATION.ordinal()){ 86 | operation = context.deserialize(array.get(1), TransferOperation.class); 87 | } 88 | } 89 | return operation; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/Chains.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * Created by nelson on 11/8/16. 5 | */ 6 | public class Chains { 7 | public static class BITSHARES { 8 | public static final String CHAIN_ID = "4018d7844c78f6a6c41c6a552b898022310fc5dec06da467ee7905a8dad512c8"; 9 | } 10 | public static class GRAPHENE { 11 | public static final String CHAIN_ID = "b8d1603965b3eb1acba27e62ff59f74efa3154d43a4188d381088ac7cdf35539"; 12 | } 13 | public static class TEST { 14 | public static final String CHAIN_ID = "39f5e2ede1f8bc1a3a54a7914414e3779e33193f1f5693510e73cb7a87617447"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/Extensions.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonDeserializationContext; 5 | import com.google.gson.JsonDeserializer; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonParseException; 8 | 9 | import java.lang.reflect.Type; 10 | import java.util.ArrayList; 11 | 12 | import cy.agorise.graphenej.interfaces.ByteSerializable; 13 | import cy.agorise.graphenej.interfaces.JsonSerializable; 14 | 15 | /** 16 | * Created by nelson on 11/9/16. 17 | */ 18 | public class Extensions implements JsonSerializable, ByteSerializable { 19 | public static final String KEY_EXTENSIONS = "extensions"; 20 | 21 | private ArrayList extensions; 22 | 23 | public Extensions(){ 24 | extensions = new ArrayList<>(); 25 | } 26 | 27 | @Override 28 | public String toJsonString() { 29 | return null; 30 | } 31 | 32 | @Override 33 | public JsonElement toJsonObject() { 34 | JsonArray array = new JsonArray(); 35 | for(JsonSerializable o : extensions) 36 | array.add(o.toJsonObject()); 37 | return array; 38 | } 39 | 40 | @Override 41 | public byte[] toBytes() { 42 | return new byte[1]; 43 | } 44 | 45 | public int size(){ 46 | return extensions.size(); 47 | } 48 | 49 | /** 50 | * Custom de-serializer used to avoid problems when de-serializing an object that contains 51 | * an extension array. 52 | */ 53 | public static class ExtensionsDeserializer implements JsonDeserializer { 54 | @Override 55 | public Extensions deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/Invoice.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonElement; 5 | 6 | import org.bitcoinj.core.Base58; 7 | 8 | import cy.agorise.graphenej.interfaces.JsonSerializable; 9 | 10 | /** 11 | * Class used to handle invoice generation, compression and QR-Code data derivation, 12 | * as detailed in this link. 13 | * @author Nelson R. Pérez 14 | */ 15 | public class Invoice implements JsonSerializable { 16 | private String to; 17 | private String to_label; 18 | private String memo; 19 | private String currency; 20 | private LineItem[] line_items; 21 | private String note; 22 | private String callback; 23 | 24 | public Invoice(String to, String to_label, String memo, String currency, LineItem[] items, String note, String callback){ 25 | this.to = to; 26 | this.to_label = to_label; 27 | this.memo = memo; 28 | this.currency = currency; 29 | this.line_items = items; 30 | this.note = note; 31 | this.callback = callback; 32 | } 33 | 34 | public String getToLabel() { 35 | return to_label; 36 | } 37 | 38 | public void setToLabel(String to_label) { 39 | this.to_label = to_label; 40 | } 41 | 42 | public String getNote() { 43 | return note; 44 | } 45 | 46 | public void setNote(String note) { 47 | this.note = note; 48 | } 49 | 50 | public String getTo() { 51 | return to; 52 | } 53 | 54 | public void setTo(String to) { 55 | this.to = to; 56 | } 57 | 58 | public String getMemo() { 59 | return memo; 60 | } 61 | 62 | public void setMemo(String memo) { 63 | this.memo = memo; 64 | } 65 | 66 | public String getCurrency() { 67 | return currency; 68 | } 69 | 70 | public void setCurrency(String currency) { 71 | this.currency = currency; 72 | } 73 | 74 | public LineItem[] getLineItems() { 75 | return line_items; 76 | } 77 | 78 | public void setLineItems(LineItem[] line_items) { 79 | this.line_items = line_items; 80 | } 81 | 82 | public String getCallback() { 83 | return callback; 84 | } 85 | 86 | public void setCallback(String callback) { 87 | this.callback = callback; 88 | } 89 | 90 | @Override 91 | public String toJsonString() { 92 | Gson gson = new Gson(); 93 | return gson.toJson(this); 94 | } 95 | 96 | @Override 97 | public JsonElement toJsonObject() { 98 | return null; 99 | } 100 | 101 | public static String toQrCode(Invoice invoice){ 102 | String json = invoice.toJsonString(); 103 | return Base58.encode(Util.compress(json.getBytes(), Util.LZMA)); 104 | } 105 | 106 | public static Invoice fromQrCode(String encoded){ 107 | String json = new String(Util.decompress(Base58.decode(encoded), Util.LZMA)); 108 | Gson gson = new Gson(); 109 | return gson.fromJson(json, Invoice.class); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/LineItem.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * Created by nelson on 1/11/17. 5 | */ 6 | public class LineItem { 7 | private String label; 8 | private int quantity; 9 | private double price; 10 | 11 | public LineItem(String label, int quantity, double price){ 12 | this.label = label; 13 | this.quantity = quantity; 14 | this.price = price; 15 | } 16 | 17 | public int getQuantity() { 18 | return quantity; 19 | } 20 | 21 | public void setQuantity(int quantity) { 22 | this.quantity = quantity; 23 | } 24 | 25 | public double getPrice() { 26 | return price; 27 | } 28 | 29 | public void setPrice(double price) { 30 | this.price = price; 31 | } 32 | 33 | public String getLabel(){ 34 | return label; 35 | } 36 | 37 | public void setLabel(String label) { 38 | this.label = label; 39 | } 40 | } -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/MarketTrade.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * 5 | * @author henry 6 | */ 7 | public class MarketTrade { 8 | public String date; 9 | public double price; 10 | public double amount; 11 | public double value; 12 | } 13 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/OperationType.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * Enum type used to keep track of all the operation types and their corresponding ids. 5 | * 6 | * Source 7 | * 8 | * Created by nelson on 11/6/16. 9 | */ 10 | public enum OperationType { 11 | TRANSFER_OPERATION, 12 | LIMIT_ORDER_CREATE_OPERATION, 13 | LIMIT_ORDER_CANCEL_OPERATION, 14 | CALL_ORDER_UPDATE_OPERATION, 15 | FILL_ORDER_OPERATION, // VIRTUAL 16 | ACCOUNT_CREATE_OPERATION, 17 | ACCOUNT_UPDATE_OPERATION, 18 | ACCOUNT_WHITELIST_OPERATION, 19 | ACCOUNT_UPGRADE_OPERATION, 20 | ACCOUNT_TRANSFER_OPERATION, 21 | ASSET_CREATE_OPERATION, 22 | ASSET_UPDATE_OPERATION, 23 | ASSET_UPDATE_BITASSET_OPERATION, 24 | ASSET_UPDATE_FEED_PRODUCERS_OPERATION, 25 | ASSET_ISSUE_OPERATION, 26 | ASSET_RESERVE_OPERATION, 27 | ASSET_FUND_FEE_POOL_OPERATION, 28 | ASSET_SETTLE_OPERATION, 29 | ASSET_GLOBAL_SETTLE_OPERATION, 30 | ASSET_PUBLISH_FEED_OPERATION, 31 | WITNESS_CREATE_OPERATION, 32 | WITNESS_UPDATE_OPERATION, 33 | PROPOSAL_CREATE_OPERATION, 34 | PROPOSAL_UPDATE_OPERATION, 35 | PROPOSAL_DELETE_OPERATION, 36 | WITHDRAW_PERMISSION_CREATE_OPERATION, 37 | WITHDRAW_PERMISSION_UPDATE_OPERATION, 38 | WITHDRAW_PERMISSION_CLAIM_OPERATION, 39 | WITHDRAW_PERMISSION_DELETE_OPERATION, 40 | COMMITTEE_MEMBER_CREATE_OPERATION, 41 | COMMITTEE_MEMBER_UPDATE_OPERATION, 42 | COMMITTEE_MEMBER_UPDATE_GLOBAL_PARAMETERS_OPERATION, 43 | VESTING_BALANCE_CREATE_OPERATION, 44 | VESTING_BALANCE_WITHDRAW_OPERATION, 45 | WORKER_CREATE_OPERATION, 46 | CUSTOM_OPERATION, 47 | ASSERT_OPERATION, 48 | BALANCE_CLAIM_OPERATION, 49 | OVERRIDE_TRANSFER_OPERATION, 50 | TRANSFER_TO_BLIND_OPERATION, 51 | BLIND_TRANSFER_OPERATION, 52 | TRANSFER_FROM_BLIND_OPERATION, 53 | ASSET_SETTLE_CANCEL_OPERATION, // VIRTUAL 54 | ASSET_CLAIM_FEES_OPERATION 55 | } 56 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/Optional.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.gson.JsonElement; 4 | 5 | import cy.agorise.graphenej.interfaces.ByteSerializable; 6 | import cy.agorise.graphenej.interfaces.GrapheneSerializable; 7 | 8 | /** 9 | * Container template class used whenever we have an optional field. 10 | * 11 | * The idea here is that the binary serialization of this field should be performed 12 | * in a specific way determined by the field implementing the {@link ByteSerializable} 13 | * interface, more specifically using the {@link ByteSerializable#toBytes()} method. 14 | * 15 | * However, if the field is missing, the Optional class should be able to know how 16 | * to serialize it, as this is always done by placing an zero byte. 17 | */ 18 | public class Optional implements GrapheneSerializable { 19 | private T optionalField; 20 | 21 | public Optional(T field){ 22 | optionalField = field; 23 | } 24 | 25 | @Override 26 | public byte[] toBytes() { 27 | if(optionalField == null) 28 | return new byte[] { (byte) 0 }; 29 | else 30 | return optionalField.toBytes(); 31 | } 32 | 33 | public boolean isSet(){ 34 | return this.optionalField != null; 35 | } 36 | 37 | @Override 38 | public String toJsonString() { 39 | return optionalField.toJsonString(); 40 | } 41 | 42 | @Override 43 | public JsonElement toJsonObject() { 44 | return optionalField.toJsonObject(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/Price.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * The price struct stores asset prices in the Graphene system. 5 | * 6 | * A price is defined as a ratio between two assets, and represents a possible exchange rate 7 | * between those two assets. prices are generally not stored in any simplified form, i.e. a price 8 | * of (1000 CORE)/(20 USD) is perfectly normal. 9 | 10 | * The assets within a price are labeled base and quote. Throughout the Graphene code base, 11 | * the convention used is that the base asset is the asset being sold, and the quote asset is 12 | * the asset being purchased, where the price is represented as base/quote, so in the example 13 | * price above the seller is looking to sell CORE asset and get USD in return. 14 | * 15 | * Note: Taken from the Graphene doxygen. 16 | * Created by nelson on 12/16/16. 17 | */ 18 | public class Price { 19 | public AssetAmount base; 20 | public AssetAmount quote; 21 | 22 | @Override 23 | public String toString() { 24 | return String.format("base:[%s, %s], quote:[%s, %s]", 25 | base.getAsset().getObjectId(), 26 | base.getAmount().toString(), 27 | quote.getAsset().getObjectId(), 28 | quote.getAmount().toString()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/PublicKey.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import org.bitcoinj.core.ECKey; 4 | import org.spongycastle.math.ec.ECPoint; 5 | 6 | import java.io.Serializable; 7 | 8 | import cy.agorise.graphenej.interfaces.ByteSerializable; 9 | 10 | /** 11 | * Created by nelson on 11/30/16. 12 | */ 13 | public class PublicKey implements ByteSerializable, Serializable { 14 | private ECKey publicKey; 15 | 16 | public PublicKey(ECKey key) { 17 | if(key.hasPrivKey()){ 18 | throw new IllegalStateException("Passing a private key to PublicKey constructor"); 19 | } 20 | this.publicKey = key; 21 | } 22 | 23 | public ECKey getKey(){ 24 | return publicKey; 25 | } 26 | 27 | @Override 28 | public byte[] toBytes() { 29 | if(publicKey.isCompressed()) { 30 | return publicKey.getPubKey(); 31 | }else{ 32 | publicKey = ECKey.fromPublicOnly(ECKey.compressPoint(publicKey.getPubKeyPoint())); 33 | return publicKey.getPubKey(); 34 | } 35 | } 36 | 37 | public String getAddress(){ 38 | ECKey pk = ECKey.fromPublicOnly(publicKey.getPubKey()); 39 | if(!pk.isCompressed()){ 40 | ECPoint point = ECKey.compressPoint(pk.getPubKeyPoint()); 41 | pk = ECKey.fromPublicOnly(point); 42 | } 43 | return new Address(pk).toString(); 44 | } 45 | 46 | @Override 47 | public int hashCode() { 48 | return publicKey.hashCode(); 49 | } 50 | 51 | @Override 52 | public boolean equals(Object obj) { 53 | PublicKey other = (PublicKey) obj; 54 | return this.publicKey.equals(other.getKey()); 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return getAddress(); 60 | } 61 | } -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/RPC.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * Created by nelson on 11/16/16. 5 | */ 6 | public class RPC { 7 | public static final String VERSION = "2.0"; 8 | public static final String CALL_LOGIN = "login"; 9 | public static final String CALL_NETWORK_BROADCAST = "network_broadcast"; 10 | public static final String CALL_HISTORY = "history"; 11 | public static final String CALL_DATABASE = "database"; 12 | public static final String CALL_ASSET = "asset"; 13 | public static final String CALL_SET_SUBSCRIBE_CALLBACK = "set_subscribe_callback"; 14 | public static final String CALL_CANCEL_ALL_SUBSCRIPTIONS = "cancel_all_subscriptions"; 15 | public static final String CALL_GET_ACCOUNT_BY_NAME = "get_account_by_name"; 16 | public static final String CALL_GET_ACCOUNTS = "get_accounts"; 17 | public static final String CALL_GET_FULL_ACCOUNTS = "get_full_accounts"; 18 | public static final String CALL_GET_DYNAMIC_GLOBAL_PROPERTIES = "get_dynamic_global_properties"; 19 | public static final String CALL_BROADCAST_TRANSACTION = "broadcast_transaction"; 20 | public static final String CALL_GET_REQUIRED_FEES = "get_required_fees"; 21 | public static final String CALL_GET_KEY_REFERENCES = "get_key_references"; 22 | public static final String CALL_GET_RELATIVE_ACCOUNT_HISTORY = "get_relative_account_history"; 23 | public static final String CALL_GET_ACCOUNT_HISTORY = "get_account_history"; 24 | public static final String CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS = "get_account_history_by_operations"; 25 | public static final String CALL_LOOKUP_ACCOUNTS = "lookup_accounts"; 26 | public static final String CALL_LIST_ASSETS = "list_assets"; 27 | public static final String CALL_GET_OBJECTS = "get_objects"; 28 | public static final String GET_ACCOUNT_BALANCES = "get_account_balances"; 29 | public static final String CALL_LOOKUP_ASSET_SYMBOLS = "lookup_asset_symbols"; 30 | public static final String CALL_GET_BLOCK_HEADER = "get_block_header"; 31 | public static final String CALL_GET_BLOCK = "get_block"; 32 | public static final String CALL_GET_LIMIT_ORDERS = "get_limit_orders"; 33 | public static final String CALL_GET_TRADE_HISTORY = "get_trade_history"; 34 | public static final String CALL_GET_MARKET_HISTORY = "get_market_history"; 35 | public static final String CALL_GET_ALL_ASSET_HOLDERS = "get_all_asset_holders"; 36 | } -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/Vote.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import cy.agorise.graphenej.interfaces.ByteSerializable; 4 | 5 | /** 6 | * Created by nelson on 12/5/16. 7 | */ 8 | public class Vote implements ByteSerializable { 9 | private int type; 10 | private int instance; 11 | 12 | public Vote(String vote){ 13 | String[] parts = vote.split(":"); 14 | assert(parts.length == 2); 15 | this.type = Integer.valueOf(parts[0]); 16 | this.instance = Integer.valueOf(parts[1]); 17 | } 18 | 19 | public Vote(int type, int instance){ 20 | this.type = type; 21 | this.instance = instance; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return String.format("%d:%d", this.type, this.instance); 27 | } 28 | 29 | @Override 30 | public byte[] toBytes() { 31 | return new byte[] { (byte) this.instance, (byte) this.type }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/ApiAccess.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | /** 4 | * Class used to list all currently supported API accesses 5 | */ 6 | 7 | public class ApiAccess { 8 | public static final int API_NONE = 0x00; 9 | public static final int API_DATABASE = 0x01; 10 | public static final int API_HISTORY = 0x02; 11 | public static final int API_NETWORK_BROADCAST = 0x04; 12 | } 13 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/BaseGrapheneHandler.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | import com.neovisionaries.ws.client.WebSocket; 4 | import com.neovisionaries.ws.client.WebSocketAdapter; 5 | import com.neovisionaries.ws.client.WebSocketException; 6 | 7 | import cy.agorise.graphenej.interfaces.NodeErrorListener; 8 | import cy.agorise.graphenej.interfaces.WitnessResponseListener; 9 | import cy.agorise.graphenej.models.BaseResponse; 10 | 11 | /** 12 | * Base class that should be extended by any implementation of a specific request to the full node. 13 | */ 14 | public abstract class BaseGrapheneHandler extends WebSocketAdapter { 15 | 16 | protected WitnessResponseListener mListener; 17 | protected NodeErrorListener mErrorListener; 18 | 19 | /** 20 | * The 'id' field of a message to the node. This is used in order to multiplex different messages 21 | * using the same websocket connection. 22 | * 23 | * For example: 24 | * 25 | * {"id":5,"method":"call","params":[0,"get_accounts",[["1.2.100"]]],"jsonrpc":"2.0"} 26 | * 27 | * The 'requestId' here is 5. 28 | */ 29 | protected long requestId; 30 | 31 | /** 32 | * Constructor (The original constructor, should be replaced with the one that receives 33 | * NodeErrorListener instead of WitnessResponseListener) 34 | * 35 | * @param listener listener to be notified in if an error occurs 36 | */ 37 | @Deprecated 38 | public BaseGrapheneHandler(WitnessResponseListener listener){ 39 | this.mListener = listener; 40 | } 41 | 42 | /** 43 | * Constructor 44 | * 45 | * @param listener listener to be notified if an error occurs 46 | */ 47 | public BaseGrapheneHandler(NodeErrorListener listener){ 48 | this.mErrorListener = listener; 49 | } 50 | 51 | @Override 52 | public void onError(WebSocket websocket, WebSocketException cause) throws Exception { 53 | System.out.println("onError. cause: "+cause.getMessage()); 54 | mErrorListener.onError(new BaseResponse.Error(cause.getMessage())); 55 | websocket.disconnect(); 56 | } 57 | 58 | @Override 59 | public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { 60 | System.out.println("handleCallbackError. message: "+cause.getMessage()+", error: "+cause.getClass()); 61 | for (StackTraceElement element : cause.getStackTrace()){ 62 | System.out.println(element.getFileName()+"#"+element.getClassName()+":"+element.getLineNumber()); 63 | } 64 | // Should be replaced for mErrorListener (NodeErrorListener type) only in the future 65 | if(mErrorListener != null){ 66 | mErrorListener.onError(new BaseResponse.Error(cause.getMessage())); 67 | } 68 | else{ 69 | mListener.onError(new BaseResponse.Error(cause.getMessage())); 70 | } 71 | 72 | websocket.disconnect(); 73 | } 74 | 75 | public void setRequestId(long id){ 76 | this.requestId = id; 77 | } 78 | 79 | public long getRequestId(){ 80 | return this.requestId; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/ConnectionStatusUpdate.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | /** 4 | * Class used to send connection status updates. 5 | * 6 | * Connection status updates can be any of the following: 7 | * - {@link ConnectionStatusUpdate#CONNECTED} 8 | * - {@link ConnectionStatusUpdate#AUTHENTICATED} 9 | * - {@link ConnectionStatusUpdate#API_UPDATE} 10 | * - {@link ConnectionStatusUpdate#DISCONNECTED} 11 | * 12 | * This is specified by the field called {@link #updateCode}. 13 | * 14 | * If the updateCode is ConnectionStatusUpdate#API_UPDATE another extra field called 15 | * {@link #api} is used to specify which api we're getting access to. 16 | */ 17 | 18 | public class ConnectionStatusUpdate { 19 | // Constant used to announce that a connection has been established 20 | public final static int CONNECTED = 0; 21 | // Constant used to announce a successful authentication 22 | public final static int AUTHENTICATED = 1; 23 | // Constant used to announce an api update 24 | public final static int API_UPDATE = 2; 25 | // Constant used to announce a disconnection event 26 | public final static int DISCONNECTED = 3; 27 | 28 | /** 29 | * The update code is the general purpose of the update message. Can be any of the following: 30 | * - {@link ConnectionStatusUpdate#CONNECTED} 31 | * - {@link ConnectionStatusUpdate#AUTHENTICATED} 32 | * - {@link ConnectionStatusUpdate#API_UPDATE} 33 | * - {@link ConnectionStatusUpdate#DISCONNECTED} 34 | */ 35 | private int updateCode; 36 | 37 | /** 38 | * This field is used in case the updateCode is {@link ConnectionStatusUpdate#API_UPDATE} and 39 | * it serves to specify which API we're getting access to. 40 | * 41 | * It can be any of the fields defined in {@link ApiAccess} 42 | */ 43 | private int api; 44 | 45 | public ConnectionStatusUpdate(int updateCode, int api){ 46 | this.updateCode = updateCode; 47 | this.api = api; 48 | } 49 | 50 | public int getUpdateCode() { 51 | return updateCode; 52 | } 53 | 54 | public void setUpdateCode(int updateCode) { 55 | this.updateCode = updateCode; 56 | } 57 | 58 | public int getApi() { 59 | return api; 60 | } 61 | 62 | public void setApi(int api) { 63 | this.api = api; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/GetAccountHistory.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | /** 4 | * Created by nelson on 12/26/16. 5 | */ 6 | //TODO: Implement if needed: http://docs.bitshares.eu/api/history.html?highlight=get_market_history#account-history-api 7 | public class GetAccountHistory { 8 | } 9 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/android/RxBus.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.android; 2 | 3 | import com.jakewharton.rxrelay2.PublishRelay; 4 | import com.jakewharton.rxrelay2.Relay; 5 | 6 | import io.reactivex.BackpressureStrategy; 7 | import io.reactivex.Flowable; 8 | 9 | /** 10 | * Explained here: https://blog.kaush.co/2014/12/24/implementing-an-event-bus-with-rxjava-rxbus/ 11 | */ 12 | public class RxBus { 13 | 14 | private static RxBus rxBus; 15 | 16 | public static final RxBus getBusInstance(){ 17 | if(rxBus == null){ 18 | rxBus = new RxBus(); 19 | } 20 | return rxBus; 21 | } 22 | 23 | private final Relay _bus = PublishRelay.create().toSerialized(); 24 | 25 | public void send(Object o) { 26 | _bus.accept(o); 27 | } 28 | 29 | public Flowable asFlowable() { 30 | return _bus.toFlowable(BackpressureStrategy.LATEST); 31 | } 32 | 33 | public boolean hasObservers() { 34 | return _bus.hasObservers(); 35 | } 36 | } -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/bitshares/Nodes.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.bitshares; 2 | 3 | /** 4 | * Known public nodes 5 | */ 6 | 7 | public class Nodes { 8 | public static final String[] NODE_URLS = { 9 | //"wss://dexnode.net/ws", // Dallas, USA TODO not working properly, verify 10 | "wss://bitshares.crypto.fans/ws", // Munich, Germany 11 | "wss://bitshares.openledger.info/ws", // Openledger node 12 | "wss://us.nodes.bitshares.ws", 13 | "wss://eu.nodes.bitshares.ws" 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/ApiCallable.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import cy.agorise.graphenej.models.ApiCall; 4 | 5 | /** 6 | * Interface to be implemented by all classes that will produce an ApiCall object instance 7 | * as a result. 8 | */ 9 | 10 | public interface ApiCallable { 11 | 12 | /** 13 | * 14 | * @return An instance of the {@link ApiCall} class 15 | */ 16 | ApiCall toApiCall(int apiId, long sequenceId); 17 | } 18 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/CancelAllSubscriptions.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | public class CancelAllSubscriptions implements ApiCallable { 11 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 12 | 13 | @Override 14 | public ApiCall toApiCall(int apiId, long sequenceId) { 15 | return new ApiCall(apiId, RPC.CALL_CANCEL_ALL_SUBSCRIPTIONS, new ArrayList(), RPC.VERSION, sequenceId); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccountByName.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | public class GetAccountByName implements ApiCallable { 11 | public static final int REQUIRED_API = ApiAccess.API_NONE; 12 | 13 | private String accountName; 14 | 15 | public GetAccountByName(String name){ 16 | this.accountName = name; 17 | } 18 | 19 | @Override 20 | public ApiCall toApiCall(int apiId, long sequenceId) { 21 | ArrayList accountParams = new ArrayList<>(); 22 | accountParams.add(this.accountName); 23 | return new ApiCall(apiId, RPC.CALL_GET_ACCOUNT_BY_NAME, accountParams, RPC.VERSION, sequenceId); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccountHistory.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.UserAccount; 8 | import cy.agorise.graphenej.api.ApiAccess; 9 | import cy.agorise.graphenej.models.ApiCall; 10 | 11 | public class GetAccountHistory implements ApiCallable { 12 | public static final int REQUIRED_API = ApiAccess.API_HISTORY; 13 | 14 | private UserAccount mUserAccount; 15 | private String startOperation; 16 | private String endOperation; 17 | private int limit; 18 | 19 | public GetAccountHistory(UserAccount userAccount, String start, String end, int limit){ 20 | this.mUserAccount = userAccount; 21 | this.startOperation = start; 22 | this.endOperation = end; 23 | this.limit = limit; 24 | } 25 | 26 | public GetAccountHistory(String userId, String start, String end, int limit){ 27 | this.mUserAccount = new UserAccount(userId); 28 | this.startOperation = start; 29 | this.endOperation = end; 30 | this.limit = limit; 31 | } 32 | 33 | 34 | @Override 35 | public ApiCall toApiCall(int apiId, long sequenceId) { 36 | ArrayList params = new ArrayList<>(); 37 | params.add(mUserAccount.getObjectId()); 38 | params.add(endOperation); 39 | params.add(limit); 40 | params.add(startOperation); 41 | return new ApiCall(apiId, RPC.CALL_GET_ACCOUNT_HISTORY, params, RPC.VERSION, sequenceId); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccountHistoryByOperations.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cy.agorise.graphenej.OperationType; 8 | import cy.agorise.graphenej.RPC; 9 | import cy.agorise.graphenej.UserAccount; 10 | import cy.agorise.graphenej.api.ApiAccess; 11 | import cy.agorise.graphenej.models.ApiCall; 12 | 13 | public class GetAccountHistoryByOperations implements ApiCallable { 14 | 15 | public static final int REQUIRED_API = ApiAccess.API_HISTORY; 16 | 17 | private UserAccount mUserAccount; 18 | private List mOperationTypes; 19 | private long mStart; 20 | private long mLimit; 21 | 22 | /** 23 | * @param userAccount The user account that should be queried 24 | * @param operationsTypes The IDs of the operation we want to get operations in the account( 0 = transfer , 1 = limit order create, ...) 25 | * @param start The sequence number where to start listing operations 26 | * @param limit The max number of entries to return (from start number) 27 | */ 28 | public GetAccountHistoryByOperations(UserAccount userAccount, List operationsTypes, long start, long limit){ 29 | this.mUserAccount = userAccount; 30 | this.mOperationTypes = operationsTypes; 31 | this.mStart = start; 32 | this.mLimit = limit; 33 | } 34 | 35 | /** 36 | * @param userAccount The user account that should be queried 37 | * @param operationsTypes The IDs of the operation we want to get operations in the account( 0 = transfer , 1 = limit order create, ...) 38 | * @param start The sequence number where to start listing operations 39 | * @param limit The max number of entries to return (from start number) 40 | */ 41 | public GetAccountHistoryByOperations(String userAccount, List operationsTypes, long start, long limit){ 42 | if(userAccount.matches("^1\\.2\\.\\d*$")){ 43 | this.mUserAccount = new UserAccount(userAccount); 44 | }else{ 45 | this.mUserAccount = new UserAccount("", userAccount); 46 | } 47 | this.mOperationTypes = operationsTypes; 48 | this.mStart = start; 49 | this.mLimit = limit; 50 | } 51 | 52 | @Override 53 | public ApiCall toApiCall(int apiId, long sequenceId) { 54 | ArrayList params = new ArrayList<>(); 55 | if(mUserAccount.getName() != null){ 56 | params.add(mUserAccount.getName()); 57 | }else{ 58 | params.add(mUserAccount.getObjectId()); 59 | } 60 | ArrayList operationTypes = new ArrayList<>(); 61 | for(OperationType operationType : mOperationTypes){ 62 | operationTypes.add(operationType.ordinal()); 63 | } 64 | params.add(operationTypes); 65 | params.add(mStart); 66 | params.add(mLimit); 67 | return new ApiCall(apiId, RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS, params, RPC.VERSION, sequenceId); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccounts.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cy.agorise.graphenej.RPC; 8 | import cy.agorise.graphenej.UserAccount; 9 | import cy.agorise.graphenej.api.ApiAccess; 10 | import cy.agorise.graphenej.models.ApiCall; 11 | 12 | /** 13 | * Wrapper around the "get_accounts" API call. 14 | */ 15 | public class GetAccounts implements ApiCallable { 16 | public static final int REQUIRED_API = ApiAccess.API_NONE; 17 | 18 | private List mUserAccounts; 19 | 20 | public GetAccounts(List accountList){ 21 | mUserAccounts = accountList; 22 | } 23 | 24 | public GetAccounts(UserAccount userAccount){ 25 | mUserAccounts = new ArrayList<>(); 26 | mUserAccounts.add(userAccount); 27 | } 28 | 29 | @Override 30 | public ApiCall toApiCall(int apiId, long sequenceId) { 31 | ArrayList params = new ArrayList<>(); 32 | ArrayList accountIds = new ArrayList<>(); 33 | for(UserAccount userAccount : mUserAccounts){ 34 | accountIds.add(userAccount.getObjectId()); 35 | } 36 | params.add(accountIds); 37 | return new ApiCall(apiId, RPC.CALL_GET_ACCOUNTS, params, RPC.VERSION, sequenceId); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetBlock.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | /** 11 | * Wrapper around the "get_block" API call. 12 | */ 13 | 14 | public class GetBlock implements ApiCallable { 15 | 16 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 17 | 18 | private long blockNumber; 19 | 20 | public GetBlock(long blockNum){ 21 | this.blockNumber = blockNum; 22 | } 23 | 24 | public ApiCall toApiCall(int apiId, long sequenceId){ 25 | ArrayList params = new ArrayList<>(); 26 | String blockNum = String.format("%d", this.blockNumber); 27 | params.add(blockNum); 28 | return new ApiCall(apiId, RPC.CALL_GET_BLOCK, params, RPC.VERSION, sequenceId); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetBlockHeader.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | /** 11 | * Wrapper around the "get_block_header" API call. To be used in the single-connection mode. 12 | */ 13 | public class GetBlockHeader implements ApiCallable { 14 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 15 | 16 | private long blockNumber; 17 | 18 | public GetBlockHeader(long number){ 19 | this.blockNumber = number; 20 | } 21 | 22 | @Override 23 | public ApiCall toApiCall(int apiId, long sequenceId) { 24 | ArrayList params = new ArrayList<>(); 25 | String blockNum = String.format("%d", this.blockNumber); 26 | params.add(blockNum); 27 | 28 | return new ApiCall(apiId, RPC.CALL_GET_BLOCK_HEADER, params, RPC.VERSION, sequenceId); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetDynamicGlobalProperties.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | public class GetDynamicGlobalProperties implements ApiCallable { 11 | public static final int REQUIRED_API = ApiAccess.API_NONE; 12 | 13 | @Override 14 | public ApiCall toApiCall(int apiId, long sequenceId) { 15 | ArrayList params = new ArrayList<>(); 16 | return new ApiCall(apiId, RPC.CALL_GET_DYNAMIC_GLOBAL_PROPERTIES, params, RPC.VERSION, sequenceId); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetFullAccounts.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cy.agorise.graphenej.RPC; 8 | import cy.agorise.graphenej.api.ApiAccess; 9 | import cy.agorise.graphenej.models.ApiCall; 10 | 11 | /** 12 | * Wrapper around the 'get_full_accounts' API call. 13 | */ 14 | public class GetFullAccounts implements ApiCallable { 15 | 16 | public static final int REQUIRED_API = ApiAccess.API_NONE; 17 | 18 | private List mUserAccounts; 19 | private boolean mSubscribe; 20 | 21 | public GetFullAccounts(List accounts, boolean subscribe){ 22 | this.mUserAccounts = accounts; 23 | this.mSubscribe = subscribe; 24 | } 25 | 26 | @Override 27 | public ApiCall toApiCall(int apiId, long sequenceId) { 28 | ArrayList params = new ArrayList<>(); 29 | ArrayList accounts = new ArrayList(mUserAccounts); 30 | params.add(accounts); 31 | params.add(mSubscribe); 32 | return new ApiCall(apiId, RPC.CALL_GET_FULL_ACCOUNTS, params, RPC.VERSION, sequenceId); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetKeyReferences.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cy.agorise.graphenej.Address; 8 | import cy.agorise.graphenej.RPC; 9 | import cy.agorise.graphenej.api.ApiAccess; 10 | import cy.agorise.graphenej.errors.MalformedAddressException; 11 | import cy.agorise.graphenej.models.ApiCall; 12 | 13 | /** 14 | * Wrapper around the 'get_key_references' API call. 15 | */ 16 | public class GetKeyReferences implements ApiCallable { 17 | public static final int REQUIRED_API = ApiAccess.API_NONE; 18 | 19 | private List
addresses = new ArrayList<>(); 20 | 21 | public GetKeyReferences(String addr) throws MalformedAddressException, IllegalArgumentException { 22 | this(new Address(addr)); 23 | } 24 | 25 | public GetKeyReferences(Address address){ 26 | addresses.add(address); 27 | } 28 | 29 | public GetKeyReferences(List
addressList){ 30 | addresses.addAll(addressList); 31 | } 32 | 33 | @Override 34 | public ApiCall toApiCall(int apiId, long sequenceId) { 35 | ArrayList inner = new ArrayList(); 36 | for(Address addr : addresses){ 37 | inner.add(addr.toString()); 38 | } 39 | ArrayList params = new ArrayList<>(); 40 | params.add(inner); 41 | return new ApiCall(apiId, RPC.CALL_GET_KEY_REFERENCES, params, RPC.VERSION, sequenceId); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetLimitOrders.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | /** Class that implements get_limit_orders request handler. 11 | * 12 | * Get limit orders in a given market. 13 | * 14 | * The request returns the limit orders, ordered from least price to greatest 15 | * 16 | * @see get_limit_orders API doc 17 | * 18 | */ 19 | public class GetLimitOrders implements ApiCallable { 20 | 21 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 22 | 23 | private String a; 24 | private String b; 25 | private int limit; 26 | 27 | public GetLimitOrders(String a, String b, int limit){ 28 | this.a = a; 29 | this.b = b; 30 | this.limit = limit; 31 | } 32 | 33 | @Override 34 | public ApiCall toApiCall(int apiId, long sequenceId) { 35 | ArrayList parameters = new ArrayList<>(); 36 | parameters.add(a); 37 | parameters.add(b); 38 | parameters.add(limit); 39 | return new ApiCall(apiId, RPC.CALL_GET_LIMIT_ORDERS, parameters, RPC.VERSION, sequenceId); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetMarketHistory.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.text.SimpleDateFormat; 5 | import java.util.ArrayList; 6 | import java.util.Calendar; 7 | import java.util.Date; 8 | 9 | import cy.agorise.graphenej.Asset; 10 | import cy.agorise.graphenej.RPC; 11 | import cy.agorise.graphenej.api.ApiAccess; 12 | import cy.agorise.graphenej.models.ApiCall; 13 | 14 | public class GetMarketHistory implements ApiCallable { 15 | public static final int REQUIRED_API = ApiAccess.API_HISTORY; 16 | 17 | public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 18 | 19 | // API call parameters 20 | private Asset base; 21 | private Asset quote; 22 | private long bucket; 23 | private Date start; 24 | private Date end; 25 | 26 | /** 27 | * Constructor that receives the start and end time as UNIX timestamp in milliseconds. 28 | * 29 | * @param base Desired asset history 30 | * @param quote Asset to which the base price will be compared to 31 | * @param bucket The time interval (in seconds) for each point should be (analog to 32 | * candles on a candle stick graph). 33 | * @param start Timestamp (POSIX) of of the most recent operation to retrieve 34 | * (Note: The name can be counter intuitive, but it follow the original 35 | * API parameter name) 36 | * @param end Timestamp (POSIX) of the the earliest operation to retrieve 37 | */ 38 | public GetMarketHistory(Asset base, Asset quote, long bucket, long start, long end){ 39 | this(base, quote, bucket, fromTimestamp(start), fromTimestamp(end)); 40 | } 41 | 42 | /** 43 | * Constructor that receives the start and end time as Date instance objects. 44 | * 45 | * @param base Desired asset history 46 | * @param quote Asset to which the base price will be compared to 47 | * @param bucket The time interval (in seconds) for each point should be (analog to 48 | * candles on a candle stick graph). 49 | * @param start Date and time of of the most recent operation to retrieve 50 | * (Note: The name can be counter intuitive, but it follow the original 51 | * API parameter name) 52 | * @param end Date and time of the the earliest operation to retrieve 53 | */ 54 | public GetMarketHistory(Asset base, Asset quote, long bucket, Date start, Date end){ 55 | this.base = base; 56 | this.quote = quote; 57 | this.bucket = bucket; 58 | this.start = start; 59 | this.end = end; 60 | } 61 | 62 | /** 63 | * Internal method used to convert a timestamp to a Date. 64 | * 65 | * @param timestamp POSIX timestamp expressed in milliseconds since 1/1/1970 66 | * @return Date instance 67 | */ 68 | private static Date fromTimestamp(long timestamp){ 69 | Calendar calendar = Calendar.getInstance(); 70 | calendar.setTimeInMillis(timestamp); 71 | calendar.set(Calendar.MINUTE, 0); 72 | calendar.set(Calendar.SECOND, 0); 73 | return calendar.getTime(); 74 | } 75 | 76 | @Override 77 | public ApiCall toApiCall(int apiId, long sequenceId) { 78 | ArrayList params = new ArrayList<>(); 79 | params.add(this.base.getObjectId()); 80 | params.add(this.quote.getObjectId()); 81 | params.add(this.bucket); 82 | params.add(DATE_FORMAT.format(this.start)); 83 | params.add(DATE_FORMAT.format(this.end)); 84 | return new ApiCall(apiId, RPC.CALL_GET_MARKET_HISTORY, params, RPC.VERSION, sequenceId); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetObjects.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cy.agorise.graphenej.RPC; 8 | import cy.agorise.graphenej.api.ApiAccess; 9 | import cy.agorise.graphenej.models.ApiCall; 10 | 11 | /** 12 | * Wrapper around the "get_objects" API call. 13 | */ 14 | public class GetObjects implements ApiCallable { 15 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 16 | private List ids; 17 | 18 | public GetObjects(List ids){ 19 | this.ids = ids; 20 | } 21 | 22 | @Override 23 | public ApiCall toApiCall(int apiId, long sequenceId) { 24 | ArrayList params = new ArrayList<>(); 25 | ArrayList subParams = new ArrayList<>(ids); 26 | params.add(subParams); 27 | return new ApiCall(apiId, RPC.CALL_GET_OBJECTS, params, RPC.VERSION, sequenceId); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetRelativeAccountHistory.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.UserAccount; 8 | import cy.agorise.graphenej.api.ApiAccess; 9 | import cy.agorise.graphenej.models.ApiCall; 10 | 11 | /** 12 | * Wrapper around the "get_relative_account_history" API call 13 | */ 14 | public class GetRelativeAccountHistory implements ApiCallable { 15 | 16 | public static final int REQUIRED_API = ApiAccess.API_HISTORY; 17 | 18 | // API call parameters 19 | private UserAccount mUserAccount; 20 | private int stop; 21 | private int limit; 22 | private int start; 23 | 24 | /** 25 | * Constructor 26 | * @param userAccount 27 | * @param stop 28 | * @param limit 29 | * @param start 30 | */ 31 | public GetRelativeAccountHistory(UserAccount userAccount, int stop, int limit, int start){ 32 | this.mUserAccount = userAccount; 33 | this.stop = stop; 34 | this.limit = limit; 35 | this.start = start; 36 | } 37 | 38 | @Override 39 | public ApiCall toApiCall(int apiId, long sequenceId) { 40 | ArrayList params = new ArrayList<>(); 41 | params.add(mUserAccount.getObjectId()); 42 | params.add(this.stop); 43 | params.add(this.limit); 44 | params.add(this.start); 45 | return new ApiCall(apiId, RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY, params, RPC.VERSION, sequenceId); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetRequiredFees.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cy.agorise.graphenej.Asset; 8 | import cy.agorise.graphenej.BaseOperation; 9 | import cy.agorise.graphenej.BlockData; 10 | import cy.agorise.graphenej.RPC; 11 | import cy.agorise.graphenej.Transaction; 12 | import cy.agorise.graphenej.api.ApiAccess; 13 | import cy.agorise.graphenej.models.ApiCall; 14 | 15 | /** 16 | * Wrapper around the "get_required_fees" API call 17 | */ 18 | 19 | public class GetRequiredFees implements ApiCallable { 20 | 21 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 22 | 23 | private Transaction mTransaction; 24 | private Asset mFeeAsset; 25 | 26 | public GetRequiredFees(Transaction transaction, Asset feeAsset){ 27 | this.mTransaction = transaction; 28 | this.mFeeAsset = feeAsset; 29 | } 30 | 31 | public GetRequiredFees(List operations, Asset feeAsset){ 32 | this.mTransaction = new Transaction(new BlockData(0, 0, 0), operations); 33 | this.mFeeAsset = feeAsset; 34 | } 35 | 36 | @Override 37 | public ApiCall toApiCall(int apiId, long sequenceId) { 38 | // Building a new API call to request fees information 39 | ArrayList accountParams = new ArrayList<>(); 40 | accountParams.add((Serializable) mTransaction.getOperations()); 41 | accountParams.add(this.mFeeAsset.getObjectId()); 42 | return new ApiCall(apiId, RPC.CALL_GET_REQUIRED_FEES, accountParams, RPC.VERSION, sequenceId); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/ListAssets.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | public class ListAssets implements ApiCallable { 11 | 12 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 13 | 14 | /** 15 | * Constant that must be used as argument to the constructor of this class to indicate 16 | * that the user wants to get all existing assets. 17 | */ 18 | public static final int LIST_ALL = -1; 19 | 20 | /** 21 | * Internal constant used to represent the maximum limit of assets retrieved in one call. 22 | */ 23 | public static final int MAX_BATCH_SIZE = 100; 24 | 25 | private String lowerBound; 26 | private int limit; 27 | 28 | public ListAssets(String lowerBoundSymbol, int limit){ 29 | this.lowerBound = lowerBoundSymbol; 30 | this.limit = limit; 31 | } 32 | 33 | @Override 34 | public ApiCall toApiCall(int apiId, long sequenceId) { 35 | ArrayList params = new ArrayList<>(); 36 | params.add(this.lowerBound); 37 | if(limit > MAX_BATCH_SIZE || limit == LIST_ALL){ 38 | params.add(MAX_BATCH_SIZE); 39 | }else{ 40 | params.add(this.limit); 41 | } 42 | return new ApiCall(apiId, RPC.CALL_LIST_ASSETS, params, RPC.VERSION, sequenceId); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/LookupAssetSymbols.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cy.agorise.graphenej.Asset; 8 | import cy.agorise.graphenej.RPC; 9 | import cy.agorise.graphenej.api.ApiAccess; 10 | import cy.agorise.graphenej.models.ApiCall; 11 | 12 | public class LookupAssetSymbols implements ApiCallable { 13 | public static final int REQUIRED_API = ApiAccess.API_NONE; 14 | 15 | private List mAssetList; 16 | 17 | public LookupAssetSymbols(List assetList){ 18 | this.mAssetList = assetList; 19 | } 20 | 21 | public LookupAssetSymbols(Asset asset){ 22 | mAssetList = new ArrayList(); 23 | mAssetList.add(asset); 24 | } 25 | 26 | @Override 27 | public ApiCall toApiCall(int apiId, long sequenceId) { 28 | ArrayList params = new ArrayList<>(); 29 | ArrayList subArray = new ArrayList<>(); 30 | for(int i = 0; i < mAssetList.size(); i++){ 31 | Asset asset = mAssetList.get(i); 32 | subArray.add(asset.getObjectId()); 33 | params.add(subArray); 34 | } 35 | return new ApiCall(apiId, RPC.CALL_LOOKUP_ASSET_SYMBOLS, params, RPC.VERSION, sequenceId); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/api/calls/SetSubscribeCallback.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | 6 | import cy.agorise.graphenej.RPC; 7 | import cy.agorise.graphenej.api.ApiAccess; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | public class SetSubscribeCallback implements ApiCallable { 11 | public static final int REQUIRED_API = ApiAccess.API_DATABASE; 12 | 13 | private boolean clearFilter; 14 | 15 | public SetSubscribeCallback(boolean clearFilter){ 16 | this.clearFilter = clearFilter; 17 | } 18 | 19 | @Override 20 | public ApiCall toApiCall(int apiId, long sequenceId) { 21 | ArrayList subscriptionParams = new ArrayList<>(); 22 | subscriptionParams.add(new Long(sequenceId)); 23 | subscriptionParams.add(clearFilter); 24 | return new ApiCall(apiId, RPC.CALL_SET_SUBSCRIBE_CALLBACK, subscriptionParams, RPC.VERSION, sequenceId); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/crypto/AndroidRandomSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013, 2014 Megion Research and Development GmbH 3 | * 4 | * Licensed under the Microsoft Reference Source License (MS-RSL) 5 | * 6 | * This license governs use of the accompanying software. If you use the software, you accept this license. 7 | * If you do not accept the license, do not use the software. 8 | * 9 | * 1. Definitions 10 | * The terms "reproduce," "reproduction," and "distribution" have the same meaning here as under U.S. copyright law. 11 | * "You" means the licensee of the software. 12 | * "Your company" means the company you worked for when you downloaded the software. 13 | * "Reference use" means use of the software within your company as a reference, in read only form, for the sole purposes 14 | * of debugging your products, maintaining your products, or enhancing the interoperability of your products with the 15 | * software, and specifically excludes the right to distribute the software outside of your company. 16 | * "Licensed patents" means any Licensor patent claims which read directly on the software as distributed by the Licensor 17 | * under this license. 18 | * 19 | * 2. Grant of Rights 20 | * (A) Copyright Grant- Subject to the terms of this license, the Licensor grants you a non-transferable, non-exclusive, 21 | * worldwide, royalty-free copyright license to reproduce the software for reference use. 22 | * (B) Patent Grant- Subject to the terms of this license, the Licensor grants you a non-transferable, non-exclusive, 23 | * worldwide, royalty-free patent license under licensed patents for reference use. 24 | * 25 | * 3. Limitations 26 | * (A) No Trademark License- This license does not grant you any rights to use the Licensor’s name, logo, or trademarks. 27 | * (B) If you begin patent litigation against the Licensor over patents that you think may apply to the software 28 | * (including a cross-claim or counterclaim in a lawsuit), your license to the software ends automatically. 29 | * (C) The software is licensed "as-is." You bear the risk of using it. The Licensor gives no express warranties, 30 | * guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot 31 | * change. To the extent permitted under your local laws, the Licensor excludes the implied warranties of merchantability, 32 | * fitness for a particular purpose and non-infringement. 33 | */ 34 | 35 | package cy.agorise.graphenej.crypto; 36 | 37 | import java.io.DataInputStream; 38 | import java.io.File; 39 | import java.io.FileInputStream; 40 | import java.io.IOException; 41 | import java.nio.ByteBuffer; 42 | 43 | 44 | public class AndroidRandomSource implements RandomSource, EntropySource { 45 | 46 | @Override 47 | public synchronized void nextBytes(byte[] bytes) { 48 | // On Android we use /dev/urandom for providing random data 49 | File file = new File("/dev/urandom"); 50 | if (!file.exists()) { 51 | throw new RuntimeException("Unable to generate random bytes on this Android device"); 52 | } 53 | try { 54 | FileInputStream stream = new FileInputStream(file); 55 | DataInputStream dis = new DataInputStream(stream); 56 | dis.readFully(bytes); 57 | dis.close(); 58 | } catch (IOException e) { 59 | throw new RuntimeException("Unable to generate random bytes on this Android device", e); 60 | } 61 | } 62 | 63 | @Override 64 | public ByteBuffer provideEntropy() { 65 | byte[] buffer = new byte[ 256 / 8]; 66 | nextBytes(buffer); 67 | ByteBuffer byteBuffer = ByteBuffer.allocate(buffer.length); 68 | byteBuffer.put(buffer, 0, buffer.length); 69 | return byteBuffer; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/crypto/EntropySource.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.crypto; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | /** 6 | * A simple interface that can be used to retrieve entropy from any source. 7 | * 8 | * @author owlstead 9 | */ 10 | public interface EntropySource { 11 | /** 12 | * Retrieves the entropy. 13 | * The position of the ByteBuffer must be advanced to the limit by any users calling this method. 14 | * The values of the bytes between the position and limit should be set to zero by any users calling this method. 15 | * 16 | * @return entropy within the position and limit of the given buffer 17 | */ 18 | ByteBuffer provideEntropy(); 19 | } -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/crypto/RandomSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013, 2014 Megion Research & Development GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cy.agorise.graphenej.crypto; 17 | 18 | public interface RandomSource { 19 | /** 20 | * Generates a user specified number of random bytes 21 | * 22 | * @param bytes 23 | * The array to fill with random bytes 24 | */ 25 | void nextBytes(byte[] bytes); 26 | } 27 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/crypto/SecureRandomGenerator.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.crypto; 2 | 3 | import java.security.SecureRandom; 4 | 5 | /** 6 | * Created by nelson on 12/20/16. 7 | */ 8 | public class SecureRandomGenerator { 9 | 10 | public static SecureRandom getSecureRandom(){ 11 | SecureRandomStrengthener randomStrengthener = SecureRandomStrengthener.getInstance(); 12 | // randomStrengthener.addEntropySource(new AndroidRandomSource()); 13 | return randomStrengthener.generateAndSeedRandomNumberGenerator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/errors/ChecksumException.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.errors; 2 | 3 | /** 4 | * Created by nelson on 12/20/16. 5 | */ 6 | public class ChecksumException extends Exception { 7 | public ChecksumException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/errors/IncompatibleOperation.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.errors; 2 | 3 | /** 4 | * Created by nelson on 1/18/17. 5 | */ 6 | public class IncompatibleOperation extends RuntimeException { 7 | 8 | public IncompatibleOperation(String message){ 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/errors/IncompleteAssetError.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.errors; 2 | 3 | /** 4 | * Created by nelson on 12/25/16. 5 | */ 6 | public class IncompleteAssetError extends RuntimeException{ 7 | 8 | public IncompleteAssetError(String message){ 9 | super(message); 10 | } 11 | 12 | public IncompleteAssetError(){ 13 | super("The asset used in this method is probably incomplete, Assets instances can be created with just its id information but this context requires more information"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/errors/MalformedAddressException.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.errors; 2 | 3 | /** 4 | * Created by nelson on 12/1/16. 5 | */ 6 | public class MalformedAddressException extends Exception { 7 | public MalformedAddressException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/errors/MalformedOperationException.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.errors; 2 | 3 | /** 4 | * Created by nelson on 3/1/17. 5 | */ 6 | public class MalformedOperationException extends RuntimeException { 7 | 8 | public MalformedOperationException(String msg){ 9 | super(msg); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/errors/MalformedTransactionException.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.errors; 2 | 3 | /** 4 | * Created by nelson on 11/14/16. 5 | */ 6 | public class MalformedTransactionException extends Exception { 7 | 8 | public MalformedTransactionException(String message){ 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/errors/RepeatedRequestIdException.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.errors; 2 | 3 | import cy.agorise.graphenej.api.BaseGrapheneHandler; 4 | 5 | /** 6 | * Thrown by the {@link cy.agorise.graphenej.api.SubscriptionMessagesHub#addRequestHandler(BaseGrapheneHandler)} 7 | * whenever the user tries to register a new handler with a previously registered id 8 | */ 9 | 10 | public class RepeatedRequestIdException extends Exception { 11 | public RepeatedRequestIdException(String message){ 12 | super(message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/interfaces/ByteSerializable.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.interfaces; 2 | 3 | /** 4 | * Interface implemented by all entities for which makes sense to have a byte-array representation. 5 | */ 6 | public interface ByteSerializable { 7 | 8 | byte[] toBytes(); 9 | } 10 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/interfaces/GrapheneSerializable.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.interfaces; 2 | 3 | /** 4 | * Interface used to group both ByteSerializable and JsonSerializable interfaces. 5 | */ 6 | public interface GrapheneSerializable extends ByteSerializable, JsonSerializable { 7 | } 8 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/interfaces/JsonSerializable.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.interfaces; 2 | 3 | import com.google.gson.JsonElement; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Interface to be implemented by any entity for which makes sense to 9 | * have a JSON-formatted string and object representation. 10 | */ 11 | public interface JsonSerializable extends Serializable { 12 | 13 | String toJsonString(); 14 | 15 | JsonElement toJsonObject(); 16 | } 17 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/interfaces/NodeErrorListener.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.interfaces; 2 | 3 | import cy.agorise.graphenej.models.BaseResponse; 4 | 5 | /** 6 | * Interface to be implemented by any listener to network errors. 7 | */ 8 | public interface NodeErrorListener { 9 | void onError(BaseResponse.Error error); 10 | } 11 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/interfaces/SubscriptionHub.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.interfaces; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Interface to be implemented by any class that hosts a SubscriptionResponseDeserializer and wants to 7 | * expose an interface for its management of its listeners. 8 | * 9 | * Created by nelson on 1/30/17. 10 | */ 11 | public interface SubscriptionHub { 12 | 13 | /** 14 | * Adds a given listener to the list of subscription listeners. 15 | * @param listener: The SubscriptionListener to add. 16 | */ 17 | void addSubscriptionListener(SubscriptionListener listener); 18 | 19 | /** 20 | * Removes a given listener from the list. 21 | * @param listener: The SubscriptionListener to remove. 22 | */ 23 | void removeSubscriptionListener(SubscriptionListener listener); 24 | 25 | /** 26 | * Retrieves a list of all subscription listeners. 27 | * @return 28 | */ 29 | List getSubscriptionListeners(); 30 | } -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/interfaces/SubscriptionListener.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.interfaces; 2 | 3 | import cy.agorise.graphenej.ObjectType; 4 | import cy.agorise.graphenej.models.SubscriptionResponse; 5 | 6 | /** 7 | * Generic interface that must be implemented by any class that wants to be informed about a specific 8 | * event notification. 9 | * 10 | * Created by nelson on 1/26/17. 11 | */ 12 | public interface SubscriptionListener { 13 | 14 | /** 15 | * Every subscription listener must implement a method that returns the type of object it is 16 | * interested in. 17 | * @return: Instance of the ObjectType enum class. 18 | */ 19 | ObjectType getInterestObjectType(); 20 | 21 | 22 | /** 23 | * Method called whenever there is an update that might be of interest for this listener. 24 | * Note however that the objects returned inside the SubscriptionResponse are not guaranteed to be 25 | * only of the object type requested by this class in the getInterestObjectType. 26 | * 27 | * @param response: SubscriptionResponse instance, which may or may not contain an object of interest. 28 | */ 29 | void onSubscriptionUpdate(SubscriptionResponse response); 30 | } 31 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/interfaces/WitnessResponseListener.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.interfaces; 2 | 3 | import cy.agorise.graphenej.models.BaseResponse; 4 | import cy.agorise.graphenej.models.WitnessResponse; 5 | 6 | /** 7 | * Class used to represent any listener to network requests. 8 | */ 9 | public interface WitnessResponseListener { 10 | 11 | void onSuccess(WitnessResponse response); 12 | 13 | void onError(BaseResponse.Error error); 14 | } 15 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/AccountBalanceUpdate.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import java.io.Serializable; 4 | 5 | import cy.agorise.graphenej.GrapheneObject; 6 | 7 | /** 8 | * Created by nelson on 1/12/17. 9 | */ 10 | 11 | public class AccountBalanceUpdate extends GrapheneObject implements Serializable { 12 | public static final String KEY_OWNER = "owner"; 13 | public static final String KEY_ASSET_TYPE = "asset_type"; 14 | public static final String KEY_BALANCE = "balance"; 15 | 16 | public String owner; 17 | public String asset_type; 18 | public long balance; 19 | 20 | public AccountBalanceUpdate(String id) { 21 | super(id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/AccountProperties.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import cy.agorise.graphenej.AccountOptions; 4 | import cy.agorise.graphenej.Authority; 5 | 6 | /** 7 | * Created by nelson on 11/15/16. 8 | * 9 | * Details of Dynamic Account specs can be found at 10 | * https://bitshares.org/technology/dynamic-account-permissions/ 11 | * 12 | */ 13 | public class AccountProperties { 14 | public String id; 15 | public String membership_expiration_date; 16 | public String registrar; 17 | public String referrer; 18 | public String lifetime_referrer; 19 | public long network_fee_percentage; 20 | public long lifetime_referrer_fee_percentage; 21 | public long referrer_rewards_percentage; 22 | public String name; 23 | public Authority owner; 24 | public Authority active; 25 | public AccountOptions options; 26 | public String statistics; 27 | public String[] whitelisting_accounts; 28 | public String[] blacklisting_accounts; 29 | public String[] whitelisted_accounts; 30 | public String[] blacklisted_accounts; 31 | public Object[] owner_special_authority; 32 | public Object[] active_special_authority; 33 | public long top_n_control_flags; 34 | } 35 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/AssetFeed.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import com.google.gson.JsonDeserializationContext; 4 | import com.google.gson.JsonDeserializer; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | import com.google.gson.JsonParseException; 8 | 9 | import java.lang.reflect.Type; 10 | 11 | import cy.agorise.graphenej.Price; 12 | 13 | /** 14 | * Price feed of a given asset. 15 | */ 16 | public class AssetFeed { 17 | public static final String KEY_SETTLEMENT_PRICE = "settlement_price"; 18 | public static final String KEY_MAINTENANCE_COLLATERAL_RATIO = "maintenance_collateral_ratio"; 19 | public static final String KEY_MAXIMUM_SHORT_SQUEEZE_RATIO = "maximum_short_squeeze_ratio"; 20 | public static final String KEY_CORE_EXCHANGE_RATE = "core_exchange_rate"; 21 | 22 | private Price settlement_price; 23 | private long maintenance_collateral_ratio; 24 | private long maximum_short_squeeze_ratio; 25 | private Price core_exchange_rate; 26 | 27 | public AssetFeed(Price settlementPrice, long maintenanceCollateralRatio, long maximumShortSqueezeRatio, Price coreExchangeRate){ 28 | this.settlement_price = settlementPrice; 29 | this.maintenance_collateral_ratio = maintenanceCollateralRatio; 30 | this.maximum_short_squeeze_ratio = maximumShortSqueezeRatio; 31 | this.core_exchange_rate = coreExchangeRate; 32 | } 33 | 34 | public Price getSettlementPrice() { 35 | return settlement_price; 36 | } 37 | 38 | public void setSettlementPrice(Price settlement_price) { 39 | this.settlement_price = settlement_price; 40 | } 41 | 42 | public long getMaintenanceCollateralRatio() { 43 | return maintenance_collateral_ratio; 44 | } 45 | 46 | public void setMaintenanceCollateralRatio(long maintenance_collateral_ratio) { 47 | this.maintenance_collateral_ratio = maintenance_collateral_ratio; 48 | } 49 | 50 | public long getMaximumShortSqueezeRatio() { 51 | return maximum_short_squeeze_ratio; 52 | } 53 | 54 | public void setMaximumShortSqueezeRatio(long maximum_short_squeeze_ratio) { 55 | this.maximum_short_squeeze_ratio = maximum_short_squeeze_ratio; 56 | } 57 | 58 | public Price getCoreExchangeRate() { 59 | return core_exchange_rate; 60 | } 61 | 62 | public void setCoreExchangeRate(Price core_exchange_rate) { 63 | this.core_exchange_rate = core_exchange_rate; 64 | } 65 | 66 | public static class AssetFeedDeserializer implements JsonDeserializer { 67 | 68 | @Override 69 | public AssetFeed deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 70 | JsonObject jsonObject = json.getAsJsonObject(); 71 | Price settlementPrice = context.deserialize(jsonObject.get(KEY_SETTLEMENT_PRICE).getAsJsonObject(), Price.class); 72 | long collateralRatio = jsonObject.get(KEY_MAINTENANCE_COLLATERAL_RATIO).getAsLong(); 73 | long maximumShortSqueezeRatio = jsonObject.get(KEY_MAXIMUM_SHORT_SQUEEZE_RATIO).getAsLong(); 74 | Price coreExchangeRate = context.deserialize(jsonObject.get(KEY_CORE_EXCHANGE_RATE), Price.class); 75 | AssetFeed assetFeed = new AssetFeed(settlementPrice, collateralRatio, maximumShortSqueezeRatio, coreExchangeRate); 76 | return assetFeed; 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/AssetHolderCount.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import com.google.gson.*; 4 | import cy.agorise.graphenej.Asset; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | /** 9 | * Created by nelson on 1/25/17. 10 | */ 11 | public class AssetHolderCount { 12 | public static final String KEY_ASSET_ID = "asset_id"; 13 | public static final String KEY_COUNT = "count"; 14 | 15 | public Asset asset; 16 | public long count; 17 | 18 | public static class HoldersCountDeserializer implements JsonDeserializer { 19 | 20 | @Override 21 | public AssetHolderCount deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 22 | JsonObject jsonObject = json.getAsJsonObject(); 23 | AssetHolderCount holdersCount = new AssetHolderCount(); 24 | holdersCount.asset = new Asset(jsonObject.get(KEY_ASSET_ID).getAsString()); 25 | holdersCount.count = jsonObject.get(KEY_COUNT).getAsLong(); 26 | return holdersCount; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/BaseResponse.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | /** 4 | * Base response class 5 | * @deprecated Use {@link JsonRpcResponse} instead 6 | */ 7 | public class BaseResponse { 8 | public long id; 9 | public Error error; 10 | 11 | public static class Error { 12 | public ErrorData data; 13 | public int code; 14 | public String message; 15 | public Error(String message){ 16 | this.message = message; 17 | } 18 | } 19 | 20 | public static class ErrorData { 21 | public int code; 22 | public String name; 23 | public String message; 24 | //TODO: Include stack data 25 | 26 | public ErrorData(String message){ 27 | this.message = message; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/Block.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import cy.agorise.graphenej.Transaction; 4 | 5 | import java.util.List; 6 | 7 | public class Block { 8 | private String previous; 9 | private String timestamp; 10 | private String witness; 11 | private String transaction_merkle_root; 12 | private Object[] extensions; 13 | private String witness_signature; 14 | private List transactions; 15 | 16 | public String getPrevious() { 17 | return previous; 18 | } 19 | 20 | public void setPrevious(String previous) { 21 | this.previous = previous; 22 | } 23 | 24 | public String getTimestamp() { 25 | return timestamp; 26 | } 27 | 28 | public void setTimestamp(String timestamp) { 29 | this.timestamp = timestamp; 30 | } 31 | 32 | public String getWitness() { 33 | return witness; 34 | } 35 | 36 | public void setWitness(String witness) { 37 | this.witness = witness; 38 | } 39 | 40 | public String getTransaction_merkle_root() { 41 | return transaction_merkle_root; 42 | } 43 | 44 | public void setTransaction_merkle_root(String transaction_merkle_root) { 45 | this.transaction_merkle_root = transaction_merkle_root; 46 | } 47 | 48 | public Object[] getExtensions() { 49 | return extensions; 50 | } 51 | 52 | public void setExtensions(Object[] extensions) { 53 | this.extensions = extensions; 54 | } 55 | 56 | public String getWitness_signature() { 57 | return witness_signature; 58 | } 59 | 60 | public void setWitness_signature(String witness_signature) { 61 | this.witness_signature = witness_signature; 62 | } 63 | 64 | public List getTransactions() { 65 | return transactions; 66 | } 67 | 68 | public void setTransactions(List transactions) { 69 | this.transactions = transactions; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/BlockHeader.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | /** 4 | * Class used to represent the response to the 'get_block_header' API call. 5 | */ 6 | public class BlockHeader { 7 | public String previous; 8 | public String timestamp; 9 | public String witness; 10 | public String transaction_merkle_root; 11 | } 12 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/BroadcastedTransaction.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import cy.agorise.graphenej.GrapheneObject; 4 | import cy.agorise.graphenej.Transaction; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Created by nelson on 1/28/17. 10 | */ 11 | public class BroadcastedTransaction extends GrapheneObject implements Serializable { 12 | public static final String KEY_TRX = "trx"; 13 | public static final String KEY_TRX_ID = "trx_id"; 14 | 15 | private Transaction trx; 16 | private String trx_id; 17 | 18 | public BroadcastedTransaction(String id){ 19 | super(id); 20 | } 21 | 22 | public void setTransaction(Transaction t){ 23 | this.trx = t; 24 | } 25 | 26 | public Transaction getTransaction() { 27 | return trx; 28 | } 29 | 30 | public void setTransactionId(String id){ 31 | this.trx_id = id; 32 | } 33 | 34 | public String getTransactionId() { 35 | return trx_id; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/FullAccountDetails.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonDeserializationContext; 5 | import com.google.gson.JsonDeserializer; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonObject; 8 | import com.google.gson.JsonParseException; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | /** 13 | * Model class used in the de-serialization of the response to the 'get_full_accounts' API call. 14 | * @see cy.agorise.graphenej.api.calls.GetFullAccounts 15 | */ 16 | public class FullAccountDetails { 17 | private AccountProperties account; 18 | private Statistics statistics; 19 | 20 | public FullAccountDetails(AccountProperties properties, Statistics statistics){ 21 | this.account = properties; 22 | this.statistics = statistics; 23 | } 24 | 25 | public AccountProperties getAccount() { 26 | return account; 27 | } 28 | 29 | public void setAccount(AccountProperties account) { 30 | this.account = account; 31 | } 32 | 33 | public Statistics getStatistics() { 34 | return statistics; 35 | } 36 | 37 | public void setStatistics(Statistics statistics) { 38 | this.statistics = statistics; 39 | } 40 | 41 | public static class Statistics { 42 | public String id; 43 | public String owner; 44 | public String name; 45 | public String most_recent_op; 46 | public long total_ops; 47 | public long removed_ops; 48 | public long total_core_in_orders; 49 | public String core_in_balance; 50 | public boolean has_cashback_vb; 51 | public boolean is_voting; 52 | public long lifetime_fees_paid; 53 | public long pending_fees; 54 | public long pending_vested_fees; 55 | } 56 | 57 | public static class FullAccountDeserializer implements JsonDeserializer { 58 | 59 | @Override 60 | public FullAccountDetails deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 61 | JsonArray array = (JsonArray) json; 62 | JsonObject jsonObject = (JsonObject) array.get(1); 63 | AccountProperties properties = context.deserialize(jsonObject.get("account"), AccountProperties.class); 64 | Statistics statistics = context.deserialize(jsonObject.get("statistics"), Statistics.class); 65 | return new FullAccountDetails(properties, statistics); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/HistoryOperationDetail.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Model class used to represent the struct defined in graphene::app::history_operation_detail and 7 | * returned as response to the 'get_account_history_by_operations' API call. 8 | */ 9 | public class HistoryOperationDetail { 10 | private long total_count; 11 | List operation_history_objs; 12 | 13 | public long getTotalCount() { 14 | return total_count; 15 | } 16 | 17 | public void setTotalCount(long total_count) { 18 | this.total_count = total_count; 19 | } 20 | 21 | public List getOperationHistoryObjs() { 22 | return operation_history_objs; 23 | } 24 | 25 | public void setOperationHistoryObjs(List operation_history_objs) { 26 | this.operation_history_objs = operation_history_objs; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/JsonRpcResponse.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | /** 4 | * Used to represent a JSON-RPC response object 5 | */ 6 | 7 | public class JsonRpcResponse { 8 | public long id; 9 | public Error error; 10 | public T result; 11 | 12 | public static class Error { 13 | public ErrorData data; 14 | public int code; 15 | public String message; 16 | public Error(String message){ 17 | this.message = message; 18 | } 19 | } 20 | 21 | public static class ErrorData { 22 | public int code; 23 | public String name; 24 | public String message; 25 | //TODO: Include stack data 26 | 27 | public ErrorData(String message){ 28 | this.message = message; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/Options.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | /** 4 | * Class used to represent the 'options' object returned inside the response obtained after 5 | * querying for an object of type 'asset_bitasset_data' (2.4.x) 6 | */ 7 | 8 | public class Options { 9 | private long feed_lifetime_sec; 10 | private long minimum_feeds; 11 | private long force_settlement_delay_sec; 12 | private long force_settlement_offset_percent; 13 | private long maximum_force_settlement_volume; 14 | private String short_backing_asset; 15 | } 16 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/ReportedAssetFeed.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonDeserializationContext; 5 | import com.google.gson.JsonDeserializer; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonParseException; 8 | 9 | import java.lang.reflect.Type; 10 | import java.text.ParseException; 11 | import java.text.SimpleDateFormat; 12 | import java.util.Date; 13 | 14 | import cy.agorise.graphenej.UserAccount; 15 | import cy.agorise.graphenej.Util; 16 | 17 | /** 18 | * Witness-provided asset price feed 19 | */ 20 | 21 | public class ReportedAssetFeed { 22 | private UserAccount reporter; 23 | private AssetFeed assetFeed; 24 | private Date reportedDate; 25 | 26 | public ReportedAssetFeed(UserAccount userAccount, Date date, AssetFeed assetFeed){ 27 | this.reporter = userAccount; 28 | this.reportedDate = date; 29 | this.assetFeed = assetFeed; 30 | } 31 | 32 | public UserAccount getReporter() { 33 | return reporter; 34 | } 35 | 36 | public void setReporter(UserAccount reporter) { 37 | this.reporter = reporter; 38 | } 39 | 40 | public AssetFeed getAssetFeed() { 41 | return assetFeed; 42 | } 43 | 44 | public void setAssetFeed(AssetFeed assetFeed) { 45 | this.assetFeed = assetFeed; 46 | } 47 | 48 | public Date getReportedDate() { 49 | return reportedDate; 50 | } 51 | 52 | public void setReportedDate(Date reportedDate) { 53 | this.reportedDate = reportedDate; 54 | } 55 | 56 | public static class ReportedAssetFeedDeserializer implements JsonDeserializer { 57 | 58 | @Override 59 | public ReportedAssetFeed deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 60 | JsonArray array = json.getAsJsonArray(); 61 | String userId = array.get(0).getAsString(); 62 | JsonArray subArray = (JsonArray) array.get(1); 63 | String dateString = subArray.get(0).getAsString(); 64 | 65 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT); 66 | Date reportDate = null; 67 | try { 68 | reportDate = simpleDateFormat.parse(dateString); 69 | } catch (ParseException e) { 70 | e.printStackTrace(); 71 | } 72 | 73 | AssetFeed assetFeed = context.deserialize(subArray.get(1), AssetFeed.class); 74 | UserAccount userAccount = new UserAccount(userId); 75 | return new ReportedAssetFeed(userAccount, reportDate, assetFeed); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/WitnessResponse.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | /** 4 | * Generic witness response 5 | * @deprecated Use {@link JsonRpcResponse} instead 6 | */ 7 | public class WitnessResponse extends BaseResponse{ 8 | public static final String KEY_ID = "id"; 9 | public static final String KEY_RESULT = "result"; 10 | 11 | public T result; 12 | } 13 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/backup/LinkedAccount.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models.backup; 2 | 3 | /** 4 | * Class used to represent an entry in the "linked_accounts" field of the JSON-formatted backup file. 5 | * Created by nelson on 2/15/17. 6 | */ 7 | public class LinkedAccount { 8 | private String name; 9 | private String chainId; 10 | 11 | public LinkedAccount(String name, String chainId){ 12 | this.name = name; 13 | this.chainId = chainId; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public String getChainId() { 25 | return chainId; 26 | } 27 | 28 | public void setChainId(String chainId) { 29 | this.chainId = chainId; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/backup/PrivateKeyBackup.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models.backup; 2 | 3 | import cy.agorise.graphenej.Address; 4 | import cy.agorise.graphenej.Util; 5 | import org.bitcoinj.core.ECKey; 6 | 7 | /** 8 | * Class used to represent an entry in the "private_keys" array field in the JSON-formatted 9 | * backup file. 10 | * 11 | * Created by nelson on 2/14/17. 12 | */ 13 | public class PrivateKeyBackup { 14 | public String encrypted_key; 15 | public String pubkey; 16 | public int brainkey_sequence; 17 | public int id; 18 | 19 | public PrivateKeyBackup(byte[] privateKey, int brainkeySequence, int id, byte[] encryptionKey){ 20 | this.encrypted_key = encryptPrivateKey(privateKey, encryptionKey); 21 | this.brainkey_sequence = brainkeySequence; 22 | this.id = id; 23 | deriveAddress(privateKey); 24 | } 25 | 26 | public byte[] decryptPrivateKey(byte[] encryptionKey){ 27 | return Util.decryptAES(Util.hexToBytes(encrypted_key), encryptionKey); 28 | } 29 | 30 | public String encryptPrivateKey(byte[] data, byte[] encryptionKey){ 31 | return Util.bytesToHex(Util.encryptAES(data, encryptionKey)); 32 | } 33 | 34 | private void deriveAddress(byte[] privateKey){ 35 | Address address = new Address(ECKey.fromPublicOnly(ECKey.fromPrivate(privateKey).getPubKey())); 36 | this.pubkey = address.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/models/backup/WalletBackup.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models.backup; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * This class is used to represent the JSON-formatted version of the file backup containing one or more 7 | * wallets and keys. 8 | * 9 | * Created by nelson on 2/14/17. 10 | */ 11 | public class WalletBackup { 12 | private Wallet[] wallet; 13 | private PrivateKeyBackup[] private_keys; 14 | private LinkedAccount[] linked_accounts; 15 | 16 | public WalletBackup(List wallets, List privateKeys, List linkedAccounts){ 17 | this.wallet = wallets.toArray(new Wallet[wallets.size()]); 18 | this.private_keys = privateKeys.toArray(new PrivateKeyBackup[privateKeys.size()]); 19 | this.linked_accounts = linkedAccounts.toArray(new LinkedAccount[linkedAccounts.size()]); 20 | } 21 | 22 | public Wallet[] getWallets(){ 23 | return wallet; 24 | } 25 | 26 | public PrivateKeyBackup[] getPrivateKeys(){ 27 | return private_keys; 28 | } 29 | 30 | public LinkedAccount[] getLinkedAccounts(){ 31 | return linked_accounts; 32 | } 33 | 34 | public Wallet getWallet(int index){ 35 | return wallet[index]; 36 | } 37 | 38 | public PrivateKeyBackup getPrivateKeyBackup(int index){ 39 | return private_keys[index]; 40 | } 41 | 42 | public int getWalletCount(){ 43 | return wallet.length; 44 | } 45 | 46 | public int getKeyCount(){ 47 | return private_keys.length; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/network/FullNode.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.network; 2 | 3 | import cy.agorise.graphenej.stats.ExponentialMovingAverage; 4 | 5 | /** 6 | * Class that represents a full node and is used to keep track of its round-trip time measured in milliseconds. 7 | */ 8 | public class FullNode implements Comparable { 9 | 10 | private String mUrl; 11 | private ExponentialMovingAverage latency; 12 | private boolean isConnected; 13 | 14 | private FullNode(){} 15 | 16 | public FullNode(String url){ 17 | latency = new ExponentialMovingAverage(ExponentialMovingAverage.DEFAULT_ALPHA); 18 | this.mUrl = url; 19 | } 20 | 21 | /** 22 | * Full node URL getter 23 | * @return 24 | */ 25 | public String getUrl() { 26 | return mUrl; 27 | } 28 | 29 | /** 30 | * Full node URL setter 31 | * @param mUrl 32 | */ 33 | public void setUrl(String mUrl) { 34 | this.mUrl = mUrl; 35 | } 36 | 37 | /** 38 | * 39 | * @return The exponential moving average object instance 40 | */ 41 | public ExponentialMovingAverage getLatencyAverage(){ 42 | return latency; 43 | } 44 | 45 | /** 46 | * 47 | * @return The latest latency average value 48 | */ 49 | public double getLatencyValue() { 50 | return latency.getAverage(); 51 | } 52 | 53 | public boolean isConnected() { 54 | return isConnected; 55 | } 56 | 57 | public void setConnected(boolean connected) { 58 | isConnected = connected; 59 | } 60 | 61 | /** 62 | * Method that updates the latency average with a new value. 63 | * @param latency Most recent latency sample to be added to the exponential average 64 | */ 65 | public void addLatencyValue(double latency) { 66 | this.latency.updateValue(latency); 67 | } 68 | 69 | @Override 70 | public int compareTo(Object o) { 71 | FullNode node = (FullNode) o; 72 | return (int) Math.ceil(latency.getAverage() - node.getLatencyValue()); 73 | } 74 | 75 | @Override 76 | public boolean equals(Object o) { 77 | if (this == o) return true; 78 | if (o == null || getClass() != o.getClass()) return false; 79 | FullNode fullNode = (FullNode) o; 80 | return mUrl.equals(fullNode.getUrl()); 81 | } 82 | 83 | @Override 84 | public int hashCode() { 85 | return mUrl.hashCode(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/network/LatencyNodeProvider.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.network; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.PriorityQueue; 8 | 9 | public class LatencyNodeProvider implements NodeProvider { 10 | private final String TAG = "LatencyNodeProvider"; 11 | private PriorityQueue mFullNodeHeap; 12 | 13 | public LatencyNodeProvider(){ 14 | mFullNodeHeap = new PriorityQueue<>(); 15 | } 16 | 17 | @Override 18 | public FullNode getBestNode() { 19 | return mFullNodeHeap.peek(); 20 | } 21 | 22 | @Override 23 | public void addNode(FullNode fullNode) { 24 | mFullNodeHeap.add(fullNode); 25 | } 26 | 27 | @Override 28 | public boolean updateNode(FullNode fullNode) { 29 | mFullNodeHeap.remove(fullNode); 30 | return mFullNodeHeap.offer(fullNode); 31 | } 32 | 33 | /** 34 | * Updates an existing node with the new latency value. 35 | * 36 | * @param fullNode Existing full node instance 37 | * @param latency New latency measurement 38 | * @return True if the node priority was updated successfully 39 | */ 40 | public boolean updateNode(FullNode fullNode, int latency){ 41 | if(mFullNodeHeap.remove(fullNode)){ 42 | fullNode.addLatencyValue(latency); 43 | return mFullNodeHeap.add(fullNode); 44 | }else{ 45 | return false; 46 | } 47 | } 48 | 49 | @Override 50 | public List getSortedNodes() { 51 | FullNode[] nodeArray = mFullNodeHeap.toArray(new FullNode[mFullNodeHeap.size()]); 52 | ArrayList nodeList = new ArrayList<>(); 53 | for(FullNode fullNode : nodeList){ 54 | if(fullNode != null){ 55 | nodeList.add(fullNode); 56 | } 57 | } 58 | Collections.sort(nodeList); 59 | return Arrays.asList(nodeArray); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/network/NodeProvider.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.network; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Interface used to describe the high level characteristics of a class that will 7 | * hold and manage a list of {@link FullNode} instances. 8 | * 9 | * The idea is that the class implementing this interface should provide node instances 10 | * and thus URLs for the {@link cy.agorise.graphenej.api.android.NetworkService} with 11 | * different sorting heuristics. 12 | */ 13 | public interface NodeProvider { 14 | 15 | /** 16 | * Returns the node with the best characteristics. Returns null if there is no {@link FullNode} 17 | * @return A FullNode instance 18 | */ 19 | FullNode getBestNode(); 20 | 21 | /** 22 | * Adds a new node to the queue 23 | * @param fullNode {@link FullNode} instance to add. 24 | */ 25 | void addNode(FullNode fullNode); 26 | 27 | /** 28 | * Updates the rating of a specific node that is already in the NodeProvider 29 | * @param fullNode 30 | */ 31 | boolean updateNode(FullNode fullNode); 32 | 33 | /** 34 | * Returns an ordered list of {@link FullNode} instances. 35 | * @return 36 | */ 37 | List getSortedNodes(); 38 | } 39 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/operations/AccountUpdateOperationBuilder.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import cy.agorise.graphenej.*; 4 | import cy.agorise.graphenej.errors.MalformedOperationException; 5 | 6 | /** 7 | * Created by nelson on 3/1/17. 8 | */ 9 | public class AccountUpdateOperationBuilder extends BaseOperationBuilder { 10 | private AssetAmount fee; 11 | private UserAccount account; 12 | private Authority owner; 13 | private Authority active; 14 | private AccountOptions new_options; 15 | 16 | public AccountUpdateOperationBuilder setFee(AssetAmount fee) { 17 | this.fee = fee; 18 | return this; 19 | } 20 | 21 | public AccountUpdateOperationBuilder setAccount(UserAccount account) { 22 | this.account = account; 23 | return this; 24 | } 25 | 26 | public AccountUpdateOperationBuilder setOwner(Authority owner) { 27 | this.owner = owner; 28 | return this; 29 | } 30 | 31 | public AccountUpdateOperationBuilder setActive(Authority active) { 32 | this.active = active; 33 | return this; 34 | } 35 | 36 | public AccountUpdateOperationBuilder setOptions(AccountOptions newOptions) { 37 | this.new_options = newOptions; 38 | return this; 39 | } 40 | 41 | @Override 42 | public AccountUpdateOperation build() { 43 | AccountUpdateOperation operation; 44 | if(this.account == null){ 45 | throw new MalformedOperationException("This operation requires an account to be set"); 46 | }else{ 47 | if(owner != null || active != null || new_options != null){ 48 | if(fee == null){ 49 | operation = new AccountUpdateOperation(account, owner, active, new_options); 50 | }else{ 51 | operation = new AccountUpdateOperation(account, owner, active, new_options, fee); 52 | } 53 | }else{ 54 | throw new MalformedOperationException("This operation requires at least either an authority or account options change"); 55 | } 56 | } 57 | return operation; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/operations/AccountUpgradeOperationBuilder.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import cy.agorise.graphenej.AssetAmount; 4 | import cy.agorise.graphenej.UserAccount; 5 | import cy.agorise.graphenej.errors.MalformedOperationException; 6 | 7 | /** 8 | * Created by henry on 19/5/2018. 9 | */ 10 | 11 | public class AccountUpgradeOperationBuilder extends BaseOperationBuilder { 12 | 13 | private UserAccount accountToUpgrade; 14 | private AssetAmount fee; 15 | private boolean isUpgrade = true; 16 | 17 | public AccountUpgradeOperationBuilder setAccountToUpgrade(UserAccount accountToUpgrade) { 18 | this.accountToUpgrade = accountToUpgrade; 19 | return this; 20 | } 21 | 22 | public AccountUpgradeOperationBuilder setFee(AssetAmount fee) { 23 | this.fee = fee; 24 | return this; 25 | } 26 | 27 | public AccountUpgradeOperationBuilder setIsUpgrade(Boolean isUpgrade) { 28 | this.isUpgrade = isUpgrade; 29 | return this; 30 | } 31 | 32 | @Override 33 | public AccountUpgradeOperation build(){ 34 | AccountUpgradeOperation accountUpgrade; 35 | if(accountToUpgrade == null ){ 36 | throw new MalformedOperationException("Missing account to upgrade information"); 37 | } 38 | 39 | if(fee != null){ 40 | accountUpgrade = new AccountUpgradeOperation(accountToUpgrade, isUpgrade, fee); 41 | }else{ 42 | accountUpgrade = new AccountUpgradeOperation(accountToUpgrade, isUpgrade); 43 | } 44 | return accountUpgrade; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/operations/BaseOperationBuilder.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import cy.agorise.graphenej.BaseOperation; 4 | 5 | /** 6 | * Base template for all operation-specific factory classes. 7 | */ 8 | public abstract class BaseOperationBuilder { 9 | 10 | /** 11 | * Must be implemented and return the specific operation the 12 | * factory is supposed to build. 13 | * 14 | * @return: A usable instance of a given operation. 15 | */ 16 | public abstract BaseOperation build(); 17 | } 18 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/operations/LimitOrderCancelOperation.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import com.google.common.primitives.Bytes; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | import cy.agorise.graphenej.*; 8 | 9 | /** 10 | * Created by nelson on 3/21/17. 11 | */ 12 | public class LimitOrderCancelOperation extends BaseOperation { 13 | 14 | // Constants used in the JSON representation 15 | public static final String KEY_FEE_PAYING_ACCOUNT = "fee_paying_account"; 16 | public static final String KEY_ORDER_ID = "order"; 17 | 18 | 19 | public LimitOrderCancelOperation(LimitOrder order, UserAccount feePayingAccount) { 20 | super(OperationType.LIMIT_ORDER_CANCEL_OPERATION); 21 | this.order = order; 22 | this.feePayingAccount = feePayingAccount; 23 | } 24 | 25 | // Inner fields of a limit order cancel operation 26 | private AssetAmount fee; 27 | private UserAccount feePayingAccount; 28 | private LimitOrder order; 29 | 30 | @Override 31 | public String toJsonString() { 32 | return null; 33 | } 34 | 35 | @Override 36 | public JsonElement toJsonObject() { 37 | JsonArray array = (JsonArray) super.toJsonObject(); 38 | JsonObject jsonObject = new JsonObject(); 39 | if(fee != null) 40 | jsonObject.add(KEY_FEE, fee.toJsonObject()); 41 | jsonObject.addProperty(KEY_FEE_PAYING_ACCOUNT, feePayingAccount.getObjectId()); 42 | jsonObject.addProperty(KEY_ORDER_ID, order.getObjectId()); 43 | jsonObject.add(KEY_EXTENSIONS, new JsonArray()); 44 | array.add(jsonObject); 45 | return array; 46 | } 47 | 48 | @Override 49 | public void setFee(AssetAmount assetAmount) { 50 | this.fee = assetAmount; 51 | } 52 | 53 | @Override 54 | public byte[] toBytes() { 55 | byte[] feeBytes = this.fee.toBytes(); 56 | byte[] feePayingAccountBytes = this.feePayingAccount.toBytes(); 57 | byte[] orderIdBytes = this.order.toBytes(); 58 | byte[] extensions = this.extensions.toBytes(); 59 | return Bytes.concat(feeBytes, feePayingAccountBytes, orderIdBytes, extensions); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/operations/TransferOperationBuilder.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import cy.agorise.graphenej.AssetAmount; 4 | import cy.agorise.graphenej.UserAccount; 5 | import cy.agorise.graphenej.errors.MalformedOperationException; 6 | import cy.agorise.graphenej.Memo; 7 | 8 | /** 9 | * Factory class used to build a transfer operation 10 | */ 11 | public class TransferOperationBuilder extends BaseOperationBuilder { 12 | private UserAccount from; 13 | private UserAccount to; 14 | private AssetAmount transferAmount; 15 | private AssetAmount fee; 16 | private Memo memo; 17 | 18 | public TransferOperationBuilder setSource(UserAccount from) { 19 | this.from = from; 20 | return this; 21 | } 22 | 23 | public TransferOperationBuilder setDestination(UserAccount to) { 24 | this.to = to; 25 | return this; 26 | } 27 | 28 | public TransferOperationBuilder setTransferAmount(AssetAmount transferAmount) { 29 | this.transferAmount = transferAmount; 30 | return this; 31 | } 32 | 33 | public TransferOperationBuilder setFee(AssetAmount fee) { 34 | this.fee = fee; 35 | return this; 36 | } 37 | 38 | public TransferOperationBuilder setMemo(Memo memo) { 39 | this.memo = memo; 40 | return this; 41 | } 42 | 43 | @Override 44 | public TransferOperation build(){ 45 | TransferOperation transferOperation; 46 | if(from == null ){ 47 | throw new MalformedOperationException("Missing source account information"); 48 | }else if(to == null){ 49 | throw new MalformedOperationException("Missing destination account information"); 50 | }else if(transferAmount == null){ 51 | throw new MalformedOperationException("Missing transfer amount information"); 52 | } 53 | if(fee != null){ 54 | transferOperation = new TransferOperation(from, to, transferAmount, fee); 55 | }else{ 56 | transferOperation = new TransferOperation(from, to, transferAmount); 57 | } 58 | if(memo != null){ 59 | transferOperation.setMemo(this.memo); 60 | } 61 | return transferOperation; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /graphenej/src/main/java/cy/agorise/graphenej/stats/ExponentialMovingAverage.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.stats; 2 | 3 | /** 4 | * Class used to compute the Exponential Moving Average of a sequence of values. 5 | * For more details see here. 6 | */ 7 | public class ExponentialMovingAverage { 8 | public static final double DEFAULT_ALPHA = 0.5; 9 | private double alpha; 10 | private Double accumulatedValue; 11 | 12 | /** 13 | * Constructor, which takes only the alpha parameter as an argument. 14 | * 15 | * @param alpha The coefficient alpha represents the degree of weighting decrease, a constant 16 | * smoothing factor between 0 and 1. A higher alpha discounts older observations faster. 17 | */ 18 | public ExponentialMovingAverage(double alpha) { 19 | this.alpha = alpha; 20 | } 21 | 22 | /** 23 | * Method that updates the average with a new sample 24 | * @param value New value 25 | * @return The updated average value 26 | */ 27 | public double updateValue(double value) { 28 | if (accumulatedValue == null) { 29 | accumulatedValue = value; 30 | return value; 31 | } 32 | double newValue = accumulatedValue + alpha * (value - accumulatedValue); 33 | accumulatedValue = newValue; 34 | return newValue; 35 | } 36 | 37 | /** 38 | * 39 | * @return Returns the current average value 40 | */ 41 | public double getAverage(){ 42 | return accumulatedValue == null ? 0 : accumulatedValue; 43 | } 44 | 45 | public void setAlpha(double alpha){ 46 | this.alpha = alpha; 47 | this.accumulatedValue = null; 48 | } 49 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/AssetAmountTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.common.primitives.UnsignedLong; 4 | 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | import static org.junit.Assert.assertNotSame; 10 | 11 | /** 12 | * Testing AssetAmount operations. 13 | */ 14 | public class AssetAmountTest { 15 | private final int LARGE_VALUE = 1000; 16 | private final int SMALL_VALUE = 500; 17 | private AssetAmount large; 18 | private AssetAmount small; 19 | private Asset testAsset = new Asset("1.3.0"); 20 | 21 | @Before 22 | public void setUp(){ 23 | large = new AssetAmount(UnsignedLong.valueOf(LARGE_VALUE), testAsset); 24 | small = new AssetAmount(UnsignedLong.valueOf(SMALL_VALUE), testAsset); 25 | } 26 | 27 | @Test 28 | public void testSubtraction(){ 29 | assertEquals(large.subtract(small).getAmount(), new AssetAmount(UnsignedLong.valueOf(LARGE_VALUE - SMALL_VALUE), testAsset).getAmount()); 30 | assertEquals(small.subtract(large).getAmount(), new AssetAmount(UnsignedLong.valueOf(Math.abs(SMALL_VALUE - LARGE_VALUE)), testAsset).getAmount()); 31 | } 32 | 33 | @Test 34 | public void testMultiplication(){ 35 | // Testing a simple multiplication by a double 36 | AssetAmount result = large.multiplyBy(0.5); 37 | assertEquals(500, result.getAmount().longValue()); 38 | 39 | // Testing the multiplication of a number that would normally give an overflow 40 | AssetAmount max = new AssetAmount(UnsignedLong.valueOf(Long.MAX_VALUE), testAsset); 41 | AssetAmount overMaxLong = max.multiplyBy(1.5); 42 | assertEquals("13835058055282163712", overMaxLong.getAmount().toString(10)); 43 | 44 | assertNotSame("Making sure the result and original references point to different instances",result, large); 45 | } 46 | 47 | @Test 48 | public void testDivision(){ 49 | // Testing a simple division by a double 50 | AssetAmount result = large.divideBy(0.5); 51 | assertEquals(2000, result.getAmount().longValue()); 52 | 53 | // Testing a division of a number that would normally give an overflow 54 | AssetAmount max = new AssetAmount(UnsignedLong.valueOf(Long.MAX_VALUE), testAsset); 55 | AssetAmount overMaxLong = max.divideBy(0.8); 56 | assertEquals("11529215046068469760", overMaxLong.getAmount().toString()); 57 | 58 | assertNotSame("Making sure the result and original references point to different instances",result, large); 59 | } 60 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/AssetTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | /** 6 | * Created by nelson on 12/24/16. 7 | */ 8 | public class AssetTest { 9 | 10 | @org.junit.Test 11 | public void equals() throws Exception { 12 | Asset bts = new Asset("1.3.0"); 13 | Asset bitUSD = new Asset("1.3.121"); 14 | assertNotEquals("Different assets should not be equal", bts, bitUSD); 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/AuthorityTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.HashMap; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | /** 12 | * Created by nelson on 12/16/16. 13 | */ 14 | public class AuthorityTest { 15 | private Authority authority; 16 | private Authority sameAuthority; 17 | private Authority differentAuthority; 18 | private Authority keyAuthority1; 19 | private Authority keyAuthority2; 20 | 21 | @Before 22 | public void setUp() throws Exception { 23 | authority = new Authority(); 24 | sameAuthority = new Authority(); 25 | HashMap accountAuthorityMap = new HashMap<>(); 26 | UserAccount userAccount = new UserAccount("1.2.20000"); 27 | accountAuthorityMap.put(userAccount, 1l); 28 | differentAuthority = new Authority(1, null, accountAuthorityMap); 29 | 30 | Address address1 = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY"); 31 | Address address2 = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY"); 32 | PublicKey publicKey = address1.getPublicKey(); 33 | PublicKey samePublicKey = address2.getPublicKey(); 34 | HashMap keyMap1 = new HashMap<>(); 35 | HashMap keyMap2 = new HashMap<>(); 36 | keyMap1.put(publicKey, 1l); 37 | keyMap2.put(samePublicKey, 1l); 38 | keyAuthority1 = new Authority(1, keyMap1, null); 39 | keyAuthority2 = new Authority(1, keyMap2, null); 40 | 41 | } 42 | 43 | @org.junit.Test 44 | public void toBytes() throws Exception { 45 | 46 | } 47 | 48 | @Test 49 | public void equals() throws Exception { 50 | assertEquals("Equal authorities", authority, sameAuthority); 51 | assertEquals("Different authorities ", authority, differentAuthority); 52 | assertEquals("Two public keys with the same public key should be equal", keyAuthority1, keyAuthority2); 53 | } 54 | 55 | @After 56 | public void tearDown(){ 57 | } 58 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/BrainKeyTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by nelson on 4/18/17. 10 | */ 11 | public class BrainKeyTest { 12 | public final String TEST_BRAINKEY = "BARIC BICKERN LITZ TIPFUL JINGLED POOL TUMBAK PURIST APOPYLE DURAIN SATLIJK FAUCAL"; 13 | 14 | public final String TEST_BRAINKEY_OPENLEDGER = "ona refan abscise neebor battik terbia bandit sundra gasser debar phytol frat hauler accede primy garland"; 15 | 16 | private BrainKey mBrainKey; 17 | 18 | @Before 19 | public void setup(){ 20 | mBrainKey = new BrainKey(TEST_BRAINKEY, BrainKey.DEFAULT_SEQUENCE_NUMBER); 21 | } 22 | 23 | /** 24 | * Test making sure that a simple brainkey can successfully generate the expected public address 25 | */ 26 | @Test 27 | public void testAddress(){ 28 | Address address = mBrainKey.getPublicAddress(Address.BITSHARES_PREFIX); 29 | Assert.assertEquals("Assert that the address created is the expected one", 30 | "BTS61UqqgE3ARuTGcckzARsdQm4EMFdBEwYyi1pbwyHrZZWrCDhT2", 31 | address.toString()); 32 | } 33 | 34 | /** 35 | * Test making sure that a OpenLedger's brainkey can successfully generate the given 36 | * 'owner' and 'active' keys. 37 | */ 38 | @Test 39 | public void testOpenledgerAddress(){ 40 | BrainKey brainKey1 = new BrainKey(TEST_BRAINKEY_OPENLEDGER, 0); 41 | BrainKey brainKey2 = new BrainKey(TEST_BRAINKEY_OPENLEDGER, 1); 42 | 43 | Address ownerAddress = brainKey1.getPublicAddress(Address.BITSHARES_PREFIX); 44 | Address activeAddress = brainKey2.getPublicAddress(Address.BITSHARES_PREFIX); 45 | 46 | Assert.assertEquals("Owner address matches", 47 | "BTS6dqT3J7tUcZP6xHo2mHkL8tq8zw5TQgGd6ntRMXH1EoNsCWTzm", 48 | ownerAddress.toString()); 49 | 50 | Assert.assertEquals("Active address matches", 51 | "BTS6DKvgY3yPyN7wKrhBGYhrnghhLSVCYz3ugUdi9pDPkicS6B7N2", 52 | activeAddress.toString()); 53 | } 54 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/KeyTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.bitcoinj.core.DumpedPrivateKey; 6 | import org.bitcoinj.core.ECKey; 7 | import org.junit.Test; 8 | 9 | /** 10 | * Created by nelson on 11/2/17. 11 | */ 12 | 13 | public class KeyTest { 14 | 15 | /** 16 | * Testing key to address derivation 17 | */ 18 | @Test 19 | public void testKeyToAddress(){ 20 | String wif = "5J96pne45qWM1WpektoeazN6k9Mt93jQ7LyueRxFfEMTiy6yxjM"; 21 | ECKey sourcePrivate = DumpedPrivateKey.fromBase58(null, wif).getKey(); 22 | Address address = new Address(ECKey.fromPublicOnly(sourcePrivate.getPubKey())); 23 | Assert.assertEquals("Generated address matches expected one", "BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY", address.toString()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/ObjectTypeTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by nelson on 5/5/17. 9 | */ 10 | public class ObjectTypeTest { 11 | 12 | @Test 13 | public void getGenericObjectId() throws Exception { 14 | ObjectType baseObject = ObjectType.BASE_OBJECT; 15 | ObjectType accountObject = ObjectType.ACCOUNT_OBJECT; 16 | ObjectType forceSettlementObject = ObjectType.FORCE_SETTLEMENT_OBJECT; 17 | ObjectType globalPropertiesObject = ObjectType.GLOBAL_PROPERTY_OBJECT; 18 | ObjectType specialAuthorityObject = ObjectType.SPECIAL_AUTHORITY_OBJECT; 19 | 20 | Assert.assertEquals("1.1.0", baseObject.getGenericObjectId()); 21 | Assert.assertEquals("1.2.0", accountObject.getGenericObjectId()); 22 | Assert.assertEquals("1.4.0", forceSettlementObject.getGenericObjectId()); 23 | Assert.assertEquals("2.0.0", globalPropertiesObject.getGenericObjectId()); 24 | Assert.assertEquals("2.14.0", specialAuthorityObject.getGenericObjectId()); 25 | } 26 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/PublicKeyTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Created by nelson on 12/16/16. 9 | */ 10 | public class PublicKeyTest { 11 | @Before 12 | public void setUp() throws Exception { 13 | 14 | } 15 | @org.junit.Test 16 | public void equals() throws Exception { 17 | Address address1 = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY"); 18 | Address address2 = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY"); 19 | Address address3 = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYp00"); 20 | PublicKey pk1 = address1.getPublicKey(); 21 | PublicKey pk2 = address2.getPublicKey(); 22 | PublicKey pk3 = address3.getPublicKey(); 23 | assertEquals("Public keys must be equal", pk1, pk2); 24 | assertNotEquals("Public keys must not be equal", pk1, pk3); 25 | } 26 | 27 | @After 28 | public void tearDown() throws Exception { 29 | 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/TestAccounts.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | /** 4 | * Created by nelson on 11/2/17. 5 | */ 6 | 7 | public class TestAccounts { 8 | 9 | public class Bilthon5 { 10 | public static final String BRAINKEY = "TIGROID BUTLER GALLOWS PAKEHA MOONJAH ACARI LUPUS BAE ACRISIA ABBACY BASSOON AKUND"; 11 | public static final String WIF = "5Jr84yteNbomGgLq5nvH2Y6WYJCBTsjugPouCtggfS3RguqxDo8"; 12 | } 13 | 14 | public class Bilthon7 { 15 | public static final String BRAINKEY = "PUMPER ISOTOME SERE STAINER CLINGER MOONLIT CHAETA UPBRIM AEDILIC BERTHER NIT SHAP SAID SHADING JUNCOUS CHOUGH"; 16 | public static final String WIF = "5J96pne45qWM1WpektoeazN6k9Mt93jQ7LyueRxFfEMTiy6yxjM"; 17 | } 18 | 19 | public class Bilthon16 { 20 | public static final String BRAINKEY = "BARIC BICKERN LITZ TIPFUL JINGLED POOL TUMBAK PURIST APOPYLE DURAIN SATLIJK FAUCAL"; 21 | public static final String WIF = "5JNxigtdkjkjM1dVGBBLk2axnUZmHrNLK4CqnUjWDzeX18HnyoD"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/UserAccountTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.neovisionaries.ws.client.WebSocketException; 4 | 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import cy.agorise.graphenej.api.BaseApiTest; 11 | import cy.agorise.graphenej.api.GetObjects; 12 | import cy.agorise.graphenej.interfaces.WitnessResponseListener; 13 | import cy.agorise.graphenej.models.BaseResponse; 14 | import cy.agorise.graphenej.models.WitnessResponse; 15 | 16 | /** 17 | * Created by nelson on 5/20/17. 18 | */ 19 | public class UserAccountTest extends BaseApiTest { 20 | private final UserAccount bilthon_25 = new UserAccount("1.2.151069"); 21 | 22 | @Test 23 | public void testToJsonString() { 24 | try{ 25 | ArrayList ids = new ArrayList<>(); 26 | ids.add(bilthon_25.getObjectId()); 27 | mWebSocket.addListener(new GetObjects(ids, new WitnessResponseListener() { 28 | 29 | @Override 30 | public void onSuccess(WitnessResponse response) { 31 | System.out.println("onSuccess"); 32 | List result = (List) response.result; 33 | UserAccount userAccount = (UserAccount) result.get(0); 34 | System.out.println("user account: "+userAccount.toJsonString()); 35 | 36 | synchronized (UserAccountTest.this){ 37 | UserAccountTest.this.notifyAll(); 38 | } 39 | } 40 | 41 | @Override 42 | public void onError(BaseResponse.Error error) { 43 | System.out.println("onError"); 44 | synchronized (UserAccountTest.this){ 45 | UserAccountTest.this.notifyAll(); 46 | } 47 | } 48 | })); 49 | 50 | mWebSocket.connect(); 51 | synchronized (this){ 52 | wait(); 53 | } 54 | }catch (WebSocketException e) { 55 | System.out.println("WebSocketException. Msg: " + e.getMessage()); 56 | } catch (InterruptedException e) { 57 | System.out.println("InterruptedException. Msg: "+e.getMessage()); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/UtilTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej; 2 | 3 | import com.google.common.primitives.UnsignedLong; 4 | 5 | import junit.framework.Assert; 6 | 7 | import org.junit.Test; 8 | 9 | /** 10 | * Class used to test Util methods 11 | */ 12 | 13 | public class UtilTest { 14 | 15 | @Test 16 | public void testRevertUnsignedLong(){ 17 | UnsignedLong unsignedLong = UnsignedLong.valueOf("12179241258665439971"); 18 | byte[] reversed = Util.revertUnsignedLong(unsignedLong); 19 | Assert.assertEquals("e3f28878655b05a9", Util.bytesToHex(reversed)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/api/BaseApiTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | import com.neovisionaries.ws.client.WebSocket; 4 | import com.neovisionaries.ws.client.WebSocketFactory; 5 | 6 | import org.junit.Before; 7 | 8 | import javax.net.ssl.SSLContext; 9 | 10 | import cy.agorise.graphenej.test.NaiveSSLContext; 11 | 12 | /** 13 | * Base class that every test that involves any communication with the API must extend 14 | */ 15 | 16 | public class BaseApiTest { 17 | protected String NODE_URL = System.getenv("NODE_URL"); 18 | 19 | protected SSLContext context; 20 | protected WebSocket mWebSocket; 21 | 22 | @Before 23 | public void setUp() throws Exception { 24 | context = NaiveSSLContext.getInstance("TLS"); 25 | WebSocketFactory factory = new WebSocketFactory(); 26 | 27 | // Set the custom SSL context. 28 | factory.setSSLContext(context); 29 | 30 | mWebSocket = factory.createSocket(NODE_URL); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/api/GetAccountsTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | import com.neovisionaries.ws.client.WebSocketException; 4 | 5 | import junit.framework.Assert; 6 | 7 | import org.junit.Test; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import cy.agorise.graphenej.UserAccount; 13 | import cy.agorise.graphenej.interfaces.WitnessResponseListener; 14 | import cy.agorise.graphenej.models.AccountProperties; 15 | import cy.agorise.graphenej.models.BaseResponse; 16 | import cy.agorise.graphenej.models.WitnessResponse; 17 | 18 | public class GetAccountsTest extends BaseApiTest { 19 | private UserAccount ltmAccount = new UserAccount("1.2.99700"); 20 | private UserAccount nonLtmAccount = new UserAccount("1.2.140994"); 21 | 22 | @Test 23 | public void testGetAccount(){ 24 | ArrayList userAccounts = new ArrayList<>(); 25 | userAccounts.add(ltmAccount); 26 | userAccounts.add(nonLtmAccount); 27 | mWebSocket.addListener(new GetAccounts(userAccounts, true, new WitnessResponseListener(){ 28 | 29 | @Override 30 | public void onSuccess(WitnessResponse response) { 31 | System.out.println("onSuccess."); 32 | List accounts = (List) response.result; 33 | System.out.println(String.format("Got %d accounts", accounts.size())); 34 | for(AccountProperties accountProperties : accounts){ 35 | System.out.println("account name....: "+accountProperties.name); 36 | System.out.println("expiration date.: "+accountProperties.membership_expiration_date); 37 | } 38 | AccountProperties ltmAccountProperties = accounts.get(0); 39 | AccountProperties nonLtmAccountProperties = accounts.get(1); 40 | Assert.assertEquals(ltmAccountProperties.membership_expiration_date, UserAccount.LIFETIME_EXPIRATION_DATE); 41 | Assert.assertFalse(nonLtmAccountProperties.membership_expiration_date.equals(UserAccount.LIFETIME_EXPIRATION_DATE)); 42 | synchronized (GetAccountsTest.this){ 43 | GetAccountsTest.this.notifyAll(); 44 | } 45 | } 46 | 47 | @Override 48 | public void onError(BaseResponse.Error error) { 49 | System.out.println("onError. Msg: "+error.message); 50 | synchronized (GetAccountsTest.this){ 51 | GetAccountsTest.this.notifyAll(); 52 | } 53 | } 54 | })); 55 | 56 | try{ 57 | mWebSocket.connect(); 58 | synchronized (this){ 59 | wait(); 60 | } 61 | }catch (WebSocketException e) { 62 | System.out.println("WebSocketException. Msg: " + e.getMessage()); 63 | } catch (InterruptedException e) { 64 | System.out.println("InterruptedException. Msg: "+e.getMessage()); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/api/GetKeyReferencesTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | import com.neovisionaries.ws.client.WebSocketException; 4 | 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import cy.agorise.graphenej.Address; 11 | import cy.agorise.graphenej.UserAccount; 12 | import cy.agorise.graphenej.errors.MalformedAddressException; 13 | import cy.agorise.graphenej.interfaces.WitnessResponseListener; 14 | import cy.agorise.graphenej.models.BaseResponse; 15 | import cy.agorise.graphenej.models.WitnessResponse; 16 | 17 | /** 18 | * Created by nelson on 4/14/17. 19 | */ 20 | public class GetKeyReferencesTest extends BaseApiTest { 21 | 22 | private String[] publicKeys = new String[] { 23 | "BTS8DuGHXpHYedq7qhT65BEEdQPvLT8nxZ862Hf8NgvSZUMuwUFkn", 24 | "BTS53ehf9Qoeg9o4E1KuxdZRXCVg3Z9ApbEDHVdQhERDJDEFkPkGs" 25 | }; 26 | 27 | @Test 28 | public void testGetKeyReferences(){ 29 | ArrayList
addresses = new ArrayList<>(); 30 | for(String addr : publicKeys){ 31 | try { 32 | Address address = new Address(addr); 33 | addresses.add(address); 34 | } catch (MalformedAddressException e) { 35 | System.out.println("MalformedAddressException. Msg: "+e.getMessage()); 36 | } 37 | } 38 | mWebSocket.addListener(new GetKeyReferences(addresses, new WitnessResponseListener() { 39 | @Override 40 | public void onSuccess(WitnessResponse response) { 41 | System.out.println("onSuccess"); 42 | int counter = 0; 43 | List> accountListList = (List>) response.result; 44 | for(List accountList : accountListList){ 45 | for(UserAccount userAccount : accountList){ 46 | System.out.println("User account: "+userAccount.getObjectId()); 47 | } 48 | if(accountList.size() > 1){ 49 | System.out.println("Key with address: "+publicKeys[counter]+" controls more than one role in account: "+accountList.get(0).getObjectId()); 50 | }else if(accountList.size() == 1){ 51 | System.out.println("Key with address: "+publicKeys[counter]+" controls just one role in account: "+accountList.get(0).getObjectId()); 52 | } 53 | counter++; 54 | } 55 | synchronized (GetKeyReferencesTest.this){ 56 | GetKeyReferencesTest.this.notifyAll(); 57 | } 58 | } 59 | 60 | @Override 61 | public void onError(BaseResponse.Error error) { 62 | System.out.println("onError. Msg: "+error.message); 63 | 64 | synchronized (GetKeyReferencesTest.this){ 65 | GetKeyReferencesTest.this.notifyAll(); 66 | } 67 | } 68 | })); 69 | 70 | try{ 71 | mWebSocket.connect(); 72 | synchronized (this){ 73 | wait(); 74 | } 75 | } catch (WebSocketException e) { 76 | System.out.println("WebSocketException. Msg: " + e.getMessage()); 77 | } catch (InterruptedException e) { 78 | System.out.println("InterruptedException. Msg: "+e.getMessage()); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/api/GetRelativeAccountHistoryTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | import com.neovisionaries.ws.client.WebSocketException; 4 | 5 | import org.junit.Test; 6 | 7 | import java.util.List; 8 | import cy.agorise.graphenej.UserAccount; 9 | import cy.agorise.graphenej.interfaces.WitnessResponseListener; 10 | import cy.agorise.graphenej.models.BaseResponse; 11 | import cy.agorise.graphenej.models.OperationHistory; 12 | import cy.agorise.graphenej.models.WitnessResponse; 13 | import cy.agorise.graphenej.operations.TransferOperation; 14 | 15 | /** 16 | * Created by nelson on 9/25/17. 17 | */ 18 | 19 | public class GetRelativeAccountHistoryTest extends BaseApiTest { 20 | private final String TAG = this.getClass().getName(); 21 | 22 | private int HISTORICAL_TRANSFER_BATCH_SIZE = 10; 23 | private final UserAccount bilthon_7 = new UserAccount("1.2.140994"); 24 | private int historicalTransferCount; 25 | 26 | @Test 27 | public void testRelativeAccountHistory(){ 28 | int start = 0; 29 | GetRelativeAccountHistory mGetRelativeAccountHistory = new GetRelativeAccountHistory(bilthon_7, 0, HISTORICAL_TRANSFER_BATCH_SIZE, start, mTransferHistoryListener); 30 | mWebSocket.addListener(mGetRelativeAccountHistory); 31 | 32 | try{ 33 | mWebSocket.connect(); 34 | synchronized (this){ 35 | wait(); 36 | } 37 | }catch (WebSocketException e) { 38 | System.out.println("WebSocketException. Msg: " + e.getMessage()); 39 | } catch (InterruptedException e) { 40 | System.out.println("InterruptedException. Msg: "+e.getMessage()); 41 | } 42 | } 43 | 44 | /** 45 | * Callback activated once we get a response back from the full node telling us about the 46 | * transfer history of the current account. 47 | */ 48 | private WitnessResponseListener mTransferHistoryListener = new WitnessResponseListener() { 49 | 50 | @Override 51 | public void onSuccess(WitnessResponse response) { 52 | System.out.println("mTransferHistoryListener.onSuccess"); 53 | historicalTransferCount++; 54 | WitnessResponse> resp = response; 55 | for(OperationHistory historicalTransfer : resp.result){ 56 | if(historicalTransfer.getOperation() != null){ 57 | System.out.println("Got transfer operation!"); 58 | TransferOperation transferOperation = (TransferOperation) historicalTransfer.getOperation(); 59 | System.out.println(String.format("%s - > %s, memo: %s", 60 | transferOperation.getFrom().getObjectId(), 61 | transferOperation.getTo().getObjectId(), 62 | transferOperation.getMemo() == null ? "*" : transferOperation.getMemo().getStringMessage())); 63 | } 64 | } 65 | } 66 | 67 | @Override 68 | public void onError(BaseResponse.Error error) { 69 | System.out.println("onError. Msg: "+error.message); 70 | } 71 | }; 72 | } 73 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/api/LookupAssetSymbolsTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import cy.agorise.graphenej.Asset; 11 | import cy.agorise.graphenej.interfaces.WitnessResponseListener; 12 | import cy.agorise.graphenej.models.BaseResponse; 13 | import cy.agorise.graphenej.models.WitnessResponse; 14 | 15 | /** 16 | * Testing the standalone usage of the {@link LookupAssetSymbols} API handler. 17 | */ 18 | 19 | public class LookupAssetSymbolsTest extends BaseApiTest { 20 | 21 | @Test 22 | public void testLookupAssetSymbolsWithString(){ 23 | ArrayList assetSymbols = new ArrayList<>(); 24 | assetSymbols.add("USD"); 25 | mWebSocket.addListener(new LookupAssetSymbols(assetSymbols, true, new WitnessResponseListener() { 26 | @Override 27 | public void onSuccess(WitnessResponse response) { 28 | System.out.println("onSuccess"); 29 | List assets = (List) response.result; 30 | Assert.assertEquals(1, assets.size()); 31 | Assert.assertEquals("1.3.121", assets.get(0).getObjectId()); 32 | } 33 | 34 | @Override 35 | public void onError(BaseResponse.Error error) { 36 | System.out.println("onError"); 37 | } 38 | })); 39 | } 40 | 41 | @Test 42 | public void testLookupAssetSymbolsWithAsset(){ 43 | ArrayList assetSymbols = new ArrayList<>(); 44 | assetSymbols.add(new Asset("1.3.121")); 45 | mWebSocket.addListener(new LookupAssetSymbols(assetSymbols, true, new WitnessResponseListener() { 46 | @Override 47 | public void onSuccess(WitnessResponse response) { 48 | System.out.println("onSuccess"); 49 | List assets = (List) response.result; 50 | Assert.assertEquals(1, assets.size()); 51 | Assert.assertEquals("1.3.121", assets.get(0).getObjectId()); 52 | } 53 | 54 | @Override 55 | public void onError(BaseResponse.Error error) { 56 | System.out.println("onError"); 57 | } 58 | })); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/api/calls/GetAccountHistoryTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.api.calls; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.junit.Test; 6 | 7 | import cy.agorise.graphenej.UserAccount; 8 | import cy.agorise.graphenej.models.ApiCall; 9 | 10 | public class GetAccountHistoryTest { 11 | 12 | @Test 13 | public void testSerialization(){ 14 | UserAccount userAccount = new UserAccount("1.2.139293"); 15 | String end = "1.11.225030218"; 16 | String start = "1.11.225487973"; 17 | int limit = 20; 18 | GetAccountHistory getAccountHistory = new GetAccountHistory(userAccount, start, end, limit); 19 | ApiCall apiCall = getAccountHistory.toApiCall(2, 3); 20 | String serialized = apiCall.toJsonString(); 21 | System.out.println("> "+serialized); 22 | String expected = "{\"id\":3,\"method\":\"call\",\"params\":[2,\"get_account_history\",[\"1.2.139293\",\"1.11.225030218\",20,\"1.11.225487973\"]],\"jsonrpc\":\"2.0\"}"; 23 | Assert.assertEquals("Serialized is as expected", expected, serialized); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/models/HistoryOperationDetailsTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | 7 | import junit.framework.Assert; 8 | 9 | import org.junit.Test; 10 | 11 | import java.lang.reflect.Type; 12 | 13 | import cy.agorise.graphenej.AssetAmount; 14 | import cy.agorise.graphenej.BaseOperation; 15 | import cy.agorise.graphenej.Extensions; 16 | import cy.agorise.graphenej.UserAccount; 17 | import cy.agorise.graphenej.api.android.DeserializationMap; 18 | import cy.agorise.graphenej.Memo; 19 | 20 | public class HistoryOperationDetailsTest { 21 | 22 | @Test 23 | public void testDeserialization(){ 24 | String text = "{\"id\":5,\"jsonrpc\":\"2.0\",\"result\":{\"total_count\":2,\"operation_history_objs\":[{\"id\":\"1.11.5701809\",\"op\":[0,{\"fee\":{\"amount\":264174,\"asset_id\":\"1.3.0\"},\"from\":\"1.2.99700\",\"to\":\"1.2.138632\",\"amount\":{\"amount\":20000,\"asset_id\":\"1.3.120\"},\"extensions\":[]}],\"result\":[0,{}],\"block_num\":11094607,\"trx_in_block\":0,\"op_in_trx\":0,\"virtual_op\":31767},{\"id\":\"1.11.5701759\",\"op\":[0,{\"fee\":{\"amount\":264174,\"asset_id\":\"1.3.0\"},\"from\":\"1.2.99700\",\"to\":\"1.2.138632\",\"amount\":{\"amount\":10000000,\"asset_id\":\"1.3.0\"},\"extensions\":[]}],\"result\":[0,{}],\"block_num\":11094501,\"trx_in_block\":0,\"op_in_trx\":0,\"virtual_op\":31717}]}}\n"; 25 | Gson gson = new GsonBuilder() 26 | .setExclusionStrategies(new DeserializationMap.SkipAccountOptionsStrategy(), new DeserializationMap.SkipAssetOptionsStrategy()) 27 | .registerTypeAdapter(BaseOperation.class, new BaseOperation.OperationDeserializer()) 28 | .registerTypeAdapter(OperationHistory.class, new OperationHistory.OperationHistoryDeserializer()) 29 | .registerTypeAdapter(Memo.class, new Memo.MemoSerializer()) 30 | .registerTypeAdapter(Extensions.class, new Extensions.ExtensionsDeserializer()) 31 | .registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer()) 32 | .registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer()) 33 | .create(); 34 | 35 | Type GetAccountHistoryByOperationsResponse = new TypeToken>(){}.getType(); 36 | JsonRpcResponse response = gson.fromJson(text, GetAccountHistoryByOperationsResponse); 37 | Assert.assertNotNull(response.result); 38 | Assert.assertNotNull(response.result.operation_history_objs); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/models/JsonRpcNotificationTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | import java.io.Serializable; 10 | import java.util.ArrayList; 11 | 12 | import cy.agorise.graphenej.AssetAmount; 13 | import cy.agorise.graphenej.Transaction; 14 | import cy.agorise.graphenej.UserAccount; 15 | import cy.agorise.graphenej.Memo; 16 | import cy.agorise.graphenej.operations.CustomOperation; 17 | import cy.agorise.graphenej.operations.LimitOrderCreateOperation; 18 | import cy.agorise.graphenej.operations.TransferOperation; 19 | 20 | public class JsonRpcNotificationTest { 21 | 22 | private String text = "{\"method\":\"notice\",\"params\":[3,[[{\"id\":\"2.1.0\",\"head_block_number\":30071834,\"head_block_id\":\"01cadc1a5f3f517e2eba9588111aef3af3c59916\",\"time\":\"2018-08-30T18:19:45\",\"current_witness\":\"1.6.74\",\"next_maintenance_time\":\"2018-08-30T19:00:00\",\"last_budget_time\":\"2018-08-30T18:00:00\",\"witness_budget\":80800000,\"accounts_registered_this_interval\":9,\"recently_missed_count\":0,\"current_aslot\":30228263,\"recent_slots_filled\":\"340282366920938463463374607431768211455\",\"dynamic_flags\":0,\"last_irreversible_block_num\":30071813}]]]}"; 23 | 24 | @Test 25 | public void failResponseDeserialization(){ 26 | Gson gson = new Gson(); 27 | JsonRpcResponse response = gson.fromJson(text, JsonRpcResponse.class); 28 | // The result field of this de-serialized object should be null 29 | Assert.assertNull(response.result); 30 | } 31 | 32 | @Test 33 | public void succeedNotificationDeserialization(){ 34 | Gson gson = new GsonBuilder() 35 | .registerTypeAdapter(Transaction.class, new Transaction.TransactionDeserializer()) 36 | .registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer()) 37 | .registerTypeAdapter(LimitOrderCreateOperation.class, new LimitOrderCreateOperation.LimitOrderCreateDeserializer()) 38 | .registerTypeAdapter(CustomOperation.class, new CustomOperation.CustomOperationDeserializer()) 39 | .registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer()) 40 | .registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer()) 41 | .registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer()) 42 | .registerTypeAdapter(Memo.class, new Memo.MemoDeserializer()) 43 | .registerTypeAdapter(OperationHistory.class, new OperationHistory.OperationHistoryDeserializer()) 44 | .registerTypeAdapter(JsonRpcNotification.class, new JsonRpcNotification.JsonRpcNotificationDeserializer()) 45 | .create(); 46 | JsonRpcNotification notification = gson.fromJson(text, JsonRpcNotification.class); 47 | // Should deserialize a 'params' array with 2 elements 48 | Assert.assertEquals(2, notification.params.size()); 49 | // The first element should be the number 3 50 | Assert.assertEquals(3, notification.params.get(0)); 51 | ArrayList secondArgument = (ArrayList) notification.params.get(1); 52 | // The second element should be an array of length 1 53 | Assert.assertEquals(1, secondArgument.size()); 54 | // Extracting the payload, which should be in itself another array 55 | DynamicGlobalProperties payload = (DynamicGlobalProperties) secondArgument.get(0); 56 | // Dynamic global properties head_block_number should match 57 | Assert.assertEquals(30071834, payload.head_block_number); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/models/JsonRpcResponseTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.models; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import junit.framework.Assert; 6 | 7 | import org.junit.Test; 8 | 9 | public class JsonRpcResponseTest { 10 | 11 | @Test 12 | public void deserializeJsonRpcResponse(){ 13 | String text = "{\"id\":4,\"jsonrpc\":\"2.0\",\"result\":[{\"id\":\"2.1.0\",\"head_block_number\":30071833,\"head_block_id\":\"01cadc1964cb04ab551463e26033ab0f159bc8e1\",\"time\":\"2018-08-30T18:19:42\",\"current_witness\":\"1.6.71\",\"next_maintenance_time\":\"2018-08-30T19:00:00\",\"last_budget_time\":\"2018-08-30T18:00:00\",\"witness_budget\":80900000,\"accounts_registered_this_interval\":9,\"recently_missed_count\":0,\"current_aslot\":30228262,\"recent_slots_filled\":\"340282366920938463463374607431768211455\",\"dynamic_flags\":0,\"last_irreversible_block_num\":30071813}]}"; 14 | Gson gson = new Gson(); 15 | JsonRpcResponse response = gson.fromJson(text, JsonRpcResponse.class); 16 | System.out.println("response: "+response.result); 17 | Assert.assertNotNull(response); 18 | Assert.assertNotNull(response.result); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/network/FullNodeTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.network; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.junit.Test; 6 | 7 | public class FullNodeTest { 8 | 9 | @Test 10 | public void testFullNodeComparable(){ 11 | FullNode nodeA = new FullNode("wss://dummy"); 12 | FullNode nodeB = new FullNode("wss://dummy"); 13 | FullNode nodeC = new FullNode("wss://dummy"); 14 | nodeA.addLatencyValue(100); 15 | nodeB.addLatencyValue(200); 16 | nodeC.addLatencyValue(100); 17 | Assert.assertTrue("Makes sure the node nodeA.compareTo(nodeB) returns a negative value", nodeA.compareTo(nodeB) < 0); 18 | Assert.assertTrue("Makes sure nodeA.compareTo(nodeB) returns zero", nodeA.compareTo(nodeC) == 0); 19 | Assert.assertTrue("Makes sure nodeB.compareTo(nodeA) returns a positive value", nodeB.compareTo(nodeA) > 0); 20 | } 21 | 22 | @Test 23 | public void testFullNodeAverageLatency(){ 24 | FullNode fullNode = new FullNode("wss://dummy"); 25 | fullNode.getLatencyAverage().setAlpha(0.5); 26 | fullNode.addLatencyValue(100); 27 | Assert.assertEquals(100.0, fullNode.getLatencyValue()); 28 | fullNode.addLatencyValue(50); 29 | Assert.assertEquals(75.0, fullNode.getLatencyValue()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/network/LatencyNodeProviderTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.network; 2 | 3 | import junit.framework.Assert; 4 | 5 | import org.junit.Test; 6 | 7 | import java.util.List; 8 | 9 | public class LatencyNodeProviderTest { 10 | private FullNode nodeA, nodeB, nodeC; 11 | private LatencyNodeProvider latencyNodeProvider; 12 | 13 | private void setupTestNodes(){ 14 | // Creating 3 nodes with different latencies 15 | nodeA = new FullNode("wss://nodeA"); 16 | nodeB = new FullNode("wss://nodeB"); 17 | nodeC = new FullNode("wss://nodeC"); 18 | 19 | // Adding latencies measurements 20 | nodeA.addLatencyValue(100); 21 | nodeB.addLatencyValue(50); 22 | nodeC.addLatencyValue(20); 23 | 24 | // Creating a node provider and adding the nodes created previously 25 | latencyNodeProvider = new LatencyNodeProvider(); 26 | latencyNodeProvider.addNode(nodeC); 27 | latencyNodeProvider.addNode(nodeA); 28 | latencyNodeProvider.addNode(nodeB); 29 | } 30 | 31 | @Test 32 | public void testSorting(){ 33 | setupTestNodes(); 34 | 35 | // Confirming that the best node is nodeC 36 | FullNode bestNode = latencyNodeProvider.getBestNode(); 37 | System.out.println("Best node latency: "+bestNode.getLatencyValue()); 38 | Assert.assertSame("Check that the best node is nodeC", nodeC, bestNode); 39 | 40 | // Improving nodeA score by feeding it with new better latency measurements 41 | latencyNodeProvider.updateNode(nodeA, 10); 42 | latencyNodeProvider.updateNode(nodeA, 10); 43 | latencyNodeProvider.updateNode(nodeA, 10); 44 | latencyNodeProvider.updateNode(nodeA, 10); 45 | 46 | // Updating the nodeA position in the provider 47 | latencyNodeProvider.updateNode(nodeA); 48 | bestNode = latencyNodeProvider.getBestNode(); 49 | System.out.println("Best node latency after update: "+bestNode.getLatencyValue()); 50 | Assert.assertSame("Check that the best node now is the nodeA", nodeA, bestNode); 51 | } 52 | 53 | @Test 54 | public void testSortedList(){ 55 | setupTestNodes(); 56 | 57 | // Confirming that the getSortedNodes gives us a sorted list of nodes in increasing latency order 58 | List fullNodeList = latencyNodeProvider.getSortedNodes(); 59 | Assert.assertSame(nodeC, fullNodeList.get(0)); 60 | Assert.assertSame(nodeB, fullNodeList.get(1)); 61 | Assert.assertSame(nodeA, fullNodeList.get(2)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/operations/AccountUpdateOperationTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import com.google.common.primitives.UnsignedLong; 4 | 5 | import org.bitcoinj.core.ECKey; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | 12 | import cy.agorise.graphenej.AccountOptions; 13 | import cy.agorise.graphenej.Address; 14 | import cy.agorise.graphenej.Asset; 15 | import cy.agorise.graphenej.AssetAmount; 16 | import cy.agorise.graphenej.Authority; 17 | import cy.agorise.graphenej.BaseOperation; 18 | import cy.agorise.graphenej.BlockData; 19 | import cy.agorise.graphenej.BrainKey; 20 | import cy.agorise.graphenej.PublicKey; 21 | import cy.agorise.graphenej.Transaction; 22 | import cy.agorise.graphenej.UserAccount; 23 | import cy.agorise.graphenej.Util; 24 | import cy.agorise.graphenej.errors.MalformedAddressException; 25 | 26 | /** 27 | * Created by nelson on 4/18/17. 28 | */ 29 | public class AccountUpdateOperationTest { 30 | 31 | private static final String BILTHON_16_BRAIN_KEY = "SOAPILY GASSING FIFIE OZONATE WHYO TOPLINE PRISMY ZEUGMA GLOTTIC DAVEN CORODY PFUI"; 32 | public final String ADDRESS = "BTS8RYD5ehEMtTrfmeWRVKJzvLK2AqunxRh2XhXyXVxKtDjeAhYs1"; 33 | 34 | private final Asset CORE = new Asset("1.3.0"); 35 | 36 | private Authority active; 37 | private AccountOptions options; 38 | 39 | @Before 40 | public void setup(){ 41 | try{ 42 | HashMap keyAuth = new HashMap<>(); 43 | keyAuth.put(new Address(ADDRESS), 1l); 44 | active = new Authority(); 45 | active.setKeyAuthorities(keyAuth); 46 | 47 | options = new AccountOptions(); 48 | options.setMemoKey(new PublicKey(ECKey.fromPublicOnly(new Address(ADDRESS).getPublicKey().toBytes()))); 49 | options.setNumWitness(0); 50 | options.setNum_comittee(0); 51 | options.setVotingAccount(new UserAccount("1.2.5")); 52 | }catch(MalformedAddressException e){ 53 | System.out.println("MalformedAddressException. Msg: "+e.getMessage()); 54 | } 55 | } 56 | 57 | @Test 58 | public void testOperationSerialization(){ 59 | AccountUpdateOperationBuilder builder = new AccountUpdateOperationBuilder() 60 | .setAccount(new UserAccount("1.2.143569")) 61 | .setFee(new AssetAmount(UnsignedLong.valueOf(14676), CORE)) 62 | .setActive(active) 63 | .setOptions(options); 64 | 65 | AccountUpdateOperation operation = builder.build(); 66 | 67 | ArrayList operations = new ArrayList<>(); 68 | operations.add(operation); 69 | ECKey privateKey = new BrainKey(BILTHON_16_BRAIN_KEY, 0).getPrivateKey(); 70 | BlockData blockData = new BlockData(3703, 2015738269, 1492551764); 71 | 72 | Transaction tx = new Transaction(privateKey, blockData, operations); 73 | 74 | // String json = tx.toJsonString(); 75 | byte[] serialized = tx.toBytes(); 76 | 77 | // System.out.println("json: "+json); 78 | System.out.println("serialized: "+ Util.bytesToHex(serialized)); 79 | } 80 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/operations/AccountUpgradeOperationTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import com.google.common.primitives.Bytes; 4 | import com.google.common.primitives.UnsignedLong; 5 | 6 | import org.bitcoinj.core.ECKey; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | import java.util.ArrayList; 11 | 12 | import cy.agorise.graphenej.Asset; 13 | import cy.agorise.graphenej.AssetAmount; 14 | import cy.agorise.graphenej.BaseOperation; 15 | import cy.agorise.graphenej.BlockData; 16 | import cy.agorise.graphenej.BrainKey; 17 | import cy.agorise.graphenej.Chains; 18 | import cy.agorise.graphenej.Transaction; 19 | import cy.agorise.graphenej.UserAccount; 20 | import cy.agorise.graphenej.Util; 21 | 22 | public class AccountUpgradeOperationTest { 23 | private static final String BILTHON_16_BRAIN_KEY = "SOAPILY GASSING FIFIE OZONATE WHYO TOPLINE PRISMY ZEUGMA GLOTTIC DAVEN CORODY PFUI"; 24 | 25 | private final Asset CORE = new Asset("1.3.0"); 26 | 27 | // This was obtained by calling the 'serialized_transaction' command of the cli_wallet utility and stripping it away 28 | // from its signature. 29 | // 30 | // Ex: 31 | // >>> serialize_transaction {"expiration":"2017-04-18T21:42:47","signatures":["207dd63cb89d05266ed4af0935270f269839154d5f04229041997e6c98f10bba21752d6638eb7539c69fb22874fb1e39aad00a5eed6dd5e81e14845e79b60a0590"],"operations":[[8,{"fee":{"amount":69470219,"asset_id":"1.3.0"},"account_to_upgrade":"1.2.143569","upgrade_to_lifetime_member":"true","extensions":[]}]],"extensions":[],"ref_block_num":3703,"ref_block_prefix":2015738269} 32 | private final String SERIALIZED_TX = "770e9db925785788f65801080b0824040000000000d1e108010000"; 33 | 34 | @Test 35 | public void testOperationSerialization(){ 36 | AccountUpgradeOperationBuilder builder = new AccountUpgradeOperationBuilder() 37 | .setAccountToUpgrade(new UserAccount("1.2.143569")) 38 | .setFee(new AssetAmount(UnsignedLong.valueOf(69470219), CORE)) 39 | .setIsUpgrade(true); 40 | 41 | AccountUpgradeOperation upgradeOperation = builder.build(); 42 | 43 | ArrayList operations = new ArrayList<>(); 44 | operations.add(upgradeOperation); 45 | ECKey privateKey = new BrainKey(BILTHON_16_BRAIN_KEY, 0).getPrivateKey(); 46 | BlockData blockData = new BlockData(3703, 2015738269, 1492551764); 47 | 48 | Transaction tx = new Transaction(privateKey, blockData, operations); 49 | 50 | // Serialized transaction 51 | byte[] serialized = tx.toBytes(); 52 | 53 | // The expected serialized transaction is a concatenation of the chain id + the serialized tx 54 | byte[] expectedTx = Bytes.concat(Util.hexToBytes(Chains.BITSHARES.CHAIN_ID),Util.hexToBytes(SERIALIZED_TX)); 55 | 56 | Assert.assertArrayEquals(expectedTx, serialized); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/operations/CustomOperationTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import com.google.common.primitives.UnsignedLong; 4 | import cy.agorise.graphenej.Asset; 5 | import cy.agorise.graphenej.AssetAmount; 6 | import cy.agorise.graphenej.UserAccount; 7 | import cy.agorise.graphenej.Util; 8 | import org.junit.Test; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | import static org.junit.Assert.assertArrayEquals; 14 | 15 | public class CustomOperationTest { 16 | private final Asset CORE_ASSET = new Asset("1.3.0"); 17 | private final AssetAmount fee = new AssetAmount(UnsignedLong.valueOf(100000L), CORE_ASSET); 18 | private final UserAccount payer = new UserAccount("1.2.20"); 19 | private final Integer operationId = 61166; 20 | private final List requiredAuths = Collections.singletonList(payer); 21 | private final String shortData = "some data"; 22 | private final String longData = "very long data, very long data, very long data, very long data, very long data, very long data, very long data, very long data, very long data, very long data, very long data, very long data, very long data, very long data..."; 23 | 24 | private static final byte[] EXPECTED_SERIALIZED_BYTES_1 = Util.hexToBytes("a08601000000000000140114eeee09736f6d652064617461"); 25 | private static final byte[] EXPECTED_SERIALIZED_BYTES_2 = Util.hexToBytes("a08601000000000000140114eeeee50176657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c202076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c202076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c202076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612c202076657279206c6f6e6720646174612c2076657279206c6f6e6720646174612e2e2e"); 26 | 27 | @Test 28 | public void testToBytes() throws Exception { 29 | CustomOperation customOperation1 = new CustomOperation(fee, payer, operationId, requiredAuths, shortData); 30 | byte[] serialized1 = customOperation1.toBytes(); 31 | assertArrayEquals(EXPECTED_SERIALIZED_BYTES_1, serialized1); 32 | 33 | // test with some long data string to check if data length is serialized correctly 34 | CustomOperation customOperation2 = new CustomOperation(fee, payer, operationId, requiredAuths, longData); 35 | byte[] serialized2 = customOperation2.toBytes(); 36 | assertArrayEquals(EXPECTED_SERIALIZED_BYTES_2, serialized2); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/operations/LimitOrderCancelOperationTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import com.google.common.primitives.UnsignedLong; 4 | import cy.agorise.graphenej.*; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertArrayEquals; 10 | 11 | /** 12 | * Created by nelson on 3/21/17. 13 | */ 14 | public class LimitOrderCancelOperationTest { 15 | private static final Asset CORE_ASSET = new Asset("1.3.0"); 16 | private UserAccount feePayingAccount; 17 | private LimitOrder limitOrder; 18 | 19 | @Before 20 | public void setup(){ 21 | feePayingAccount = new UserAccount("1.2.143563"); 22 | limitOrder = new LimitOrder("1.7.2360289"); 23 | } 24 | 25 | @Test 26 | public void toBytes() throws Exception { 27 | LimitOrderCancelOperation operation = new LimitOrderCancelOperation(limitOrder, feePayingAccount); 28 | operation.setFee(new AssetAmount(UnsignedLong.valueOf(2), CORE_ASSET)); 29 | byte[] serialized = operation.toBytes(); 30 | assertArrayEquals("Correct serialization", Util.hexToBytes("020000000000000000cbe108e187900100"), serialized); 31 | } 32 | } -------------------------------------------------------------------------------- /graphenej/src/test/java/cy/agorise/graphenej/operations/LimitOrderCreateOperationTest.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.graphenej.operations; 2 | 3 | import com.google.common.primitives.UnsignedLong; 4 | 5 | import org.hamcrest.core.IsEqual; 6 | import org.hamcrest.core.IsNot; 7 | import org.junit.Assert; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import cy.agorise.graphenej.Asset; 12 | import cy.agorise.graphenej.AssetAmount; 13 | import cy.agorise.graphenej.UserAccount; 14 | import cy.agorise.graphenej.Util; 15 | 16 | /** 17 | * Created by nelson on 3/6/17. 18 | */ 19 | public class LimitOrderCreateOperationTest { 20 | private static final int AMOUNT_TO_SELL = 25000000; 21 | private static final int MIN_TO_RECEIVE = 1; 22 | private static final Asset CORE_ASSET = new Asset("1.3.0"); 23 | private static final Asset BIT_USD = new Asset("1.3.121"); 24 | private static final int DEFAULT_EXPIRATION = 1488831620; // 2017-03-06T20:20:20 25 | 26 | private UserAccount seller; 27 | private AssetAmount amountToSell; 28 | private AssetAmount minToReceive; 29 | private int expiration; 30 | private boolean fillOrKill; 31 | 32 | @Before 33 | public void setup(){ 34 | seller = new UserAccount("1.2.143563"); 35 | amountToSell = new AssetAmount(UnsignedLong.valueOf(AMOUNT_TO_SELL), CORE_ASSET); 36 | minToReceive = new AssetAmount(UnsignedLong.valueOf(MIN_TO_RECEIVE), BIT_USD); 37 | expiration = DEFAULT_EXPIRATION; 38 | } 39 | 40 | @Test 41 | public void toBytes() throws Exception { 42 | // Testing serialization of operation with fillOrKill parameter == true 43 | LimitOrderCreateOperation operation = new LimitOrderCreateOperation(seller, amountToSell, minToReceive, expiration, true); 44 | operation.setFee(new AssetAmount(UnsignedLong.valueOf(2), CORE_ASSET)); 45 | byte[] serialized = operation.toBytes(); 46 | Assert.assertArrayEquals("Correct serialization", serialized, Util.hexToBytes("020000000000000000cbe10840787d01000000000001000000000000007984c4bd580100")); 47 | Assert.assertThat("Incorrect serialization", serialized, IsNot.not(IsEqual.equalTo(Util.hexToBytes("020000000000000000cbe10840787d01000000000001000000000000007984c4bd580000")))); 48 | 49 | // Testing serialization of operation with fillOrKill parameter == false 50 | operation = new LimitOrderCreateOperation(seller, amountToSell, minToReceive, expiration, false); 51 | operation.setFee(new AssetAmount(UnsignedLong.valueOf(2), CORE_ASSET)); 52 | serialized = operation.toBytes(); 53 | Assert.assertArrayEquals("Correct serialization", serialized, Util.hexToBytes("020000000000000000cbe10840787d01000000000001000000000000007984c4bd580000")); 54 | Assert.assertThat("Incorrect serialization", serialized, IsNot.not(IsEqual.equalTo(Util.hexToBytes("020000000000000000cbe10840787d01000000000001000000000000007984c4bd580100")))); 55 | } 56 | } -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | 6 | 7 | defaultConfig { 8 | applicationId "cy.agorise.labs.sample" 9 | minSdkVersion 14 10 | targetSdkVersion 27 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | multiDexEnabled true 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | compileOptions { 25 | sourceCompatibility JavaVersion.VERSION_1_8 26 | targetCompatibility JavaVersion.VERSION_1_8 27 | } 28 | } 29 | 30 | dependencies { 31 | implementation fileTree(dir: 'libs', include: ['*.jar']) 32 | api project(':graphenej') 33 | implementation 'com.android.support:appcompat-v7:27.1.1' 34 | implementation 'com.android.support:recyclerview-v7:27.1.1' 35 | implementation 'com.android.support:design:27.1.1' 36 | implementation 'com.android.support.constraint:constraint-layout:1.1.2' 37 | implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1' 38 | implementation 'com.jakewharton:butterknife:8.8.1' 39 | implementation 'com.google.code.gson:gson:2.8.4' 40 | implementation 'com.google.guava:guava:25.0-jre' 41 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 42 | testImplementation 'junit:junit:4.12' 43 | androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', { 44 | exclude group: 'com.android.support', module: 'support-annotations' 45 | }) 46 | implementation 'com.android.support:multidex:1.0.1' 47 | } 48 | -------------------------------------------------------------------------------- /sample/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 | -------------------------------------------------------------------------------- /sample/src/androidTest/java/cy/sample/labs/sample/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cy.sample.labs.sample; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("cy.agorise.labs.sample", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.labs.sample; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.DividerItemDecoration; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.view.LayoutInflater; 11 | import android.view.ViewGroup; 12 | import android.widget.TextView; 13 | 14 | import butterknife.BindView; 15 | import butterknife.ButterKnife; 16 | import cy.agorise.graphenej.RPC; 17 | 18 | public class CallsActivity extends AppCompatActivity { 19 | 20 | @BindView(R.id.call_list) 21 | RecyclerView mRecyclerView; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_calls); 27 | ButterKnife.bind(this); 28 | mRecyclerView.setHasFixedSize(true); 29 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 30 | mRecyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL)); 31 | mRecyclerView.setAdapter(new CallAdapter()); 32 | } 33 | 34 | private final class CallAdapter extends RecyclerView.Adapter { 35 | 36 | private String[] supportedCalls = new String[]{ 37 | RPC.CALL_GET_OBJECTS, 38 | RPC.CALL_GET_ACCOUNTS, 39 | RPC.CALL_GET_BLOCK, 40 | RPC.CALL_GET_BLOCK_HEADER, 41 | RPC.CALL_GET_MARKET_HISTORY, 42 | RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY, 43 | RPC.CALL_GET_REQUIRED_FEES, 44 | RPC.CALL_LOOKUP_ASSET_SYMBOLS, 45 | RPC.CALL_LIST_ASSETS, 46 | RPC.CALL_GET_ACCOUNT_BY_NAME, 47 | RPC.CALL_GET_LIMIT_ORDERS, 48 | RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS, 49 | RPC.CALL_GET_FULL_ACCOUNTS, 50 | RPC.CALL_SET_SUBSCRIBE_CALLBACK, 51 | RPC.CALL_GET_DYNAMIC_GLOBAL_PROPERTIES, 52 | RPC.CALL_GET_KEY_REFERENCES 53 | }; 54 | 55 | @NonNull 56 | @Override 57 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 58 | TextView v = (TextView) LayoutInflater.from(parent.getContext()) 59 | .inflate(R.layout.item_call, parent, false); 60 | return new ViewHolder(v); 61 | } 62 | 63 | @Override 64 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 65 | String name = supportedCalls[position]; 66 | String formattedName = name.replace("_", " ").toUpperCase(); 67 | holder.mCallNameView.setText(formattedName); 68 | holder.mCallNameView.setOnClickListener((view) -> { 69 | String selectedCall = supportedCalls[position]; 70 | Intent intent; 71 | if(selectedCall.equals(RPC.CALL_SET_SUBSCRIBE_CALLBACK)){ 72 | intent = new Intent(CallsActivity.this, SubscriptionActivity.class); 73 | }else{ 74 | intent = new Intent(CallsActivity.this, PerformCallActivity.class); 75 | intent.putExtra(Constants.KEY_SELECTED_CALL, selectedCall); 76 | } 77 | startActivity(intent); 78 | }); 79 | } 80 | 81 | @Override 82 | public int getItemCount() { 83 | return supportedCalls.length; 84 | } 85 | 86 | public class ViewHolder extends RecyclerView.ViewHolder { 87 | public TextView mCallNameView; 88 | 89 | public ViewHolder(TextView view) { 90 | super(view); 91 | this.mCallNameView = view; 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /sample/src/main/java/cy/agorise/labs/sample/ConnectedActivity.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.labs.sample; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.ServiceConnection; 7 | import android.os.IBinder; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.util.Log; 10 | 11 | import cy.agorise.graphenej.api.android.NetworkService; 12 | import cy.agorise.graphenej.network.NodeLatencyVerifier; 13 | 14 | public abstract class ConnectedActivity extends AppCompatActivity implements ServiceConnection { 15 | private final String TAG = this.getClass().getName(); 16 | 17 | /* Network service connection */ 18 | protected NetworkService mNetworkService; 19 | 20 | /** 21 | * Flag used to keep track of the NetworkService binding state 22 | */ 23 | private boolean mShouldUnbindNetwork; 24 | 25 | private ServiceConnection mNetworkServiceConnection = new ServiceConnection() { 26 | @Override 27 | public void onServiceConnected(ComponentName className, 28 | IBinder service) { 29 | // We've bound to LocalService, cast the IBinder and get LocalService instance 30 | NetworkService.LocalBinder binder = (NetworkService.LocalBinder) service; 31 | mNetworkService = binder.getService(); 32 | ConnectedActivity.this.onServiceConnected(className, service); 33 | } 34 | 35 | @Override 36 | public void onServiceDisconnected(ComponentName componentName) { 37 | ConnectedActivity.this.onServiceDisconnected(componentName); 38 | } 39 | }; 40 | 41 | @Override 42 | protected void onStart() { 43 | super.onStart(); 44 | Intent intent = new Intent(this, NetworkService.class); 45 | // Binding to NetworkService 46 | if(bindService(intent, mNetworkServiceConnection, Context.BIND_AUTO_CREATE)){ 47 | mShouldUnbindNetwork = true; 48 | }else{ 49 | Log.e(TAG,"Binding to the network service failed."); 50 | } 51 | } 52 | 53 | @Override 54 | protected void onPause() { 55 | super.onPause(); 56 | // Unbinding from network service 57 | if(mShouldUnbindNetwork){ 58 | unbindService(mNetworkServiceConnection); 59 | mShouldUnbindNetwork = false; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /sample/src/main/java/cy/agorise/labs/sample/Constants.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.labs.sample; 2 | 3 | public class Constants { 4 | /** 5 | * Key used to pass the selected call as an intent extra 6 | */ 7 | public static final String KEY_SELECTED_CALL = "key_call"; 8 | } 9 | -------------------------------------------------------------------------------- /sample/src/main/java/cy/agorise/labs/sample/SampleApplication.java: -------------------------------------------------------------------------------- 1 | package cy.agorise.labs.sample; 2 | 3 | import android.app.Application; 4 | 5 | import cy.agorise.graphenej.api.ApiAccess; 6 | import cy.agorise.graphenej.api.android.NetworkServiceManager; 7 | 8 | /** 9 | * Sample application class 10 | */ 11 | 12 | public class SampleApplication extends Application { 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | // Specifying some important information regarding the connection, such as the 18 | // credentials and the requested API accesses 19 | int requestedApis = ApiAccess.API_DATABASE | ApiAccess.API_HISTORY | ApiAccess.API_NETWORK_BROADCAST; 20 | 21 | NetworkServiceManager networkManager = new NetworkServiceManager.Builder() 22 | .setUserName("username") 23 | .setPassword("secret") 24 | .setRequestedApis(requestedApis) 25 | .setCustomNodeUrls("wss://eu.nodes.bitshares.ws") 26 | .setAutoConnect(true) 27 | .setNodeLatencyVerification(true) 28 | .build(this); 29 | 30 | // Registering this class as a listener to all activity's callback cycle events, in order to 31 | // better estimate when the user has left the app and it is safe to disconnect the websocket connection 32 | registerActivityLifecycleCallbacks(networkManager); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_calls.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_second.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 17 | 23 |