Create synchronizer and add layer of business logic onto the data layer
App is functional and displays transactions
This commit is contained in:
parent
1501f1a7d2
commit
6c869a47df
64
build.gradle
64
build.gradle
|
@ -5,8 +5,10 @@ buildscript {
|
|||
'targetSdkVersion': 28
|
||||
]
|
||||
ext.versions = [
|
||||
'architectureComponents': '2.0.0',
|
||||
'grpc':'1.17.1',
|
||||
'kotlin': '1.3.10',
|
||||
'architectureComponents': '2.0.0'
|
||||
'coroutines': '1.1.0'
|
||||
]
|
||||
repositories {
|
||||
google()
|
||||
|
@ -17,6 +19,7 @@ buildscript {
|
|||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
classpath "com.github.ben-manes:gradle-versions-plugin:0.20.0"
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
|
||||
classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.7"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +28,7 @@ apply plugin: 'com.android.library'
|
|||
apply plugin: "kotlin-android-extensions"
|
||||
apply plugin: "kotlin-android"
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'com.google.protobuf'
|
||||
apply plugin: 'com.github.ben-manes.versions'
|
||||
apply plugin: 'com.github.dcendents.android-maven'
|
||||
|
||||
|
@ -34,6 +38,7 @@ version = '1.2.4'
|
|||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -42,9 +47,10 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
versionCode = 1_02_03
|
||||
versionName = "1.2.3"
|
||||
versionCode = 1_03_00
|
||||
versionName = "1.3.0"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled false
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -56,7 +62,10 @@ android {
|
|||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDirs "build/generated/source/wire"
|
||||
srcDirs "build/generated/source/grpc"
|
||||
}
|
||||
proto {
|
||||
srcDir 'src/main/proto'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,29 +75,60 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
clean {
|
||||
delete "$project.projectDir/src/generated/source/grpc"
|
||||
}
|
||||
|
||||
|
||||
protobuf {
|
||||
generatedFilesBaseDir = "$projectDir/src/generated/source/grpc"
|
||||
protoc { artifact = 'com.google.protobuf:protoc:3.6.1' }
|
||||
plugins {
|
||||
javalite { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
|
||||
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${versions.grpc}" }
|
||||
}
|
||||
generateProtoTasks {
|
||||
all().each { task ->
|
||||
task.plugins {
|
||||
javalite {}
|
||||
grpc { // Options added to --grpc_out
|
||||
option 'lite' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Square
|
||||
api "com.squareup.wire:wire-runtime:2.2.0"
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
|
||||
// Architecture components
|
||||
implementation "androidx.lifecycle:lifecycle-runtime:${versions.architectureComponents}"
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:${versions.architectureComponents}"
|
||||
implementation "androidx.room:room-runtime:${versions.architectureComponents}"
|
||||
implementation "androidx.room:room-common:${versions.architectureComponents}"
|
||||
kapt "androidx.lifecycle:lifecycle-compiler:${versions.architectureComponents}"
|
||||
kapt "androidx.room:room-compiler:${versions.architectureComponents}"
|
||||
|
||||
// Other
|
||||
// kotlin
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}"
|
||||
implementation "com.android.support:appcompat-v7:28.0.0"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutines}"
|
||||
|
||||
// grpc-java
|
||||
implementation "io.grpc:grpc-okhttp:${versions.grpc}"
|
||||
implementation "io.grpc:grpc-protobuf-lite:${versions.grpc}"
|
||||
implementation "io.grpc:grpc-stub:${versions.grpc}"
|
||||
implementation 'javax.annotation:javax.annotation-api:1.2'
|
||||
|
||||
// Tests
|
||||
testImplementation "junit:junit:4.12"
|
||||
androidTestImplementation "androidx.test:runner:1.1.0"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:3.1.0"
|
||||
androidTestImplementation "androidx.test:core:1.0.0"
|
||||
androidTestImplementation "androidx.test:runner:1.1.1"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:3.1.1"
|
||||
androidTestImplementation "androidx.test:core:1.1.0"
|
||||
androidTestImplementation "androidx.arch.core:core-testing:${versions.architectureComponents}"
|
||||
}
|
||||
|
||||
|
||||
preBuild.dependsOn generateProtobufClasses
|
||||
preBuild.dependsOn includeDirBugFix
|
||||
preBuild.dependsOn copyAllJniLibs
|
|
@ -1,5 +1,6 @@
|
|||
def protoSrcDir = "src/main/proto"
|
||||
def protoDestDir = "build/generated/source/wire"
|
||||
//def protoSrcDir = "src/main/proto"
|
||||
//def protoDestDir = "build/generated/source/grpc"
|
||||
def protoIncludeDir = "build/extracted-include-protos/main"
|
||||
def jniSrcDir = "src/main/rust"
|
||||
def jniDestDir = "build/rust/target"
|
||||
|
||||
|
@ -11,36 +12,64 @@ def libArm64Dir = "src/main/jniLibs/arm64-v8a"
|
|||
def libArmeabiFile = "build/rust/target/armv7-linux-androideabi/release/$libFile"
|
||||
def libArmeabiDir = "src/main/jniLibs/armeabi-v7a"
|
||||
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath("com.squareup.wire:wire-compiler:2.2.0")
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
//buildscript {
|
||||
// dependencies {
|
||||
// classpath("com.squareup.wire:wire-compiler:2.2.0")
|
||||
// }
|
||||
// repositories {
|
||||
// mavenCentral()
|
||||
// }
|
||||
//}
|
||||
|
||||
tasks.register("generateProtobufClasses") {
|
||||
//tasks.register("generateGrpcClasses") {
|
||||
// doFirst {
|
||||
// println("**** CREATING PROTOS ****")
|
||||
// delete(protoDestDir)
|
||||
// mkdir(protoDestDir)
|
||||
// }
|
||||
// description = "Generate Java classes from protocol buffer (.proto) schema files for use with grpc"
|
||||
//
|
||||
// fileTree(dir: protoSrcDir, include: '**/*.proto').each { File file ->
|
||||
// doLast {
|
||||
// javaexec {
|
||||
// main = "com.squareup.wire.WireCompiler"
|
||||
// classpath = buildscript.configurations.classpath
|
||||
// args = ["--proto_path=$protoSrcDir", "--java_out=$protoDestDir", file.path]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// inputs.files(fileTree(dir: protoSrcDir, include: '**/*.proto'))
|
||||
// outputs.files(fileTree(dir: protoDestDir, include: '**'))
|
||||
//}
|
||||
|
||||
//tasks.register("generateProtobufClasses") {
|
||||
// doFirst {
|
||||
// println("**** CREATING PROTOS ****")
|
||||
// delete(protoDestDir)
|
||||
// mkdir(protoDestDir)
|
||||
// }
|
||||
// description = "Generate Java classes from protocol buffer (.proto) schema files for use with Square's Wire library"
|
||||
//
|
||||
// fileTree(dir: protoSrcDir, include: '**/*.proto').each { File file ->
|
||||
// doLast {
|
||||
// javaexec {
|
||||
// main = "com.squareup.wire.WireCompiler"
|
||||
// classpath = buildscript.configurations.classpath
|
||||
// args = ["--proto_path=$protoSrcDir", "--java_out=$protoDestDir", file.path]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// inputs.files(fileTree(dir: protoSrcDir, include: '**/*.proto'))
|
||||
// outputs.files(fileTree(dir: protoDestDir, include: '**'))
|
||||
//}
|
||||
tasks.register("includeDirBugFix") {
|
||||
doFirst {
|
||||
println("**** CREATING PROTOS ****")
|
||||
delete(protoDestDir)
|
||||
mkdir(protoDestDir)
|
||||
mkdir(protoIncludeDir)
|
||||
}
|
||||
description = "Generate Java classes from protocol buffer (.proto) schema files for use with Square's Wire library"
|
||||
|
||||
fileTree(dir: protoSrcDir, include: '**/*.proto').each { File file ->
|
||||
doLast {
|
||||
javaexec {
|
||||
main = "com.squareup.wire.WireCompiler"
|
||||
classpath = buildscript.configurations.classpath
|
||||
args = ["--proto_path=$protoSrcDir", "--java_out=$protoDestDir", file.path]
|
||||
}
|
||||
}
|
||||
}
|
||||
inputs.files(fileTree(dir: protoSrcDir, include: '**/*.proto'))
|
||||
outputs.files(fileTree(dir: protoDestDir, include: '**'))
|
||||
}
|
||||
|
||||
// TODO: run these in paralell with the worker API: https://guides.gradle.org/using-the-worker-api/
|
||||
// note: this will require modifying the build script and having 3 separate calls
|
||||
tasks.register("generateJniLibs") {
|
||||
doFirst {
|
||||
println("**** CREATING JNI LIBS ****")
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package cash.z.wallet.sdk.data
|
||||
|
||||
import android.util.Log
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import kotlinx.coroutines.*
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import rpc.CompactFormats
|
||||
|
||||
class CompactBlockDownloaderTest {
|
||||
@get:Rule
|
||||
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||
|
||||
@Test
|
||||
fun testSynchronizerExists() {
|
||||
assertNotNull(downloader)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBlocks() = runBlocking {
|
||||
msg("about to receive (is the channel Closed? ${downloader.blocks().isClosedForReceive})")
|
||||
val result = downloader.blocks().receive()
|
||||
msg("donezo")
|
||||
assertTrue(printFailure(result), result.isSuccess)
|
||||
}
|
||||
|
||||
private fun printFailure(result: Result<CompactFormats.CompactBlock>): String {
|
||||
return if (result.isFailure) "result failed due to: ${result.exceptionOrNull()!!.let { "$it caused by: ${it.cause}" }}}"
|
||||
else "success"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBlockHeight() = runBlocking {
|
||||
delay(200)
|
||||
val result = downloader.blocks().receive()
|
||||
assertTrue(printFailure(result), result.isSuccess)
|
||||
assertTrue("Unexpected height value", result.getOrThrow().height > 300000)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val job = Job()
|
||||
val testScope = CoroutineScope(Dispatchers.IO + job)
|
||||
val downloader = CompactBlockDownloader(testScope)
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
downloader.start()
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun close() {
|
||||
downloader.stop()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
fun msg(message: String) {
|
||||
Log.e("DBUG", "[${Thread.currentThread().name}] $message")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package cash.z.wallet.sdk.data
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import rpc.CompactFormats
|
||||
|
||||
class SynchronizerTest {
|
||||
@get:Rule
|
||||
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||
|
||||
@Test
|
||||
fun testSynchronizerExists() {
|
||||
assertNotNull(synchronizer)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBlockSaving() {
|
||||
// synchronizer.saveBlocks()
|
||||
}
|
||||
@Test
|
||||
fun testBlockScanning() {
|
||||
Thread.sleep(180000L)
|
||||
}
|
||||
private fun printFailure(result: Result<CompactFormats.CompactBlock>): String {
|
||||
return if (result.isFailure) "result failed due to: ${result.exceptionOrNull()!!.let { "$it caused by: ${it.cause}" }}}"
|
||||
else "success"
|
||||
}
|
||||
|
||||
companion object {
|
||||
val job = Job()
|
||||
val testScope = CoroutineScope(Dispatchers.IO + job)
|
||||
val synchronizer = Synchronizer(ApplicationProvider.getApplicationContext(), testScope)
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
synchronizer.start()
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun close() {
|
||||
synchronizer.stop()
|
||||
testScope.cancel()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package cash.z.wallet.sdk.db
|
||||
|
||||
import android.util.Log
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import cash.z.wallet.sdk.dao.BlockDao
|
||||
import cash.z.wallet.sdk.dao.CompactBlockDao
|
||||
import cash.z.wallet.sdk.dao.NoteDao
|
||||
import cash.z.wallet.sdk.dao.TransactionDao
|
||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||
import cash.z.wallet.sdk.jni.JniConverter
|
||||
import cash.z.wallet.sdk.vo.CompactBlock
|
||||
import io.grpc.ManagedChannel
|
||||
import io.grpc.ManagedChannelBuilder
|
||||
import org.junit.*
|
||||
import org.junit.Assert.*
|
||||
import rpc.CompactTxStreamerGrpc
|
||||
import rpc.Service
|
||||
import rpc.Service.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class GlueIntegrationTest {
|
||||
@get:Rule
|
||||
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||
|
||||
@Test
|
||||
fun testDbExists() {
|
||||
Log.e("tezt", "addData")
|
||||
addData()
|
||||
Log.e("tezt", "scanData")
|
||||
scanData()
|
||||
Log.e("tezt", "checkResults")
|
||||
checkResults()
|
||||
}
|
||||
|
||||
private fun checkResults() {
|
||||
Thread.sleep(15000L)
|
||||
}
|
||||
|
||||
private fun addData() {
|
||||
val result = blockingStub.getBlockRange(
|
||||
BlockRange.newBuilder()
|
||||
.setStart(373070L.toBlockHeight())
|
||||
.setEnd(373085L.toBlockHeight())
|
||||
.build()
|
||||
)
|
||||
while (result.hasNext()) {
|
||||
val compactBlock = result.next()
|
||||
dao.insert(CompactBlock(compactBlock.height.toInt(), compactBlock.toByteArray()))
|
||||
System.err.println("stored block at height: ${compactBlock.height}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanData() {
|
||||
Log.e("tezt", "scanning blocks...")
|
||||
val result = converter.scanBlocks(
|
||||
cacheDbPath,
|
||||
"/data/user/0/cash.z.wallet.sdk.test/databases/data-glue.db",
|
||||
"dummyseed".toByteArray(),
|
||||
373070
|
||||
)
|
||||
System.err.println("done.")
|
||||
}
|
||||
|
||||
fun heightOf(height: Long): Service.BlockID {
|
||||
return BlockID.newBuilder().setHeight(height).build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
// jni
|
||||
val converter: JniConverter = JniConverter()
|
||||
|
||||
// db
|
||||
private lateinit var dao: CompactBlockDao
|
||||
private lateinit var db: CompactBlockDb
|
||||
private const val cacheDbName = "dummy-cache-glue.db"
|
||||
private const val cacheDbPath = "/data/user/0/cash.z.wallet.sdk.test/databases/$cacheDbName"
|
||||
|
||||
// grpc
|
||||
lateinit var blockingStub: CompactTxStreamerGrpc.CompactTxStreamerBlockingStub
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
converter.initLogs()
|
||||
|
||||
val channel = ManagedChannelBuilder.forAddress("10.0.2.2", 9067).usePlaintext().build()
|
||||
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
||||
|
||||
db = Room
|
||||
.databaseBuilder(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
CompactBlockDb::class.java,
|
||||
cacheDbName
|
||||
)
|
||||
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
.apply { dao = complactBlockDao() }
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun close() {
|
||||
db.close()
|
||||
(blockingStub.channel as ManagedChannel).shutdown().awaitTermination(2000L, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package cash.z.wallet.sdk.db
|
||||
|
||||
import android.util.Log
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import cash.z.wallet.sdk.dao.BlockDao
|
||||
import cash.z.wallet.sdk.dao.CompactBlockDao
|
||||
import cash.z.wallet.sdk.dao.NoteDao
|
||||
import cash.z.wallet.sdk.dao.TransactionDao
|
||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||
import cash.z.wallet.sdk.jni.JniConverter
|
||||
import cash.z.wallet.sdk.vo.CompactBlock
|
||||
import io.grpc.ManagedChannel
|
||||
import io.grpc.ManagedChannelBuilder
|
||||
import org.junit.*
|
||||
import org.junit.Assert.*
|
||||
import rpc.CompactTxStreamerGrpc
|
||||
import rpc.Service
|
||||
import rpc.Service.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class GlueSetupIntegrationTest {
|
||||
@get:Rule
|
||||
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||
|
||||
@Test
|
||||
fun testDbExists() {
|
||||
assertNotNull(db)
|
||||
// Log.e("tezt", "addData")
|
||||
// addData()
|
||||
// Log.e("tezt", "scanData")
|
||||
// scanData()
|
||||
// Log.e("tezt", "checkResults")
|
||||
// checkResults()
|
||||
}
|
||||
|
||||
private fun checkResults() {
|
||||
Thread.sleep(15000L)
|
||||
}
|
||||
|
||||
private fun addData() {
|
||||
val result = blockingStub.getBlockRange(
|
||||
BlockRange.newBuilder()
|
||||
.setStart(373070L.toBlockHeight())
|
||||
.setEnd(373085L.toBlockHeight())
|
||||
.build()
|
||||
)
|
||||
while (result.hasNext()) {
|
||||
val compactBlock = result.next()
|
||||
dao.insert(CompactBlock(compactBlock.height.toInt(), compactBlock.toByteArray()))
|
||||
System.err.println("stored block at height: ${compactBlock.height}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanData() {
|
||||
Log.e("tezt", "scanning blocks...")
|
||||
val result = converter.scanBlocks(
|
||||
cacheDbPath,
|
||||
"/data/user/0/cash.z.wallet.sdk.test/databases/data-glue.db",
|
||||
"dummyseed".toByteArray(),
|
||||
373070
|
||||
)
|
||||
System.err.println("done.")
|
||||
}
|
||||
|
||||
fun heightOf(height: Long): Service.BlockID {
|
||||
return BlockID.newBuilder().setHeight(height).build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
// jni
|
||||
val converter: JniConverter = JniConverter()
|
||||
|
||||
// db
|
||||
private lateinit var dao: CompactBlockDao
|
||||
private lateinit var db: CompactBlockDb
|
||||
private const val cacheDbName = "dummy-cache-glue.db"
|
||||
private const val cacheDbPath = "/data/user/0/cash.z.wallet.sdk.test/databases/$cacheDbName"
|
||||
|
||||
// grpc
|
||||
lateinit var blockingStub: CompactTxStreamerGrpc.CompactTxStreamerBlockingStub
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
converter.initLogs()
|
||||
|
||||
val channel = ManagedChannelBuilder.forAddress("10.0.2.2", 9067).usePlaintext().build()
|
||||
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
||||
|
||||
db = Room
|
||||
.databaseBuilder(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
CompactBlockDb::class.java,
|
||||
cacheDbName
|
||||
)
|
||||
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
.apply { dao = complactBlockDao() }
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun close() {
|
||||
db.close()
|
||||
(blockingStub.channel as ManagedChannel).shutdown().awaitTermination(2000L, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,532 @@
|
|||
package rpc;
|
||||
|
||||
import static io.grpc.MethodDescriptor.generateFullMethodName;
|
||||
import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall;
|
||||
import static io.grpc.stub.ClientCalls.asyncClientStreamingCall;
|
||||
import static io.grpc.stub.ClientCalls.asyncServerStreamingCall;
|
||||
import static io.grpc.stub.ClientCalls.asyncUnaryCall;
|
||||
import static io.grpc.stub.ClientCalls.blockingServerStreamingCall;
|
||||
import static io.grpc.stub.ClientCalls.blockingUnaryCall;
|
||||
import static io.grpc.stub.ClientCalls.futureUnaryCall;
|
||||
import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
|
||||
import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
|
||||
import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
|
||||
import static io.grpc.stub.ServerCalls.asyncUnaryCall;
|
||||
import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;
|
||||
import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;
|
||||
|
||||
/**
|
||||
*/
|
||||
@javax.annotation.Generated(
|
||||
value = "by gRPC proto compiler (version 1.17.1)",
|
||||
comments = "Source: service.proto")
|
||||
public final class CompactTxStreamerGrpc {
|
||||
|
||||
private CompactTxStreamerGrpc() {}
|
||||
|
||||
public static final String SERVICE_NAME = "rpc.CompactTxStreamer";
|
||||
|
||||
// Static method descriptors that strictly reflect the proto.
|
||||
private static volatile io.grpc.MethodDescriptor<rpc.Service.ChainSpec,
|
||||
rpc.Service.BlockID> getGetLatestBlockMethod;
|
||||
|
||||
@io.grpc.stub.annotations.RpcMethod(
|
||||
fullMethodName = SERVICE_NAME + '/' + "GetLatestBlock",
|
||||
requestType = rpc.Service.ChainSpec.class,
|
||||
responseType = rpc.Service.BlockID.class,
|
||||
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
public static io.grpc.MethodDescriptor<rpc.Service.ChainSpec,
|
||||
rpc.Service.BlockID> getGetLatestBlockMethod() {
|
||||
io.grpc.MethodDescriptor<rpc.Service.ChainSpec, rpc.Service.BlockID> getGetLatestBlockMethod;
|
||||
if ((getGetLatestBlockMethod = CompactTxStreamerGrpc.getGetLatestBlockMethod) == null) {
|
||||
synchronized (CompactTxStreamerGrpc.class) {
|
||||
if ((getGetLatestBlockMethod = CompactTxStreamerGrpc.getGetLatestBlockMethod) == null) {
|
||||
CompactTxStreamerGrpc.getGetLatestBlockMethod = getGetLatestBlockMethod =
|
||||
io.grpc.MethodDescriptor.<rpc.Service.ChainSpec, rpc.Service.BlockID>newBuilder()
|
||||
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
.setFullMethodName(generateFullMethodName(
|
||||
"rpc.CompactTxStreamer", "GetLatestBlock"))
|
||||
.setSampledToLocalTracing(true)
|
||||
.setRequestMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.ChainSpec.getDefaultInstance()))
|
||||
.setResponseMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.BlockID.getDefaultInstance()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getGetLatestBlockMethod;
|
||||
}
|
||||
|
||||
private static volatile io.grpc.MethodDescriptor<rpc.Service.BlockID,
|
||||
rpc.CompactFormats.CompactBlock> getGetBlockMethod;
|
||||
|
||||
@io.grpc.stub.annotations.RpcMethod(
|
||||
fullMethodName = SERVICE_NAME + '/' + "GetBlock",
|
||||
requestType = rpc.Service.BlockID.class,
|
||||
responseType = rpc.CompactFormats.CompactBlock.class,
|
||||
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
public static io.grpc.MethodDescriptor<rpc.Service.BlockID,
|
||||
rpc.CompactFormats.CompactBlock> getGetBlockMethod() {
|
||||
io.grpc.MethodDescriptor<rpc.Service.BlockID, rpc.CompactFormats.CompactBlock> getGetBlockMethod;
|
||||
if ((getGetBlockMethod = CompactTxStreamerGrpc.getGetBlockMethod) == null) {
|
||||
synchronized (CompactTxStreamerGrpc.class) {
|
||||
if ((getGetBlockMethod = CompactTxStreamerGrpc.getGetBlockMethod) == null) {
|
||||
CompactTxStreamerGrpc.getGetBlockMethod = getGetBlockMethod =
|
||||
io.grpc.MethodDescriptor.<rpc.Service.BlockID, rpc.CompactFormats.CompactBlock>newBuilder()
|
||||
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
.setFullMethodName(generateFullMethodName(
|
||||
"rpc.CompactTxStreamer", "GetBlock"))
|
||||
.setSampledToLocalTracing(true)
|
||||
.setRequestMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.BlockID.getDefaultInstance()))
|
||||
.setResponseMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.CompactFormats.CompactBlock.getDefaultInstance()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getGetBlockMethod;
|
||||
}
|
||||
|
||||
private static volatile io.grpc.MethodDescriptor<rpc.Service.BlockRange,
|
||||
rpc.CompactFormats.CompactBlock> getGetBlockRangeMethod;
|
||||
|
||||
@io.grpc.stub.annotations.RpcMethod(
|
||||
fullMethodName = SERVICE_NAME + '/' + "GetBlockRange",
|
||||
requestType = rpc.Service.BlockRange.class,
|
||||
responseType = rpc.CompactFormats.CompactBlock.class,
|
||||
methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING)
|
||||
public static io.grpc.MethodDescriptor<rpc.Service.BlockRange,
|
||||
rpc.CompactFormats.CompactBlock> getGetBlockRangeMethod() {
|
||||
io.grpc.MethodDescriptor<rpc.Service.BlockRange, rpc.CompactFormats.CompactBlock> getGetBlockRangeMethod;
|
||||
if ((getGetBlockRangeMethod = CompactTxStreamerGrpc.getGetBlockRangeMethod) == null) {
|
||||
synchronized (CompactTxStreamerGrpc.class) {
|
||||
if ((getGetBlockRangeMethod = CompactTxStreamerGrpc.getGetBlockRangeMethod) == null) {
|
||||
CompactTxStreamerGrpc.getGetBlockRangeMethod = getGetBlockRangeMethod =
|
||||
io.grpc.MethodDescriptor.<rpc.Service.BlockRange, rpc.CompactFormats.CompactBlock>newBuilder()
|
||||
.setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING)
|
||||
.setFullMethodName(generateFullMethodName(
|
||||
"rpc.CompactTxStreamer", "GetBlockRange"))
|
||||
.setSampledToLocalTracing(true)
|
||||
.setRequestMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.BlockRange.getDefaultInstance()))
|
||||
.setResponseMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.CompactFormats.CompactBlock.getDefaultInstance()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getGetBlockRangeMethod;
|
||||
}
|
||||
|
||||
private static volatile io.grpc.MethodDescriptor<rpc.Service.TxFilter,
|
||||
rpc.Service.RawTransaction> getGetTransactionMethod;
|
||||
|
||||
@io.grpc.stub.annotations.RpcMethod(
|
||||
fullMethodName = SERVICE_NAME + '/' + "GetTransaction",
|
||||
requestType = rpc.Service.TxFilter.class,
|
||||
responseType = rpc.Service.RawTransaction.class,
|
||||
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
public static io.grpc.MethodDescriptor<rpc.Service.TxFilter,
|
||||
rpc.Service.RawTransaction> getGetTransactionMethod() {
|
||||
io.grpc.MethodDescriptor<rpc.Service.TxFilter, rpc.Service.RawTransaction> getGetTransactionMethod;
|
||||
if ((getGetTransactionMethod = CompactTxStreamerGrpc.getGetTransactionMethod) == null) {
|
||||
synchronized (CompactTxStreamerGrpc.class) {
|
||||
if ((getGetTransactionMethod = CompactTxStreamerGrpc.getGetTransactionMethod) == null) {
|
||||
CompactTxStreamerGrpc.getGetTransactionMethod = getGetTransactionMethod =
|
||||
io.grpc.MethodDescriptor.<rpc.Service.TxFilter, rpc.Service.RawTransaction>newBuilder()
|
||||
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
.setFullMethodName(generateFullMethodName(
|
||||
"rpc.CompactTxStreamer", "GetTransaction"))
|
||||
.setSampledToLocalTracing(true)
|
||||
.setRequestMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.TxFilter.getDefaultInstance()))
|
||||
.setResponseMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.RawTransaction.getDefaultInstance()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getGetTransactionMethod;
|
||||
}
|
||||
|
||||
private static volatile io.grpc.MethodDescriptor<rpc.Service.RawTransaction,
|
||||
rpc.Service.SendResponse> getSendTransactionMethod;
|
||||
|
||||
@io.grpc.stub.annotations.RpcMethod(
|
||||
fullMethodName = SERVICE_NAME + '/' + "SendTransaction",
|
||||
requestType = rpc.Service.RawTransaction.class,
|
||||
responseType = rpc.Service.SendResponse.class,
|
||||
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
public static io.grpc.MethodDescriptor<rpc.Service.RawTransaction,
|
||||
rpc.Service.SendResponse> getSendTransactionMethod() {
|
||||
io.grpc.MethodDescriptor<rpc.Service.RawTransaction, rpc.Service.SendResponse> getSendTransactionMethod;
|
||||
if ((getSendTransactionMethod = CompactTxStreamerGrpc.getSendTransactionMethod) == null) {
|
||||
synchronized (CompactTxStreamerGrpc.class) {
|
||||
if ((getSendTransactionMethod = CompactTxStreamerGrpc.getSendTransactionMethod) == null) {
|
||||
CompactTxStreamerGrpc.getSendTransactionMethod = getSendTransactionMethod =
|
||||
io.grpc.MethodDescriptor.<rpc.Service.RawTransaction, rpc.Service.SendResponse>newBuilder()
|
||||
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||
.setFullMethodName(generateFullMethodName(
|
||||
"rpc.CompactTxStreamer", "SendTransaction"))
|
||||
.setSampledToLocalTracing(true)
|
||||
.setRequestMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.RawTransaction.getDefaultInstance()))
|
||||
.setResponseMarshaller(io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(
|
||||
rpc.Service.SendResponse.getDefaultInstance()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getSendTransactionMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new async stub that supports all call types for the service
|
||||
*/
|
||||
public static CompactTxStreamerStub newStub(io.grpc.Channel channel) {
|
||||
return new CompactTxStreamerStub(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new blocking-style stub that supports unary and streaming output calls on the service
|
||||
*/
|
||||
public static CompactTxStreamerBlockingStub newBlockingStub(
|
||||
io.grpc.Channel channel) {
|
||||
return new CompactTxStreamerBlockingStub(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ListenableFuture-style stub that supports unary calls on the service
|
||||
*/
|
||||
public static CompactTxStreamerFutureStub newFutureStub(
|
||||
io.grpc.Channel channel) {
|
||||
return new CompactTxStreamerFutureStub(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static abstract class CompactTxStreamerImplBase implements io.grpc.BindableService {
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getLatestBlock(rpc.Service.ChainSpec request,
|
||||
io.grpc.stub.StreamObserver<rpc.Service.BlockID> responseObserver) {
|
||||
asyncUnimplementedUnaryCall(getGetLatestBlockMethod(), responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getBlock(rpc.Service.BlockID request,
|
||||
io.grpc.stub.StreamObserver<rpc.CompactFormats.CompactBlock> responseObserver) {
|
||||
asyncUnimplementedUnaryCall(getGetBlockMethod(), responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getBlockRange(rpc.Service.BlockRange request,
|
||||
io.grpc.stub.StreamObserver<rpc.CompactFormats.CompactBlock> responseObserver) {
|
||||
asyncUnimplementedUnaryCall(getGetBlockRangeMethod(), responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getTransaction(rpc.Service.TxFilter request,
|
||||
io.grpc.stub.StreamObserver<rpc.Service.RawTransaction> responseObserver) {
|
||||
asyncUnimplementedUnaryCall(getGetTransactionMethod(), responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void sendTransaction(rpc.Service.RawTransaction request,
|
||||
io.grpc.stub.StreamObserver<rpc.Service.SendResponse> responseObserver) {
|
||||
asyncUnimplementedUnaryCall(getSendTransactionMethod(), responseObserver);
|
||||
}
|
||||
|
||||
@java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
|
||||
return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
|
||||
.addMethod(
|
||||
getGetLatestBlockMethod(),
|
||||
asyncUnaryCall(
|
||||
new MethodHandlers<
|
||||
rpc.Service.ChainSpec,
|
||||
rpc.Service.BlockID>(
|
||||
this, METHODID_GET_LATEST_BLOCK)))
|
||||
.addMethod(
|
||||
getGetBlockMethod(),
|
||||
asyncUnaryCall(
|
||||
new MethodHandlers<
|
||||
rpc.Service.BlockID,
|
||||
rpc.CompactFormats.CompactBlock>(
|
||||
this, METHODID_GET_BLOCK)))
|
||||
.addMethod(
|
||||
getGetBlockRangeMethod(),
|
||||
asyncServerStreamingCall(
|
||||
new MethodHandlers<
|
||||
rpc.Service.BlockRange,
|
||||
rpc.CompactFormats.CompactBlock>(
|
||||
this, METHODID_GET_BLOCK_RANGE)))
|
||||
.addMethod(
|
||||
getGetTransactionMethod(),
|
||||
asyncUnaryCall(
|
||||
new MethodHandlers<
|
||||
rpc.Service.TxFilter,
|
||||
rpc.Service.RawTransaction>(
|
||||
this, METHODID_GET_TRANSACTION)))
|
||||
.addMethod(
|
||||
getSendTransactionMethod(),
|
||||
asyncUnaryCall(
|
||||
new MethodHandlers<
|
||||
rpc.Service.RawTransaction,
|
||||
rpc.Service.SendResponse>(
|
||||
this, METHODID_SEND_TRANSACTION)))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static final class CompactTxStreamerStub extends io.grpc.stub.AbstractStub<CompactTxStreamerStub> {
|
||||
private CompactTxStreamerStub(io.grpc.Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
private CompactTxStreamerStub(io.grpc.Channel channel,
|
||||
io.grpc.CallOptions callOptions) {
|
||||
super(channel, callOptions);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected CompactTxStreamerStub build(io.grpc.Channel channel,
|
||||
io.grpc.CallOptions callOptions) {
|
||||
return new CompactTxStreamerStub(channel, callOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getLatestBlock(rpc.Service.ChainSpec request,
|
||||
io.grpc.stub.StreamObserver<rpc.Service.BlockID> responseObserver) {
|
||||
asyncUnaryCall(
|
||||
getChannel().newCall(getGetLatestBlockMethod(), getCallOptions()), request, responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getBlock(rpc.Service.BlockID request,
|
||||
io.grpc.stub.StreamObserver<rpc.CompactFormats.CompactBlock> responseObserver) {
|
||||
asyncUnaryCall(
|
||||
getChannel().newCall(getGetBlockMethod(), getCallOptions()), request, responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getBlockRange(rpc.Service.BlockRange request,
|
||||
io.grpc.stub.StreamObserver<rpc.CompactFormats.CompactBlock> responseObserver) {
|
||||
asyncServerStreamingCall(
|
||||
getChannel().newCall(getGetBlockRangeMethod(), getCallOptions()), request, responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void getTransaction(rpc.Service.TxFilter request,
|
||||
io.grpc.stub.StreamObserver<rpc.Service.RawTransaction> responseObserver) {
|
||||
asyncUnaryCall(
|
||||
getChannel().newCall(getGetTransactionMethod(), getCallOptions()), request, responseObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void sendTransaction(rpc.Service.RawTransaction request,
|
||||
io.grpc.stub.StreamObserver<rpc.Service.SendResponse> responseObserver) {
|
||||
asyncUnaryCall(
|
||||
getChannel().newCall(getSendTransactionMethod(), getCallOptions()), request, responseObserver);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static final class CompactTxStreamerBlockingStub extends io.grpc.stub.AbstractStub<CompactTxStreamerBlockingStub> {
|
||||
private CompactTxStreamerBlockingStub(io.grpc.Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
private CompactTxStreamerBlockingStub(io.grpc.Channel channel,
|
||||
io.grpc.CallOptions callOptions) {
|
||||
super(channel, callOptions);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected CompactTxStreamerBlockingStub build(io.grpc.Channel channel,
|
||||
io.grpc.CallOptions callOptions) {
|
||||
return new CompactTxStreamerBlockingStub(channel, callOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public rpc.Service.BlockID getLatestBlock(rpc.Service.ChainSpec request) {
|
||||
return blockingUnaryCall(
|
||||
getChannel(), getGetLatestBlockMethod(), getCallOptions(), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public rpc.CompactFormats.CompactBlock getBlock(rpc.Service.BlockID request) {
|
||||
return blockingUnaryCall(
|
||||
getChannel(), getGetBlockMethod(), getCallOptions(), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public java.util.Iterator<rpc.CompactFormats.CompactBlock> getBlockRange(
|
||||
rpc.Service.BlockRange request) {
|
||||
return blockingServerStreamingCall(
|
||||
getChannel(), getGetBlockRangeMethod(), getCallOptions(), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public rpc.Service.RawTransaction getTransaction(rpc.Service.TxFilter request) {
|
||||
return blockingUnaryCall(
|
||||
getChannel(), getGetTransactionMethod(), getCallOptions(), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public rpc.Service.SendResponse sendTransaction(rpc.Service.RawTransaction request) {
|
||||
return blockingUnaryCall(
|
||||
getChannel(), getSendTransactionMethod(), getCallOptions(), request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static final class CompactTxStreamerFutureStub extends io.grpc.stub.AbstractStub<CompactTxStreamerFutureStub> {
|
||||
private CompactTxStreamerFutureStub(io.grpc.Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
private CompactTxStreamerFutureStub(io.grpc.Channel channel,
|
||||
io.grpc.CallOptions callOptions) {
|
||||
super(channel, callOptions);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected CompactTxStreamerFutureStub build(io.grpc.Channel channel,
|
||||
io.grpc.CallOptions callOptions) {
|
||||
return new CompactTxStreamerFutureStub(channel, callOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public com.google.common.util.concurrent.ListenableFuture<rpc.Service.BlockID> getLatestBlock(
|
||||
rpc.Service.ChainSpec request) {
|
||||
return futureUnaryCall(
|
||||
getChannel().newCall(getGetLatestBlockMethod(), getCallOptions()), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public com.google.common.util.concurrent.ListenableFuture<rpc.CompactFormats.CompactBlock> getBlock(
|
||||
rpc.Service.BlockID request) {
|
||||
return futureUnaryCall(
|
||||
getChannel().newCall(getGetBlockMethod(), getCallOptions()), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public com.google.common.util.concurrent.ListenableFuture<rpc.Service.RawTransaction> getTransaction(
|
||||
rpc.Service.TxFilter request) {
|
||||
return futureUnaryCall(
|
||||
getChannel().newCall(getGetTransactionMethod(), getCallOptions()), request);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public com.google.common.util.concurrent.ListenableFuture<rpc.Service.SendResponse> sendTransaction(
|
||||
rpc.Service.RawTransaction request) {
|
||||
return futureUnaryCall(
|
||||
getChannel().newCall(getSendTransactionMethod(), getCallOptions()), request);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int METHODID_GET_LATEST_BLOCK = 0;
|
||||
private static final int METHODID_GET_BLOCK = 1;
|
||||
private static final int METHODID_GET_BLOCK_RANGE = 2;
|
||||
private static final int METHODID_GET_TRANSACTION = 3;
|
||||
private static final int METHODID_SEND_TRANSACTION = 4;
|
||||
|
||||
private static final class MethodHandlers<Req, Resp> implements
|
||||
io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
|
||||
io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
|
||||
io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
|
||||
io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
|
||||
private final CompactTxStreamerImplBase serviceImpl;
|
||||
private final int methodId;
|
||||
|
||||
MethodHandlers(CompactTxStreamerImplBase serviceImpl, int methodId) {
|
||||
this.serviceImpl = serviceImpl;
|
||||
this.methodId = methodId;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("unchecked")
|
||||
public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
|
||||
switch (methodId) {
|
||||
case METHODID_GET_LATEST_BLOCK:
|
||||
serviceImpl.getLatestBlock((rpc.Service.ChainSpec) request,
|
||||
(io.grpc.stub.StreamObserver<rpc.Service.BlockID>) responseObserver);
|
||||
break;
|
||||
case METHODID_GET_BLOCK:
|
||||
serviceImpl.getBlock((rpc.Service.BlockID) request,
|
||||
(io.grpc.stub.StreamObserver<rpc.CompactFormats.CompactBlock>) responseObserver);
|
||||
break;
|
||||
case METHODID_GET_BLOCK_RANGE:
|
||||
serviceImpl.getBlockRange((rpc.Service.BlockRange) request,
|
||||
(io.grpc.stub.StreamObserver<rpc.CompactFormats.CompactBlock>) responseObserver);
|
||||
break;
|
||||
case METHODID_GET_TRANSACTION:
|
||||
serviceImpl.getTransaction((rpc.Service.TxFilter) request,
|
||||
(io.grpc.stub.StreamObserver<rpc.Service.RawTransaction>) responseObserver);
|
||||
break;
|
||||
case METHODID_SEND_TRANSACTION:
|
||||
serviceImpl.sendTransaction((rpc.Service.RawTransaction) request,
|
||||
(io.grpc.stub.StreamObserver<rpc.Service.SendResponse>) responseObserver);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("unchecked")
|
||||
public io.grpc.stub.StreamObserver<Req> invoke(
|
||||
io.grpc.stub.StreamObserver<Resp> responseObserver) {
|
||||
switch (methodId) {
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static volatile io.grpc.ServiceDescriptor serviceDescriptor;
|
||||
|
||||
public static io.grpc.ServiceDescriptor getServiceDescriptor() {
|
||||
io.grpc.ServiceDescriptor result = serviceDescriptor;
|
||||
if (result == null) {
|
||||
synchronized (CompactTxStreamerGrpc.class) {
|
||||
result = serviceDescriptor;
|
||||
if (result == null) {
|
||||
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
|
||||
.addMethod(getGetLatestBlockMethod())
|
||||
.addMethod(getGetBlockMethod())
|
||||
.addMethod(getGetBlockRangeMethod())
|
||||
.addMethod(getGetTransactionMethod())
|
||||
.addMethod(getSendTransactionMethod())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,505 @@
|
|||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: WalletData.proto
|
||||
|
||||
package rpc;
|
||||
|
||||
public final class WalletDataOuterClass {
|
||||
private WalletDataOuterClass() {}
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||
}
|
||||
public interface WalletDataOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:rpc.WalletData)
|
||||
com.google.protobuf.MessageLiteOrBuilder {
|
||||
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
java.lang.String getName();
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getNameBytes();
|
||||
|
||||
/**
|
||||
* <code>optional int32 id = 2;</code>
|
||||
*/
|
||||
int getId();
|
||||
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
java.lang.String getEmails();
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getEmailsBytes();
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code rpc.WalletData}
|
||||
*/
|
||||
public static final class WalletData extends
|
||||
com.google.protobuf.GeneratedMessageLite<
|
||||
WalletData, WalletData.Builder> implements
|
||||
// @@protoc_insertion_point(message_implements:rpc.WalletData)
|
||||
WalletDataOrBuilder {
|
||||
private WalletData() {
|
||||
name_ = "";
|
||||
emails_ = "";
|
||||
}
|
||||
public static final int NAME_FIELD_NUMBER = 1;
|
||||
private java.lang.String name_;
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
public java.lang.String getName() {
|
||||
return name_;
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getNameBytes() {
|
||||
return com.google.protobuf.ByteString.copyFromUtf8(name_);
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
private void setName(
|
||||
java.lang.String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
name_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
private void clearName() {
|
||||
|
||||
name_ = getDefaultInstance().getName();
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
private void setNameBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
|
||||
name_ = value.toStringUtf8();
|
||||
}
|
||||
|
||||
public static final int ID_FIELD_NUMBER = 2;
|
||||
private int id_;
|
||||
/**
|
||||
* <code>optional int32 id = 2;</code>
|
||||
*/
|
||||
public int getId() {
|
||||
return id_;
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 id = 2;</code>
|
||||
*/
|
||||
private void setId(int value) {
|
||||
|
||||
id_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 id = 2;</code>
|
||||
*/
|
||||
private void clearId() {
|
||||
|
||||
id_ = 0;
|
||||
}
|
||||
|
||||
public static final int EMAILS_FIELD_NUMBER = 3;
|
||||
private java.lang.String emails_;
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
public java.lang.String getEmails() {
|
||||
return emails_;
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getEmailsBytes() {
|
||||
return com.google.protobuf.ByteString.copyFromUtf8(emails_);
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
private void setEmails(
|
||||
java.lang.String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
emails_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
private void clearEmails() {
|
||||
|
||||
emails_ = getDefaultInstance().getEmails();
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
private void setEmailsBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
|
||||
emails_ = value.toStringUtf8();
|
||||
}
|
||||
|
||||
public void writeTo(com.google.protobuf.CodedOutputStream output)
|
||||
throws java.io.IOException {
|
||||
if (!name_.isEmpty()) {
|
||||
output.writeString(1, getName());
|
||||
}
|
||||
if (id_ != 0) {
|
||||
output.writeInt32(2, id_);
|
||||
}
|
||||
if (!emails_.isEmpty()) {
|
||||
output.writeString(3, getEmails());
|
||||
}
|
||||
}
|
||||
|
||||
public int getSerializedSize() {
|
||||
int size = memoizedSerializedSize;
|
||||
if (size != -1) return size;
|
||||
|
||||
size = 0;
|
||||
if (!name_.isEmpty()) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeStringSize(1, getName());
|
||||
}
|
||||
if (id_ != 0) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt32Size(2, id_);
|
||||
}
|
||||
if (!emails_.isEmpty()) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeStringSize(3, getEmails());
|
||||
}
|
||||
memoizedSerializedSize = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(
|
||||
com.google.protobuf.ByteString data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(
|
||||
com.google.protobuf.ByteString data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(byte[] data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(
|
||||
byte[] data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input, extensionRegistry);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseDelimitedFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return parseDelimitedFrom(DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseDelimitedFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(
|
||||
com.google.protobuf.CodedInputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static rpc.WalletDataOuterClass.WalletData parseFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input, extensionRegistry);
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return DEFAULT_INSTANCE.toBuilder();
|
||||
}
|
||||
public static Builder newBuilder(rpc.WalletDataOuterClass.WalletData prototype) {
|
||||
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protobuf type {@code rpc.WalletData}
|
||||
*/
|
||||
public static final class Builder extends
|
||||
com.google.protobuf.GeneratedMessageLite.Builder<
|
||||
rpc.WalletDataOuterClass.WalletData, Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:rpc.WalletData)
|
||||
rpc.WalletDataOuterClass.WalletDataOrBuilder {
|
||||
// Construct using rpc.WalletDataOuterClass.WalletData.newBuilder()
|
||||
private Builder() {
|
||||
super(DEFAULT_INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
public java.lang.String getName() {
|
||||
return instance.getName();
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getNameBytes() {
|
||||
return instance.getNameBytes();
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
public Builder setName(
|
||||
java.lang.String value) {
|
||||
copyOnWrite();
|
||||
instance.setName(value);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
public Builder clearName() {
|
||||
copyOnWrite();
|
||||
instance.clearName();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string name = 1;</code>
|
||||
*/
|
||||
public Builder setNameBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
copyOnWrite();
|
||||
instance.setNameBytes(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>optional int32 id = 2;</code>
|
||||
*/
|
||||
public int getId() {
|
||||
return instance.getId();
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 id = 2;</code>
|
||||
*/
|
||||
public Builder setId(int value) {
|
||||
copyOnWrite();
|
||||
instance.setId(value);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional int32 id = 2;</code>
|
||||
*/
|
||||
public Builder clearId() {
|
||||
copyOnWrite();
|
||||
instance.clearId();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
public java.lang.String getEmails() {
|
||||
return instance.getEmails();
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getEmailsBytes() {
|
||||
return instance.getEmailsBytes();
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
public Builder setEmails(
|
||||
java.lang.String value) {
|
||||
copyOnWrite();
|
||||
instance.setEmails(value);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
public Builder clearEmails() {
|
||||
copyOnWrite();
|
||||
instance.clearEmails();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string emails = 3;</code>
|
||||
*/
|
||||
public Builder setEmailsBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
copyOnWrite();
|
||||
instance.setEmailsBytes(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:rpc.WalletData)
|
||||
}
|
||||
protected final Object dynamicMethod(
|
||||
com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,
|
||||
Object arg0, Object arg1) {
|
||||
switch (method) {
|
||||
case NEW_MUTABLE_INSTANCE: {
|
||||
return new rpc.WalletDataOuterClass.WalletData();
|
||||
}
|
||||
case IS_INITIALIZED: {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
case MAKE_IMMUTABLE: {
|
||||
return null;
|
||||
}
|
||||
case NEW_BUILDER: {
|
||||
return new Builder();
|
||||
}
|
||||
case VISIT: {
|
||||
Visitor visitor = (Visitor) arg0;
|
||||
rpc.WalletDataOuterClass.WalletData other = (rpc.WalletDataOuterClass.WalletData) arg1;
|
||||
name_ = visitor.visitString(!name_.isEmpty(), name_,
|
||||
!other.name_.isEmpty(), other.name_);
|
||||
id_ = visitor.visitInt(id_ != 0, id_,
|
||||
other.id_ != 0, other.id_);
|
||||
emails_ = visitor.visitString(!emails_.isEmpty(), emails_,
|
||||
!other.emails_.isEmpty(), other.emails_);
|
||||
if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor
|
||||
.INSTANCE) {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
case MERGE_FROM_STREAM: {
|
||||
com.google.protobuf.CodedInputStream input =
|
||||
(com.google.protobuf.CodedInputStream) arg0;
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry =
|
||||
(com.google.protobuf.ExtensionRegistryLite) arg1;
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
int tag = input.readTag();
|
||||
switch (tag) {
|
||||
case 0:
|
||||
done = true;
|
||||
break;
|
||||
default: {
|
||||
if (!input.skipField(tag)) {
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
String s = input.readStringRequireUtf8();
|
||||
|
||||
name_ = s;
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
|
||||
id_ = input.readInt32();
|
||||
break;
|
||||
}
|
||||
case 26: {
|
||||
String s = input.readStringRequireUtf8();
|
||||
|
||||
emails_ = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw new RuntimeException(e.setUnfinishedMessage(this));
|
||||
} catch (java.io.IOException e) {
|
||||
throw new RuntimeException(
|
||||
new com.google.protobuf.InvalidProtocolBufferException(
|
||||
e.getMessage()).setUnfinishedMessage(this));
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
case GET_DEFAULT_INSTANCE: {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
case GET_PARSER: {
|
||||
if (PARSER == null) { synchronized (rpc.WalletDataOuterClass.WalletData.class) {
|
||||
if (PARSER == null) {
|
||||
PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return PARSER;
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(class_scope:rpc.WalletData)
|
||||
private static final rpc.WalletDataOuterClass.WalletData DEFAULT_INSTANCE;
|
||||
static {
|
||||
DEFAULT_INSTANCE = new WalletData();
|
||||
DEFAULT_INSTANCE.makeImmutable();
|
||||
}
|
||||
|
||||
public static rpc.WalletDataOuterClass.WalletData getDefaultInstance() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
private static volatile com.google.protobuf.Parser<WalletData> PARSER;
|
||||
|
||||
public static com.google.protobuf.Parser<WalletData> parser() {
|
||||
return DEFAULT_INSTANCE.getParserForType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static {
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(outer_class_scope)
|
||||
}
|
|
@ -1,2 +1,6 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cash.z.wallet.sdk"/>
|
||||
package="cash.z.wallet.sdk">
|
||||
<!--<application-->
|
||||
<!--android:name="androidx.multidex.MultiDexApplication" />-->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
|
|
|
@ -5,7 +5,7 @@ import cash.z.wallet.sdk.vo.CompactBlock
|
|||
|
||||
@Dao
|
||||
interface CompactBlockDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
fun insert(block: CompactBlock)
|
||||
|
||||
@Query("SELECT * FROM compactblocks WHERE height = :height")
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
package cash.z.wallet.sdk.data
|
||||
|
||||
import cash.z.wallet.sdk.ext.debug
|
||||
import cash.z.wallet.sdk.ext.toBlockHeight
|
||||
import io.grpc.ManagedChannelBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.BroadcastChannel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import rpc.CompactFormats.CompactBlock
|
||||
import rpc.CompactTxStreamerGrpc
|
||||
import rpc.Service
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* Downloads compact blocks to the database
|
||||
*/
|
||||
class CompactBlockDownloader(val scope: CoroutineScope) : CompactBlockSource {
|
||||
|
||||
private var connection: Connection? = null
|
||||
|
||||
override fun blocks(): ReceiveChannel<Result<CompactBlock>> = connection!!.subscribe()
|
||||
|
||||
fun start() {
|
||||
connection = Connection()
|
||||
scope.launch {
|
||||
connection!!.loadBlockRange(373070L..373085L).join()
|
||||
connection = Connection().open()
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
connection?.close()
|
||||
connection = null
|
||||
}
|
||||
|
||||
inner class Connection: Closeable {
|
||||
private var job: Job? = null
|
||||
private var syncJob: Job? = null
|
||||
private val compactBlockChannel = BroadcastChannel<Result<CompactBlock>>(100)
|
||||
private val errorHandler: CoroutineExceptionHandler
|
||||
|
||||
val channel = ManagedChannelBuilder.forAddress("10.0.2.2", 9067).usePlaintext().build()
|
||||
val blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
||||
|
||||
init {
|
||||
errorHandler = CoroutineExceptionHandler { _, error ->
|
||||
debug("handling error: $error")
|
||||
try {
|
||||
debug("totally about to launch something sweet")
|
||||
GlobalScope.launch {
|
||||
debug("sending error")
|
||||
compactBlockChannel.send(Result.failure(error))
|
||||
debug("error sent")
|
||||
}
|
||||
|
||||
}catch (t:Throwable) {
|
||||
debug("failed to send error because of $t")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun subscribe() = compactBlockChannel.openSubscription()
|
||||
|
||||
fun loadBlockRange(range: LongRange) : Job {
|
||||
syncJob = scope.launch {
|
||||
if (isActive) {
|
||||
debug("requesting a block range: ...")
|
||||
channel.
|
||||
val result = blockingStub.getBlockRange(
|
||||
Service.BlockRange.newBuilder()
|
||||
.setStart(range.first.toBlockHeight())
|
||||
.setEnd(range.last.toBlockHeight())
|
||||
.build()
|
||||
)
|
||||
while (result.hasNext()) {
|
||||
try {
|
||||
val nextBlock = result.next()
|
||||
debug("received new block in range: ${nextBlock.height}")
|
||||
|
||||
async { debug("sending block from range: ${nextBlock.height}"); compactBlockChannel.send(Result.success(nextBlock)); debug("done sending block from range: ${nextBlock.height}") }
|
||||
} catch (t: Throwable) {
|
||||
async { debug("sending failure"); compactBlockChannel.send(Result.failure(t)); debug("done sending failure"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return syncJob!!
|
||||
}
|
||||
|
||||
fun open(): Connection {
|
||||
// TODO: use CoroutineScope.open to avoid the need to pass scope around
|
||||
job = scope.launch {
|
||||
var lastHeight = 0L
|
||||
while (isActive) {
|
||||
debug("requesting a block...")
|
||||
val result = blockingStub.getLatestBlock(Service.ChainSpec.newBuilder().build())
|
||||
if (result.height > lastHeight) {
|
||||
debug("received new block: ${result.height}")
|
||||
// if we have new data, send it and then wait a while
|
||||
try {
|
||||
|
||||
async { debug("sending block: ${result.height}"); compactBlockChannel.send(Result.success(blockingStub.getBlock(result))); debug("done sending block: ${result.height}"); }
|
||||
} catch (t: Throwable) {
|
||||
async { debug("sending failure"); compactBlockChannel.send(Result.failure(t)); debug("done sending failure"); }
|
||||
}
|
||||
|
||||
lastHeight = result.height
|
||||
delay(25 * 1000)
|
||||
|
||||
} else {
|
||||
debug("received same old block: ${result.height}")
|
||||
// otherwise keep checking fairly often until we have new data
|
||||
delay(3000)
|
||||
}
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
compactBlockChannel.cancel()
|
||||
syncJob?.cancel()
|
||||
syncJob = null
|
||||
job?.cancel()
|
||||
job = null
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package cash.z.wallet.sdk.data
|
||||
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import rpc.CompactFormats.CompactBlock
|
||||
|
||||
interface CompactBlockSource {
|
||||
fun blocks(): ReceiveChannel<Result<CompactBlock>>
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package cash.z.wallet.sdk.data
|
||||
|
||||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
|
||||
class ScanResultDbCreator(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
SQL_CREATE_DB.split(";").forEach { db.execSQL(it.trim()) }
|
||||
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
onCreate(db)
|
||||
}
|
||||
|
||||
override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
onUpgrade(db, oldVersion, newVersion)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DB_NAME = "ScannedBlockResults.db"
|
||||
const val DB_VERSION = 1
|
||||
val SQL_CREATE_DB: String = """
|
||||
CREATE TABLE IF NOT EXISTS blocks (
|
||||
height INTEGER PRIMARY KEY,
|
||||
time INTEGER,
|
||||
sapling_tree BLOB
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS transactions (
|
||||
id_tx INTEGER PRIMARY KEY,
|
||||
txid BLOB NOT NULL UNIQUE,
|
||||
block INTEGER,
|
||||
raw BLOB,
|
||||
FOREIGN KEY (block) REFERENCES blocks(height)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS received_notes (
|
||||
id_note INTEGER PRIMARY KEY,
|
||||
tx INTEGER NOT NULL,
|
||||
output_index INTEGER NOT NULL,
|
||||
account INTEGER NOT NULL,
|
||||
diversifier BLOB NOT NULL,
|
||||
value INTEGER NOT NULL,
|
||||
rcm BLOB NOT NULL,
|
||||
nf BLOB NOT NULL UNIQUE,
|
||||
memo BLOB,
|
||||
spent INTEGER,
|
||||
FOREIGN KEY (tx) REFERENCES transactions(id_tx),
|
||||
FOREIGN KEY (spent) REFERENCES transactions(id_tx),
|
||||
CONSTRAINT tx_output UNIQUE (tx, output_index)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sapling_witnesses (
|
||||
id_witness INTEGER PRIMARY KEY,
|
||||
note INTEGER NOT NULL,
|
||||
block INTEGER NOT NULL,
|
||||
witness BLOB NOT NULL,
|
||||
FOREIGN KEY (note) REFERENCES received_notes(id_note),
|
||||
FOREIGN KEY (block) REFERENCES blocks(height),
|
||||
CONSTRAINT witness_height UNIQUE (note, block)
|
||||
)
|
||||
""".trimIndent()
|
||||
|
||||
fun create(context: Context) {
|
||||
val db = ScanResultDbCreator(context).writableDatabase
|
||||
db.close()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package cash.z.wallet.sdk.data
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import cash.z.wallet.sdk.dao.CompactBlockDao
|
||||
import cash.z.wallet.sdk.db.CompactBlockDb
|
||||
import cash.z.wallet.sdk.ext.debug
|
||||
import cash.z.wallet.sdk.jni.JniConverter
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import rpc.CompactFormats
|
||||
|
||||
/**
|
||||
* Downloads compact blocks to the database and then scans them for transactions
|
||||
*/
|
||||
class Synchronizer(val applicationContext: Context, val scope: CoroutineScope, val birthday: Long = 373070L) : CompactBlockSource {
|
||||
|
||||
// TODO: convert to CompactBlockSource that just has a stream and then have the downloader operate on the stream
|
||||
private val downloader = CompactBlockDownloader(scope)
|
||||
private val savedBlockChannel = ConflatedBroadcastChannel<Result<CompactFormats.CompactBlock>>()
|
||||
private lateinit var cacheDao: CompactBlockDao
|
||||
private lateinit var cacheDb: CompactBlockDb
|
||||
private lateinit var saveJob: Job
|
||||
private lateinit var scanJob: Job
|
||||
override fun blocks(): ReceiveChannel<Result<CompactFormats.CompactBlock>> = savedBlockChannel.openSubscription()
|
||||
|
||||
fun start() {
|
||||
createDb()
|
||||
downloader.start()
|
||||
saveJob = saveBlocks()
|
||||
scanJob = scanBlocks()
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
scanJob.cancel()
|
||||
saveJob.cancel()
|
||||
downloader.stop()
|
||||
cacheDb.close()
|
||||
}
|
||||
|
||||
private fun createDb() {
|
||||
// TODO: inject the db and dao
|
||||
cacheDb = Room.databaseBuilder(
|
||||
applicationContext,
|
||||
CompactBlockDb::class.java,
|
||||
CACHEDB_NAME
|
||||
)
|
||||
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
.apply { cacheDao = complactBlockDao() }
|
||||
}
|
||||
|
||||
private fun saveBlocks(): Job = scope.launch {
|
||||
val downloadedBlockChannel = downloader.blocks()
|
||||
while (isActive) {
|
||||
try {
|
||||
val nextBlock = downloadedBlockChannel.receive().getOrThrow()
|
||||
cacheDao.insert(cash.z.wallet.sdk.vo.CompactBlock(nextBlock.height.toInt(), nextBlock.toByteArray()))
|
||||
async {
|
||||
savedBlockChannel.send(Result.success(nextBlock))
|
||||
debug("stored block at height: ${nextBlock.height}")
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
debug("failed to store block due to $t")
|
||||
async {
|
||||
savedBlockChannel.send(Result.failure(t))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanBlocks(): Job = scope.launch {
|
||||
val savedBlocks = blocks()
|
||||
val converter = JniConverter()
|
||||
converter.initLogs()
|
||||
ScanResultDbCreator.create(applicationContext)
|
||||
while (isActive) {
|
||||
try {
|
||||
debug("scanning blocks from $birthday onward...")
|
||||
val nextBlock = savedBlocks.receive().getOrThrow() // wait until a block was saved
|
||||
debug("...scanner observed a block (${nextBlock.height}) without crashing!")
|
||||
delay(5000L)
|
||||
val result = converter.scanBlocks(
|
||||
applicationContext.getDatabasePath(CACHEDB_NAME).absolutePath,
|
||||
applicationContext.getDatabasePath(ScanResultDbCreator.DB_NAME).absolutePath,
|
||||
"dummyseed".toByteArray(),
|
||||
birthday.toInt()
|
||||
)
|
||||
debug("scan complete")
|
||||
} catch (t: Throwable) {
|
||||
debug("error while scanning blocks: $t")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CACHEDB_NAME = "DownloadedCompactBlocks.db"
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ import cash.z.wallet.sdk.vo.Transaction
|
|||
Block::class,
|
||||
Note::class
|
||||
],
|
||||
version = 1,
|
||||
version = 2,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class DerivedDataDb : RoomDatabase() {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package cash.z.wallet.sdk.ext
|
||||
|
||||
import android.util.Log
|
||||
|
||||
internal fun debug(message: String) {
|
||||
Log.e("DBUG", message)
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package cash.z.wallet.sdk.ext
|
||||
|
||||
import rpc.Service
|
||||
|
||||
fun Long.toBlockHeight(): Service.BlockID = Service.BlockID.newBuilder().setHeight(this).build()
|
|
@ -6,7 +6,7 @@ import androidx.room.Entity
|
|||
@Entity(primaryKeys = ["height"], tableName = "blocks")
|
||||
data class Block(
|
||||
val height: Int,
|
||||
val time: Int,
|
||||
val time: Int?,
|
||||
@ColumnInfo(typeAffinity = ColumnInfo.BLOB, name = "sapling_tree")
|
||||
val saplingTree: ByteArray
|
||||
) {
|
||||
|
@ -20,7 +20,7 @@ data class Block(
|
|||
|
||||
override fun hashCode(): Int {
|
||||
var result = height
|
||||
result = 31 * result + time
|
||||
result = 31 * result + (time ?: 0)
|
||||
result = 31 * result + saplingTree.contentHashCode()
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ data class Note(
|
|||
|
||||
val account: Int,
|
||||
val value: Int,
|
||||
val spent: Int,
|
||||
val spent: Int?,
|
||||
|
||||
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
|
||||
val diversifier: ByteArray,
|
||||
|
@ -69,7 +69,7 @@ data class Note(
|
|||
result = 31 * result + outputIndex
|
||||
result = 31 * result + account
|
||||
result = 31 * result + value
|
||||
result = 31 * result + spent
|
||||
result = 31 * result + (spent ?: 0)
|
||||
result = 31 * result + diversifier.contentHashCode()
|
||||
result = 31 * result + rcm.contentHashCode()
|
||||
result = 31 * result + nf.contentHashCode()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cash.z.wallet.sdk.proto;
|
||||
syntax = "proto3";
|
||||
package rpc;
|
||||
message WalletData {
|
||||
required string name = 1;
|
||||
required int32 id = 2;
|
||||
optional string emails = 3;
|
||||
string name = 1;
|
||||
int32 id = 2;
|
||||
string emails = 3;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = "walletrpc";
|
||||
package rpc;
|
||||
|
||||
// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value.
|
||||
// bytes fields of hashes are in canonical little-endian format.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = "walletrpc";
|
||||
package rpc;
|
||||
|
||||
import "compact_formats.proto";
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package cash.z.wallet.sdk
|
||||
|
||||
|
||||
import android.util.Log
|
||||
import io.grpc.ManagedChannel
|
||||
import io.grpc.ManagedChannelBuilder
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import rpc.CompactTxStreamerGrpc
|
||||
import rpc.Service
|
||||
import rpc.Service.*
|
||||
import rpc.WalletDataOuterClass
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class GlueTest {
|
||||
|
||||
@Test
|
||||
fun testSanity_transactionParsing() {
|
||||
val result =
|
||||
blockingStub.getBlockRange(
|
||||
BlockRange.newBuilder()
|
||||
.setStart(heightOf(373070))
|
||||
.setEnd(heightOf(373085))
|
||||
.build()
|
||||
)
|
||||
assertNotNull(result)
|
||||
assertEquals(372950, result.next().height)
|
||||
}
|
||||
|
||||
fun heightOf(height: Long): Service.BlockID {
|
||||
return BlockID.newBuilder().setHeight(height).build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var blockingStub: CompactTxStreamerGrpc.CompactTxStreamerBlockingStub
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
val channel = ManagedChannelBuilder.forAddress("localhost", 9067).usePlaintext().build()
|
||||
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun tearDown() {
|
||||
(blockingStub.channel as ManagedChannel).shutdown().awaitTermination(2000L, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package cash.z.wallet.sdk
|
||||
|
||||
|
||||
import android.util.Log
|
||||
import io.grpc.ManagedChannel
|
||||
import io.grpc.ManagedChannelBuilder
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import rpc.CompactTxStreamerGrpc
|
||||
import rpc.Service
|
||||
import rpc.Service.*
|
||||
import rpc.WalletDataOuterClass
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class GrpcTest {
|
||||
@Test
|
||||
fun testSanity_protoFilesCreated() {
|
||||
val name = "Zooko"
|
||||
val data = WalletDataOuterClass.WalletData.newBuilder()
|
||||
.setName(name)
|
||||
.setId(1)
|
||||
.build()
|
||||
assertEquals(name, data.name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSanity_serviceCreated() {
|
||||
val result = blockingStub.getLatestBlock(ChainSpec.newBuilder().build())
|
||||
assertNotNull(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSanity_transactionParsing() {
|
||||
val result =
|
||||
blockingStub.getBlockRange(
|
||||
BlockRange.newBuilder()
|
||||
.setStart(heightOf(372950))
|
||||
.setEnd(heightOf(372954))
|
||||
.build()
|
||||
)
|
||||
assertNotNull(result)
|
||||
assertEquals(372950, result.next().height)
|
||||
}
|
||||
|
||||
fun heightOf(height: Long): Service.BlockID {
|
||||
return BlockID.newBuilder().setHeight(height).build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var blockingStub: CompactTxStreamerGrpc.CompactTxStreamerBlockingStub
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
val channel = ManagedChannelBuilder.forAddress("localhost", 9067).usePlaintext().build()
|
||||
blockingStub = CompactTxStreamerGrpc.newBlockingStub(channel)
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun tearDown() {
|
||||
(blockingStub.channel as ManagedChannel).shutdown().awaitTermination(2000L, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
task unregistered {
|
||||
println "configuring unregistered"
|
||||
doLast {
|
||||
println 'unregistered'
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("pb") {
|
||||
println "configuring pb"
|
||||
doLast {
|
||||
println 'preBuild'
|
||||
}
|
||||
}
|
||||
tasks.register("generateJni") {
|
||||
println "configuring generateJni"
|
||||
doLast {
|
||||
println 'jni'
|
||||
}
|
||||
}
|
||||
tasks.register("copyA") {
|
||||
dependsOn generateJni
|
||||
println "configuring copyA"
|
||||
doLast {
|
||||
println 'copyA'
|
||||
}
|
||||
}
|
||||
tasks.register("copyB") {
|
||||
dependsOn generateJni
|
||||
println "configuring copyB"
|
||||
doLast {
|
||||
println 'copyB'
|
||||
}
|
||||
}
|
||||
tasks.register("copyC") {
|
||||
dependsOn generateJni
|
||||
println "configuring copyC"
|
||||
doLast {
|
||||
println 'copyC'
|
||||
}
|
||||
}
|
||||
|
||||
task copyAll {
|
||||
dependsOn copyA, copyB, copyC
|
||||
}
|
||||
|
||||
pb.dependsOn copyAll
|
Loading…
Reference in New Issue