diff --git a/.gitignore b/.gitignore index 7d50858..094313f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ # ------ .gradle gradle +graphenej/build /build /buildSrc/build /subprojects/*/build diff --git a/gradle.properties b/gradle.properties index b568a9b..2dc6a3e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME=0.4.1 +VERSION_NAME=0.4.1-SNAPSHOT VERSION_CODE=3 GROUP=com.github.kenCode-de diff --git a/graphenej/build/libs/graphenej-0.1-SNAPSHOT.jar b/graphenej/build/libs/graphenej-0.1-SNAPSHOT.jar deleted file mode 100644 index d2ef14f..0000000 Binary files a/graphenej/build/libs/graphenej-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/graphenej/build/libs/graphenej-all-0.1-SNAPSHOT.jar b/graphenej/build/libs/graphenej-all-0.1-SNAPSHOT.jar deleted file mode 100644 index b29ccb6..0000000 Binary files a/graphenej/build/libs/graphenej-all-0.1-SNAPSHOT.jar and /dev/null differ diff --git a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.AssetTest.html b/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.AssetTest.html deleted file mode 100644 index 86624cb..0000000 --- a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.AssetTest.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - -Test results - Class de.bitsharesmunich.graphenej.AssetTest - - - - - -
-

Class de.bitsharesmunich.graphenej.AssetTest

- -
- - - - - -
-
- - - - - - - -
-
-
1
-

tests

-
-
-
-
0
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.004s
-

duration

-
-
-
-
-
-
100%
-

successful

-
-
-
-
- -
-

Tests

- - - - - - - - - - - - - -
TestDurationResult
equals0.004spassed
-
-
- -
- - diff --git a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.AuthorityTest.html b/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.AuthorityTest.html deleted file mode 100644 index 9fc091e..0000000 --- a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.AuthorityTest.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - -Test results - Class de.bitsharesmunich.graphenej.AuthorityTest - - - - - -
-

Class de.bitsharesmunich.graphenej.AuthorityTest

- -
- - - - - -
-
- - - - - - - -
-
-
2
-

tests

-
-
-
-
1
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.215s
-

duration

-
-
-
-
-
-
50%
-

successful

-
-
-
-
- -
-

Failed tests

-
- -

equals

- -
java.lang.AssertionError: Different authorities  expected:<de.bitsharesmunich.graphenej.Authority@4108679d> but was:<de.bitsharesmunich.graphenej.Authority@5155d26c>
-	at org.junit.Assert.fail(Assert.java:88)
-	at org.junit.Assert.failNotEquals(Assert.java:834)
-	at org.junit.Assert.assertEquals(Assert.java:118)
-	at de.bitsharesmunich.graphenej.AuthorityTest.equals(AuthorityTest.java:54)
-	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-	at java.lang.reflect.Method.invoke(Method.java:497)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
-	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
-	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
-	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
-	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
-	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
-	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-	at java.lang.reflect.Method.invoke(Method.java:497)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
-	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
-	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
-	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
-	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
-	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-	at java.lang.reflect.Method.invoke(Method.java:497)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
-	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377)
-	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
-	at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
-	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
-	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
-	at java.lang.Thread.run(Thread.java:745)
-
-
-
-
-
-

Tests

- - - - - - - - - - - - - - - - - - -
TestDurationResult
equals0.214sfailed
toBytes0.001spassed
-
-
-

Standard output

- -
key auths match: true
-account auths match: true
-weight threshold matches: true
-key auths match: true
-account auths match: false
-weight threshold matches: true
-
-
-
-
-

Standard error

- -
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
-SLF4J: Defaulting to no-operation (NOP) logger implementation
-SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
-
-
-
-
- -
- - diff --git a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.PublicKeyTest.html b/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.PublicKeyTest.html deleted file mode 100644 index 54fcc64..0000000 --- a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.PublicKeyTest.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - -Test results - Class de.bitsharesmunich.graphenej.PublicKeyTest - - - - - -
-

Class de.bitsharesmunich.graphenej.PublicKeyTest

- -
- - - - - -
-
- - - - - - - -
-
-
1
-

tests

-
-
-
-
1
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.001s
-

duration

-
-
-
-
-
-
0%
-

successful

-
-
-
-
- -
-

Failed tests

-
- -

equals

- -
org.bitcoinj.core.AddressFormatException: Illegal character 0 at position 48
-	at org.bitcoinj.core.Base58.decode(Base58.java:110)
-	at de.bitsharesmunich.graphenej.Address.<init>(Address.java:33)
-	at de.bitsharesmunich.graphenej.PublicKeyTest.equals(PublicKeyTest.java:20)
-	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-	at java.lang.reflect.Method.invoke(Method.java:497)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
-	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
-	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
-	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
-	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
-	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
-	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-	at java.lang.reflect.Method.invoke(Method.java:497)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
-	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
-	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
-	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
-	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
-	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-	at java.lang.reflect.Method.invoke(Method.java:497)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
-	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
-	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377)
-	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
-	at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
-	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
-	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
-	at java.lang.Thread.run(Thread.java:745)
-
-
-
-
-
-

Tests

- - - - - - - - - - - - - -
TestDurationResult
equals0.001sfailed
-
-
- -
- - diff --git a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.objects.MemoTest.html b/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.objects.MemoTest.html deleted file mode 100644 index a475d84..0000000 --- a/graphenej/build/reports/tests/test/classes/de.bitsharesmunich.graphenej.objects.MemoTest.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - -Test results - Class de.bitsharesmunich.graphenej.objects.MemoTest - - - - - -
-

Class de.bitsharesmunich.graphenej.objects.MemoTest

- -
- - - - - -
-
- - - - - - - -
-
-
6
-

tests

-
-
-
-
0
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.067s
-

duration

-
-
-
-
-
-
100%
-

successful

-
-
-
-
- -
-

Tests

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TestDurationResult
shouldBeByteSerializable0.003spassed
shouldBeJsonObjectSerializable0.009spassed
shouldEncryptAndDecryptLongerMessage0.006spassed
shouldEncryptAndDecryptShortMessage0.031spassed
shouldMatchPredefinedChiphertext0.005spassed
shouldThrowException0.013spassed
-
-
- -
- - diff --git a/graphenej/build/reports/tests/test/css/base-style.css b/graphenej/build/reports/tests/test/css/base-style.css deleted file mode 100644 index 4afa73e..0000000 --- a/graphenej/build/reports/tests/test/css/base-style.css +++ /dev/null @@ -1,179 +0,0 @@ - -body { - margin: 0; - padding: 0; - font-family: sans-serif; - font-size: 12pt; -} - -body, a, a:visited { - color: #303030; -} - -#content { - padding-left: 50px; - padding-right: 50px; - padding-top: 30px; - padding-bottom: 30px; -} - -#content h1 { - font-size: 160%; - margin-bottom: 10px; -} - -#footer { - margin-top: 100px; - font-size: 80%; - white-space: nowrap; -} - -#footer, #footer a { - color: #a0a0a0; -} - -#line-wrapping-toggle { - vertical-align: middle; -} - -#label-for-line-wrapping-toggle { - vertical-align: middle; -} - -ul { - margin-left: 0; -} - -h1, h2, h3 { - white-space: nowrap; -} - -h2 { - font-size: 120%; -} - -ul.tabLinks { - padding-left: 0; - padding-top: 10px; - padding-bottom: 10px; - overflow: auto; - min-width: 800px; - width: auto !important; - width: 800px; -} - -ul.tabLinks li { - float: left; - height: 100%; - list-style: none; - padding-left: 10px; - padding-right: 10px; - padding-top: 5px; - padding-bottom: 5px; - margin-bottom: 0; - -moz-border-radius: 7px; - border-radius: 7px; - margin-right: 25px; - border: solid 1px #d4d4d4; - background-color: #f0f0f0; -} - -ul.tabLinks li:hover { - background-color: #fafafa; -} - -ul.tabLinks li.selected { - background-color: #c5f0f5; - border-color: #c5f0f5; -} - -ul.tabLinks a { - font-size: 120%; - display: block; - outline: none; - text-decoration: none; - margin: 0; - padding: 0; -} - -ul.tabLinks li h2 { - margin: 0; - padding: 0; -} - -div.tab { -} - -div.selected { - display: block; -} - -div.deselected { - display: none; -} - -div.tab table { - min-width: 350px; - width: auto !important; - width: 350px; - border-collapse: collapse; -} - -div.tab th, div.tab table { - border-bottom: solid #d0d0d0 1px; -} - -div.tab th { - text-align: left; - white-space: nowrap; - padding-left: 6em; -} - -div.tab th:first-child { - padding-left: 0; -} - -div.tab td { - white-space: nowrap; - padding-left: 6em; - padding-top: 5px; - padding-bottom: 5px; -} - -div.tab td:first-child { - padding-left: 0; -} - -div.tab td.numeric, div.tab th.numeric { - text-align: right; -} - -span.code { - display: inline-block; - margin-top: 0em; - margin-bottom: 1em; -} - -span.code pre { - font-size: 11pt; - padding-top: 10px; - padding-bottom: 10px; - padding-left: 10px; - padding-right: 10px; - margin: 0; - background-color: #f7f7f7; - border: solid 1px #d0d0d0; - min-width: 700px; - width: auto !important; - width: 700px; -} - -span.wrapped pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: break-all; -} - -label.hidden { - display: none; -} \ No newline at end of file diff --git a/graphenej/build/reports/tests/test/css/style.css b/graphenej/build/reports/tests/test/css/style.css deleted file mode 100644 index 3dc4913..0000000 --- a/graphenej/build/reports/tests/test/css/style.css +++ /dev/null @@ -1,84 +0,0 @@ - -#summary { - margin-top: 30px; - margin-bottom: 40px; -} - -#summary table { - border-collapse: collapse; -} - -#summary td { - vertical-align: top; -} - -.breadcrumbs, .breadcrumbs a { - color: #606060; -} - -.infoBox { - width: 110px; - padding-top: 15px; - padding-bottom: 15px; - text-align: center; -} - -.infoBox p { - margin: 0; -} - -.counter, .percent { - font-size: 120%; - font-weight: bold; - margin-bottom: 8px; -} - -#duration { - width: 125px; -} - -#successRate, .summaryGroup { - border: solid 2px #d0d0d0; - -moz-border-radius: 10px; - border-radius: 10px; -} - -#successRate { - width: 140px; - margin-left: 35px; -} - -#successRate .percent { - font-size: 180%; -} - -.success, .success a { - color: #008000; -} - -div.success, #successRate.success { - background-color: #bbd9bb; - border-color: #008000; -} - -.failures, .failures a { - color: #b60808; -} - -.skipped, .skipped a { - color: #c09853; -} - -div.failures, #successRate.failures { - background-color: #ecdada; - border-color: #b60808; -} - -ul.linkList { - padding-left: 0; -} - -ul.linkList li { - list-style: none; - margin-bottom: 5px; -} diff --git a/graphenej/build/reports/tests/test/index.html b/graphenej/build/reports/tests/test/index.html deleted file mode 100644 index 0df48ed..0000000 --- a/graphenej/build/reports/tests/test/index.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - -Test results - Test Summary - - - - - -
-

Test Summary

-
- - - - - -
-
- - - - - - - -
-
-
10
-

tests

-
-
-
-
2
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.287s
-

duration

-
-
-
-
-
-
80%
-

successful

-
-
-
-
- -
-

Failed tests

- -
-
-

Packages

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PackageTestsFailuresIgnoredDurationSuccess rate
-de.bitsharesmunich.graphenej -4200.220s50%
-de.bitsharesmunich.graphenej.objects -6000.067s100%
-
-
-

Classes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ClassTestsFailuresIgnoredDurationSuccess rate
-de.bitsharesmunich.graphenej.AssetTest -1000.004s100%
-de.bitsharesmunich.graphenej.AuthorityTest -2100.215s50%
-de.bitsharesmunich.graphenej.PublicKeyTest -1100.001s0%
-de.bitsharesmunich.graphenej.objects.MemoTest -6000.067s100%
-
-
- -
- - diff --git a/graphenej/build/reports/tests/test/js/report.js b/graphenej/build/reports/tests/test/js/report.js deleted file mode 100644 index 83bab4a..0000000 --- a/graphenej/build/reports/tests/test/js/report.js +++ /dev/null @@ -1,194 +0,0 @@ -(function (window, document) { - "use strict"; - - var tabs = {}; - - function changeElementClass(element, classValue) { - if (element.getAttribute("className")) { - element.setAttribute("className", classValue); - } else { - element.setAttribute("class", classValue); - } - } - - function getClassAttribute(element) { - if (element.getAttribute("className")) { - return element.getAttribute("className"); - } else { - return element.getAttribute("class"); - } - } - - function addClass(element, classValue) { - changeElementClass(element, getClassAttribute(element) + " " + classValue); - } - - function removeClass(element, classValue) { - changeElementClass(element, getClassAttribute(element).replace(classValue, "")); - } - - function initTabs() { - var container = document.getElementById("tabs"); - - tabs.tabs = findTabs(container); - tabs.titles = findTitles(tabs.tabs); - tabs.headers = findHeaders(container); - tabs.select = select; - tabs.deselectAll = deselectAll; - tabs.select(0); - - return true; - } - - function getCheckBox() { - return document.getElementById("line-wrapping-toggle"); - } - - function getLabelForCheckBox() { - return document.getElementById("label-for-line-wrapping-toggle"); - } - - function findCodeBlocks() { - var spans = document.getElementById("tabs").getElementsByTagName("span"); - var codeBlocks = []; - for (var i = 0; i < spans.length; ++i) { - if (spans[i].className.indexOf("code") >= 0) { - codeBlocks.push(spans[i]); - } - } - return codeBlocks; - } - - function forAllCodeBlocks(operation) { - var codeBlocks = findCodeBlocks(); - - for (var i = 0; i < codeBlocks.length; ++i) { - operation(codeBlocks[i], "wrapped"); - } - } - - function toggleLineWrapping() { - var checkBox = getCheckBox(); - - if (checkBox.checked) { - forAllCodeBlocks(addClass); - } else { - forAllCodeBlocks(removeClass); - } - } - - function initControls() { - if (findCodeBlocks().length > 0) { - var checkBox = getCheckBox(); - var label = getLabelForCheckBox(); - - checkBox.onclick = toggleLineWrapping; - checkBox.checked = false; - - removeClass(label, "hidden"); - } - } - - function switchTab() { - var id = this.id.substr(1); - - for (var i = 0; i < tabs.tabs.length; i++) { - if (tabs.tabs[i].id === id) { - tabs.select(i); - break; - } - } - - return false; - } - - function select(i) { - this.deselectAll(); - - changeElementClass(this.tabs[i], "tab selected"); - changeElementClass(this.headers[i], "selected"); - - while (this.headers[i].firstChild) { - this.headers[i].removeChild(this.headers[i].firstChild); - } - - var h2 = document.createElement("H2"); - - h2.appendChild(document.createTextNode(this.titles[i])); - this.headers[i].appendChild(h2); - } - - function deselectAll() { - for (var i = 0; i < this.tabs.length; i++) { - changeElementClass(this.tabs[i], "tab deselected"); - changeElementClass(this.headers[i], "deselected"); - - while (this.headers[i].firstChild) { - this.headers[i].removeChild(this.headers[i].firstChild); - } - - var a = document.createElement("A"); - - a.setAttribute("id", "ltab" + i); - a.setAttribute("href", "#tab" + i); - a.onclick = switchTab; - a.appendChild(document.createTextNode(this.titles[i])); - - this.headers[i].appendChild(a); - } - } - - function findTabs(container) { - return findChildElements(container, "DIV", "tab"); - } - - function findHeaders(container) { - var owner = findChildElements(container, "UL", "tabLinks"); - return findChildElements(owner[0], "LI", null); - } - - function findTitles(tabs) { - var titles = []; - - for (var i = 0; i < tabs.length; i++) { - var tab = tabs[i]; - var header = findChildElements(tab, "H2", null)[0]; - - header.parentNode.removeChild(header); - - if (header.innerText) { - titles.push(header.innerText); - } else { - titles.push(header.textContent); - } - } - - return titles; - } - - function findChildElements(container, name, targetClass) { - var elements = []; - var children = container.childNodes; - - for (var i = 0; i < children.length; i++) { - var child = children.item(i); - - if (child.nodeType === 1 && child.nodeName === name) { - if (targetClass && child.className.indexOf(targetClass) < 0) { - continue; - } - - elements.push(child); - } - } - - return elements; - } - - // Entry point. - - window.onload = function() { - initTabs(); - initControls(); - }; -} (window, window.document)); \ No newline at end of file diff --git a/graphenej/build/reports/tests/test/packages/de.bitsharesmunich.graphenej.html b/graphenej/build/reports/tests/test/packages/de.bitsharesmunich.graphenej.html deleted file mode 100644 index 0ce0406..0000000 --- a/graphenej/build/reports/tests/test/packages/de.bitsharesmunich.graphenej.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - -Test results - Package de.bitsharesmunich.graphenej - - - - - -
-

Package de.bitsharesmunich.graphenej

- -
- - - - - -
-
- - - - - - - -
-
-
4
-

tests

-
-
-
-
2
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.220s
-

duration

-
-
-
-
-
-
50%
-

successful

-
-
-
-
- -
-

Failed tests

- -
-
-

Classes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ClassTestsFailuresIgnoredDurationSuccess rate
-AssetTest -1000.004s100%
-AuthorityTest -2100.215s50%
-PublicKeyTest -1100.001s0%
-
-
- -
- - diff --git a/graphenej/build/reports/tests/test/packages/de.bitsharesmunich.graphenej.objects.html b/graphenej/build/reports/tests/test/packages/de.bitsharesmunich.graphenej.objects.html deleted file mode 100644 index 31dc27a..0000000 --- a/graphenej/build/reports/tests/test/packages/de.bitsharesmunich.graphenej.objects.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - -Test results - Package de.bitsharesmunich.graphenej.objects - - - - - -
-

Package de.bitsharesmunich.graphenej.objects

- -
- - - - - -
-
- - - - - - - -
-
-
6
-

tests

-
-
-
-
0
-

failures

-
-
-
-
0
-

ignored

-
-
-
-
0.067s
-

duration

-
-
-
-
-
-
100%
-

successful

-
-
-
-
- -
-

Classes

- - - - - - - - - - - - - - - - - - - -
ClassTestsFailuresIgnoredDurationSuccess rate
-MemoTest -6000.067s100%
-
-
- -
- - diff --git a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.AssetTest.xml b/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.AssetTest.xml deleted file mode 100644 index 1e77fe2..0000000 --- a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.AssetTest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.AuthorityTest.xml b/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.AuthorityTest.xml deleted file mode 100644 index 381b7e2..0000000 --- a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.AuthorityTest.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - java.lang.AssertionError: Different authorities expected:<de.bitsharesmunich.graphenej.Authority@4108679d> but was:<de.bitsharesmunich.graphenej.Authority@5155d26c> - at org.junit.Assert.fail(Assert.java:88) - at org.junit.Assert.failNotEquals(Assert.java:834) - at org.junit.Assert.assertEquals(Assert.java:118) - at de.bitsharesmunich.graphenej.AuthorityTest.equals(AuthorityTest.java:54) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:497) - at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) - at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) - at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) - at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) - at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) - at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) - at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) - at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) - at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) - at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) - at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) - at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) - at org.junit.runners.ParentRunner.run(ParentRunner.java:363) - at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114) - at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) - at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) - at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:497) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) - at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) - at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) - at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) - at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:497) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) - at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377) - at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) - at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) - at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) - at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) - at java.lang.Thread.run(Thread.java:745) - - - - - - diff --git a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.PublicKeyTest.xml b/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.PublicKeyTest.xml deleted file mode 100644 index a32c871..0000000 --- a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.PublicKeyTest.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - org.bitcoinj.core.AddressFormatException: Illegal character 0 at position 48 - at org.bitcoinj.core.Base58.decode(Base58.java:110) - at de.bitsharesmunich.graphenej.Address.<init>(Address.java:33) - at de.bitsharesmunich.graphenej.PublicKeyTest.equals(PublicKeyTest.java:20) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:497) - at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) - at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) - at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) - at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) - at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) - at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) - at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) - at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) - at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) - at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) - at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) - at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) - at org.junit.runners.ParentRunner.run(ParentRunner.java:363) - at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114) - at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) - at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) - at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:497) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) - at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) - at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) - at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) - at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:497) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) - at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) - at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377) - at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) - at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) - at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) - at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) - at java.lang.Thread.run(Thread.java:745) - - - - - diff --git a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.objects.MemoTest.xml b/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.objects.MemoTest.xml deleted file mode 100644 index 8602385..0000000 --- a/graphenej/build/test-results/test/TEST-de.bitsharesmunich.graphenej.objects.MemoTest.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/graphenej/build/test-results/test/binary/output.bin.idx b/graphenej/build/test-results/test/binary/output.bin.idx deleted file mode 100644 index a9658ee..0000000 Binary files a/graphenej/build/test-results/test/binary/output.bin.idx and /dev/null differ diff --git a/graphenej/build/tmp/fatJar/MANIFEST.MF b/graphenej/build/tmp/fatJar/MANIFEST.MF deleted file mode 100644 index 5b0d8fb..0000000 --- a/graphenej/build/tmp/fatJar/MANIFEST.MF +++ /dev/null @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -Implementation-Title: Graphenej test -Implementation-Version: 0.1-SNAPSHOT -Main-Class: de.bitsharesmunich.graphenej.Main - diff --git a/graphenej/build/tmp/jar/MANIFEST.MF b/graphenej/build/tmp/jar/MANIFEST.MF deleted file mode 100644 index 59499bc..0000000 --- a/graphenej/build/tmp/jar/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 - diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/AccountOptions.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/AccountOptions.java index 8206591..43c060e 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/AccountOptions.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/AccountOptions.java @@ -1,14 +1,20 @@ package de.bitsharesmunich.graphenej; import com.google.common.primitives.Bytes; -import com.google.gson.*; -import de.bitsharesmunich.graphenej.errors.MalformedAddressException; -import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import de.bitsharesmunich.graphenej.errors.MalformedAddressException; +import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable; + /** * Created by nelson on 12/5/16. */ @@ -107,6 +113,9 @@ public class AccountOptions implements GrapheneSerializable { //TODO: Check this serialization byteArray.addAll(Bytes.asList(vote.toBytes())); } + + // Account options's extensions + byteArray.addAll(Bytes.asList(extensions.toBytes())); }else{ byteArray.add((byte) 0); } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/AssetAmount.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/AssetAmount.java index 76abc69..cd0ea49 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/AssetAmount.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/AssetAmount.java @@ -1,17 +1,27 @@ package de.bitsharesmunich.graphenej; +import com.google.common.math.DoubleMath; import com.google.common.primitives.Bytes; import com.google.common.primitives.UnsignedLong; -import com.google.gson.*; -import de.bitsharesmunich.graphenej.errors.IncompatibleOperation; -import de.bitsharesmunich.graphenej.interfaces.ByteSerializable; -import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; import java.io.ByteArrayOutputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.lang.reflect.Type; +import java.math.RoundingMode; + +import de.bitsharesmunich.graphenej.errors.IncompatibleOperation; +import de.bitsharesmunich.graphenej.interfaces.ByteSerializable; +import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; /** * Created by nelson on 11/7/16. @@ -73,6 +83,49 @@ public class AssetAmount implements ByteSerializable, JsonSerializable { return new AssetAmount(result, asset); } + /** + * Multiplies the current amount by a factor provided as the first parameter. The second parameter + * specifies the rounding method to be used. + * @param factor: The multiplying factor + * @param roundingMode: The rounding mode as an instance of the {@link RoundingMode} class + * @return The same AssetAmount instance, but with the changed amount value. + */ + public AssetAmount multiplyBy(double factor, RoundingMode roundingMode){ + this.amount = UnsignedLong.valueOf(DoubleMath.roundToLong(this.amount.longValue() * factor, roundingMode)); + return this; + } + + /** + * Multiplies the current amount by a factor, using the {@link RoundingMode#HALF_DOWN} constant. + * @param factor: The multiplying factor + * @return The same AssetAmount instance, but with the changed amount value. + */ + public AssetAmount multiplyBy(double factor){ + return this.multiplyBy(factor, RoundingMode.HALF_DOWN); + } + + /** + * Divides the current amount by a divisor provided as the first parameter. The second parameter + * specifies the rounding method to be used. + * @param divisor: The divisor + * @return: The same AssetAMount instance, but with the divided amount value + */ + public AssetAmount dividedBy(double divisor, RoundingMode roundingMode){ + this.amount = UnsignedLong.valueOf(DoubleMath.roundToLong(this.amount.longValue() / divisor, roundingMode)); + return this; + } + + + /** + * Divides the current amount by a divisor provided as the first parameter, using + * the {@link RoundingMode#HALF_DOWN} constant + * @param divisor: The divisor + * @return: The same AssetAMount instance, but with the divided amount value + */ + public AssetAmount dividedBy(double divisor){ + return this.dividedBy(divisor, RoundingMode.HALF_DOWN); + } + public void setAmount(UnsignedLong amount){ this.amount = amount; } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Authority.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Authority.java index 54279f5..2224225 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Authority.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Authority.java @@ -1,15 +1,25 @@ package de.bitsharesmunich.graphenej; import com.google.common.primitives.Bytes; -import com.google.gson.*; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + import de.bitsharesmunich.graphenej.errors.MalformedAddressException; import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable; -import java.lang.reflect.Type; -import java.util.*; - /** - * Created by nelson on 11/30/16. + * Class used to represent the weighted set of keys and accounts that must approve operations. + * + * {@see Authority} */ public class Authority implements GrapheneSerializable { public static final String KEY_ACCOUNT_AUTHS = "account_auths"; @@ -18,14 +28,14 @@ public class Authority implements GrapheneSerializable { public static final String KEY_EXTENSIONS = "extensions"; private long weight_threshold; - private HashMap account_auths; - private HashMap key_auths; + private HashMap account_auths; + private HashMap key_auths; private Extensions extensions; public Authority(){ this.weight_threshold = 1; - this.account_auths = new HashMap(); - this.key_auths = new HashMap(); + this.account_auths = new HashMap(); + this.key_auths = new HashMap(); extensions = new Extensions(); } @@ -36,7 +46,7 @@ public class Authority implements GrapheneSerializable { * @param accountAuths: Map of account to weights relationships. Can be null. * @throws MalformedAddressException */ - public Authority(long weight_threshold, HashMap keyAuths, HashMap accountAuths) { + public Authority(long weight_threshold, HashMap keyAuths, HashMap accountAuths) { this(); this.weight_threshold = weight_threshold; if(keyAuths != null) @@ -49,7 +59,7 @@ public class Authority implements GrapheneSerializable { this.account_auths = new HashMap<>(); } - public void setKeyAuthorities(HashMap keyAuths){ + public void setKeyAuthorities(HashMap keyAuths){ if(keyAuths != null){ for(Address address : keyAuths.keySet()){ key_auths.put(address.getPublicKey(), keyAuths.get(address)); @@ -57,10 +67,13 @@ public class Authority implements GrapheneSerializable { } } - public void setAccountAuthorities(HashMap accountAuthorities){ + public void setAccountAuthorities(HashMap accountAuthorities){ this.account_auths = accountAuthorities; } + /** + * @return: Returns a list of public keys linked to this authority + */ public List getKeyAuthList(){ ArrayList keys = new ArrayList<>(); for(PublicKey pk : key_auths.keySet()){ @@ -69,11 +82,22 @@ public class Authority implements GrapheneSerializable { return keys; } - public HashMap getKeyAuths(){ + /** + * @return: Returns a list of accounts linked to this authority + */ + public List getAccountAuthList(){ + ArrayList accounts = new ArrayList<>(); + for(UserAccount account : account_auths.keySet()){ + accounts.add(account); + } + return accounts; + } + + public HashMap getKeyAuths(){ return this.key_auths; } - public HashMap getAccountAuths(){ + public HashMap getAccountAuths(){ return this.account_auths; } @@ -149,8 +173,8 @@ public class Authority implements GrapheneSerializable { @Override public boolean equals(Object obj) { Authority authority = (Authority) obj; - HashMap keyAuths = authority.getKeyAuths(); - HashMap accountAuths = authority.getAccountAuths(); + HashMap keyAuths = authority.getKeyAuths(); + HashMap accountAuths = authority.getAccountAuths(); System.out.println("key auths match: "+this.key_auths.equals(keyAuths)); System.out.println("account auths match: "+this.account_auths.equals(accountAuths)); System.out.println("weight threshold matches: "+(this.weight_threshold == authority.weight_threshold)); @@ -179,12 +203,12 @@ public class Authority implements GrapheneSerializable { long weightThreshold = baseObject.get(KEY_WEIGHT_THRESHOLD).getAsLong(); JsonArray keyAuthArray = baseObject.getAsJsonArray(KEY_KEY_AUTHS); JsonArray accountAuthArray = baseObject.getAsJsonArray(KEY_ACCOUNT_AUTHS); - HashMap keyAuthMap = new HashMap<>(); - HashMap accountAuthMap = new HashMap<>(); + HashMap keyAuthMap = new HashMap<>(); + HashMap accountAuthMap = new HashMap<>(); for(int i = 0; i < keyAuthArray.size(); i++){ JsonArray subArray = keyAuthArray.get(i).getAsJsonArray(); String addr = subArray.get(0).getAsString(); - int weight = subArray.get(1).getAsInt(); + long weight = subArray.get(1).getAsLong(); try { keyAuthMap.put(new Address(addr).getPublicKey(), weight); } catch (MalformedAddressException e) { @@ -192,7 +216,11 @@ public class Authority implements GrapheneSerializable { } } for(int i = 0; i < accountAuthArray.size(); i++){ - //TODO: Implement this + JsonArray subArray = accountAuthArray.get(i).getAsJsonArray(); + String userId = subArray.get(0).getAsString(); + long weight = subArray.get(1).getAsLong(); + UserAccount userAccount = new UserAccount(userId); + accountAuthMap.put(userAccount, weight); } return new Authority(weightThreshold, keyAuthMap, accountAuthMap); } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/BrainKey.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/BrainKey.java index 39710c4..7812ee9 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/BrainKey.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/BrainKey.java @@ -1,6 +1,5 @@ package de.bitsharesmunich.graphenej; -import de.bitsharesmunich.graphenej.crypto.SecureRandomGenerator; import org.bitcoinj.core.DumpedPrivateKey; import org.bitcoinj.core.ECKey; import org.bitcoinj.core.NetworkParameters; @@ -11,6 +10,8 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; +import de.bitsharesmunich.graphenej.crypto.SecureRandomGenerator; + /** * Class used to encapsulate all BrainKey-related operations. */ @@ -22,6 +23,9 @@ public class BrainKey { /* The required number of words */ public static final int BRAINKEY_WORD_COUNT = 12; + /* The default sequence number is zero */ + public static final int DEFAULT_SEQUENCE_NUMBER = 0; + /* The corresponding private key derivated from the brain key */ private ECKey mPrivateKey; @@ -106,10 +110,28 @@ public class BrainKey { return wif.toString(); } + /** + * Returns the public address derived from this brain key + * @param prefix: The prefix to use in this address. + * @return An instance of the {@link Address} class + */ + public Address getPublicAddress(String prefix){ + return new Address(ECKey.fromPublicOnly(getPublicKey()), prefix); + } + + /** + * Brain key words getter + * @return: The word sequence that comprises this brain key + */ public String getBrainKey(){ return mBrainKey; } + /** + * Sequence number getter + * @return: The sequence number used alongside with the brain key words in order + * to derive the private key + */ public int getSequenceNumber(){ return sequenceNumber; } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Converter.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Converter.java index d6e1f33..257c422 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Converter.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Converter.java @@ -3,7 +3,6 @@ package de.bitsharesmunich.graphenej; import java.math.BigDecimal; import java.math.MathContext; -import com.google.common.primitives.UnsignedLong; import de.bitsharesmunich.graphenej.errors.IncompleteAssetError; import de.bitsharesmunich.graphenej.models.BucketObject; diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/ObjectType.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/ObjectType.java index d39c32a..537eaf1 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/ObjectType.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/ObjectType.java @@ -1,7 +1,7 @@ package de.bitsharesmunich.graphenej; /** - * Created by nelson on 1/12/17. + * Enum type used to list all possible object types and obtain their space + type id */ public enum ObjectType { @@ -33,5 +33,150 @@ public enum ObjectType { CHAIN_PROPERTY_OBJECT, WITNESS_SCHEDULE_OBJECT, BUDGET_RECORD_OBJECT, - SPECIAL_AUTHORITY_OBJECT + SPECIAL_AUTHORITY_OBJECT; + + private int getSpace(){ + int space = 1; + switch(this){ + case BASE_OBJECT: + case ACCOUNT_OBJECT: + case ASSET_OBJECT: + case FORCE_SETTLEMENT_OBJECT: + case COMMITTEE_MEMBER_OBJECT: + case WITNESS_OBJECT: + case LIMIT_ORDER_OBJECT: + case CALL_ORDER_OBJECT: + case CUSTOM_OBJECT: + case PROPOSAL_OBJECT: + case OPERATION_HISTORY_OBJECT: + case WITHDRAW_PERMISSION_OBJECT: + case VESTING_BALANCE_OBJECT: + case WORKER_OBJECT: + case BALANCE_OBJECT: + space = 1; + break; + case GLOBAL_PROPERTY_OBJECT: + case DYNAMIC_GLOBAL_PROPERTY_OBJECT: + case ASSET_DYNAMIC_DATA: + case ASSET_BITASSET_DATA: + case ACCOUNT_BALANCE_OBJECT: + case ACCOUNT_STATISTICS_OBJECT: + case TRANSACTION_OBJECT: + case BLOCK_SUMMARY_OBJECT: + case ACCOUNT_TRANSACTION_HISTORY_OBJECT: + case BLINDED_BALANCE_OBJECT: + case CHAIN_PROPERTY_OBJECT: + case WITNESS_SCHEDULE_OBJECT: + case BUDGET_RECORD_OBJECT: + case SPECIAL_AUTHORITY_OBJECT: + space = 2; + break; + } + return space; + } + + private int getType(){ + int type = 0; + switch(this){ + case BASE_OBJECT: + type = 1; + break; + case ACCOUNT_OBJECT: + type = 2; + break; + case ASSET_OBJECT: + type = 3; + break; + case FORCE_SETTLEMENT_OBJECT: + type = 4; + break; + case COMMITTEE_MEMBER_OBJECT: + type = 5; + break; + case WITNESS_OBJECT: + type = 6; + break; + case LIMIT_ORDER_OBJECT: + type = 7; + break; + case CALL_ORDER_OBJECT: + type = 8; + break; + case CUSTOM_OBJECT: + type = 9; + break; + case PROPOSAL_OBJECT: + type = 10; + break; + case OPERATION_HISTORY_OBJECT: + type = 11; + break; + case WITHDRAW_PERMISSION_OBJECT: + type = 12; + break; + case VESTING_BALANCE_OBJECT: + type = 13; + break; + case WORKER_OBJECT: + type = 14; + break; + case BALANCE_OBJECT: + type = 15; + break; + case GLOBAL_PROPERTY_OBJECT: + type = 0; + break; + case DYNAMIC_GLOBAL_PROPERTY_OBJECT: + type = 1; + break; + case ASSET_DYNAMIC_DATA: + type = 3; + break; + case ASSET_BITASSET_DATA: + type = 4; + break; + case ACCOUNT_BALANCE_OBJECT: + type = 5; + break; + case ACCOUNT_STATISTICS_OBJECT: + type = 6; + break; + case TRANSACTION_OBJECT: + type = 7; + break; + case BLOCK_SUMMARY_OBJECT: + type = 8; + break; + case ACCOUNT_TRANSACTION_HISTORY_OBJECT: + type = 9; + break; + case BLINDED_BALANCE_OBJECT: + type = 10; + break; + case CHAIN_PROPERTY_OBJECT: + type = 11; + break; + case WITNESS_SCHEDULE_OBJECT: + type = 12; + break; + case BUDGET_RECORD_OBJECT: + type = 13; + break; + case SPECIAL_AUTHORITY_OBJECT: + type = 14; + } + return type; + } + + /** + * This method is used to return the generic object type in the form space.type.0. + * + * Not to be confused with {@link GrapheneObject#getObjectId()}, which will return + * the full object id in the form space.type.id. + * + * @return: The generic object type + */ + public String getGenericObjectId(){ + return String.format("%d.%d.0", getSpace(), getType()); + } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Optional.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Optional.java index cc02c7b..8f48c5e 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Optional.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Optional.java @@ -1,10 +1,19 @@ package de.bitsharesmunich.graphenej; import com.google.gson.JsonElement; + +import de.bitsharesmunich.graphenej.interfaces.ByteSerializable; import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable; /** - * Used whenever we have an optional field. + * Container template class used whenever we have an optional field. + * + * The idea here is that the binary serialization of this field should be performed + * in a specific way determined by the field implementing the {@link ByteSerializable} + * interface, more specifically using the {@link ByteSerializable#toBytes()} method. + * + * However, if the field is missing, the Optional class should be able to know how + * to serialize it, as this is always done by placing an zero byte. */ public class Optional implements GrapheneSerializable { private T optionalField; diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/OrderBook.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/OrderBook.java new file mode 100644 index 0000000..3615b0b --- /dev/null +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/OrderBook.java @@ -0,0 +1,98 @@ +package de.bitsharesmunich.graphenej; + +import com.google.common.math.DoubleMath; +import com.google.common.primitives.UnsignedLong; + +import java.math.RoundingMode; +import java.util.List; + +import de.bitsharesmunich.graphenej.operations.LimitOrderCreateOperation; + +/** + * This class will maintain a snapshot of the order book between two assets. + * + * It also provides a handy method that should return the appropriate LimitOrderCreateOperation + * object needed in case the user wants to perform market-priced operations. + * + * It is important to keep the order book updated, ideally by listening to blockchain events, and calling the 'update' method. + * + * Created by nelson on 3/25/17. + */ +public class OrderBook { + private List limitOrders; + + public OrderBook(List limitOrders){ + this.limitOrders = limitOrders; + } + + /** + * Replaces the current limit order by the list provided as parameter. + * @param limitOrders: New list of orders + */ + public void update(List limitOrders){ + this.limitOrders = limitOrders; + } + + public void update(LimitOrder limitOrder){ + //TODO: Implement the method that will update a single limit order from the order book + } + + /** + * High level method used to exchange a specific amount of an asset (The base) for another + * one (The quote) at market value. + * + * It should analyze the order book and figure out the optimal amount of the base asset to give + * away in order to obtain the desired amount of the quote asset. + * + * @param seller: User account of the seller, used to build the limit order create operation + * @param myBaseAsset: The asset the user is willing to give away + * @param myQuoteAmount: The amount of a given asset the user wants + * @param expiration: The expiration time of the limit order + * + * @return An instance of the LimitOrderCreateOperation class, which is ready to be broadcasted. + */ + public LimitOrderCreateOperation exchange(UserAccount seller, Asset myBaseAsset, AssetAmount myQuoteAmount, int expiration){ + AssetAmount toSell = new AssetAmount(UnsignedLong.valueOf(calculateRequiredBase(myQuoteAmount)), myBaseAsset); + AssetAmount toReceive = myQuoteAmount; + LimitOrderCreateOperation buyOrder = new LimitOrderCreateOperation(seller, toSell, toReceive, expiration, true); + + return buyOrder; + } + + /** + * Given a specific amount of a desired asset, this method will calculate how much of the corresponding + * asset we need to offer to perform a successful transaction with the current order book. + * @param quoteAmount: The amount of the desired asset. + * @return: The minimum amount of the base asset that we need to give away + */ + public long calculateRequiredBase(AssetAmount quoteAmount){ + long totalBought = 0; + long totalSold = 0; + for(int i = 0; i < this.limitOrders.size() && totalBought < quoteAmount.getAmount().longValue(); i++){ + LimitOrder order = this.limitOrders.get(i); + + // If the base asset is the same as our quote asset, we have a match + if(order.getSellPrice().base.getAsset().getObjectId().equals(quoteAmount.getAsset().getObjectId())){ + // My quote amount, is the order's base amount + long orderAmount = order.getForSale(); + + // The amount of the quote asset we still need + long stillNeed = quoteAmount.getAmount().longValue() - totalBought; + + // If the offered amount is greater than what we still need, we exchange just what we need + if(orderAmount >= stillNeed) { + totalBought += stillNeed; + double additionalRatio = (double) stillNeed / (double) order.getSellPrice().base.getAmount().longValue(); + double additionalAmount = order.getSellPrice().quote.getAmount().longValue() * additionalRatio; + long longAdditional = DoubleMath.roundToLong(additionalAmount, RoundingMode.HALF_UP); + totalSold += longAdditional; + }else{ + // If the offered amount is less than what we need, we exchange the whole order + totalBought += orderAmount; + totalSold += order.getSellPrice().quote.getAmount().longValue(); + } + } + } + return totalSold; + } +} diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Transaction.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Transaction.java index 13c3443..9c8ca5b 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/Transaction.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/Transaction.java @@ -1,11 +1,16 @@ package de.bitsharesmunich.graphenej; import com.google.common.primitives.Bytes; -import com.google.gson.*; -import de.bitsharesmunich.graphenej.interfaces.ByteSerializable; -import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; -import de.bitsharesmunich.graphenej.operations.TransferOperation; import org.bitcoinj.core.DumpedPrivateKey; import org.bitcoinj.core.ECKey; import org.bitcoinj.core.Sha256Hash; @@ -19,6 +24,11 @@ import java.util.Date; import java.util.List; import java.util.TimeZone; +import de.bitsharesmunich.graphenej.interfaces.ByteSerializable; +import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; +import de.bitsharesmunich.graphenej.operations.LimitOrderCreateOperation; +import de.bitsharesmunich.graphenej.operations.TransferOperation; + /** * Class used to represent a generic Graphene transaction. */ @@ -263,10 +273,9 @@ public class Transaction implements ByteSerializable, JsonSerializable { for (JsonElement jsonOperation : jsonObject.get(KEY_OPERATIONS).getAsJsonArray()) { int operationId = jsonOperation.getAsJsonArray().get(0).getAsInt(); if (operationId == OperationType.TRANSFER_OPERATION.ordinal()) { - System.out.println("Transfer operation detected!"); operation = context.deserialize(jsonOperation, TransferOperation.class); } else if (operationId == OperationType.LIMIT_ORDER_CREATE_OPERATION.ordinal()) { - //TODO: Add operation deserialization support + operation = context.deserialize(jsonOperation, LimitOrderCreateOperation.class); } else if (operationId == OperationType.LIMIT_ORDER_CANCEL_OPERATION.ordinal()) { //TODO: Add operation deserialization support } else if (operationId == OperationType.CALL_ORDER_UPDATE_OPERATION.ordinal()) { diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/UserAccount.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/UserAccount.java index 235f03c..49b66b0 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/UserAccount.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/UserAccount.java @@ -1,15 +1,23 @@ package de.bitsharesmunich.graphenej; -import com.google.gson.*; -import de.bitsharesmunich.graphenej.interfaces.ByteSerializable; -import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import java.io.ByteArrayOutputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.lang.reflect.Type; -import java.util.ArrayList; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import de.bitsharesmunich.graphenej.interfaces.ByteSerializable; +import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; /** * Class tha represents a graphene user account. @@ -18,8 +26,39 @@ import java.util.ArrayList; public class UserAccount extends GrapheneObject implements ByteSerializable, JsonSerializable { public static final String PROXY_TO_SELF = "1.2.5"; + public static final String KEY_MEMBERSHIP_EXPIRATION_DATE = "membership_expiration_date"; + public static final String KEY_REGISTRAR = "registrar"; + public static final String KEY_REFERRER = "referrer"; + public static final String KEY_LIFETIME_REFERRER = "lifetime_referrer"; + public static final String KEY_NETWORK_FEE_PERCENTAGE = "network_fee_percentage"; + public static final String KEY_LIFETIME_REFERRER_FEE_PERCENTAGE = "lifetime_referrer_fee_percentage"; + public static final String KEY_REFERRER_REWARD_PERCENTAGE = "referrer_rewards_percentage"; + public static final String KEY_NAME = "name"; + public static final String KEY_OWNER = "owner"; + public static final String KEY_ACTIVE = "active"; + public static final String KEY_OPTIONS = "options"; + public static final String KEY_STATISTICS = "statistics"; + public static final String KEY_WHITELISTING_ACCOUNTS = "whitelisting_accounts"; + public static final String KEY_BLACKLISTING_ACCOUNTS = "blacklisting_accounts"; + public static final String KEY_WHITELISTED_ACCOUNTS = "whitelisted_accounts"; + public static final String KEY_BLACKLISTED_ACCOUNTS = "blacklisted_accounts"; + public static final String KEY_OWNER_SPECIAL_AUTHORITY = "owner_special_authority"; + public static final String KEY_ACTIVE_SPECIAL_AUTHORITY = "active_special_authority"; + public static final String KEY_N_CONTROL_FLAGS = "top_n_control_flags"; + + private long membershipExpirationDate; + private String registrar; + private String referrer; + private String lifetimeReferrer; + private long networkFeePercentage; + private long lifetimeReferrerFeePercentage; + private long referrerRewardsPercentage; + private String name; + private Authority owner; + private Authority active; + private AccountOptions options; + private String statistics; - private String accountName; /** * Constructor that expects a user account in the string representation. @@ -37,24 +76,24 @@ public class UserAccount extends GrapheneObject implements ByteSerializable, Jso */ public UserAccount(String id, String name){ super(id); - this.accountName = name; + this.name = name; } /** * Getter for the account name field. * @return: The name of this account. */ - public String getAccountName() { - return accountName; + public String getName() { + return name; } /** * Setter for the account name field. - * @param accountName: The account name. + * @param name: The account name. */ - public void setAccountName(String accountName) { - this.accountName = accountName; + public void setName(String name) { + this.name = name; } @Override @@ -94,6 +133,140 @@ public class UserAccount extends GrapheneObject implements ByteSerializable, Jso return this.toJsonString(); } + public long getMembershipExpirationDate() { + return membershipExpirationDate; + } + + public void setMembershipExpirationDate(long membershipExpirationDate) { + this.membershipExpirationDate = membershipExpirationDate; + } + + public String getRegistrar() { + return registrar; + } + + public void setRegistrar(String registrar) { + this.registrar = registrar; + } + + public String getReferrer() { + return referrer; + } + + public void setReferrer(String referrer) { + this.referrer = referrer; + } + + public String getLifetimeReferrer() { + return lifetimeReferrer; + } + + public void setLifetimeReferrer(String lifetimeReferrer) { + this.lifetimeReferrer = lifetimeReferrer; + } + + public long getNetworkFeePercentage() { + return networkFeePercentage; + } + + public void setNetworkFeePercentage(long networkFeePercentage) { + this.networkFeePercentage = networkFeePercentage; + } + + public long getLifetimeReferrerFeePercentage() { + return lifetimeReferrerFeePercentage; + } + + public void setLifetimeReferrerFeePercentage(long lifetimeReferrerFeePercentage) { + this.lifetimeReferrerFeePercentage = lifetimeReferrerFeePercentage; + } + + public long getReferrerRewardsPercentage() { + return referrerRewardsPercentage; + } + + public void setReferrerRewardsPercentage(long referrerRewardsPercentage) { + this.referrerRewardsPercentage = referrerRewardsPercentage; + } + + public Authority getOwner() { + return owner; + } + + public void setOwner(Authority owner) { + this.owner = owner; + } + + public Authority getActive() { + return active; + } + + public void setActive(Authority active) { + this.active = active; + } + + public AccountOptions getOptions() { + return options; + } + + public void setOptions(AccountOptions options) { + this.options = options; + } + + public String getStatistics() { + return statistics; + } + + public void setStatistics(String statistics) { + this.statistics = statistics; + } + + /** + * Deserializer used to build a UserAccount instance from the full JSON-formatted response obtained + * by the 'get_objects' API call. + */ + public static class UserAccountFullDeserializer implements JsonDeserializer { + + @Override + public UserAccount deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonAccount = json.getAsJsonObject(); + + SimpleDateFormat dateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT); + + // Retrieving and deserializing fields + String id = jsonAccount.get(KEY_ID).getAsString(); + String name = jsonAccount.get(KEY_NAME).getAsString(); + UserAccount userAccount = new UserAccount(id, name); + AccountOptions options = context.deserialize(jsonAccount.get(KEY_OPTIONS), AccountOptions.class); + Authority owner = context.deserialize(jsonAccount.get(KEY_OWNER), Authority.class); + Authority active = context.deserialize(jsonAccount.get(KEY_ACTIVE), Authority.class); + + // Setting deserialized fields into the created instance + userAccount.setRegistrar(jsonAccount.get(KEY_REGISTRAR).getAsString()); + + // Handling the deserialization and assignation of the membership date, which internally + // is stored as a long POSIX time value + try{ + Date date = dateFormat.parse(jsonAccount.get(KEY_MEMBERSHIP_EXPIRATION_DATE).getAsString()); + userAccount.setMembershipExpirationDate(date.getTime()); + } catch (ParseException e) { + System.out.println("ParseException. Msg: "+e.getMessage()); + } + + // Setting the other fields + userAccount.setReferrer(jsonAccount.get(KEY_REFERRER).getAsString()); + userAccount.setLifetimeReferrer(jsonAccount.get(KEY_LIFETIME_REFERRER).getAsString()); + userAccount.setNetworkFeePercentage(jsonAccount.get(KEY_NETWORK_FEE_PERCENTAGE).getAsLong()); + userAccount.setLifetimeReferrerFeePercentage(jsonAccount.get(KEY_LIFETIME_REFERRER_FEE_PERCENTAGE).getAsLong()); + userAccount.setReferrerRewardsPercentage(jsonAccount.get(KEY_REFERRER_REWARD_PERCENTAGE).getAsLong()); + userAccount.setOwner(owner); + userAccount.setActive(active); + userAccount.setOptions(options); + userAccount.setStatistics(jsonAccount.get(KEY_STATISTICS).getAsString()); + return userAccount; + } + } + /** * Custom deserializer used to deserialize user accounts provided as response from the 'lookup_accounts' api call. * This response contains serialized user accounts in the form [[{id1},{name1}][{id1},{name1}]]. diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountByName.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountByName.java index bb5117a..f4f17f8 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountByName.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountByName.java @@ -1,19 +1,8 @@ package de.bitsharesmunich.graphenej.api; -import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; -import de.bitsharesmunich.graphenej.AccountOptions; -import de.bitsharesmunich.graphenej.Authority; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.AccountProperties; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.BaseResponse; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; import java.io.Serializable; @@ -22,15 +11,24 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.AccountOptions; +import de.bitsharesmunich.graphenej.Authority; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.AccountProperties; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * Created by nelson on 11/15/16. */ -public class GetAccountByName extends WebSocketAdapter { +public class GetAccountByName extends BaseGrapheneHandler { private String accountName; private WitnessResponseListener mListener; public GetAccountByName(String accountName, WitnessResponseListener listener){ + super(listener); this.accountName = accountName; this.mListener = listener; } @@ -70,17 +68,4 @@ public class GetAccountByName extends WebSocketAdapter { System.out.println(">>> "+frame.getPayloadText()); } } - - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccounts.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccounts.java index 70b9f76..11377db 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccounts.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccounts.java @@ -1,23 +1,9 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; -import de.bitsharesmunich.graphenej.AccountOptions; -import de.bitsharesmunich.graphenej.Authority; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.UserAccount; -import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.AccountProperties; -import de.bitsharesmunich.graphenej.models.BaseResponse; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import java.io.Serializable; import java.lang.reflect.Type; @@ -25,22 +11,33 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.AccountOptions; +import de.bitsharesmunich.graphenej.Authority; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.AccountProperties; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * * @author henry */ -public class GetAccounts extends WebSocketAdapter { +public class GetAccounts extends BaseGrapheneHandler { private String accountId; private List userAccounts; private WitnessResponseListener mListener; public GetAccounts(String accountId, WitnessResponseListener listener){ + super(listener); this.accountId = accountId; this.mListener = listener; } public GetAccounts(List accounts, WitnessResponseListener listener){ + super(listener); this.userAccounts = accounts; this.mListener = listener; } @@ -85,22 +82,4 @@ public class GetAccounts extends WebSocketAdapter { if(frame.isTextFrame()) System.out.println(">>> "+frame.getPayloadText()); } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - System.out.println("onError"); - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - System.out.println("handleCallbackError. Msg: "+cause.getMessage()); - StackTraceElement[] stack = cause.getStackTrace(); - for(StackTraceElement element : stack) { - System.out.println("> "+element.getClassName()+"."+element.getMethodName()+" : "+element.getLineNumber()); - } - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetBlockHeader.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetBlockHeader.java index 3844a2b..4cab506 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetBlockHeader.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetBlockHeader.java @@ -3,12 +3,7 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.*; import java.io.Serializable; import java.lang.reflect.Type; @@ -16,10 +11,18 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.BaseResponse; +import de.bitsharesmunich.graphenej.models.BlockHeader; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * Created by nelson on 12/13/16. */ -public class GetBlockHeader extends WebSocketAdapter { +public class GetBlockHeader extends BaseGrapheneHandler { + // Sequence of message ids private final static int LOGIN_ID = 1; private final static int GET_DATABASE_ID = 2; @@ -32,6 +35,7 @@ public class GetBlockHeader extends WebSocketAdapter { private int apiId = -1; public GetBlockHeader(long blockNumber, WitnessResponseListener listener){ + super(listener); this.blockNumber = blockNumber; this.mListener = listener; } @@ -87,16 +91,4 @@ public class GetBlockHeader extends WebSocketAdapter { if(frame.isTextFrame()) System.out.println(">>> "+frame.getPayloadText()); } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - System.out.println("onError. Msg: "+cause.getMessage()); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - System.out.println("handleCallbackError. Msg: "+cause.getMessage()); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountsByAddress.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetKeyReferences.java similarity index 67% rename from graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountsByAddress.java rename to graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetKeyReferences.java index 86fa9ba..5eb4243 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountsByAddress.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetKeyReferences.java @@ -2,16 +2,7 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; -import de.bitsharesmunich.graphenej.Address; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.UserAccount; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.BaseResponse; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; import java.io.Serializable; @@ -20,25 +11,41 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.Address; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * Created by nelson on 11/15/16. */ -public class GetAccountsByAddress extends WebSocketAdapter { +public class GetKeyReferences extends BaseGrapheneHandler { - private Address address; - private WitnessResponseListener mListener; + private List
addresses; - public GetAccountsByAddress(Address address, WitnessResponseListener listener) { - this.address = address; + public GetKeyReferences(Address address, WitnessResponseListener listener){ + super(listener); + addresses = new ArrayList<>(); + addresses.add(address); + + } + + public GetKeyReferences(List
addresses, WitnessResponseListener listener) { + super(listener); + this.addresses = addresses; this.mListener = listener; } @Override public void onConnected(WebSocket websocket, Map> headers) throws Exception { - ArrayList params = new ArrayList(); - ArrayList addresses = new ArrayList(); - addresses.add(address.toString()); - params.add(addresses); + ArrayList inner = new ArrayList(); + for(Address addr : addresses){ + inner.add(addr.toString()); + } + ArrayList params = new ArrayList<>(); + params.add(inner); ApiCall getAccountByAddress = new ApiCall(0, RPC.CALL_GET_KEY_REFERENCES, params, RPC.VERSION, 1); websocket.sendText(getAccountByAddress.toJsonString()); } @@ -65,16 +72,4 @@ public class GetAccountsByAddress extends WebSocketAdapter { if(frame.isTextFrame()) System.out.println(">>> "+frame.getPayloadText()); } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetLimitOrders.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetLimitOrders.java index 60c7f4d..eacdda9 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetLimitOrders.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetLimitOrders.java @@ -3,9 +3,15 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; + +import java.io.Serializable; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import de.bitsharesmunich.graphenej.AssetAmount; import de.bitsharesmunich.graphenej.LimitOrder; import de.bitsharesmunich.graphenej.RPC; @@ -15,16 +21,10 @@ import de.bitsharesmunich.graphenej.models.ApiCall; import de.bitsharesmunich.graphenej.models.BaseResponse; import de.bitsharesmunich.graphenej.models.WitnessResponse; -import java.io.Serializable; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - /** * Created by nelson on 11/15/16. */ -public class GetLimitOrders extends WebSocketAdapter { +public class GetLimitOrders extends BaseGrapheneHandler { private String a; private String b; @@ -32,6 +32,7 @@ public class GetLimitOrders extends WebSocketAdapter { private WitnessResponseListener mListener; public GetLimitOrders(String a, String b, int limit, WitnessResponseListener mListener) { + super(mListener); this.a = a; this.b = b; this.limit = limit; diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java index 06a6a81..b570839 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java @@ -4,13 +4,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; -import de.bitsharesmunich.graphenej.Asset; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.*; import java.io.Serializable; import java.lang.reflect.Type; @@ -20,10 +14,19 @@ import java.util.Date; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.BaseResponse; +import de.bitsharesmunich.graphenej.models.BucketObject; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * Created by nelson on 12/22/16. */ -public class GetMarketHistory extends WebSocketAdapter { +public class GetMarketHistory extends BaseGrapheneHandler { + // Sequence of message ids private final static int LOGIN_ID = 1; private final static int GET_HISTORY_ID = 2; @@ -36,11 +39,13 @@ public class GetMarketHistory extends WebSocketAdapter { private Date start; private Date end; private WitnessResponseListener mListener; - + private WebSocket mWebsocket; private int currentId = 1; private int apiId = -1; + private int counter = 0; public GetMarketHistory(Asset base, Asset quote, long bucket, Date start, Date end, WitnessResponseListener listener){ + super(listener); this.base = base; this.quote = quote; this.bucket = bucket; @@ -49,8 +54,68 @@ public class GetMarketHistory extends WebSocketAdapter { this.mListener = listener; } + public Asset getBase() { + return base; + } + + public void setBase(Asset base) { + this.base = base; + } + + public Asset getQuote() { + return quote; + } + + public void setQuote(Asset quote) { + this.quote = quote; + } + + public long getBucket() { + return bucket; + } + + public void setBucket(long bucket) { + this.bucket = bucket; + } + + public Date getStart() { + return start; + } + + public void setStart(Date start) { + this.start = start; + } + + public Date getEnd() { + return end; + } + + public void setEnd(Date end) { + this.end = end; + } + + public int getCount(){ + return this.counter; + } + + public void disconnect(){ + if(mWebsocket != null && mWebsocket.isOpen()){ + mWebsocket.disconnect(); + } + } + + /** + * Retries the 'get_market_history' API call. + * Hopefully with different 'start' and 'stop' parameters. + */ + public void retry(){ + sendHistoricalMarketDataRequest(); + } + + @Override public void onConnected(WebSocket websocket, Map> headers) throws Exception { + mWebsocket = websocket; ArrayList loginParams = new ArrayList<>(); loginParams.add(null); loginParams.add(null); @@ -89,37 +154,40 @@ public class GetMarketHistory extends WebSocketAdapter { ApiCall getRelativeAccountHistoryCall = new ApiCall(apiId, RPC.CALL_GET_MARKET_HISTORY, params, RPC.VERSION, currentId); websocket.sendText(getRelativeAccountHistoryCall.toJsonString()); - }else if(baseResponse.id == GET_HISTORY_DATA){ + }else if(baseResponse.id >= GET_HISTORY_DATA){ GsonBuilder builder = new GsonBuilder(); Type MarketHistoryResponse = new TypeToken>>(){}.getType(); builder.registerTypeAdapter(BucketObject.class, new BucketObject.BucketDeserializer()); WitnessResponse> marketHistoryResponse = builder.create().fromJson(response, MarketHistoryResponse); mListener.onSuccess(marketHistoryResponse); - websocket.disconnect(); } } } + /** + * Actually sends the 'get_market_history' API call request. This method might be called multiple + * times during the life-cycle of this instance because we might not have gotten anything + * in the first requested interval. + */ + private void sendHistoricalMarketDataRequest(){ + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + + ArrayList params = new ArrayList<>(); + params.add(this.base.getObjectId()); + params.add(this.quote.getObjectId()); + params.add(this.bucket); + params.add(dateFormat.format(this.start)); + params.add(dateFormat.format(this.end)); + + ApiCall getRelativeAccountHistoryCall = new ApiCall(apiId, RPC.CALL_GET_MARKET_HISTORY, params, RPC.VERSION, currentId); + mWebsocket.sendText(getRelativeAccountHistoryCall.toJsonString()); + + counter++; + } + @Override public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception { if(frame.isTextFrame()) System.out.println(">>> "+frame.getPayloadText()); } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - System.out.println("onError. Msg: "+cause.getMessage()); - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - System.out.println("handleCallbackError. cause: "+cause.getMessage()+", error: "+cause.getClass()); - for (StackTraceElement element : cause.getStackTrace()){ - System.out.println(element.getFileName()+"#"+element.getClassName()+":"+element.getLineNumber()); - } - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetObjects.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetObjects.java index 33347da..548dfcd 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetObjects.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetObjects.java @@ -1,15 +1,13 @@ package de.bitsharesmunich.graphenej.api; +import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; import com.neovisionaries.ws.client.WebSocket; import com.neovisionaries.ws.client.WebSocketFrame; -import de.bitsharesmunich.graphenej.AssetAmount; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.BitAssetData; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import java.io.Serializable; import java.lang.reflect.Type; @@ -17,6 +15,18 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.AccountOptions; +import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.AssetAmount; +import de.bitsharesmunich.graphenej.Authority; +import de.bitsharesmunich.graphenej.GrapheneObject; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.BitAssetData; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * Created by nelson on 1/8/17. */ @@ -48,16 +58,40 @@ public class GetObjects extends BaseGrapheneHandler { String response = frame.getPayloadText(); GsonBuilder gsonBuilder = new GsonBuilder(); - //TODO: Uncomment this line after the deserializer is implemented. gsonBuilder.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer()); -// gsonBuilder.registerTypeAdapter(BitAssetData.class, new BitAssetData.BitAssetDeserializer()); + gsonBuilder.registerTypeAdapter(Asset.class, new Asset.AssetDeserializer()); + gsonBuilder.registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountFullDeserializer()); + gsonBuilder.registerTypeAdapter(Authority.class, new Authority.AuthorityDeserializer()); + gsonBuilder.registerTypeAdapter(AccountOptions.class, new AccountOptions.AccountOptionsDeserializer()); + Gson gson = gsonBuilder.create(); - // Only homogeneus array is currently supported - if(ids.get(0).split("\\.")[1].equals("4")){ - Type BitAssetDataType = new TypeToken>>(){}.getType(); - WitnessResponse> witnessResponse = gsonBuilder.create().fromJson(response, BitAssetDataType); - mListener.onSuccess(witnessResponse); + List parsedResult = new ArrayList<>(); + + JsonParser parser = new JsonParser(); + JsonArray resultArray = parser.parse(response).getAsJsonObject().get(WitnessResponse.KEY_RESULT).getAsJsonArray(); + for(JsonElement element : resultArray){ + String id = element.getAsJsonObject().get(GrapheneObject.KEY_ID).getAsString(); + GrapheneObject grapheneObject = new GrapheneObject(id); + switch (grapheneObject.getObjectType()){ + case ASSET_OBJECT: + Asset asset = gson.fromJson(element, Asset.class); + parsedResult.add(asset); + break; + case ACCOUNT_OBJECT: + UserAccount account = gson.fromJson(element, UserAccount.class); + parsedResult.add(account); + break; + case ASSET_BITASSET_DATA: + Type BitAssetDataType = new TypeToken>>(){}.getType(); + WitnessResponse> witnessResponse = gsonBuilder.create().fromJson(response, BitAssetDataType); + BitAssetData bitAssetData = witnessResponse.result.get(0); + parsedResult.add(bitAssetData); + } } + + WitnessResponse> output = new WitnessResponse<>(); + output.result = parsedResult; + mListener.onSuccess(output); websocket.disconnect(); } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java index 5507263..fda7b19 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java @@ -3,18 +3,7 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; -import de.bitsharesmunich.graphenej.AssetAmount; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.operations.TransferOperation; -import de.bitsharesmunich.graphenej.UserAccount; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.BaseResponse; -import de.bitsharesmunich.graphenej.models.HistoricalTransfer; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; import java.io.Serializable; @@ -23,11 +12,21 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.AssetAmount; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.BaseResponse; +import de.bitsharesmunich.graphenej.models.HistoricalTransfer; +import de.bitsharesmunich.graphenej.models.WitnessResponse; +import de.bitsharesmunich.graphenej.operations.TransferOperation; + /** * Class used to encapsulate the communication sequence used to retrieve the transaction history of * a given user. */ -public class GetRelativeAccountHistory extends WebSocketAdapter { +public class GetRelativeAccountHistory extends BaseGrapheneHandler { // Sequence of message ids private final static int LOGIN_ID = 1; private final static int GET_HISTORY_ID = 2; @@ -44,6 +43,7 @@ public class GetRelativeAccountHistory extends WebSocketAdapter { private int limit; private int start; private WitnessResponseListener mListener; + private WebSocket mWebsocket; private int currentId = 1; private int apiId = -1; @@ -57,6 +57,7 @@ public class GetRelativeAccountHistory extends WebSocketAdapter { * @param listener Listener to be notified with the result of this query */ public GetRelativeAccountHistory(UserAccount userAccount, int stop, int limit, int start, WitnessResponseListener listener){ + super(listener); if(limit > MAX_LIMIT) limit = MAX_LIMIT; this.mUserAccount = userAccount; this.stop = stop; @@ -71,6 +72,7 @@ public class GetRelativeAccountHistory extends WebSocketAdapter { * @param listener Listener to be notified with the result of this query */ public GetRelativeAccountHistory(UserAccount userAccount, WitnessResponseListener listener){ + super(listener); this.mUserAccount = userAccount; this.stop = DEFAULT_STOP; this.limit = MAX_LIMIT; @@ -80,6 +82,7 @@ public class GetRelativeAccountHistory extends WebSocketAdapter { @Override public void onConnected(WebSocket websocket, Map> headers) throws Exception { + mWebsocket = websocket; ArrayList loginParams = new ArrayList<>(); loginParams.add(null); loginParams.add(null); @@ -107,43 +110,57 @@ public class GetRelativeAccountHistory extends WebSocketAdapter { WitnessResponse witnessResponse = gson.fromJson(response, ApiIdResponse); apiId = witnessResponse.result.intValue(); - ArrayList params = new ArrayList<>(); - params.add(mUserAccount.toJsonString()); - params.add(this.stop); - params.add(this.limit); - params.add(this.start); - - ApiCall getRelativeAccountHistoryCall = new ApiCall(apiId, RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY, params, RPC.VERSION, currentId); - websocket.sendText(getRelativeAccountHistoryCall.toJsonString()); - }else if(baseResponse.id == GET_HISTORY_DATA){ + sendRelativeAccountHistoryRequest(); + }else if(baseResponse.id >= GET_HISTORY_DATA){ Type RelativeAccountHistoryResponse = new TypeToken>>(){}.getType(); GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer()); gsonBuilder.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer()); WitnessResponse> transfersResponse = gsonBuilder.create().fromJson(response, RelativeAccountHistoryResponse); mListener.onSuccess(transfersResponse); - websocket.disconnect(); } } } + /** + * Sends the actual get_relative_account_history request. + */ + private void sendRelativeAccountHistoryRequest(){ + ArrayList params = new ArrayList<>(); + params.add(mUserAccount.toJsonString()); + params.add(this.stop); + params.add(this.limit); + params.add(this.start); + + ApiCall getRelativeAccountHistoryCall = new ApiCall(apiId, RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY, params, RPC.VERSION, currentId); + mWebsocket.sendText(getRelativeAccountHistoryCall.toJsonString()); + } + + /** + * Updates the arguments and makes a new call to the get_relative_account_history API + * @param stop Sequence number of earliest operation + * @param limit Maximum number of operations to retrieve (must not exceed 100) + * @param start Sequence number of the most recent operation to retrieve + */ + public void retry(int stop, int limit, int start){ + this.stop = stop; + this.limit = limit; + this.start = start; + sendRelativeAccountHistoryRequest(); + } + + /** + * Disconnects the websocket + */ + public void disconnect(){ + if(mWebsocket != null && mWebsocket.isOpen()){ + mWebsocket.disconnect(); + } + } + @Override public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception { if(frame.isTextFrame()) System.out.println(">>> "+frame.getPayloadText()); } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - System.out.println("onError. Msg: "+cause.getMessage()); - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - System.out.println("handleCallbackError. Msg: "+cause.getMessage()); - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java index 073ea25..46dd72d 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java @@ -3,15 +3,7 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; -import de.bitsharesmunich.graphenej.MarketTrade; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.BaseResponse; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import java.io.Serializable; import java.lang.reflect.Type; @@ -19,10 +11,16 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.MarketTrade; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * @author henry */ -public class GetTradeHistory extends WebSocketAdapter { +public class GetTradeHistory extends BaseGrapheneHandler { private String a; private String b; @@ -32,6 +30,7 @@ public class GetTradeHistory extends WebSocketAdapter { private WitnessResponseListener mListener; public GetTradeHistory(String a, String b, String toTime, String fromTime,int limit, WitnessResponseListener mListener) { + super(mListener); this.a = a; this.b = b; this.toTime = toTime; @@ -82,16 +81,4 @@ public class GetTradeHistory extends WebSocketAdapter { System.out.println(">>> " + frame.getPayloadText()); } } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAccounts.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAccounts.java index 37274bd..6b424b9 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAccounts.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAccounts.java @@ -2,15 +2,7 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.UserAccount; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.BaseResponse; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; import java.io.Serializable; @@ -19,10 +11,16 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * Created by henry on 07/12/16. */ -public class LookupAccounts extends WebSocketAdapter { +public class LookupAccounts extends BaseGrapheneHandler { public static final int DEFAULT_MAX = 1000; private final String accountName; @@ -30,12 +28,14 @@ public class LookupAccounts extends WebSocketAdapter { private final WitnessResponseListener mListener; public LookupAccounts(String accountName, WitnessResponseListener listener){ + super(listener); this.accountName = accountName; this.maxAccounts = DEFAULT_MAX; this.mListener = listener; } public LookupAccounts(String accountName, int maxAccounts, WitnessResponseListener listener){ + super(listener); this.accountName = accountName; this.maxAccounts = maxAccounts; this.mListener = listener; @@ -73,16 +73,4 @@ public class LookupAccounts extends WebSocketAdapter { if(frame.isTextFrame()) System.out.println(">>> "+frame.getPayloadText()); } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } \ No newline at end of file diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAssetSymbols.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAssetSymbols.java index 59e609f..3c24247 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAssetSymbols.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/LookupAssetSymbols.java @@ -3,15 +3,7 @@ package de.bitsharesmunich.graphenej.api; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; -import de.bitsharesmunich.graphenej.Asset; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.BaseResponse; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import java.io.Serializable; import java.lang.reflect.Type; @@ -19,14 +11,21 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + /** * Created by nelson on 12/12/16. */ -public class LookupAssetSymbols extends WebSocketAdapter { +public class LookupAssetSymbols extends BaseGrapheneHandler { private WitnessResponseListener mListener; private List assets; public LookupAssetSymbols(List assets, WitnessResponseListener listener){ + super(listener); this.assets = assets; this.mListener = listener; } @@ -59,21 +58,4 @@ public class LookupAssetSymbols extends WebSocketAdapter { if(frame.isTextFrame()) System.out.println(">>> "+frame.getPayloadText()); } - - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - System.out.println("onError. cause: "+cause.getMessage()); - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - System.out.println("handleCallbackError. cause: "+cause.getMessage()+", error: "+cause.getClass()); - for (StackTraceElement element : cause.getStackTrace()){ - System.out.println(element.getFileName()+"#"+element.getClassName()+":"+element.getLineNumber()); - } - mListener.onError(new BaseResponse.Error(cause.getMessage())); - websocket.disconnect(); - } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/SubscriptionMessagesHub.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/SubscriptionMessagesHub.java index 547236e..510b8c8 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/SubscriptionMessagesHub.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/SubscriptionMessagesHub.java @@ -4,18 +4,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; import com.neovisionaries.ws.client.WebSocketFrame; -import de.bitsharesmunich.graphenej.AssetAmount; -import de.bitsharesmunich.graphenej.RPC; -import de.bitsharesmunich.graphenej.Transaction; -import de.bitsharesmunich.graphenej.operations.TransferOperation; -import de.bitsharesmunich.graphenej.interfaces.SubscriptionHub; -import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener; -import de.bitsharesmunich.graphenej.models.ApiCall; -import de.bitsharesmunich.graphenej.models.SubscriptionResponse; -import de.bitsharesmunich.graphenej.models.WitnessResponse; import java.io.Serializable; import java.lang.reflect.Type; @@ -23,12 +12,27 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import de.bitsharesmunich.graphenej.AssetAmount; +import de.bitsharesmunich.graphenej.ObjectType; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.Transaction; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.interfaces.SubscriptionHub; +import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.ApiCall; +import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties; +import de.bitsharesmunich.graphenej.models.SubscriptionResponse; +import de.bitsharesmunich.graphenej.models.WitnessResponse; +import de.bitsharesmunich.graphenej.operations.LimitOrderCreateOperation; +import de.bitsharesmunich.graphenej.operations.TransferOperation; + /** * A websocket adapter prepared to be used as a basic dispatch hub for subscription messages. * * Created by nelson on 1/26/17. */ -public class SubscriptionMessagesHub extends WebSocketAdapter implements SubscriptionHub { +public class SubscriptionMessagesHub extends BaseGrapheneHandler implements SubscriptionHub { // Sequence of message ids private final static int LOGIN_ID = 1; private final static int GET_DATABASE_ID = 2; @@ -41,21 +45,60 @@ public class SubscriptionMessagesHub extends WebSocketAdapter implements Subscri private Gson gson; private String user; private String password; - private int currentId = LOGIN_ID; + private boolean clearFilter; + private List objectTypes; + private int currentId; private int databaseApiId = -1; + private int subscriptionCounter = 0; - public SubscriptionMessagesHub(String user, String password){ + /** + * Id used to separate requests regarding the subscriptions + */ + private final int SUBSCRIPTION_ID = 10; + + /** + * Constructor used to create a subscription message hub that will call the set_subscribe_callback + * API with the clear_filter parameter set to false, meaning that it will only receive automatic updates + * from objects we register. + * + * A list of ObjectTypes must be provided, otherwise we won't get any update. + * + * @param user: User name, in case the node to which we're going to connect to requires authentication + * @param password: Password, same as above + * @param objectTypes: List of objects of interest + * @param errorListener: Callback that will be fired in case there is an error. + */ + public SubscriptionMessagesHub(String user, String password, List objectTypes, WitnessResponseListener errorListener){ + super(errorListener); + this.objectTypes = objectTypes; this.user = user; this.password = password; + this.clearFilter = true; this.mSubscriptionDeserializer = new SubscriptionResponse.SubscriptionResponseDeserializer(); GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(SubscriptionResponse.class, mSubscriptionDeserializer); builder.registerTypeAdapter(Transaction.class, new Transaction.TransactionDeserializer()); builder.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer()); + builder.registerTypeAdapter(LimitOrderCreateOperation.class, new LimitOrderCreateOperation.LimitOrderCreateDeserializer()); builder.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer()); + builder.registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer()); + builder.registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer()); this.gson = builder.create(); } + /** + * Constructor used to create a subscription message hub that will call the set_subscribe_callback + * API with the clear_filter parameter set to true, meaning that it will receive automatic updates + * on all network events. + * + * @param user: User name, in case the node to which we're going to connect to requires authentication + * @param password: Password, same as above + * @param errorListener: Callback that will be fired in case there is an error. + */ + public SubscriptionMessagesHub(String user, String password, WitnessResponseListener errorListener){ + this(user, password, new ArrayList(), errorListener); + } + @Override public void addSubscriptionListener(SubscriptionListener listener){ this.mSubscriptionDeserializer.addSubscriptionListener(listener); @@ -74,6 +117,7 @@ public class SubscriptionMessagesHub extends WebSocketAdapter implements Subscri @Override public void onConnected(WebSocket websocket, Map> headers) throws Exception { ArrayList loginParams = new ArrayList<>(); + currentId = LOGIN_ID; loginParams.add(user); loginParams.add(password); ApiCall loginCall = new ApiCall(1, RPC.CALL_LOGIN, loginParams, RPC.VERSION, currentId); @@ -88,6 +132,7 @@ public class SubscriptionMessagesHub extends WebSocketAdapter implements Subscri ArrayList emptyParams = new ArrayList<>(); ApiCall getDatabaseId = new ApiCall(1, RPC.CALL_DATABASE, emptyParams, RPC.VERSION, currentId); websocket.sendText(getDatabaseId.toJsonString()); + currentId++; }else if(currentId == GET_DATABASE_ID){ Type ApiIdResponse = new TypeToken>() {}.getType(); WitnessResponse witnessResponse = gson.fromJson(message, ApiIdResponse); @@ -95,15 +140,23 @@ public class SubscriptionMessagesHub extends WebSocketAdapter implements Subscri ArrayList subscriptionParams = new ArrayList<>(); subscriptionParams.add(String.format("%d", SUBCRIPTION_NOTIFICATION)); - subscriptionParams.add(false); - ApiCall getDatabaseId = new ApiCall(databaseApiId, RPC.CALL_SET_SUBSCRIBE_CALLBACK, subscriptionParams, RPC.VERSION, currentId); + subscriptionParams.add(clearFilter); + ApiCall getDatabaseId = new ApiCall(databaseApiId, RPC.CALL_SET_SUBSCRIBE_CALLBACK, subscriptionParams, RPC.VERSION, SUBCRIPTION_REQUEST); websocket.sendText(getDatabaseId.toJsonString()); - }else if(currentId == SUBCRIPTION_REQUEST){ - // Listeners are called from within the SubscriptionResponseDeserializer, so there's nothing to handle here. - }else{ - SubscriptionResponse subscriptionResponse = gson.fromJson(message, SubscriptionResponse.class); + currentId++; + } else if(currentId == SUBCRIPTION_REQUEST){ + if(objectTypes != null && objectTypes.size() > 0 && subscriptionCounter < objectTypes.size()){ + ArrayList objectOfInterest = new ArrayList<>(); + objectOfInterest.add(objectTypes.get(subscriptionCounter).getGenericObjectId()); + ArrayList payload = new ArrayList<>(); + payload.add(objectOfInterest); + ApiCall subscribe = new ApiCall(databaseApiId, RPC.GET_OBJECTS, payload, RPC.VERSION, SUBSCRIPTION_ID); + websocket.sendText(subscribe.toJsonString()); + subscriptionCounter++; + }else{ + gson.fromJson(message, SubscriptionResponse.class); + } } - currentId++; } @Override @@ -111,13 +164,9 @@ public class SubscriptionMessagesHub extends WebSocketAdapter implements Subscri System.out.println(">> "+frame.getPayloadText()); } - @Override - public void onError(WebSocket websocket, WebSocketException cause) throws Exception { - super.onError(websocket, cause); - } - - @Override - public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - super.handleCallbackError(websocket, cause); + public void reset(){ + currentId = 0; + databaseApiId = -1; + subscriptionCounter = 0; } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/TransactionBroadcastSequence.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/TransactionBroadcastSequence.java index bd6bfc3..30549d9 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/TransactionBroadcastSequence.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/api/TransactionBroadcastSequence.java @@ -1,27 +1,33 @@ package de.bitsharesmunich.graphenej.api; -import java.io.Serializable; -import java.lang.reflect.Type; -import java.text.SimpleDateFormat; -import java.util.*; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; -import de.bitsharesmunich.graphenej.*; +import com.neovisionaries.ws.client.WebSocket; +import com.neovisionaries.ws.client.WebSocketException; +import com.neovisionaries.ws.client.WebSocketFrame; + +import java.io.Serializable; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.AssetAmount; +import de.bitsharesmunich.graphenej.BlockData; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.Transaction; import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; import de.bitsharesmunich.graphenej.models.ApiCall; import de.bitsharesmunich.graphenej.models.BaseResponse; import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties; import de.bitsharesmunich.graphenej.models.WitnessResponse; -import com.neovisionaries.ws.client.WebSocket; -import com.neovisionaries.ws.client.WebSocketAdapter; -import com.neovisionaries.ws.client.WebSocketException; -import com.neovisionaries.ws.client.WebSocketFrame; /** * Class that will handle the transaction publication procedure. */ -public class TransactionBroadcastSequence extends WebSocketAdapter { +public class TransactionBroadcastSequence extends BaseGrapheneHandler { private final String TAG = this.getClass().getName(); private final static int LOGIN_ID = 1; @@ -45,6 +51,7 @@ public class TransactionBroadcastSequence extends WebSocketAdapter { * of the transaction broadcast operation. */ public TransactionBroadcastSequence(Transaction transaction, Asset feeAsset, WitnessResponseListener listener){ + super(listener); this.transaction = transaction; this.feeAsset = feeAsset; this.mListener = listener; @@ -64,7 +71,9 @@ public class TransactionBroadcastSequence extends WebSocketAdapter { if(frame.isTextFrame()) System.out.println("<<< "+frame.getPayloadText()); String response = frame.getPayloadText(); - Gson gson = new Gson(); + GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer()); + Gson gson = builder.create(); BaseResponse baseResponse = gson.fromJson(response, BaseResponse.class); if(baseResponse.error != null){ mListener.onError(baseResponse.error); @@ -94,12 +103,8 @@ public class TransactionBroadcastSequence extends WebSocketAdapter { WitnessResponse witnessResponse = gson.fromJson(response, DynamicGlobalPropertiesResponse); DynamicGlobalProperties dynamicProperties = witnessResponse.result; - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - Date date = dateFormat.parse(dynamicProperties.time); - // Adjusting dynamic block data to every transaction - long expirationTime = (date.getTime() / 1000) + Transaction.DEFAULT_EXPIRATION_TIME; + long expirationTime = (dynamicProperties.time.getTime() / 1000) + Transaction.DEFAULT_EXPIRATION_TIME; String headBlockId = dynamicProperties.head_block_id; long headBlockNumber = dynamicProperties.head_block_number; transaction.setBlockData(new BlockData(headBlockNumber, headBlockId, expirationTime)); diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/BitAssetData.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/BitAssetData.java index eaf36ac..5625a03 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/BitAssetData.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/BitAssetData.java @@ -1,5 +1,6 @@ package de.bitsharesmunich.graphenej.models; +import de.bitsharesmunich.graphenej.GrapheneObject; import de.bitsharesmunich.graphenej.Price; /** @@ -8,8 +9,7 @@ import de.bitsharesmunich.graphenej.Price; * * Created by nelson on 1/8/17. */ -public class BitAssetData { - public String id; +public class BitAssetData extends GrapheneObject { public Object[] feeds; public AssetFeed current_feed; public String current_feed_publication_time; @@ -18,4 +18,8 @@ public class BitAssetData { public boolean is_prediction_market; public Price settlement_price; public long settlement_fund; + + public BitAssetData(String id) { + super(id); + } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/DynamicGlobalProperties.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/DynamicGlobalProperties.java index 59819b3..e27cbc0 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/DynamicGlobalProperties.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/DynamicGlobalProperties.java @@ -1,8 +1,20 @@ package de.bitsharesmunich.graphenej.models; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; + import java.io.Serializable; +import java.lang.reflect.Type; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; import de.bitsharesmunich.graphenej.GrapheneObject; +import de.bitsharesmunich.graphenej.Util; /** * Class used to deserialize the 'result' field returned by the full node after making a call @@ -25,19 +37,63 @@ public class DynamicGlobalProperties extends GrapheneObject implements Serializa public long head_block_number; public String head_block_id; - public String time; + public Date time; public String current_witness; - public String next_maintenance_time; + public Date next_maintenance_time; public String last_budget_time; public long witness_budget; public long accounts_registered_this_interval; public long recently_missed_count; public long current_aslot; public String recent_slots_filled; - public long dynamic_flags; + public int dynamic_flags; public long last_irreversible_block_num; public DynamicGlobalProperties(String id) { super(id); } + + /** + * Class that will parse the JSON element containing the dynamic global properties object and + * return an instance of the {@link DynamicGlobalProperties} class. + */ + public static class DynamicGlobalPropertiesDeserializer implements JsonDeserializer { + + @Override + public DynamicGlobalProperties deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + + // Creating an instance of the DynamicGlobalProperties + DynamicGlobalProperties dynamicGlobal = new DynamicGlobalProperties(jsonElement.getAsJsonObject().get(KEY_ID).getAsString()); + + // Start to fill in the parsed details + dynamicGlobal.head_block_number = jsonObject.get(DynamicGlobalProperties.KEY_HEAD_BLOCK_NUMBER).getAsLong(); + dynamicGlobal.head_block_id = jsonObject.get(DynamicGlobalProperties.KEY_HEAD_BLOCK_ID).getAsString(); + + SimpleDateFormat dateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + try { + dynamicGlobal.time = dateFormat.parse(jsonObject.get(DynamicGlobalProperties.KEY_TIME).getAsString()); + } catch (ParseException e) { + System.out.println("ParseException. Msg: "+e.getMessage()); + } + + try { + dynamicGlobal.next_maintenance_time = dateFormat.parse(jsonObject.get(DynamicGlobalProperties.KEY_NEXT_MAINTENANCE_TIME).getAsString()); + } catch (ParseException e) { + System.out.println("ParseException. Msg: "+e.getMessage()); + } + + dynamicGlobal.current_witness = jsonObject.get(DynamicGlobalProperties.KEY_CURRENT_WITNESS).getAsString(); + dynamicGlobal.last_budget_time = jsonObject.get(DynamicGlobalProperties.KEY_LAST_BUDGET_TIME).getAsString(); + dynamicGlobal.witness_budget = jsonObject.get(DynamicGlobalProperties.KEY_WITNESS_BUDGET).getAsLong(); + dynamicGlobal.accounts_registered_this_interval = jsonObject.get(DynamicGlobalProperties.KEY_ACCOUNTS_REGISTERED_THIS_INTERVAL).getAsLong(); + dynamicGlobal.recently_missed_count = jsonObject.get(DynamicGlobalProperties.KEY_RECENTLY_MISSED_COUNT).getAsLong(); + dynamicGlobal.current_aslot = jsonObject.get(DynamicGlobalProperties.KEY_CURRENT_ASLOT).getAsLong(); + dynamicGlobal.recent_slots_filled = jsonObject.get(DynamicGlobalProperties.KEY_RECENT_SLOTS_FILLED).getAsString(); + dynamicGlobal.dynamic_flags = jsonObject.get(DynamicGlobalProperties.KEY_DYNAMIC_FLAGS).getAsInt(); + dynamicGlobal.last_irreversible_block_num = jsonObject.get(DynamicGlobalProperties.KEY_LAST_IRREVERSIBLE_BLOCK_NUM).getAsLong(); + return dynamicGlobal; + } + } } \ No newline at end of file diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/SubscriptionResponse.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/SubscriptionResponse.java index dbf896a..4e27b55 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/SubscriptionResponse.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/SubscriptionResponse.java @@ -9,9 +9,14 @@ import com.google.gson.JsonParseException; import java.io.Serializable; import java.lang.reflect.Type; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; -import de.bitsharesmunich.graphenej.*; +import de.bitsharesmunich.graphenej.GrapheneObject; +import de.bitsharesmunich.graphenej.ObjectType; +import de.bitsharesmunich.graphenej.Transaction; import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener; /** @@ -57,7 +62,14 @@ public class SubscriptionResponse { * objects that might come once the are subscribed to the witness notifications. */ public static class SubscriptionResponseDeserializer implements JsonDeserializer { + /** + * Map of ObjectType to Integer used to keep track of the current amount of listener per type + */ private HashMap listenerTypeCount; + + /** + * List of listeners + */ private LinkedList mListeners; /** @@ -97,6 +109,9 @@ public class SubscriptionResponse { public SubscriptionResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { SubscriptionResponse response = new SubscriptionResponse(); JsonObject responseObject = json.getAsJsonObject(); + if(!responseObject.has(KEY_METHOD)){ + return response; + } response.method = responseObject.get(KEY_METHOD).getAsString(); JsonArray paramsArray = responseObject.get(KEY_PARAMS).getAsJsonArray(); @@ -105,11 +120,15 @@ public class SubscriptionResponse { ArrayList secondArgument = new ArrayList<>(); response.params.add(secondArgument); + // Hash map used to record the type of objects present in this subscription message + // and only alert listeners that might be interested + HashMap objectMap = new HashMap<>(); + JsonArray subArray = paramsArray.get(1).getAsJsonArray().get(0).getAsJsonArray(); for(JsonElement object : subArray){ if(object.isJsonObject()){ - GrapheneObject grapheneObject = new GrapheneObject(object.getAsJsonObject().get(KEY_ID).getAsString()); + int listenerTypeCount = 0; if(this.listenerTypeCount.containsKey(grapheneObject.getObjectType())){ listenerTypeCount = this.listenerTypeCount.get(grapheneObject.getObjectType()); @@ -126,18 +145,17 @@ public class SubscriptionResponse { balanceObject.owner = jsonObject.get(AccountBalanceUpdate.KEY_OWNER).getAsString(); balanceObject.asset_type = jsonObject.get(AccountBalanceUpdate.KEY_ASSET_TYPE).getAsString(); balanceObject.balance = jsonObject.get(AccountBalanceUpdate.KEY_BALANCE).getAsLong(); + objectMap.put(ObjectType.ACCOUNT_BALANCE_OBJECT, true); secondArgument.add(balanceObject); }else if(grapheneObject.getObjectType() == ObjectType.DYNAMIC_GLOBAL_PROPERTY_OBJECT){ - DynamicGlobalProperties dynamicGlobal = new DynamicGlobalProperties(grapheneObject.getObjectId()); - dynamicGlobal.head_block_number = jsonObject.get(DynamicGlobalProperties.KEY_HEAD_BLOCK_NUMBER).getAsLong(); - dynamicGlobal.head_block_id = jsonObject.get(DynamicGlobalProperties.KEY_HEAD_BLOCK_ID).getAsString(); - dynamicGlobal.time = jsonObject.get(DynamicGlobalProperties.KEY_TIME).getAsString(); - //TODO: Deserialize all other attributes - secondArgument.add(dynamicGlobal); + DynamicGlobalProperties dynamicGlobalProperties = context.deserialize(object, DynamicGlobalProperties.class); + objectMap.put(ObjectType.DYNAMIC_GLOBAL_PROPERTY_OBJECT, true); + secondArgument.add(dynamicGlobalProperties); }else if(grapheneObject.getObjectType() == ObjectType.TRANSACTION_OBJECT){ BroadcastedTransaction broadcastedTransaction = new BroadcastedTransaction(grapheneObject.getObjectId()); broadcastedTransaction.setTransaction((Transaction) context.deserialize(jsonObject.get(BroadcastedTransaction.KEY_TRX), Transaction.class)); broadcastedTransaction.setTransactionId(jsonObject.get(BroadcastedTransaction.KEY_TRX_ID).getAsString()); + objectMap.put(ObjectType.TRANSACTION_OBJECT, true); secondArgument.add(broadcastedTransaction); }else{ //TODO: Add support for other types of objects @@ -148,7 +166,11 @@ public class SubscriptionResponse { } } for(SubscriptionListener listener : mListeners){ - listener.onSubscriptionUpdate(response); + // Only notify the listener if there is an object of interest in + // this notification + if(objectMap.containsKey(listener.getInterestObjectType())){ + listener.onSubscriptionUpdate(response); + } } return response; } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/WitnessResponse.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/WitnessResponse.java index 3e5e7da..0f7dc78 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/WitnessResponse.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/models/WitnessResponse.java @@ -4,5 +4,8 @@ package de.bitsharesmunich.graphenej.models; * Generic witness response */ public class WitnessResponse extends BaseResponse{ + public static final String KEY_ID = "id"; + public static final String KEY_RESULT = "result"; + public T result; } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/AccountUpdateOperation.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/AccountUpdateOperation.java index 5abe334..5798f2e 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/AccountUpdateOperation.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/AccountUpdateOperation.java @@ -24,7 +24,6 @@ public class AccountUpdateOperation extends BaseOperation { private Optional owner; private Optional active; private Optional new_options; - private Extensions extensions; /** * Account update operation constructor. diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/LimitOrderCreateOperation.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/LimitOrderCreateOperation.java index 7b60c70..195682a 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/LimitOrderCreateOperation.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/LimitOrderCreateOperation.java @@ -2,15 +2,25 @@ package de.bitsharesmunich.graphenej.operations; import com.google.common.primitives.Bytes; import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import de.bitsharesmunich.graphenej.*; +import com.google.gson.JsonParseException; +import java.lang.reflect.Type; import java.nio.ByteBuffer; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; +import de.bitsharesmunich.graphenej.AssetAmount; +import de.bitsharesmunich.graphenej.BaseOperation; +import de.bitsharesmunich.graphenej.OperationType; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.Util; + /** * Operation used to denote the creation of a limit order on the blockchain. * @@ -88,6 +98,48 @@ public class LimitOrderCreateOperation extends BaseOperation { this.fee = assetAmount; } + public AssetAmount getFee(){ return this.fee; } + + public UserAccount getSeller() { + return seller; + } + + public void setSeller(UserAccount seller) { + this.seller = seller; + } + + public AssetAmount getAmountToSell() { + return amountToSell; + } + + public void setAmountToSell(AssetAmount amountToSell) { + this.amountToSell = amountToSell; + } + + public AssetAmount getMinToReceive() { + return minToReceive; + } + + public void setMinToReceive(AssetAmount minToReceive) { + this.minToReceive = minToReceive; + } + + public int getExpiration() { + return expiration; + } + + public void setExpiration(int expiration) { + this.expiration = expiration; + } + + public boolean isFillOrKill() { + return fillOrKill; + } + + public void setFillOrKill(boolean fillOrKill) { + this.fillOrKill = fillOrKill; + } + @Override public byte[] toBytes() { byte[] feeBytes = this.fee.toBytes(); @@ -104,4 +156,78 @@ public class LimitOrderCreateOperation extends BaseOperation { return Bytes.concat(feeBytes, sellerBytes, amountBytes, minAmountBytes, expirationBytes, fillOrKill, extensions); } + + /** + * Deserializer used to convert the JSON-formatted representation of a limit_order_create_operation + * into its java object version. + * + * The following is an example of the serialized form of this operation: + * + * [ + * 1, + * { + * "fee": { + * "amount": 14676, + * "asset_id": "1.3.0" + * }, + * "seller": "1.2.36449", + * "amount_to_sell": { + * "amount": 945472, + * "asset_id": "1.3.850" + * }, + * "min_to_receive": { + * "amount": 4354658, + * "asset_id": "1.3.861" + * }, + * "expiration": "1963-11-25T06:31:44", + * "fill_or_kill": false, + * "extensions": [] + * } + * ] + * + * + */ + public static class LimitOrderCreateDeserializer implements JsonDeserializer { + + @Override + public LimitOrderCreateOperation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if(json.isJsonArray()){ + // This block is used just to check if we are in the first step of the deserialization + // when we are dealing with an array. + JsonArray serializedTransfer = json.getAsJsonArray(); + if(serializedTransfer.get(0).getAsInt() != OperationType.LIMIT_ORDER_CREATE_OPERATION.ordinal()){ + // If the operation type does not correspond to a transfer operation, we return null + return null; + }else{ + // Calling itself recursively, this is only done once, so there will be no problems. + return context.deserialize(serializedTransfer.get(1), LimitOrderCreateOperation.class); + } + }else{ + // This block is called in the second recursion and takes care of deserializing the + // limit order data itself. + JsonObject jsonObject = json.getAsJsonObject(); + + AssetAmount fee = context.deserialize(jsonObject.get(KEY_FEE), AssetAmount.class); + UserAccount seller = context.deserialize(jsonObject.get(KEY_SELLER), UserAccount.class); + AssetAmount amountToSell = context.deserialize(jsonObject.get(KEY_AMOUNT_TO_SELL), AssetAmount.class); + AssetAmount minToReceive = context.deserialize(jsonObject.get(KEY_MIN_TO_RECEIVE), AssetAmount.class); + String expiration = jsonObject.get(KEY_EXPIRATION).getAsString(); + boolean fillOrKill = jsonObject.get(KEY_FILL_OR_KILL).getAsBoolean(); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT); + int expirationPosix = 0; + try { + Date expirationDate = simpleDateFormat.parse(expiration); + expirationPosix = (int) (expirationDate.getTime() / 1000); + } catch (ParseException e) { + e.printStackTrace(); + } + + // Creating an instance of the LimitOrderCreateOperation and setting the fee + LimitOrderCreateOperation operation = new LimitOrderCreateOperation(seller, amountToSell, minToReceive, expirationPosix, fillOrKill); + operation.setFee(fee); + return operation; + } + } + } } diff --git a/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/TransferOperation.java b/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/TransferOperation.java index 882c584..8eee847 100644 --- a/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/TransferOperation.java +++ b/graphenej/src/main/java/de/bitsharesmunich/graphenej/operations/TransferOperation.java @@ -1,14 +1,23 @@ package de.bitsharesmunich.graphenej.operations; +import com.google.common.primitives.Bytes; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; + import de.bitsharesmunich.graphenej.AssetAmount; import de.bitsharesmunich.graphenej.BaseOperation; import de.bitsharesmunich.graphenej.OperationType; import de.bitsharesmunich.graphenej.UserAccount; import de.bitsharesmunich.graphenej.objects.Memo; -import com.google.common.primitives.Bytes; -import com.google.gson.*; - -import java.lang.reflect.Type; /** * Class used to encapsulate the TransferOperation operation related functionalities. @@ -70,6 +79,14 @@ public class TransferOperation extends BaseOperation { this.to = to; } + public void setMemo(Memo memo) { + this.memo = memo; + } + + public Memo getMemo() { + return this.memo; + } + @Override public void setFee(AssetAmount newFee){ this.fee = newFee; @@ -110,10 +127,6 @@ public class TransferOperation extends BaseOperation { return array; } - public void setMemo(Memo memo) { - this.memo = memo; - } - public static class TransferSerializer implements JsonSerializer { @Override diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/AuthorityTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/AuthorityTest.java index cc9846d..eb34c17 100644 --- a/graphenej/src/test/java/de/bitsharesmunich/graphenej/AuthorityTest.java +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/AuthorityTest.java @@ -1,15 +1,12 @@ package de.bitsharesmunich.graphenej; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.HashMap; -import java.util.InputMismatchException; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; /** * Created by nelson on 12/16/16. @@ -25,19 +22,19 @@ public class AuthorityTest { public void setUp() throws Exception { authority = new Authority(); sameAuthority = new Authority(); - HashMap accountAuthorityMap = new HashMap<>(); + HashMap accountAuthorityMap = new HashMap<>(); UserAccount userAccount = new UserAccount("1.2.20000"); - accountAuthorityMap.put(userAccount, 1); + accountAuthorityMap.put(userAccount, 1l); differentAuthority = new Authority(1, null, accountAuthorityMap); Address address1 = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY"); Address address2 = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY"); PublicKey publicKey = address1.getPublicKey(); PublicKey samePublicKey = address2.getPublicKey(); - HashMap keyMap1 = new HashMap<>(); - HashMap keyMap2 = new HashMap<>(); - keyMap1.put(publicKey, 1); - keyMap2.put(samePublicKey, 1); + HashMap keyMap1 = new HashMap<>(); + HashMap keyMap2 = new HashMap<>(); + keyMap1.put(publicKey, 1l); + keyMap2.put(samePublicKey, 1l); keyAuthority1 = new Authority(1, keyMap1, null); keyAuthority2 = new Authority(1, keyMap2, null); diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/BrainKeyTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/BrainKeyTest.java new file mode 100644 index 0000000..a534eb5 --- /dev/null +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/BrainKeyTest.java @@ -0,0 +1,27 @@ +package de.bitsharesmunich.graphenej; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; + +/** + * Created by nelson on 4/18/17. + */ +public class BrainKeyTest { + public final String TEST_BRAINKEY = "BARIC BICKERN LITZ TIPFUL JINGLED POOL TUMBAK PURIST APOPYLE DURAIN SATLIJK FAUCAL"; + private BrainKey mBrainKey; + + @Before + public void setup(){ + mBrainKey = new BrainKey(TEST_BRAINKEY, BrainKey.DEFAULT_SEQUENCE_NUMBER); + } + + @Test + public void testAddress(){ + Address address = mBrainKey.getPublicAddress(Address.BITSHARES_PREFIX); + Assert.assertEquals("Assert that the address created is the expected one", + "BTS61UqqgE3ARuTGcckzARsdQm4EMFdBEwYyi1pbwyHrZZWrCDhT2", + address.toString()); + } +} \ No newline at end of file diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/ObjectTypeTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/ObjectTypeTest.java new file mode 100644 index 0000000..915c313 --- /dev/null +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/ObjectTypeTest.java @@ -0,0 +1,26 @@ +package de.bitsharesmunich.graphenej; + +import junit.framework.Assert; + +import org.junit.Test; + +/** + * Created by nelson on 5/5/17. + */ +public class ObjectTypeTest { + + @Test + public void getGenericObjectId() throws Exception { + ObjectType baseObject = ObjectType.BASE_OBJECT; + ObjectType accountObject = ObjectType.ACCOUNT_OBJECT; + ObjectType forceSettlementObject = ObjectType.FORCE_SETTLEMENT_OBJECT; + ObjectType globalPropertiesObject = ObjectType.GLOBAL_PROPERTY_OBJECT; + ObjectType specialAuthorityObject = ObjectType.SPECIAL_AUTHORITY_OBJECT; + + Assert.assertEquals("1.1.0", baseObject.getGenericObjectId()); + Assert.assertEquals("1.2.0", accountObject.getGenericObjectId()); + Assert.assertEquals("1.4.0", forceSettlementObject.getGenericObjectId()); + Assert.assertEquals("2.0.0", globalPropertiesObject.getGenericObjectId()); + Assert.assertEquals("2.14.0", specialAuthorityObject.getGenericObjectId()); + } +} \ No newline at end of file diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/BaseApiTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/BaseApiTest.java new file mode 100644 index 0000000..0a2f24f --- /dev/null +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/BaseApiTest.java @@ -0,0 +1,33 @@ +package de.bitsharesmunich.graphenej.api; + +import com.neovisionaries.ws.client.WebSocket; +import com.neovisionaries.ws.client.WebSocketFactory; + +import org.junit.Before; + +import javax.net.ssl.SSLContext; + +import de.bitsharesmunich.graphenej.test.NaiveSSLContext; + +/** + * Created by nelson on 4/14/17. + */ + +public class BaseApiTest { + protected String BLOCK_PAY_DE = System.getenv("OPENLEDGER_EU"); + + protected SSLContext context; + protected WebSocket mWebSocket; + + @Before + public void setUp() throws Exception { + context = NaiveSSLContext.getInstance("TLS"); + WebSocketFactory factory = new WebSocketFactory(); + + // Set the custom SSL context. + factory.setSSLContext(context); + + mWebSocket = factory.createSocket(BLOCK_PAY_DE); + } + +} diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetKeyReferencesTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetKeyReferencesTest.java new file mode 100644 index 0000000..c774973 --- /dev/null +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetKeyReferencesTest.java @@ -0,0 +1,81 @@ +package de.bitsharesmunich.graphenej.api; + +import com.neovisionaries.ws.client.WebSocketException; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import de.bitsharesmunich.graphenej.Address; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.errors.MalformedAddressException; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.BaseResponse; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + +/** + * Created by nelson on 4/14/17. + */ +public class GetKeyReferencesTest extends BaseApiTest { + + private String[] publicKeys = new String[] { + "BTS8DuGHXpHYedq7qhT65BEEdQPvLT8nxZ862Hf8NgvSZUMuwUFkn", + "BTS53ehf9Qoeg9o4E1KuxdZRXCVg3Z9ApbEDHVdQhERDJDEFkPkGs" + }; + + @Test + public void testGetKeyReferences(){ + ArrayList
addresses = new ArrayList<>(); + for(String addr : publicKeys){ + try { + Address address = new Address(addr); + addresses.add(address); + } catch (MalformedAddressException e) { + System.out.println("MalformedAddressException. Msg: "+e.getMessage()); + } + } + mWebSocket.addListener(new GetKeyReferences(addresses, new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + int counter = 0; + List> accountListList = (List>) response.result; + for(List accountList : accountListList){ + for(UserAccount userAccount : accountList){ + System.out.println("User account: "+userAccount.getObjectId()); + } + if(accountList.size() > 1){ + System.out.println("Key with address: "+publicKeys[counter]+" controls more than one role in account: "+accountList.get(0).getObjectId()); + }else if(accountList.size() == 1){ + System.out.println("Key with address: "+publicKeys[counter]+" controls just one role in account: "+accountList.get(0).getObjectId()); + } + counter++; + } + synchronized (GetKeyReferencesTest.this){ + GetKeyReferencesTest.this.notifyAll(); + } + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError. Msg: "+error.message); + + synchronized (GetKeyReferencesTest.this){ + GetKeyReferencesTest.this.notifyAll(); + } + } + })); + + try{ + mWebSocket.connect(); + synchronized (this){ + wait(); + } + } catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (InterruptedException e) { + System.out.println("InterruptedException. Msg: "+e.getMessage()); + } + } +} \ No newline at end of file diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetLimitOrdersTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetLimitOrdersTest.java index f23fbe0..74b9764 100644 --- a/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetLimitOrdersTest.java +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetLimitOrdersTest.java @@ -1,70 +1,67 @@ package de.bitsharesmunich.graphenej.api; -import com.neovisionaries.ws.client.WebSocket; +import com.google.common.primitives.UnsignedLong; import com.neovisionaries.ws.client.WebSocketException; -import com.neovisionaries.ws.client.WebSocketFactory; import org.junit.After; -import org.junit.Before; +import org.junit.Assert; import org.junit.Test; -import java.io.IOException; -import java.security.NoSuchAlgorithmException; import java.util.List; -import javax.net.ssl.SSLContext; - import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.AssetAmount; import de.bitsharesmunich.graphenej.Converter; import de.bitsharesmunich.graphenej.LimitOrder; +import de.bitsharesmunich.graphenej.OrderBook; +import de.bitsharesmunich.graphenej.UserAccount; import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; import de.bitsharesmunich.graphenej.models.BaseResponse; import de.bitsharesmunich.graphenej.models.WitnessResponse; -import de.bitsharesmunich.graphenej.test.NaiveSSLContext; +import de.bitsharesmunich.graphenej.operations.LimitOrderCreateOperation; + +import static org.hamcrest.CoreMatchers.is; /** * Created by nelson on 3/24/17. */ -public class GetLimitOrdersTest { - private String BLOCK_PAY_DE = System.getenv("BLOCKPAY_DE"); - private final Asset base = new Asset("1.3.120", "EUR", 4); - private final Asset quote = new Asset("1.3.121", "USD", 4); - - - @Before - public void setUp() throws Exception { - - } +public class GetLimitOrdersTest extends BaseApiTest { + private UserAccount seller = new UserAccount("1.2.143563"); + private final Asset base = new Asset("1.3.121", "USD", 4); + private final Asset quote = new Asset("1.3.0", "BTS", 5); @Test public void testGetLimitOrders(){ - SSLContext context = null; try { - context = NaiveSSLContext.getInstance("TLS"); - WebSocketFactory factory = new WebSocketFactory(); - - // Set the custom SSL context. - factory.setSSLContext(context); - - WebSocket mWebSocket = factory.createSocket(BLOCK_PAY_DE); - mWebSocket.addListener(new GetLimitOrders(base.getObjectId(), quote.getObjectId(), 100, new WitnessResponseListener() { @Override public void onSuccess(WitnessResponse response) { List orders = (List) response.result; + Assert.assertThat("Checking that we have orders", orders.isEmpty(), is(false)); Converter converter = new Converter(); - System.out.println(); - for(LimitOrder order : orders){ - order.getSellPrice().base.getAsset().setPrecision(base.getPrecision()); - order.getSellPrice().quote.getAsset().setPrecision(quote.getPrecision()); - double baseToQuoteExchange = converter.getConversionRate(order.getSellPrice(), Converter.BASE_TO_QUOTE); - double quoteToBaseExchange = converter.getConversionRate(order.getSellPrice(), Converter.QUOTE_TO_BASE); - System.out.println(String.format("base to quote: %.5f, quote to base: %.5f", baseToQuoteExchange, quoteToBaseExchange)); + double baseToQuoteExchange, quoteToBaseExchange; - synchronized (GetLimitOrdersTest.this){ - GetLimitOrdersTest.this.notifyAll(); + for(LimitOrder order : orders){ + if(order.getSellPrice().base.getAsset().getObjectId().equals(base.getObjectId())){ + order.getSellPrice().base.getAsset().setPrecision(base.getPrecision()); + order.getSellPrice().quote.getAsset().setPrecision(quote.getPrecision()); + + baseToQuoteExchange = converter.getConversionRate(order.getSellPrice(), Converter.BASE_TO_QUOTE); + quoteToBaseExchange = converter.getConversionRate(order.getSellPrice(), Converter.QUOTE_TO_BASE); + System.out.println(String.format("> id: %s, base to quote: %.5f, quote to base: %.5f", order.getObjectId(), baseToQuoteExchange, quoteToBaseExchange)); + }else{ + order.getSellPrice().base.getAsset().setPrecision(quote.getPrecision()); + order.getSellPrice().quote.getAsset().setPrecision(base.getPrecision()); + + baseToQuoteExchange = converter.getConversionRate(order.getSellPrice(), Converter.BASE_TO_QUOTE); + quoteToBaseExchange = converter.getConversionRate(order.getSellPrice(), Converter.QUOTE_TO_BASE); + System.out.println(String.format("< id: %s, base to quote: %.5f, quote to base: %.5f", order.getObjectId(), baseToQuoteExchange, quoteToBaseExchange)); } } + + synchronized (GetLimitOrdersTest.this){ + GetLimitOrdersTest.this.notifyAll(); + } } @Override @@ -75,18 +72,64 @@ public class GetLimitOrdersTest { } } })); + mWebSocket.connect(); - System.out.println("Waiting.."); + synchronized (this){ wait(); } - System.out.println("Released!"); - } catch (NoSuchAlgorithmException e) { - System.out.println("NoSuchAlgorithmException. Msg: " + e.getMessage()); } catch (WebSocketException e) { System.out.println("WebSocketException. Msg: " + e.getMessage()); - } catch (IOException e) { - System.out.println("IOException. Msg: " + e.getMessage()); + } catch (InterruptedException e) { + System.out.println("InterruptedException. Msg: "+e.getMessage()); + } + } + + /** + * This method is designed to test how the OrderBook class handles data obtained + * from the GetLimitOrders API call. + */ + @Test + public void testOrderBook(){ + LimitOrderCreateOperation limitOrderOperation; + + try { + mWebSocket.addListener(new GetLimitOrders(base.getObjectId(), quote.getObjectId(), 100, new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + List orders = (List) response.result; + OrderBook orderBook = new OrderBook(orders); + + AssetAmount toBuy = new AssetAmount(UnsignedLong.valueOf(100000), quote); + int expiration = (int) ((System.currentTimeMillis() + 60000) / 1000); + LimitOrderCreateOperation operation = orderBook.exchange(seller, base, toBuy, expiration); + + // Testing the successfull creation of a limit order create operation + Assert.assertTrue(operation != null); + double price = (double) Math.pow(10, base.getPrecision() - quote.getPrecision()) * operation.getMinToReceive().getAmount().longValue() / operation.getAmountToSell().getAmount().longValue(); + System.out.println("price: "+price); + synchronized (GetLimitOrdersTest.this){ + GetLimitOrdersTest.this.notifyAll(); + } + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError. Msg: "+error.message); + synchronized (GetLimitOrdersTest.this){ + GetLimitOrdersTest.this.notifyAll(); + } + } + })); + + mWebSocket.connect(); + + synchronized (this){ + wait(); + } + + } catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); } catch (InterruptedException e) { System.out.println("InterruptedException. Msg: "+e.getMessage()); } @@ -94,7 +137,6 @@ public class GetLimitOrdersTest { @After public void tearDown() throws Exception { - + mWebSocket.disconnect(); } - } \ No newline at end of file diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetObjectsTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetObjectsTest.java new file mode 100644 index 0000000..2e36a17 --- /dev/null +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/GetObjectsTest.java @@ -0,0 +1,141 @@ +package de.bitsharesmunich.graphenej.api; + +import com.neovisionaries.ws.client.WebSocketException; + +import junit.framework.Assert; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.GrapheneObject; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.BaseResponse; +import de.bitsharesmunich.graphenej.models.BitAssetData; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + +/** + * Testing the {@link GetObjects} API wrapper and its deserialization + * + * Created by nelson on 5/10/17. + */ +public class GetObjectsTest extends BaseApiTest{ + private final Asset asset = new Asset("1.3.0", "BTS", 5); + private final UserAccount account = new UserAccount("1.2.116354"); + private final UserAccount bilthon_25 = new UserAccount("1.2.151069"); + private final String bitAssetId = "2.4.13"; + + @Test + public void testGetAsset(){ + try{ + ArrayList ids = new ArrayList<>(); + ids.add(asset.getObjectId()); + mWebSocket.addListener(new GetObjects(ids, new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + List result = (List) response.result; + System.out.println("Got " + result.size() + " result"); + Assert.assertEquals("Making sure we only get one address back", 1, result.size()); + synchronized (GetObjectsTest.this){ + GetObjectsTest.this.notifyAll(); + } + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError"); + synchronized (GetObjectsTest.this){ + GetObjectsTest.this.notifyAll(); + } + } + })); + + mWebSocket.connect(); + synchronized (this){ + wait(); + } + }catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (InterruptedException e) { + System.out.println("InterruptedException. Msg: "+e.getMessage()); + } + } + + @Test + public void testGetAccount(){ + try{ + ArrayList ids = new ArrayList<>(); + ids.add(bilthon_25.getObjectId()); + mWebSocket.addListener(new GetObjects(ids, new WitnessResponseListener() { + + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + List result = (List) response.result; + UserAccount userAccount = (UserAccount) result.get(0); + System.out.println("Account name.....: "+userAccount.getName()); + System.out.println("json string......: "+userAccount.toJsonString()); + System.out.println("owner............: "+userAccount.getOwner().getKeyAuthList().get(0).getAddress()); + System.out.println("active key.......: "+userAccount.getActive().getKeyAuthList().get(0).getAddress()); + System.out.println("active account...: "+userAccount.getActive().getAccountAuthList().get(0).getObjectId()); + System.out.println("memo: "+userAccount.getOptions().getMemoKey().getAddress()); + synchronized (GetObjectsTest.this){ + GetObjectsTest.this.notifyAll(); + } + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError"); + synchronized (GetObjectsTest.this){ + GetObjectsTest.this.notifyAll(); + } + } + })); + + mWebSocket.connect(); + synchronized (this){ + wait(); + } + }catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (InterruptedException e) { + System.out.println("InterruptedException. Msg: "+e.getMessage()); + } + } + + @Test + public void testBitAssetData(){ + try{ + ArrayList ids = new ArrayList<>(); + ids.add(bitAssetId); + mWebSocket.addListener(new GetObjects(ids, new WitnessResponseListener() { + + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + List list = (List) response.result; + BitAssetData bitAssetData = (BitAssetData) list.get(0); + System.out.println("feed time: " + bitAssetData.current_feed_publication_time); + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError"); + } + })); + + mWebSocket.connect(); + synchronized (this){ + wait(); + } + }catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (InterruptedException e) { + System.out.println("InterruptedException. Msg: "+e.getMessage()); + } } +} \ No newline at end of file diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/SubscriptionMessagesHubTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/SubscriptionMessagesHubTest.java new file mode 100644 index 0000000..0311180 --- /dev/null +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/api/SubscriptionMessagesHubTest.java @@ -0,0 +1,162 @@ +package de.bitsharesmunich.graphenej.api; + +import com.neovisionaries.ws.client.WebSocketException; + +import org.junit.Test; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import de.bitsharesmunich.graphenej.ObjectType; +import de.bitsharesmunich.graphenej.Transaction; +import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.BaseResponse; +import de.bitsharesmunich.graphenej.models.BroadcastedTransaction; +import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties; +import de.bitsharesmunich.graphenej.models.SubscriptionResponse; +import de.bitsharesmunich.graphenej.models.WitnessResponse; + +/** + * Created by nelson on 4/25/17. + */ +public class SubscriptionMessagesHubTest extends BaseApiTest { + + private SubscriptionMessagesHub mMessagesHub; + private WitnessResponseListener mErrorListener = new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError"); + } + }; + + @Test + public void testGlobalPropertiesDeserializer(){ + ArrayList interestingObjects = new ArrayList(); + interestingObjects.add(ObjectType.TRANSACTION_OBJECT); + interestingObjects.add(ObjectType.DYNAMIC_GLOBAL_PROPERTY_OBJECT); + try{ + mMessagesHub = new SubscriptionMessagesHub("", "", interestingObjects, mErrorListener); + mMessagesHub.addSubscriptionListener(new SubscriptionListener() { + private int MAX_MESSAGES = 10; + private int messageCounter = 0; + + @Override + public ObjectType getInterestObjectType() { + return ObjectType.DYNAMIC_GLOBAL_PROPERTY_OBJECT; + } + + @Override + public void onSubscriptionUpdate(SubscriptionResponse response) { + System.out.println("On block"); + if(response.params.size() == 2){ + try{ + List payload = (List) response.params.get(1); + if(payload.size() > 0 && payload.get(0) instanceof DynamicGlobalProperties){ + DynamicGlobalProperties globalProperties = (DynamicGlobalProperties) payload.get(0); +// System.out.println("time.....................: "+globalProperties.time); +// System.out.println("next_maintenance_time....: "+globalProperties.next_maintenance_time); +// System.out.println("recent_slots_filled......: "+globalProperties.recent_slots_filled); + } + }catch(Exception e){ + System.out.println("Exception"); + System.out.println("Type: "+e.getClass()); + System.out.println("Msg: "+e.getMessage()); + } + } + // Waiting for MAX_MESSAGES messages before releasing the wait lock + messageCounter++; + if(messageCounter > MAX_MESSAGES){ + synchronized (SubscriptionMessagesHubTest.this){ + SubscriptionMessagesHubTest.this.notifyAll(); + } + } + } + }); + + mMessagesHub.addSubscriptionListener(new SubscriptionListener() { + @Override + public ObjectType getInterestObjectType() { + return ObjectType.TRANSACTION_OBJECT; + } + + @Override + public void onSubscriptionUpdate(SubscriptionResponse response) { + System.out.println("onTx"); + } + }); + mWebSocket.addListener(mMessagesHub); + mWebSocket.connect(); + + // Holding this thread while we get update notifications + synchronized (this){ + wait(); + } + } catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (InterruptedException e) { + System.out.println("InterruptedException. Msg: "+e.getMessage()); + } + } + + /** + * This is a basic test that will only display a count of operations per received broadcasted transactions. + */ + @Test + public void testBroadcastedTransactionDeserializer(){ + try{ + mMessagesHub = new SubscriptionMessagesHub("", "", mErrorListener); + mMessagesHub.addSubscriptionListener(new SubscriptionListener() { + private int MAX_MESSAGES = 15; + private int messageCounter = 0; + + @Override + public ObjectType getInterestObjectType() { + return ObjectType.TRANSACTION_OBJECT; + } + + @Override + public void onSubscriptionUpdate(SubscriptionResponse response) { + if(response.params.size() == 2){ + List payload = (List) response.params.get(1); + if(payload.size() > 0){ + for(Serializable item : payload){ + if(item instanceof BroadcastedTransaction){ + BroadcastedTransaction broadcastedTransaction = (BroadcastedTransaction) item; + Transaction tx = broadcastedTransaction.getTransaction(); + System.out.println(String.format("Got %d operations", tx.getOperations().size())); + } + } + } + } + + // Waiting for MAX_MESSAGES messages before releasing the wait lock + messageCounter++; + if(messageCounter > MAX_MESSAGES){ + synchronized (SubscriptionMessagesHubTest.this){ + SubscriptionMessagesHubTest.this.notifyAll(); + } + } + } + }); + + mWebSocket.addListener(mMessagesHub); + mWebSocket.connect(); + + // Holding this thread while we get update notifications + synchronized (this){ + wait(); + } + } catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (InterruptedException e) { + System.out.println("InterruptedException. Msg: "+e.getMessage()); + } + } +} \ No newline at end of file diff --git a/graphenej/src/test/java/de/bitsharesmunich/graphenej/operations/AccountUpdateOperationTest.java b/graphenej/src/test/java/de/bitsharesmunich/graphenej/operations/AccountUpdateOperationTest.java new file mode 100644 index 0000000..61ff0d1 --- /dev/null +++ b/graphenej/src/test/java/de/bitsharesmunich/graphenej/operations/AccountUpdateOperationTest.java @@ -0,0 +1,80 @@ +package de.bitsharesmunich.graphenej.operations; + +import com.google.common.primitives.UnsignedLong; + +import org.bitcoinj.core.ECKey; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; + +import de.bitsharesmunich.graphenej.AccountOptions; +import de.bitsharesmunich.graphenej.Address; +import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.AssetAmount; +import de.bitsharesmunich.graphenej.Authority; +import de.bitsharesmunich.graphenej.BaseOperation; +import de.bitsharesmunich.graphenej.BlockData; +import de.bitsharesmunich.graphenej.BrainKey; +import de.bitsharesmunich.graphenej.PublicKey; +import de.bitsharesmunich.graphenej.Transaction; +import de.bitsharesmunich.graphenej.UserAccount; +import de.bitsharesmunich.graphenej.Util; +import de.bitsharesmunich.graphenej.errors.MalformedAddressException; + +/** + * Created by nelson on 4/18/17. + */ +public class AccountUpdateOperationTest { + + private static final String BILTHON_16_BRAIN_KEY = "SOAPILY GASSING FIFIE OZONATE WHYO TOPLINE PRISMY ZEUGMA GLOTTIC DAVEN CORODY PFUI"; + public final String ADDRESS = "BTS8RYD5ehEMtTrfmeWRVKJzvLK2AqunxRh2XhXyXVxKtDjeAhYs1"; + + private final Asset CORE = new Asset("1.3.0"); + + private Authority active; + private AccountOptions options; + + @Before + public void setup(){ + try{ + HashMap keyAuth = new HashMap<>(); + keyAuth.put(new Address(ADDRESS), 1l); + active = new Authority(); + active.setKeyAuthorities(keyAuth); + + options = new AccountOptions(); + options.setMemoKey(new PublicKey(ECKey.fromPublicOnly(new Address(ADDRESS).getPublicKey().toBytes()))); + options.setNumWitness(0); + options.setNum_comittee(0); + options.setVotingAccount(new UserAccount("1.2.5")); + }catch(MalformedAddressException e){ + System.out.println("MalformedAddressException. Msg: "+e.getMessage()); + } + } + + @Test + public void testOperationSerialization(){ + AccountUpdateOperationBuilder builder = new AccountUpdateOperationBuilder() + .setAccount(new UserAccount("1.2.143569")) + .setFee(new AssetAmount(UnsignedLong.valueOf(14676), CORE)) + .setActive(active) + .setOptions(options); + + AccountUpdateOperation operation = builder.build(); + + ArrayList operations = new ArrayList<>(); + operations.add(operation); + ECKey privateKey = new BrainKey(BILTHON_16_BRAIN_KEY, 0).getPrivateKey(); + BlockData blockData = new BlockData(3703, 2015738269, 1492551764); + + Transaction tx = new Transaction(privateKey, blockData, operations); + +// String json = tx.toJsonString(); + byte[] serialized = tx.toBytes(); + +// System.out.println("json: "+json); + System.out.println("serialized: "+ Util.bytesToHex(serialized)); + } +} \ No newline at end of file