solution: refactoring, more clean class names
This commit is contained in:
@@ -81,7 +81,6 @@ dependencies {
|
|||||||
implementation "io.infinitape:etherjar-hex:$etherjarVersion"
|
implementation "io.infinitape:etherjar-hex:$etherjarVersion"
|
||||||
implementation "io.infinitape:etherjar-rpc-http:$etherjarVersion"
|
implementation "io.infinitape:etherjar-rpc-http:$etherjarVersion"
|
||||||
implementation "io.infinitape:etherjar-rpc-ws:$etherjarVersion"
|
implementation "io.infinitape:etherjar-rpc-ws:$etherjarVersion"
|
||||||
implementation "io.infinitape:etherjar-rpc-emerald:$etherjarVersion"
|
|
||||||
implementation "io.infinitape:etherjar-tx:$etherjarVersion"
|
implementation "io.infinitape:etherjar-tx:$etherjarVersion"
|
||||||
implementation 'org.bitcoinj:bitcoinj-core:0.15.8'
|
implementation 'org.bitcoinj:bitcoinj-core:0.15.8'
|
||||||
|
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ import reactor.core.publisher.Mono
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class Describe(
|
class Describe(
|
||||||
@Autowired private val upstreams: Upstreams,
|
@Autowired private val multistreamHolder: MultistreamHolder,
|
||||||
@Autowired private val subscribeStatus: SubscribeStatus
|
@Autowired private val subscribeStatus: SubscribeStatus
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun describe(requestMono: Mono<BlockchainOuterClass.DescribeRequest>): Mono<BlockchainOuterClass.DescribeResponse> {
|
fun describe(requestMono: Mono<BlockchainOuterClass.DescribeRequest>): Mono<BlockchainOuterClass.DescribeResponse> {
|
||||||
return requestMono.map { _ ->
|
return requestMono.map { _ ->
|
||||||
val resp = BlockchainOuterClass.DescribeResponse.newBuilder()
|
val resp = BlockchainOuterClass.DescribeResponse.newBuilder()
|
||||||
upstreams.getAvailable().forEach { chain ->
|
multistreamHolder.getAvailable().forEach { chain ->
|
||||||
upstreams.getUpstream(chain)?.let { chainUpstreams ->
|
multistreamHolder.getUpstream(chain)?.let { chainUpstreams ->
|
||||||
val status = subscribeStatus.chainStatus(chain, chainUpstreams.getAll())
|
val status = subscribeStatus.chainStatus(chain, chainUpstreams.getAll())
|
||||||
val targets = chainUpstreams.getMethods().getSupportedMethods()
|
val targets = chainUpstreams.getMethods().getSupportedMethods()
|
||||||
val chainDescription = BlockchainOuterClass.DescribeChain.newBuilder()
|
val chainDescription = BlockchainOuterClass.DescribeChain.newBuilder()
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import java.lang.Exception
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
open class NativeCall(
|
open class NativeCall(
|
||||||
@Autowired private val upstreams: Upstreams,
|
@Autowired private val multistreamHolder: MultistreamHolder,
|
||||||
@Autowired private val objectMapper: ObjectMapper
|
@Autowired private val objectMapper: ObjectMapper
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -88,17 +88,17 @@ open class NativeCall(
|
|||||||
return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(request.chain.number)))
|
return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(request.chain.number)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!upstreams.isAvailable(chain)) {
|
if (!multistreamHolder.isAvailable(chain)) {
|
||||||
return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(request.chain.number)))
|
return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(request.chain.number)))
|
||||||
}
|
}
|
||||||
|
|
||||||
val upstream = upstreams.getUpstream(chain)
|
val upstream = multistreamHolder.getUpstream(chain)
|
||||||
?: return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(chain)))
|
?: return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(chain)))
|
||||||
|
|
||||||
return prepareCall(request, upstream)
|
return prepareCall(request, upstream)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun prepareCall(request: BlockchainOuterClass.NativeCallRequest, upstream: AggregatedUpstream): Flux<CallContext<RawCallDetails>> {
|
fun prepareCall(request: BlockchainOuterClass.NativeCallRequest, upstream: Multistream): Flux<CallContext<RawCallDetails>> {
|
||||||
return request.itemsList.toFlux().map {
|
return request.itemsList.toFlux().map {
|
||||||
val method = it.method
|
val method = it.method
|
||||||
val params = it.payload.toStringUtf8()
|
val params = it.payload.toStringUtf8()
|
||||||
@@ -202,7 +202,7 @@ open class NativeCall(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class CallContext<T>(val id: Int,
|
open class CallContext<T>(val id: Int,
|
||||||
val upstream: AggregatedUpstream,
|
val upstream: Multistream,
|
||||||
val matcher: Selector.Matcher,
|
val matcher: Selector.Matcher,
|
||||||
val callQuorum: CallQuorum,
|
val callQuorum: CallQuorum,
|
||||||
val payload: T) {
|
val payload: T) {
|
||||||
|
|||||||
@@ -21,10 +21,8 @@ import io.emeraldpay.api.proto.BlockchainOuterClass
|
|||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.dshackle.BlockchainType
|
import io.emeraldpay.dshackle.BlockchainType
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
|
||||||
import io.infinitape.etherjar.rpc.json.TransactionRefJson
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
@@ -33,7 +31,7 @@ import reactor.core.publisher.Mono
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class StreamHead(
|
class StreamHead(
|
||||||
@Autowired private val upstreams: Upstreams
|
@Autowired private val multistreamHolder: MultistreamHolder
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(StreamHead::class.java)
|
private val log = LoggerFactory.getLogger(StreamHead::class.java)
|
||||||
@@ -42,7 +40,7 @@ class StreamHead(
|
|||||||
return requestMono.map { request ->
|
return requestMono.map { request ->
|
||||||
Chain.byId(request.type.number)
|
Chain.byId(request.type.number)
|
||||||
}.flatMapMany { chain ->
|
}.flatMapMany { chain ->
|
||||||
val up = upstreams.getUpstream(chain)
|
val up = multistreamHolder.getUpstream(chain)
|
||||||
?: return@flatMapMany Flux.error<BlockchainOuterClass.ChainHead>(Exception("Unavailable chain: $chain"))
|
?: return@flatMapMany Flux.error<BlockchainOuterClass.ChainHead>(Exception("Unavailable chain: $chain"))
|
||||||
up.getHead()
|
up.getHead()
|
||||||
.getFlux()
|
.getFlux()
|
||||||
|
|||||||
@@ -27,13 +27,13 @@ import reactor.core.publisher.Mono
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class SubscribeStatus(
|
class SubscribeStatus(
|
||||||
@Autowired private val upstreams: Upstreams
|
@Autowired private val multistreamHolder: MultistreamHolder
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun subscribeStatus(requestMono: Mono<BlockchainOuterClass.StatusRequest>): Flux<BlockchainOuterClass.ChainStatus> {
|
fun subscribeStatus(requestMono: Mono<BlockchainOuterClass.StatusRequest>): Flux<BlockchainOuterClass.ChainStatus> {
|
||||||
return requestMono.flatMapMany {
|
return requestMono.flatMapMany {
|
||||||
val ups = upstreams.getAvailable().mapNotNull { chain ->
|
val ups = multistreamHolder.getAvailable().mapNotNull { chain ->
|
||||||
val chainUpstream = upstreams.getUpstream(chain)
|
val chainUpstream = multistreamHolder.getUpstream(chain)
|
||||||
chainUpstream?.observeStatus()?.map { avail ->
|
chainUpstream?.observeStatus()?.map { avail ->
|
||||||
ChainSubscription(chain, chainUpstream, avail)
|
ChainSubscription(chain, chainUpstream, avail)
|
||||||
}
|
}
|
||||||
@@ -60,6 +60,6 @@ class SubscribeStatus(
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChainSubscription(val chain: Chain, val up: AggregatedUpstream, val avail: UpstreamAvailability)
|
class ChainSubscription(val chain: Chain, val up: Multistream, val avail: UpstreamAvailability)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -19,9 +19,8 @@ import io.emeraldpay.api.proto.BlockchainOuterClass
|
|||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.dshackle.BlockchainType
|
import io.emeraldpay.dshackle.BlockchainType
|
||||||
import io.emeraldpay.dshackle.SilentException
|
import io.emeraldpay.dshackle.SilentException
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinChainUpstreams
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
@@ -35,7 +34,7 @@ import kotlin.collections.HashMap
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class TrackBitcoinAddress(
|
class TrackBitcoinAddress(
|
||||||
@Autowired private val upstreams: Upstreams
|
@Autowired private val multistreamHolder: MultistreamHolder
|
||||||
) : TrackAddress {
|
) : TrackAddress {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -43,7 +42,7 @@ class TrackBitcoinAddress(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isSupported(chain: Chain): Boolean {
|
override fun isSupported(chain: Chain): Boolean {
|
||||||
return BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN && upstreams.isAvailable(chain)
|
return BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN && multistreamHolder.isAvailable(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allAddresses(request: BlockchainOuterClass.BalanceRequest): List<String>? {
|
fun allAddresses(request: BlockchainOuterClass.BalanceRequest): List<String>? {
|
||||||
@@ -63,7 +62,7 @@ class TrackBitcoinAddress(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestBalances(chain: Chain, api: BitcoinChainUpstreams, addresses: List<String>): Flux<AddressBalance> {
|
fun requestBalances(chain: Chain, api: BitcoinMultistream, addresses: List<String>): Flux<AddressBalance> {
|
||||||
return api.getReader().listUnspent()
|
return api.getReader().listUnspent()
|
||||||
.flatMapMany { unspents ->
|
.flatMapMany { unspents ->
|
||||||
val result = getTotal(chain, addresses, unspents)
|
val result = getTotal(chain, addresses, unspents)
|
||||||
@@ -73,7 +72,7 @@ class TrackBitcoinAddress(
|
|||||||
|
|
||||||
override fun getBalance(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
override fun getBalance(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
||||||
val chain = Chain.byId(request.asset.chainValue)
|
val chain = Chain.byId(request.asset.chainValue)
|
||||||
val upstream = upstreams.getUpstream(chain)?.cast(BitcoinChainUpstreams::class.java)
|
val upstream = multistreamHolder.getUpstream(chain)?.cast(BitcoinMultistream::class.java)
|
||||||
?: return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue))
|
?: return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue))
|
||||||
val addresses = allAddresses(request) ?: return Flux.error(SilentException("Unsupported address"))
|
val addresses = allAddresses(request) ?: return Flux.error(SilentException("Unsupported address"))
|
||||||
if (addresses.isEmpty()) {
|
if (addresses.isEmpty()) {
|
||||||
@@ -119,9 +118,9 @@ class TrackBitcoinAddress(
|
|||||||
|
|
||||||
override fun subscribe(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
override fun subscribe(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
||||||
val chain = Chain.byId(request.asset.chainValue)
|
val chain = Chain.byId(request.asset.chainValue)
|
||||||
println("up: ${upstreams.getUpstream(chain)}")
|
println("up: ${multistreamHolder.getUpstream(chain)}")
|
||||||
println("up cast: ${upstreams.getUpstream(chain)?.cast(BitcoinChainUpstreams::class.java)}")
|
println("up cast: ${multistreamHolder.getUpstream(chain)?.cast(BitcoinMultistream::class.java)}")
|
||||||
val upstream = upstreams.getUpstream(chain)?.cast(BitcoinChainUpstreams::class.java)
|
val upstream = multistreamHolder.getUpstream(chain)?.cast(BitcoinMultistream::class.java)
|
||||||
?: return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue))
|
?: return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue))
|
||||||
val addresses = allAddresses(request) ?: return Flux.error(SilentException("Unsupported address"))
|
val addresses = allAddresses(request) ?: return Flux.error(SilentException("Unsupported address"))
|
||||||
if (addresses.isEmpty()) {
|
if (addresses.isEmpty()) {
|
||||||
|
|||||||
@@ -20,9 +20,8 @@ import io.emeraldpay.api.proto.BlockchainOuterClass
|
|||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.dshackle.BlockchainType
|
import io.emeraldpay.dshackle.BlockchainType
|
||||||
import io.emeraldpay.dshackle.SilentException
|
import io.emeraldpay.dshackle.SilentException
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinChainUpstreams
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.ExtractBlock
|
import io.emeraldpay.dshackle.upstream.bitcoin.ExtractBlock
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@@ -38,7 +37,7 @@ import kotlin.math.min
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class TrackBitcoinTx(
|
class TrackBitcoinTx(
|
||||||
@Autowired private val upstreams: Upstreams
|
@Autowired private val multistreamHolder: MultistreamHolder
|
||||||
) : TrackTx {
|
) : TrackTx {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -46,12 +45,12 @@ class TrackBitcoinTx(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isSupported(chain: Chain): Boolean {
|
override fun isSupported(chain: Chain): Boolean {
|
||||||
return BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN && upstreams.isAvailable(chain)
|
return BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN && multistreamHolder.isAvailable(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun subscribe(request: BlockchainOuterClass.TxStatusRequest): Flux<BlockchainOuterClass.TxStatus> {
|
override fun subscribe(request: BlockchainOuterClass.TxStatusRequest): Flux<BlockchainOuterClass.TxStatus> {
|
||||||
val chain = Chain.byId(request.chainValue)
|
val chain = Chain.byId(request.chainValue)
|
||||||
val upstream = upstreams.getUpstream(chain)?.cast(BitcoinChainUpstreams::class.java)
|
val upstream = multistreamHolder.getUpstream(chain)?.cast(BitcoinMultistream::class.java)
|
||||||
?: return Flux.error(SilentException.UnsupportedBlockchain(chain))
|
?: return Flux.error(SilentException.UnsupportedBlockchain(chain))
|
||||||
val txid = request.txId
|
val txid = request.txId
|
||||||
val confirmations = max(min(1, request.confirmationLimit), 12)
|
val confirmations = max(min(1, request.confirmationLimit), 12)
|
||||||
@@ -61,7 +60,7 @@ class TrackBitcoinTx(
|
|||||||
}.map(this::asProto)
|
}.map(this::asProto)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun subscribe(chain: Chain, upstream: BitcoinChainUpstreams, txid: String): Flux<TxStatus> {
|
fun subscribe(chain: Chain, upstream: BitcoinMultistream, txid: String): Flux<TxStatus> {
|
||||||
return loadExisting(upstream, txid)
|
return loadExisting(upstream, txid)
|
||||||
.flatMapMany { status ->
|
.flatMapMany { status ->
|
||||||
if (status.mined) {
|
if (status.mined) {
|
||||||
@@ -83,7 +82,7 @@ class TrackBitcoinTx(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun continueWithMined(upstream: BitcoinChainUpstreams, status: TxStatus): Flux<TxStatus> {
|
fun continueWithMined(upstream: BitcoinMultistream, status: TxStatus): Flux<TxStatus> {
|
||||||
return upstream.getReader().getBlock(status.blockHash!!)
|
return upstream.getReader().getBlock(status.blockHash!!)
|
||||||
.map { block ->
|
.map { block ->
|
||||||
TxStatus(status.txid, true, ExtractBlock.getHeight(block), true, status.blockHash, ExtractBlock.getTime(block), ExtractBlock.getDifficulty(block))
|
TxStatus(status.txid, true, ExtractBlock.getHeight(block), true, status.blockHash, ExtractBlock.getTime(block), ExtractBlock.getDifficulty(block))
|
||||||
@@ -92,7 +91,7 @@ class TrackBitcoinTx(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun untilFound(chain: Chain, upstream: BitcoinChainUpstreams, txid: String): Flux<TxStatus> {
|
fun untilFound(chain: Chain, upstream: BitcoinMultistream, txid: String): Flux<TxStatus> {
|
||||||
return Flux.interval(Duration.ofSeconds(1))
|
return Flux.interval(Duration.ofSeconds(1))
|
||||||
.take(Duration.ofMinutes(10))
|
.take(Duration.ofMinutes(10))
|
||||||
.flatMap { loadMempool(upstream, txid) }
|
.flatMap { loadMempool(upstream, txid) }
|
||||||
@@ -103,20 +102,20 @@ class TrackBitcoinTx(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun untilMined(upstream: BitcoinChainUpstreams, tx: TxStatus): Mono<TxStatus> {
|
fun untilMined(upstream: BitcoinMultistream, tx: TxStatus): Mono<TxStatus> {
|
||||||
return upstream.getHead().getFlux().flatMap {
|
return upstream.getHead().getFlux().flatMap {
|
||||||
loadExisting(upstream, tx.txid)
|
loadExisting(upstream, tx.txid)
|
||||||
.filter { it.mined }
|
.filter { it.mined }
|
||||||
}.single()
|
}.single()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withConfirmations(upstream: BitcoinChainUpstreams, tx: TxStatus): Flux<TxStatus> {
|
fun withConfirmations(upstream: BitcoinMultistream, tx: TxStatus): Flux<TxStatus> {
|
||||||
return upstream.getHead().getFlux().map {
|
return upstream.getHead().getFlux().map {
|
||||||
tx.withHead(it.height)
|
tx.withHead(it.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadExisting(api: BitcoinChainUpstreams, txid: String): Mono<TxStatus> {
|
fun loadExisting(api: BitcoinMultistream, txid: String): Mono<TxStatus> {
|
||||||
val mined = api.getReader().getTx(txid)
|
val mined = api.getReader().getTx(txid)
|
||||||
return mined.map {
|
return mined.map {
|
||||||
val block = it["blockhash"] as String?
|
val block = it["blockhash"] as String?
|
||||||
@@ -124,7 +123,7 @@ class TrackBitcoinTx(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadMempool(upstream: BitcoinChainUpstreams, txid: String): Mono<TxStatus> {
|
fun loadMempool(upstream: BitcoinMultistream, txid: String): Mono<TxStatus> {
|
||||||
val mempool = upstream.getReader().getMempool().get()
|
val mempool = upstream.getReader().getMempool().get()
|
||||||
return mempool.map {
|
return mempool.map {
|
||||||
if (it.contains(txid)) {
|
if (it.contains(txid)) {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import io.emeraldpay.api.proto.Common
|
|||||||
import io.emeraldpay.dshackle.BlockchainType
|
import io.emeraldpay.dshackle.BlockchainType
|
||||||
import io.emeraldpay.dshackle.Defaults
|
import io.emeraldpay.dshackle.Defaults
|
||||||
import io.emeraldpay.dshackle.SilentException
|
import io.emeraldpay.dshackle.SilentException
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.Address
|
import io.infinitape.etherjar.domain.Address
|
||||||
import io.infinitape.etherjar.domain.Wei
|
import io.infinitape.etherjar.domain.Wei
|
||||||
@@ -34,13 +34,13 @@ import reactor.core.publisher.Mono
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class TrackEthereumAddress(
|
class TrackEthereumAddress(
|
||||||
@Autowired private val upstreams: Upstreams
|
@Autowired private val multistreamHolder: MultistreamHolder
|
||||||
) : TrackAddress {
|
) : TrackAddress {
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(TrackEthereumAddress::class.java)
|
private val log = LoggerFactory.getLogger(TrackEthereumAddress::class.java)
|
||||||
|
|
||||||
override fun isSupported(chain: Chain): Boolean {
|
override fun isSupported(chain: Chain): Boolean {
|
||||||
return BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM && upstreams.isAvailable(chain)
|
return BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBalance(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
override fun getBalance(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
||||||
@@ -51,7 +51,7 @@ class TrackEthereumAddress(
|
|||||||
|
|
||||||
override fun subscribe(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
override fun subscribe(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {
|
||||||
val chain = Chain.byId(request.asset.chainValue)
|
val chain = Chain.byId(request.asset.chainValue)
|
||||||
val head = upstreams.getUpstream(chain)?.getHead()?.getFlux() ?: Flux.empty()
|
val head = multistreamHolder.getUpstream(chain)?.getHead()?.getFlux() ?: Flux.empty()
|
||||||
val balances = initAddress(request)
|
val balances = initAddress(request)
|
||||||
.flatMap { tracked ->
|
.flatMap { tracked ->
|
||||||
val current = getBalance(tracked)
|
val current = getBalance(tracked)
|
||||||
@@ -86,14 +86,14 @@ class TrackEthereumAddress(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUpstream(chain: Chain): EthereumChainUpstream {
|
fun getUpstream(chain: Chain): EthereumMultistream {
|
||||||
return upstreams.getUpstream(chain)?.cast(EthereumChainUpstream::class.java)
|
return multistreamHolder.getUpstream(chain)?.cast(EthereumMultistream::class.java)
|
||||||
?: throw SilentException.UnsupportedBlockchain(chain)
|
?: throw SilentException.UnsupportedBlockchain(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initAddress(request: BlockchainOuterClass.BalanceRequest): Flux<TrackedAddress> {
|
private fun initAddress(request: BlockchainOuterClass.BalanceRequest): Flux<TrackedAddress> {
|
||||||
val chain = Chain.byId(request.asset.chainValue)
|
val chain = Chain.byId(request.asset.chainValue)
|
||||||
if (!upstreams.isAvailable(chain)) {
|
if (!multistreamHolder.isAvailable(chain)) {
|
||||||
return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue))
|
return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue))
|
||||||
}
|
}
|
||||||
if (request.asset.code?.toLowerCase() != "ether") {
|
if (request.asset.code?.toLowerCase() != "ether") {
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import io.emeraldpay.dshackle.BlockchainType
|
|||||||
import io.emeraldpay.dshackle.SilentException
|
import io.emeraldpay.dshackle.SilentException
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.data.TxId
|
import io.emeraldpay.dshackle.data.TxId
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.domain.TransactionId
|
import io.infinitape.etherjar.domain.TransactionId
|
||||||
@@ -48,7 +48,7 @@ import kotlin.math.min
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
class TrackEthereumTx(
|
class TrackEthereumTx(
|
||||||
@Autowired private val upstreams: Upstreams
|
@Autowired private val multistreamHolder: MultistreamHolder
|
||||||
) : TrackTx {
|
) : TrackTx {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -63,7 +63,7 @@ class TrackEthereumTx(
|
|||||||
private val log = LoggerFactory.getLogger(TrackEthereumTx::class.java)
|
private val log = LoggerFactory.getLogger(TrackEthereumTx::class.java)
|
||||||
|
|
||||||
override fun isSupported(chain: Chain): Boolean {
|
override fun isSupported(chain: Chain): Boolean {
|
||||||
return BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM && upstreams.isAvailable(chain)
|
return BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun subscribe(request: BlockchainOuterClass.TxStatusRequest): Flux<BlockchainOuterClass.TxStatus> {
|
override fun subscribe(request: BlockchainOuterClass.TxStatusRequest): Flux<BlockchainOuterClass.TxStatus> {
|
||||||
@@ -83,12 +83,12 @@ class TrackEthereumTx(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getUpstream(chain: Chain): EthereumChainUpstream {
|
fun getUpstream(chain: Chain): EthereumMultistream {
|
||||||
return upstreams.getUpstream(chain)?.cast(EthereumChainUpstream::class.java)
|
return multistreamHolder.getUpstream(chain)?.cast(EthereumMultistream::class.java)
|
||||||
?: throw SilentException.UnsupportedBlockchain(chain)
|
?: throw SilentException.UnsupportedBlockchain(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun subscribe(base: TxDetails, up: EthereumChainUpstream): Flux<TxDetails> {
|
fun subscribe(base: TxDetails, up: EthereumMultistream): Flux<TxDetails> {
|
||||||
var latestTx = base
|
var latestTx = base
|
||||||
|
|
||||||
val untilFound = Mono.just(latestTx)
|
val untilFound = Mono.just(latestTx)
|
||||||
@@ -213,7 +213,7 @@ class TrackEthereumTx(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateFromBlock(upstream: EthereumChainUpstream, tx: TxDetails, blockTx: TransactionJson): Mono<TxDetails> {
|
fun updateFromBlock(upstream: EthereumMultistream, tx: TxDetails, blockTx: TransactionJson): Mono<TxDetails> {
|
||||||
return if (blockTx.blockNumber != null && blockTx.blockHash != null && blockTx.blockHash != ZERO_BLOCK) {
|
return if (blockTx.blockNumber != null && blockTx.blockHash != null && blockTx.blockHash != ZERO_BLOCK) {
|
||||||
val updated = tx.withStatus(
|
val updated = tx.withStatus(
|
||||||
blockHash = blockTx.blockHash,
|
blockHash = blockTx.blockHash,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import io.emeraldpay.dshackle.FileResolver
|
|||||||
import io.emeraldpay.dshackle.cache.CachesFactory
|
import io.emeraldpay.dshackle.cache.CachesFactory
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
import io.emeraldpay.dshackle.reader.Reader
|
||||||
import io.emeraldpay.dshackle.upstream.CurrentUpstreams
|
import io.emeraldpay.dshackle.upstream.CurrentMultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
|
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
|
||||||
@@ -45,7 +45,7 @@ import kotlin.collections.HashMap
|
|||||||
@Repository
|
@Repository
|
||||||
open class ConfiguredUpstreams(
|
open class ConfiguredUpstreams(
|
||||||
@Autowired private val objectMapper: ObjectMapper,
|
@Autowired private val objectMapper: ObjectMapper,
|
||||||
@Autowired private val currentUpstreams: CurrentUpstreams,
|
@Autowired private val currentUpstreams: CurrentMultistreamHolder,
|
||||||
@Autowired private val fileResolver: FileResolver,
|
@Autowired private val fileResolver: FileResolver,
|
||||||
@Autowired private val config: UpstreamsConfig,
|
@Autowired private val config: UpstreamsConfig,
|
||||||
@Autowired private val cachesFactory: CachesFactory
|
@Autowired private val cachesFactory: CachesFactory
|
||||||
@@ -201,8 +201,7 @@ open class ConfiguredUpstreams(
|
|||||||
endpoint.port ?: 2449,
|
endpoint.port ?: 2449,
|
||||||
objectMapper,
|
objectMapper,
|
||||||
endpoint.auth,
|
endpoint.auth,
|
||||||
fileResolver,
|
fileResolver
|
||||||
cachesFactory
|
|
||||||
).apply {
|
).apply {
|
||||||
timeout = options.timeout
|
timeout = options.timeout
|
||||||
}
|
}
|
||||||
@@ -214,7 +213,6 @@ open class ConfiguredUpstreams(
|
|||||||
.subscribe(currentUpstreams::update)
|
.subscribe(currentUpstreams::update)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun buildHttpClient(config: UpstreamsConfig.Upstream<out UpstreamsConfig.RpcConnection>): JsonRpcHttpClient? {
|
private fun buildHttpClient(config: UpstreamsConfig.Upstream<out UpstreamsConfig.RpcConnection>): JsonRpcHttpClient? {
|
||||||
val conn = config.connection!!
|
val conn = config.connection!!
|
||||||
val urls = ArrayList<URI>()
|
val urls = ArrayList<URI>()
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2020 EmeraldPay, Inc
|
|
||||||
* Copyright (c) 2019 ETCDEV GmbH
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package io.emeraldpay.dshackle.upstream
|
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
|
||||||
import io.emeraldpay.grpc.Chain
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import org.springframework.context.Lifecycle
|
|
||||||
import reactor.core.Disposable
|
|
||||||
import reactor.core.publisher.Mono
|
|
||||||
import java.lang.IllegalStateException
|
|
||||||
import java.time.Duration
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General interface to upstream(s) to a single chain
|
|
||||||
*/
|
|
||||||
abstract class ChainUpstreams(
|
|
||||||
val chain: Chain,
|
|
||||||
private val upstreams: MutableList<Upstream>,
|
|
||||||
caches: Caches
|
|
||||||
) : AggregatedUpstream(caches), Lifecycle {
|
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(ChainUpstreams::class.java)
|
|
||||||
private var seq = 0
|
|
||||||
protected var lagObserver: HeadLagObserver? = null
|
|
||||||
private var subscription: Disposable? = null
|
|
||||||
|
|
||||||
open fun init() {
|
|
||||||
onUpstreamsUpdated()
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun updateHead(): Head
|
|
||||||
abstract fun setHead(head: Head)
|
|
||||||
|
|
||||||
override fun getId(): String {
|
|
||||||
return "!all:${chain.chainCode}"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isRunning(): Boolean {
|
|
||||||
return subscription != null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun start() {
|
|
||||||
super.start()
|
|
||||||
subscription = observeStatus()
|
|
||||||
.distinctUntilChanged()
|
|
||||||
.subscribe { printStatus() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun stop() {
|
|
||||||
super.stop()
|
|
||||||
subscription?.dispose()
|
|
||||||
subscription = null
|
|
||||||
getHead().let {
|
|
||||||
if (it is Lifecycle) {
|
|
||||||
it.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lagObserver?.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAll(): List<Upstream> {
|
|
||||||
return upstreams
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addUpstream(upstream: Upstream) {
|
|
||||||
upstreams.add(upstream)
|
|
||||||
setHead(updateHead())
|
|
||||||
onUpstreamsUpdated()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeUpstream(id: String) {
|
|
||||||
if (upstreams.removeIf { it.getId() == id }) {
|
|
||||||
setHead(updateHead())
|
|
||||||
onUpstreamsUpdated()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getApiSource(matcher: Selector.Matcher): ApiSource {
|
|
||||||
val i = seq++
|
|
||||||
if (seq >= Int.MAX_VALUE / 2) {
|
|
||||||
seq = 0
|
|
||||||
}
|
|
||||||
return FilteredApis(upstreams, matcher, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDirectApi(matcher: Selector.Matcher): Mono<Reader<JsonRpcRequest, JsonRpcResponse>> {
|
|
||||||
val apis = getApiSource(matcher)
|
|
||||||
apis.request(1)
|
|
||||||
return Mono.from(apis)
|
|
||||||
.switchIfEmpty(Mono.error(Exception("No API available")))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLag(lag: Long) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLag(): Long {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fun printStatus() {
|
|
||||||
var height: Long? = null
|
|
||||||
try {
|
|
||||||
height = getHead().getFlux().next().block(Duration.ofSeconds(1))?.height
|
|
||||||
} catch (e: IllegalStateException) {
|
|
||||||
//timout
|
|
||||||
} catch (e: Exception) {
|
|
||||||
log.warn("Head processing error: ${e.javaClass} ${e.message}")
|
|
||||||
}
|
|
||||||
val statuses = upstreams.map { it.getStatus() }
|
|
||||||
.groupBy { it }
|
|
||||||
.map { "${it.key.name}/${it.value.size}" }
|
|
||||||
.joinToString(",")
|
|
||||||
val lag = upstreams.map { it.getLag() }
|
|
||||||
.joinToString(", ")
|
|
||||||
|
|
||||||
log.info("State of ${chain.chainCode}: height=${height ?: '?'}, status=$statuses, lag=[$lag]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,12 +21,12 @@ import io.emeraldpay.dshackle.BlockchainType
|
|||||||
import io.emeraldpay.dshackle.cache.CachesEnabled
|
import io.emeraldpay.dshackle.cache.CachesEnabled
|
||||||
import io.emeraldpay.dshackle.cache.CachesFactory
|
import io.emeraldpay.dshackle.cache.CachesFactory
|
||||||
import io.emeraldpay.dshackle.startup.UpstreamChange
|
import io.emeraldpay.dshackle.startup.UpstreamChange
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinChainUpstreams
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
|
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
|
||||||
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
|
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@@ -42,14 +42,14 @@ import java.util.concurrent.locks.ReentrantLock
|
|||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
class CurrentUpstreams(
|
class CurrentMultistreamHolder(
|
||||||
@Autowired private val objectMapper: ObjectMapper,
|
@Autowired private val objectMapper: ObjectMapper,
|
||||||
@Autowired private val cachesFactory: CachesFactory
|
@Autowired private val cachesFactory: CachesFactory
|
||||||
): Upstreams {
|
) : MultistreamHolder {
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(CurrentUpstreams::class.java)
|
private val log = LoggerFactory.getLogger(CurrentMultistreamHolder::class.java)
|
||||||
|
|
||||||
private val chainMapping = ConcurrentHashMap<Chain, ChainUpstreams>()
|
private val chainMapping = ConcurrentHashMap<Chain, Multistream>()
|
||||||
private val chainsBus = TopicProcessor.create<Chain>()
|
private val chainsBus = TopicProcessor.create<Chain>()
|
||||||
private val callTargets = HashMap<Chain, CallMethods>()
|
private val callTargets = HashMap<Chain, CallMethods>()
|
||||||
private val updateLock = ReentrantLock()
|
private val updateLock = ReentrantLock()
|
||||||
@@ -60,17 +60,17 @@ class CurrentUpstreams(
|
|||||||
when (BlockchainType.fromBlockchain(chain)) {
|
when (BlockchainType.fromBlockchain(chain)) {
|
||||||
BlockchainType.ETHEREUM -> {
|
BlockchainType.ETHEREUM -> {
|
||||||
val up = change.upstream.cast(EthereumUpstream::class.java)
|
val up = change.upstream.cast(EthereumUpstream::class.java)
|
||||||
val current = chainMapping[chain] as ChainUpstreams?
|
val current = chainMapping[chain] as Multistream?
|
||||||
val factory = Callable {
|
val factory = Callable {
|
||||||
EthereumChainUpstream(chain, ArrayList(), cachesFactory.getCaches(chain), objectMapper) as ChainUpstreams
|
EthereumMultistream(chain, ArrayList(), cachesFactory.getCaches(chain), objectMapper) as Multistream
|
||||||
}
|
}
|
||||||
processUpdate(change, up, current, factory)
|
processUpdate(change, up, current, factory)
|
||||||
}
|
}
|
||||||
BlockchainType.BITCOIN -> {
|
BlockchainType.BITCOIN -> {
|
||||||
val up = change.upstream.cast(BitcoinUpstream::class.java)
|
val up = change.upstream.cast(BitcoinUpstream::class.java)
|
||||||
val current = chainMapping[chain] as ChainUpstreams?
|
val current = chainMapping[chain] as Multistream?
|
||||||
val factory = Callable {
|
val factory = Callable {
|
||||||
BitcoinChainUpstreams(chain, ArrayList(), cachesFactory.getCaches(chain), objectMapper) as ChainUpstreams
|
BitcoinMultistream(chain, ArrayList(), cachesFactory.getCaches(chain), objectMapper) as Multistream
|
||||||
}
|
}
|
||||||
processUpdate(change, up, current, factory)
|
processUpdate(change, up, current, factory)
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ class CurrentUpstreams(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun processUpdate(change: UpstreamChange, up: Upstream, current: ChainUpstreams?, factory: Callable<ChainUpstreams>) {
|
fun processUpdate(change: UpstreamChange, up: Upstream, current: Multistream?, factory: Callable<Multistream>) {
|
||||||
val chain = change.chain
|
val chain = change.chain
|
||||||
if (change.type == UpstreamChange.ChangeType.REMOVED) {
|
if (change.type == UpstreamChange.ChangeType.REMOVED) {
|
||||||
current?.removeUpstream(up.getId())
|
current?.removeUpstream(up.getId())
|
||||||
@@ -109,7 +109,7 @@ class CurrentUpstreams(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUpstream(chain: Chain): AggregatedUpstream? {
|
override fun getUpstream(chain: Chain): Multistream? {
|
||||||
return chainMapping[chain]
|
return chainMapping[chain]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
import io.emeraldpay.dshackle.cache.*
|
import io.emeraldpay.dshackle.cache.*
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
import io.emeraldpay.dshackle.reader.Reader
|
||||||
@@ -24,6 +23,8 @@ import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods
|
|||||||
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||||
|
import io.emeraldpay.grpc.Chain
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.context.Lifecycle
|
import org.springframework.context.Lifecycle
|
||||||
import reactor.core.Disposable
|
import reactor.core.Disposable
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
@@ -38,33 +39,70 @@ import kotlin.concurrent.withLock
|
|||||||
/**
|
/**
|
||||||
* Aggregation of multiple upstreams responding to a single blockchain
|
* Aggregation of multiple upstreams responding to a single blockchain
|
||||||
*/
|
*/
|
||||||
abstract class AggregatedUpstream(
|
abstract class Multistream(
|
||||||
|
val chain: Chain,
|
||||||
|
private val upstreams: MutableList<Upstream>,
|
||||||
val caches: Caches
|
val caches: Caches
|
||||||
) : Upstream, Lifecycle {
|
) : Upstream, Lifecycle {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val log = LoggerFactory.getLogger(Multistream::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
private var cacheSubscription: Disposable? = null
|
private var cacheSubscription: Disposable? = null
|
||||||
private val reconfigLock = ReentrantLock()
|
private val reconfigLock = ReentrantLock()
|
||||||
private var callMethods: CallMethods? = null
|
private var callMethods: CallMethods? = null
|
||||||
|
private var seq = 0
|
||||||
|
protected var lagObserver: HeadLagObserver? = null
|
||||||
|
private var subscription: Disposable? = null
|
||||||
|
|
||||||
|
open fun init() {
|
||||||
|
onUpstreamsUpdated()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get list of all underlying upstreams
|
* Get list of all underlying upstreams
|
||||||
*/
|
*/
|
||||||
abstract fun getAll(): List<Upstream>
|
fun getAll(): List<Upstream> {
|
||||||
|
return upstreams
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an upstream
|
* Add an upstream
|
||||||
*/
|
*/
|
||||||
abstract fun addUpstream(upstream: Upstream)
|
fun addUpstream(upstream: Upstream) {
|
||||||
|
upstreams.add(upstream)
|
||||||
|
setHead(updateHead())
|
||||||
|
onUpstreamsUpdated()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeUpstream(id: String) {
|
||||||
|
if (upstreams.removeIf { it.getId() == id }) {
|
||||||
|
setHead(updateHead())
|
||||||
|
onUpstreamsUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a source for direct APIs
|
* Get a source for direct APIs
|
||||||
*/
|
*/
|
||||||
abstract fun getApiSource(matcher: Selector.Matcher): ApiSource
|
fun getApiSource(matcher: Selector.Matcher): ApiSource {
|
||||||
|
val i = seq++
|
||||||
|
if (seq >= Int.MAX_VALUE / 2) {
|
||||||
|
seq = 0
|
||||||
|
}
|
||||||
|
return FilteredApis(upstreams, matcher, i)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds an API that executed directly on a remote.
|
* Finds an API that executed directly on a remote.
|
||||||
*/
|
*/
|
||||||
abstract fun getDirectApi(matcher: Selector.Matcher): Mono<Reader<JsonRpcRequest, JsonRpcResponse>>
|
fun getDirectApi(matcher: Selector.Matcher): Mono<Reader<JsonRpcRequest, JsonRpcResponse>> {
|
||||||
|
val apis = getApiSource(matcher)
|
||||||
|
apis.request(1)
|
||||||
|
return Mono.from(apis)
|
||||||
|
.switchIfEmpty(Mono.error(Exception("No API available")))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds an API that leverages caches and other optimizations/transformations of the request.
|
* Finds an API that leverages caches and other optimizations/transformations of the request.
|
||||||
@@ -109,11 +147,22 @@ abstract class AggregatedUpstream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
|
subscription = observeStatus()
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.subscribe { printStatus() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
cacheSubscription?.dispose()
|
cacheSubscription?.dispose()
|
||||||
cacheSubscription = null
|
cacheSubscription = null
|
||||||
|
subscription?.dispose()
|
||||||
|
subscription = null
|
||||||
|
getHead().let {
|
||||||
|
if (it is Lifecycle) {
|
||||||
|
it.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lagObserver?.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onHeadUpdated(head: Head) {
|
fun onHeadUpdated(head: Head) {
|
||||||
@@ -125,6 +174,43 @@ abstract class AggregatedUpstream(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract fun updateHead(): Head
|
||||||
|
abstract fun setHead(head: Head)
|
||||||
|
|
||||||
|
override fun getId(): String {
|
||||||
|
return "!all:${chain.chainCode}"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isRunning(): Boolean {
|
||||||
|
return subscription != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setLag(lag: Long) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLag(): Long {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printStatus() {
|
||||||
|
var height: Long? = null
|
||||||
|
try {
|
||||||
|
height = getHead().getFlux().next().block(Duration.ofSeconds(1))?.height
|
||||||
|
} catch (e: java.lang.IllegalStateException) {
|
||||||
|
//timout
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log.warn("Head processing error: ${e.javaClass} ${e.message}")
|
||||||
|
}
|
||||||
|
val statuses = upstreams.map { it.getStatus() }
|
||||||
|
.groupBy { it }
|
||||||
|
.map { "${it.key.name}/${it.value.size}" }
|
||||||
|
.joinToString(",")
|
||||||
|
val lag = upstreams.map { it.getLag() }
|
||||||
|
.joinToString(", ")
|
||||||
|
|
||||||
|
log.info("State of ${chain.chainCode}: height=${height ?: '?'}, status=$statuses, lag=[$lag]")
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class UpstreamStatus(val upstream: Upstream, val status: UpstreamAvailability, val ts: Instant = Instant.now())
|
class UpstreamStatus(val upstream: Upstream, val status: UpstreamAvailability, val ts: Instant = Instant.now())
|
||||||
@@ -16,16 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
|
||||||
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
import reactor.core.publisher.Mono
|
|
||||||
|
|
||||||
interface Upstreams {
|
/**
|
||||||
fun getUpstream(chain: Chain): AggregatedUpstream?
|
* Holds Multistreams configured for a chain.
|
||||||
|
*/
|
||||||
|
interface MultistreamHolder {
|
||||||
|
fun getUpstream(chain: Chain): Multistream?
|
||||||
fun getAvailable(): List<Chain>
|
fun getAvailable(): List<Chain>
|
||||||
fun observeChains(): Flux<Chain>
|
fun observeChains(): Flux<Chain>
|
||||||
fun getDefaultMethods(chain: Chain): CallMethods
|
fun getDefaultMethods(chain: Chain): CallMethods
|
||||||
@@ -27,20 +27,18 @@ import org.slf4j.LoggerFactory
|
|||||||
import org.springframework.context.Lifecycle
|
import org.springframework.context.Lifecycle
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
|
|
||||||
open class BitcoinChainUpstreams(
|
open class BitcoinMultistream(
|
||||||
chain: Chain,
|
chain: Chain,
|
||||||
val upstreams: MutableList<BitcoinUpstream>,
|
val upstreams: MutableList<BitcoinUpstream>,
|
||||||
caches: Caches,
|
caches: Caches,
|
||||||
private val objectMapper: ObjectMapper
|
private val objectMapper: ObjectMapper
|
||||||
) : ChainUpstreams(chain, upstreams as MutableList<Upstream>, caches), Lifecycle {
|
) : Multistream(chain, upstreams as MutableList<Upstream>, caches), Lifecycle {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val log = LoggerFactory.getLogger(BitcoinChainUpstreams::class.java)
|
private val log = LoggerFactory.getLogger(BitcoinMultistream::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var head: Head? = null
|
private var head: Head? = null
|
||||||
|
|
||||||
//TODO head
|
|
||||||
private var reader = BitcoinReader(this, EmptyHead(), objectMapper)
|
private var reader = BitcoinReader(this, EmptyHead(), objectMapper)
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
@@ -26,7 +26,7 @@ import reactor.core.publisher.Mono
|
|||||||
import reactor.kotlin.core.publisher.cast
|
import reactor.kotlin.core.publisher.cast
|
||||||
|
|
||||||
open class BitcoinReader(
|
open class BitcoinReader(
|
||||||
private val upstreams: BitcoinChainUpstreams,
|
private val upstreams: BitcoinMultistream,
|
||||||
head: Head,
|
head: Head,
|
||||||
private val objectMapper: ObjectMapper
|
private val objectMapper: ObjectMapper
|
||||||
) : Lifecycle {
|
) : Lifecycle {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicReference
|
|||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
open class CachingMempoolData(
|
open class CachingMempoolData(
|
||||||
private val upstreams: BitcoinChainUpstreams,
|
private val upstreams: BitcoinMultistream,
|
||||||
private val head: Head,
|
private val head: Head,
|
||||||
private val objectMapper: ObjectMapper
|
private val objectMapper: ObjectMapper
|
||||||
) : Lifecycle {
|
) : Lifecycle {
|
||||||
|
|||||||
@@ -28,15 +28,15 @@ import org.slf4j.LoggerFactory
|
|||||||
import org.springframework.context.Lifecycle
|
import org.springframework.context.Lifecycle
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
|
|
||||||
open class EthereumChainUpstream(
|
open class EthereumMultistream(
|
||||||
chain: Chain,
|
chain: Chain,
|
||||||
val upstreams: MutableList<EthereumUpstream>,
|
val upstreams: MutableList<EthereumUpstream>,
|
||||||
caches: Caches,
|
caches: Caches,
|
||||||
private val objectMapper: ObjectMapper
|
private val objectMapper: ObjectMapper
|
||||||
) : ChainUpstreams(chain, upstreams as MutableList<Upstream>, caches) {
|
) : Multistream(chain, upstreams as MutableList<Upstream>, caches) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val log = LoggerFactory.getLogger(EthereumChainUpstream::class.java)
|
private val log = LoggerFactory.getLogger(EthereumMultistream::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var head: Head? = null
|
private var head: Head? = null
|
||||||
@@ -21,10 +21,8 @@ import io.emeraldpay.dshackle.cache.Caches
|
|||||||
import io.emeraldpay.dshackle.cache.CurrentBlockCache
|
import io.emeraldpay.dshackle.cache.CurrentBlockCache
|
||||||
import io.emeraldpay.dshackle.data.*
|
import io.emeraldpay.dshackle.data.*
|
||||||
import io.emeraldpay.dshackle.reader.*
|
import io.emeraldpay.dshackle.reader.*
|
||||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
import io.emeraldpay.dshackle.upstream.Multistream
|
||||||
import io.emeraldpay.dshackle.upstream.Selector
|
import io.emeraldpay.dshackle.upstream.Selector
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||||
import io.infinitape.etherjar.domain.Address
|
import io.infinitape.etherjar.domain.Address
|
||||||
@@ -35,7 +33,6 @@ import io.infinitape.etherjar.hex.HexQuantity
|
|||||||
import io.infinitape.etherjar.rpc.RpcException
|
import io.infinitape.etherjar.rpc.RpcException
|
||||||
import io.infinitape.etherjar.rpc.RpcResponseError
|
import io.infinitape.etherjar.rpc.RpcResponseError
|
||||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||||
import io.infinitape.etherjar.rpc.json.BlockTag
|
|
||||||
import io.infinitape.etherjar.rpc.json.TransactionJson
|
import io.infinitape.etherjar.rpc.json.TransactionJson
|
||||||
import io.infinitape.etherjar.rpc.json.TransactionRefJson
|
import io.infinitape.etherjar.rpc.json.TransactionRefJson
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@@ -48,7 +45,7 @@ import java.util.concurrent.TimeoutException
|
|||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
|
|
||||||
open class EthereumReader(
|
open class EthereumReader(
|
||||||
private val up: AggregatedUpstream,
|
private val up: Multistream,
|
||||||
private val caches: Caches,
|
private val caches: Caches,
|
||||||
private val objectMapper: ObjectMapper
|
private val objectMapper: ObjectMapper
|
||||||
) : Lifecycle {
|
) : Lifecycle {
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ import io.emeraldpay.api.proto.BlockchainOuterClass
|
|||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.api.proto.ReactorBlockchainGrpc
|
import io.emeraldpay.api.proto.ReactorBlockchainGrpc
|
||||||
import io.emeraldpay.dshackle.Defaults
|
import io.emeraldpay.dshackle.Defaults
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
|
||||||
import io.emeraldpay.dshackle.cache.CachesEnabled
|
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.data.BlockId
|
import io.emeraldpay.dshackle.data.BlockId
|
||||||
@@ -39,7 +37,6 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
|||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.rpc.*
|
import io.infinitape.etherjar.rpc.*
|
||||||
import io.infinitape.etherjar.rpc.emerald.ReactorEmeraldClient
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.context.Lifecycle
|
import org.springframework.context.Lifecycle
|
||||||
import reactor.core.Disposable
|
import reactor.core.Disposable
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import io.emeraldpay.api.proto.ReactorBlockchainGrpc
|
|||||||
import io.emeraldpay.dshackle.BlockchainType
|
import io.emeraldpay.dshackle.BlockchainType
|
||||||
import io.emeraldpay.dshackle.Defaults
|
import io.emeraldpay.dshackle.Defaults
|
||||||
import io.emeraldpay.dshackle.FileResolver
|
import io.emeraldpay.dshackle.FileResolver
|
||||||
import io.emeraldpay.dshackle.cache.CachesFactory
|
|
||||||
import io.emeraldpay.dshackle.config.AuthConfig
|
import io.emeraldpay.dshackle.config.AuthConfig
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||||
import io.emeraldpay.dshackle.startup.UpstreamChange
|
import io.emeraldpay.dshackle.startup.UpstreamChange
|
||||||
@@ -30,7 +29,6 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcGrpcClient
|
|||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.grpc.ManagedChannelBuilder
|
import io.grpc.ManagedChannelBuilder
|
||||||
import io.grpc.netty.NettyChannelBuilder
|
import io.grpc.netty.NettyChannelBuilder
|
||||||
import io.infinitape.etherjar.rpc.emerald.ReactorEmeraldClient
|
|
||||||
import io.netty.handler.ssl.*
|
import io.netty.handler.ssl.*
|
||||||
import org.apache.commons.lang3.StringUtils
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
import org.apache.commons.lang3.exception.ExceptionUtils
|
||||||
@@ -50,8 +48,7 @@ class GrpcUpstreams(
|
|||||||
private val port: Int,
|
private val port: Int,
|
||||||
private val objectMapper: ObjectMapper,
|
private val objectMapper: ObjectMapper,
|
||||||
private val auth: AuthConfig.ClientTlsAuth? = null,
|
private val auth: AuthConfig.ClientTlsAuth? = null,
|
||||||
private val fileResolver: FileResolver,
|
private val fileResolver: FileResolver
|
||||||
private val cachesFactory: CachesFactory
|
|
||||||
) {
|
) {
|
||||||
private val log = LoggerFactory.getLogger(GrpcUpstreams::class.java)
|
private val log = LoggerFactory.getLogger(GrpcUpstreams::class.java)
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ import io.emeraldpay.dshackle.test.TestingCommons
|
|||||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||||
import io.emeraldpay.dshackle.quorum.NonEmptyQuorum
|
import io.emeraldpay.dshackle.quorum.NonEmptyQuorum
|
||||||
import io.emeraldpay.dshackle.upstream.Selector
|
import io.emeraldpay.dshackle.upstream.Selector
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
||||||
import io.infinitape.etherjar.rpc.RpcException
|
import io.infinitape.etherjar.rpc.RpcException
|
||||||
@@ -44,7 +43,7 @@ class NativeCallSpec extends Specification {
|
|||||||
def "Quorum is applied"() {
|
def "Quorum is applied"() {
|
||||||
setup:
|
setup:
|
||||||
def quorum = Spy(new AlwaysQuorum())
|
def quorum = Spy(new AlwaysQuorum())
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
|
|
||||||
apiMock.answer("eth_test", [], "foo")
|
apiMock.answer("eth_test", [], "foo")
|
||||||
@@ -67,7 +66,7 @@ class NativeCallSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
||||||
|
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
|
|
||||||
apiMock.answerOnce("eth_test", [], null)
|
apiMock.answerOnce("eth_test", [], null)
|
||||||
@@ -93,7 +92,7 @@ class NativeCallSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
||||||
|
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
|
|
||||||
apiMock.answerOnce("eth_test", [], null)
|
apiMock.answerOnce("eth_test", [], null)
|
||||||
@@ -119,7 +118,7 @@ class NativeCallSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
||||||
|
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
ReactorRpcClient rpcClient = Stub(ReactorRpcClient)
|
ReactorRpcClient rpcClient = Stub(ReactorRpcClient)
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
|
|
||||||
@@ -143,7 +142,7 @@ class NativeCallSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
def quorum = Spy(new NonEmptyQuorum(TestingCommons.objectMapper(), 3))
|
||||||
|
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
ReactorRpcClient rpcClient = Stub(ReactorRpcClient)
|
ReactorRpcClient rpcClient = Stub(ReactorRpcClient)
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
|
|
||||||
@@ -167,7 +166,7 @@ class NativeCallSpec extends Specification {
|
|||||||
|
|
||||||
def "Packs call exception into response with id"() {
|
def "Packs call exception into response with id"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||||
when:
|
when:
|
||||||
def resp = nativeCall.processException(new NativeCall.CallFailure(5, new IllegalArgumentException("test test")))
|
def resp = nativeCall.processException(new NativeCall.CallFailure(5, new IllegalArgumentException("test test")))
|
||||||
@@ -184,7 +183,7 @@ class NativeCallSpec extends Specification {
|
|||||||
|
|
||||||
def "Packs unknown exception into response"() {
|
def "Packs unknown exception into response"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||||
when:
|
when:
|
||||||
def resp = nativeCall.processException(new IllegalArgumentException("test test"))
|
def resp = nativeCall.processException(new IllegalArgumentException("test test"))
|
||||||
@@ -200,7 +199,7 @@ class NativeCallSpec extends Specification {
|
|||||||
|
|
||||||
def "Builds normal response"() {
|
def "Builds normal response"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||||
def json = [jsonrpc:"2.0", id:1, result: "foo"]
|
def json = [jsonrpc:"2.0", id:1, result: "foo"]
|
||||||
|
|
||||||
@@ -216,7 +215,7 @@ class NativeCallSpec extends Specification {
|
|||||||
|
|
||||||
def "Returns error for invalid chain"() {
|
def "Returns error for invalid chain"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||||
|
|
||||||
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
|
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
|
||||||
@@ -239,7 +238,7 @@ class NativeCallSpec extends Specification {
|
|||||||
|
|
||||||
def "Returns error for unsupported chain"() {
|
def "Returns error for unsupported chain"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = Mock(Upstreams)
|
def upstreams = Mock(MultistreamHolder)
|
||||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||||
|
|
||||||
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
|
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
|
||||||
@@ -265,7 +264,7 @@ class NativeCallSpec extends Specification {
|
|||||||
//TODO
|
//TODO
|
||||||
def "Calls cache before remote"() {
|
def "Calls cache before remote"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||||
def api = TestingCommons.api()
|
def api = TestingCommons.api()
|
||||||
def upstream = TestingCommons.aggregatedUpstream(api)
|
def upstream = TestingCommons.aggregatedUpstream(api)
|
||||||
@@ -284,7 +283,7 @@ class NativeCallSpec extends Specification {
|
|||||||
//TODO
|
//TODO
|
||||||
def "Uses cached value"() {
|
def "Uses cached value"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||||
def upstream = TestingCommons.aggregatedUpstream(TestingCommons.api())
|
def upstream = TestingCommons.aggregatedUpstream(TestingCommons.api())
|
||||||
|
|
||||||
@@ -303,7 +302,7 @@ class NativeCallSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def quorum = Spy(new AlwaysQuorum())
|
def quorum = Spy(new AlwaysQuorum())
|
||||||
|
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
|
|
||||||
apiMock.answer("eth_test", [], null, 1, new TimeoutException("test 1"))
|
apiMock.answer("eth_test", [], null, 1, new TimeoutException("test 1"))
|
||||||
@@ -329,7 +328,7 @@ class NativeCallSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def quorum = Spy(new BroadcastQuorum(TestingCommons.objectMapper(), 3))
|
def quorum = Spy(new BroadcastQuorum(TestingCommons.objectMapper(), 3))
|
||||||
|
|
||||||
def upstreams = Stub(Upstreams)
|
def upstreams = Stub(MultistreamHolder)
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
|
|
||||||
apiMock.answer("eth_sendRawTransaction", ["0x1234"],
|
apiMock.answer("eth_sendRawTransaction", ["0x1234"],
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import io.emeraldpay.api.proto.Common
|
|||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.test.UpstreamsMock
|
import io.emeraldpay.dshackle.test.MultistreamHolderMock
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
@@ -42,7 +42,7 @@ class StreamHeadSpec extends Specification {
|
|||||||
|
|
||||||
def "Errors on unavailable chain"() {
|
def "Errors on unavailable chain"() {
|
||||||
setup:
|
setup:
|
||||||
def upstreams = new UpstreamsMock(Chain.ETHEREUM, Stub(EthereumUpstream))
|
def upstreams = new MultistreamHolderMock(Chain.ETHEREUM, Stub(EthereumUpstream))
|
||||||
def streamHead = new StreamHead(upstreams)
|
def streamHead = new StreamHead(upstreams)
|
||||||
when:
|
when:
|
||||||
def flux = streamHead.add(
|
def flux = streamHead.add(
|
||||||
@@ -78,7 +78,7 @@ class StreamHeadSpec extends Specification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def upstream = new EthereumUpstreamMock(Chain.ETHEREUM, TestingCommons.api())
|
def upstream = new EthereumUpstreamMock(Chain.ETHEREUM, TestingCommons.api())
|
||||||
def upstreams = new UpstreamsMock(Chain.ETHEREUM, upstream)
|
def upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstream)
|
||||||
def streamHead = new StreamHead(upstreams)
|
def streamHead = new StreamHead(upstreams)
|
||||||
when:
|
when:
|
||||||
def flux = streamHead.add(
|
def flux = streamHead.add(
|
||||||
|
|||||||
@@ -19,18 +19,12 @@ import io.emeraldpay.api.proto.BlockchainOuterClass
|
|||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.data.BlockId
|
import io.emeraldpay.dshackle.data.BlockId
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
|
||||||
import io.emeraldpay.dshackle.test.ReaderMock
|
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.test.UpstreamsMock
|
import io.emeraldpay.dshackle.test.MultistreamHolderMock
|
||||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
|
||||||
import io.emeraldpay.dshackle.upstream.Head
|
import io.emeraldpay.dshackle.upstream.Head
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinChainUpstreams
|
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinReader
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinReader
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
@@ -49,7 +43,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-one-addr.json")
|
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-one-addr.json")
|
||||||
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
when:
|
when:
|
||||||
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], unspents)
|
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], unspents)
|
||||||
|
|
||||||
@@ -64,7 +58,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json")
|
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json")
|
||||||
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
when:
|
when:
|
||||||
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], unspents)
|
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], unspents)
|
||||||
|
|
||||||
@@ -79,7 +73,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json")
|
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json")
|
||||||
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
when:
|
when:
|
||||||
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", "35hK24tcLEWcgNA4JxpvbkNkoAcDGqQPsP"], unspents).sort { it.address.address }
|
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", "35hK24tcLEWcgNA4JxpvbkNkoAcDGqQPsP"], unspents).sort { it.address.address }
|
||||||
|
|
||||||
@@ -99,7 +93,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
|
|
||||||
def "Zero for empty unspents"() {
|
def "Zero for empty unspents"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
when:
|
when:
|
||||||
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], [])
|
def total = track.getTotal(Chain.BITCOIN, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], [])
|
||||||
|
|
||||||
@@ -114,7 +108,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json")
|
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json")
|
||||||
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
def unspents = TestingCommons.objectMapper().readValue(json, List)
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
when:
|
when:
|
||||||
def total = track.getTotal(Chain.BITCOIN, ["16rCmCmbuWDhPjWTrpQGaU3EPdZF7MTdUk", "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], unspents).sort { it.address.address }
|
def total = track.getTotal(Chain.BITCOIN, ["16rCmCmbuWDhPjWTrpQGaU3EPdZF7MTdUk", "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"], unspents).sort { it.address.address }
|
||||||
|
|
||||||
@@ -132,7 +126,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
|
|
||||||
def "One address for single provided"() {
|
def "One address for single provided"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
|
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
|
||||||
.setAddress(
|
.setAddress(
|
||||||
Common.AnyAddress.newBuilder()
|
Common.AnyAddress.newBuilder()
|
||||||
@@ -150,7 +144,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
|
|
||||||
def "Sorted addresses for multiple provided"() {
|
def "Sorted addresses for multiple provided"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
|
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
|
||||||
.setAddress(
|
.setAddress(
|
||||||
Common.AnyAddress.newBuilder()
|
Common.AnyAddress.newBuilder()
|
||||||
@@ -171,7 +165,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
|
|
||||||
def "Null for no address provided"() {
|
def "Null for no address provided"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
|
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
|
||||||
.build()
|
.build()
|
||||||
when:
|
when:
|
||||||
@@ -182,7 +176,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
|
|
||||||
def "Build proto for common balance"() {
|
def "Build proto for common balance"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
def balance = new TrackBitcoinAddress.AddressBalance(Chain.BITCOIN, "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", BigInteger.valueOf(123456))
|
def balance = new TrackBitcoinAddress.AddressBalance(Chain.BITCOIN, "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", BigInteger.valueOf(123456))
|
||||||
when:
|
when:
|
||||||
def act = track.buildResponse(balance)
|
def act = track.buildResponse(balance)
|
||||||
@@ -195,7 +189,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
|
|
||||||
def "Build proto for zero balance"() {
|
def "Build proto for zero balance"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
def balance = new TrackBitcoinAddress.AddressBalance(Chain.BITCOIN, "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", BigInteger.ZERO)
|
def balance = new TrackBitcoinAddress.AddressBalance(Chain.BITCOIN, "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", BigInteger.ZERO)
|
||||||
when:
|
when:
|
||||||
def act = track.buildResponse(balance)
|
def act = track.buildResponse(balance)
|
||||||
@@ -208,7 +202,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
|
|
||||||
def "Build proto for all bitcoins"() {
|
def "Build proto for all bitcoins"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(Upstreams))
|
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
|
||||||
def balance = new TrackBitcoinAddress.AddressBalance(Chain.BITCOIN, "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", BigInteger.valueOf(21_000_000).multiply(BigInteger.TEN.pow(8)))
|
def balance = new TrackBitcoinAddress.AddressBalance(Chain.BITCOIN, "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK", BigInteger.valueOf(21_000_000).multiply(BigInteger.TEN.pow(8)))
|
||||||
when:
|
when:
|
||||||
def act = track.buildResponse(balance)
|
def act = track.buildResponse(balance)
|
||||||
@@ -227,7 +221,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
1 * getFlux() >> Flux.from(blocks)
|
1 * getFlux() >> Flux.from(blocks)
|
||||||
}
|
}
|
||||||
def upstream = null
|
def upstream = null
|
||||||
upstream = Mock(BitcoinChainUpstreams) {
|
upstream = Mock(BitcoinMultistream) {
|
||||||
_ * getReader() >> Mock(BitcoinReader) {
|
_ * getReader() >> Mock(BitcoinReader) {
|
||||||
2 * listUnspent() >>> [
|
2 * listUnspent() >>> [
|
||||||
Mono.just([]),
|
Mono.just([]),
|
||||||
@@ -239,7 +233,7 @@ class TrackBitcoinAddressSpec extends Specification {
|
|||||||
upstream
|
upstream
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.BITCOIN, upstream)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.BITCOIN, upstream)
|
||||||
TrackBitcoinAddress track = new TrackBitcoinAddress(upstreams)
|
TrackBitcoinAddress track = new TrackBitcoinAddress(upstreams)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
|
|||||||
@@ -17,13 +17,10 @@ package io.emeraldpay.dshackle.rpc
|
|||||||
|
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.data.BlockId
|
import io.emeraldpay.dshackle.data.BlockId
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
|
||||||
import io.emeraldpay.dshackle.upstream.Head
|
import io.emeraldpay.dshackle.upstream.Head
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinChainUpstreams
|
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinReader
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinReader
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.CachingMempoolData
|
import io.emeraldpay.dshackle.upstream.bitcoin.CachingMempoolData
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
@@ -38,7 +35,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "loadMempool() returns not found when not found"() {
|
def "loadMempool() returns not found when not found"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
|
|
||||||
CachingMempoolData mempoolAccess = Mock(CachingMempoolData) {
|
CachingMempoolData mempoolAccess = Mock(CachingMempoolData) {
|
||||||
1 * get() >> Mono.just([
|
1 * get() >> Mono.just([
|
||||||
@@ -46,7 +43,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
"d296c6d47335a7f283574b06f1d6303b30ac75631e081ab128346a549ad93350"
|
"d296c6d47335a7f283574b06f1d6303b30ac75631e081ab128346a549ad93350"
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
_ * getReader() >> Mock(BitcoinReader) {
|
_ * getReader() >> Mock(BitcoinReader) {
|
||||||
_ * getMempool() >> mempoolAccess
|
_ * getMempool() >> mempoolAccess
|
||||||
}
|
}
|
||||||
@@ -65,14 +62,14 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "loadMempool() returns ok when found"() {
|
def "loadMempool() returns ok when found"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
CachingMempoolData mempoolAccess = Mock(CachingMempoolData) {
|
CachingMempoolData mempoolAccess = Mock(CachingMempoolData) {
|
||||||
1 * get() >> Mono.just([
|
1 * get() >> Mono.just([
|
||||||
"69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9",
|
"69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9",
|
||||||
"d296c6d47335a7f283574b06f1d6303b30ac75631e081ab128346a549ad93350"
|
"d296c6d47335a7f283574b06f1d6303b30ac75631e081ab128346a549ad93350"
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
_ * getReader() >> Mock(BitcoinReader) {
|
_ * getReader() >> Mock(BitcoinReader) {
|
||||||
_ * getMempool() >> mempoolAccess
|
_ * getMempool() >> mempoolAccess
|
||||||
}
|
}
|
||||||
@@ -91,9 +88,9 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "loadExiting() returns not found if not mined"() {
|
def "loadExiting() returns not found if not mined"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
_ * getReader() >> Mock(BitcoinReader) {
|
_ * getReader() >> Mock(BitcoinReader) {
|
||||||
1 * getTx(txid) >> Mono.just([
|
1 * getTx(txid) >> Mono.just([
|
||||||
txid: txid
|
txid: txid
|
||||||
@@ -114,9 +111,9 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "loadExiting() returns block if mined"() {
|
def "loadExiting() returns block if mined"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
_ * getReader() >> Mock(BitcoinReader) {
|
_ * getReader() >> Mock(BitcoinReader) {
|
||||||
1 * getTx(txid) >> Mono.just([
|
1 * getTx(txid) >> Mono.just([
|
||||||
txid : txid,
|
txid : txid,
|
||||||
@@ -141,7 +138,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "Goes with confirmations"() {
|
def "Goes with confirmations"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
||||||
// start with the current block
|
// start with the current block
|
||||||
def next = Flux.fromIterable([10, 12, 13, 14, 15]).map { h ->
|
def next = Flux.fromIterable([10, 12, 13, 14, 15]).map { h ->
|
||||||
@@ -150,7 +147,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
Head head = Mock(Head) {
|
Head head = Mock(Head) {
|
||||||
1 * getFlux() >> next
|
1 * getFlux() >> next
|
||||||
}
|
}
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
1 * getHead() >> head
|
1 * getHead() >> head
|
||||||
}
|
}
|
||||||
def status = new TrackBitcoinTx.TxStatus(
|
def status = new TrackBitcoinTx.TxStatus(
|
||||||
@@ -172,7 +169,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "Wait until mined"() {
|
def "Wait until mined"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
||||||
// start with the current block
|
// start with the current block
|
||||||
def next = Flux.fromIterable([10, 12, 13]).map { h ->
|
def next = Flux.fromIterable([10, 12, 13]).map { h ->
|
||||||
@@ -196,7 +193,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
])
|
])
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
1 * getHead() >> head
|
1 * getHead() >> head
|
||||||
_ * getReader() >> api
|
_ * getReader() >> api
|
||||||
}
|
}
|
||||||
@@ -215,7 +212,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "Check mempool until found"() {
|
def "Check mempool until found"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
||||||
|
|
||||||
Head head = Mock(Head) {
|
Head head = Mock(Head) {
|
||||||
@@ -235,7 +232,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
])
|
])
|
||||||
_ * getMempool() >> mempoolAccess
|
_ * getMempool() >> mempoolAccess
|
||||||
}
|
}
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
_ * getHead() >> head
|
_ * getHead() >> head
|
||||||
_ * getReader() >> api
|
_ * getReader() >> api
|
||||||
}
|
}
|
||||||
@@ -256,7 +253,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
|
|
||||||
def "Subscribe to an existing tx"() {
|
def "Subscribe to an existing tx"() {
|
||||||
setup:
|
setup:
|
||||||
TrackBitcoinTx track = new TrackBitcoinTx(Stub(Upstreams))
|
TrackBitcoinTx track = new TrackBitcoinTx(Stub(MultistreamHolder))
|
||||||
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
def txid = "69cd44d7c641db82e69824523c7ac0c5c1e5628f025474529cf5ffe64527efc9"
|
||||||
BitcoinReader api = Mock(BitcoinReader) {
|
BitcoinReader api = Mock(BitcoinReader) {
|
||||||
_ * getTx(txid) >> Mono.just([
|
_ * getTx(txid) >> Mono.just([
|
||||||
@@ -276,7 +273,7 @@ class TrackBitcoinTxSpec extends Specification {
|
|||||||
Head head = Mock(Head) {
|
Head head = Mock(Head) {
|
||||||
_ * getFlux() >> next
|
_ * getFlux() >> next
|
||||||
}
|
}
|
||||||
BitcoinChainUpstreams upstream = Mock(BitcoinChainUpstreams) {
|
BitcoinMultistream upstream = Mock(BitcoinMultistream) {
|
||||||
_ * getReader() >> api
|
_ * getReader() >> api
|
||||||
_ * getHead() >> head
|
_ * getHead() >> head
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,21 +19,12 @@ package io.emeraldpay.dshackle.rpc
|
|||||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.test.UpstreamsMock
|
import io.emeraldpay.dshackle.test.MultistreamHolderMock
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumReader
|
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.Address
|
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
|
||||||
import io.infinitape.etherjar.rpc.RpcCall
|
|
||||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||||
import reactor.core.publisher.Flux
|
|
||||||
import reactor.core.publisher.Mono
|
|
||||||
import reactor.core.publisher.TopicProcessor
|
|
||||||
import reactor.core.scheduler.Schedulers
|
|
||||||
import reactor.test.StepVerifier
|
import reactor.test.StepVerifier
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
@@ -66,7 +57,7 @@ class TrackEthereumAddressSpec extends Specification {
|
|||||||
|
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
TrackEthereumAddress trackAddress = new TrackEthereumAddress(upstreams)
|
TrackEthereumAddress trackAddress = new TrackEthereumAddress(upstreams)
|
||||||
|
|
||||||
apiMock.answer("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")
|
apiMock.answer("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")
|
||||||
@@ -106,7 +97,7 @@ class TrackEthereumAddressSpec extends Specification {
|
|||||||
|
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
TrackEthereumAddress trackAddress = new TrackEthereumAddress(upstreams)
|
TrackEthereumAddress trackAddress = new TrackEthereumAddress(upstreams)
|
||||||
|
|
||||||
apiMock.answerOnce("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")
|
apiMock.answerOnce("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ import io.emeraldpay.dshackle.data.BlockContainer
|
|||||||
import io.emeraldpay.dshackle.data.BlockId
|
import io.emeraldpay.dshackle.data.BlockId
|
||||||
import io.emeraldpay.dshackle.data.TxId
|
import io.emeraldpay.dshackle.data.TxId
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.test.UpstreamsMock
|
import io.emeraldpay.dshackle.test.MultistreamHolderMock
|
||||||
import io.emeraldpay.dshackle.upstream.Head
|
import io.emeraldpay.dshackle.upstream.Head
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.domain.TransactionId
|
import io.infinitape.etherjar.domain.TransactionId
|
||||||
@@ -98,7 +98,7 @@ class TrackEthereumTxSpec extends Specification {
|
|||||||
|
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
||||||
|
|
||||||
apiMock.answer("eth_getTransactionByHash", [txId], txJson)
|
apiMock.answer("eth_getTransactionByHash", [txId], txJson)
|
||||||
@@ -118,8 +118,8 @@ class TrackEthereumTxSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
((EthereumChainUpstream) upstreams.getUpstream(Chain.ETHEREUM)).head = Mock(Head) {
|
((EthereumMultistream) upstreams.getUpstream(Chain.ETHEREUM)).head = Mock(Head) {
|
||||||
_ * getFlux() >> Flux.empty()
|
_ * getFlux() >> Flux.empty()
|
||||||
}
|
}
|
||||||
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
||||||
@@ -131,7 +131,7 @@ class TrackEthereumTxSpec extends Specification {
|
|||||||
when:
|
when:
|
||||||
def tx = new TrackEthereumTx.TxDetails(Chain.ETHEREUM, Instant.now(), TransactionId.from(txId), 6)
|
def tx = new TrackEthereumTx.TxDetails(Chain.ETHEREUM, Instant.now(), TransactionId.from(txId), 6)
|
||||||
def act = StepVerifier.withVirtualTime(
|
def act = StepVerifier.withVirtualTime(
|
||||||
{ trackTx.subscribe(tx, upstreams.getUpstream(Chain.ETHEREUM).cast(EthereumChainUpstream)) },
|
{ trackTx.subscribe(tx, upstreams.getUpstream(Chain.ETHEREUM).cast(EthereumMultistream)) },
|
||||||
{ scheduler },
|
{ scheduler },
|
||||||
5)
|
5)
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ class TrackEthereumTxSpec extends Specification {
|
|||||||
|
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
||||||
def scheduler = VirtualTimeScheduler.create(true)
|
def scheduler = VirtualTimeScheduler.create(true)
|
||||||
trackTx.scheduler = scheduler
|
trackTx.scheduler = scheduler
|
||||||
@@ -193,7 +193,7 @@ class TrackEthereumTxSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
||||||
|
|
||||||
def tx = new TrackEthereumTx.TxDetails(Chain.ETHEREUM, Instant.now(), TransactionId.from(txId), 6)
|
def tx = new TrackEthereumTx.TxDetails(Chain.ETHEREUM, Instant.now(), TransactionId.from(txId), 6)
|
||||||
@@ -215,7 +215,7 @@ class TrackEthereumTxSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
||||||
|
|
||||||
def tx = new TrackEthereumTx.TxDetails(Chain.ETHEREUM, Instant.now(), TransactionId.from(txId), 6)
|
def tx = new TrackEthereumTx.TxDetails(Chain.ETHEREUM, Instant.now(), TransactionId.from(txId), 6)
|
||||||
@@ -288,7 +288,7 @@ class TrackEthereumTxSpec extends Specification {
|
|||||||
|
|
||||||
def apiMock = TestingCommons.api()
|
def apiMock = TestingCommons.api()
|
||||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
MultistreamHolder upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstreamMock)
|
||||||
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams)
|
||||||
|
|
||||||
apiMock.answerOnce("eth_getTransactionByHash", [txId], null)
|
apiMock.answerOnce("eth_getTransactionByHash", [txId], null)
|
||||||
|
|||||||
@@ -16,47 +16,47 @@
|
|||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.test
|
package io.emeraldpay.dshackle.test
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
import io.emeraldpay.dshackle.BlockchainType
|
import io.emeraldpay.dshackle.BlockchainType
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
import io.emeraldpay.dshackle.upstream.Multistream
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinChainUpstreams
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
|
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.MultistreamHolder
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumReader
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumReader
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import org.jetbrains.annotations.NotNull
|
import org.jetbrains.annotations.NotNull
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
|
|
||||||
class UpstreamsMock implements Upstreams {
|
class MultistreamHolderMock implements MultistreamHolder {
|
||||||
|
|
||||||
private Map<Chain, DefaultEthereumMethods> target = [:]
|
private Map<Chain, DefaultEthereumMethods> target = [:]
|
||||||
private Map<Chain, AggregatedUpstream> upstreams = [:]
|
private Map<Chain, Multistream> upstreams = [:]
|
||||||
|
|
||||||
UpstreamsMock(Chain chain, Upstream up) {
|
MultistreamHolderMock(Chain chain, Upstream up) {
|
||||||
addUpstream(chain, up)
|
addUpstream(chain, up)
|
||||||
}
|
}
|
||||||
|
|
||||||
AggregatedUpstream addUpstream(@NotNull Chain chain, @NotNull Upstream up) {
|
Multistream addUpstream(@NotNull Chain chain, @NotNull Upstream up) {
|
||||||
if (!upstreams.containsKey(chain)) {
|
if (!upstreams.containsKey(chain)) {
|
||||||
if (BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM) {
|
if (BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM) {
|
||||||
if (up instanceof EthereumChainUpstream) {
|
if (up instanceof EthereumMultistream) {
|
||||||
upstreams[chain] = up
|
upstreams[chain] = up
|
||||||
} else if (up instanceof EthereumUpstream) {
|
} else if (up instanceof EthereumUpstream) {
|
||||||
upstreams[chain] = new EthereumChainUpstreamMock(chain, [up as EthereumUpstream], Caches.default(TestingCommons.objectMapper()))
|
upstreams[chain] = new EthereumMultistreamMock(chain, [up as EthereumUpstream], Caches.default(TestingCommons.objectMapper()))
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unsupported upstream type ${up.class}")
|
throw new IllegalArgumentException("Unsupported upstream type ${up.class}")
|
||||||
}
|
}
|
||||||
upstreams[chain].start()
|
upstreams[chain].start()
|
||||||
} else if (BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN) {
|
} else if (BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN) {
|
||||||
if (up instanceof BitcoinChainUpstreams) {
|
if (up instanceof BitcoinMultistream) {
|
||||||
upstreams[chain] = up
|
upstreams[chain] = up
|
||||||
} else if (up instanceof BitcoinUpstream) {
|
} else if (up instanceof BitcoinUpstream) {
|
||||||
upstreams[chain] = new BitcoinChainUpstreams(chain, [up as BitcoinUpstream], Caches.default(TestingCommons.objectMapper()), TestingCommons.objectMapper())
|
upstreams[chain] = new BitcoinMultistream(chain, [up as BitcoinUpstream], Caches.default(TestingCommons.objectMapper()), TestingCommons.objectMapper())
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unsupported upstream type ${up.class}")
|
throw new IllegalArgumentException("Unsupported upstream type ${up.class}")
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ class UpstreamsMock implements Upstreams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
AggregatedUpstream getUpstream(@NotNull Chain chain) {
|
Multistream getUpstream(@NotNull Chain chain) {
|
||||||
return upstreams[chain]
|
return upstreams[chain]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,11 +97,11 @@ class UpstreamsMock implements Upstreams {
|
|||||||
return upstreams.containsKey(chain)
|
return upstreams.containsKey(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EthereumChainUpstreamMock extends EthereumChainUpstream {
|
static class EthereumMultistreamMock extends EthereumMultistream {
|
||||||
|
|
||||||
EthereumReader customReader = null
|
EthereumReader customReader = null
|
||||||
|
|
||||||
EthereumChainUpstreamMock(@NotNull Chain chain, @NotNull List<EthereumUpstream> upstreams, @NotNull Caches caches) {
|
EthereumMultistreamMock(@NotNull Chain chain, @NotNull List<EthereumUpstream> upstreams, @NotNull Caches caches) {
|
||||||
super(chain, upstreams, caches, TestingCommons.objectMapper())
|
super(chain, upstreams, caches, TestingCommons.objectMapper())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,9 +25,9 @@ import io.emeraldpay.dshackle.cache.Caches
|
|||||||
import io.emeraldpay.dshackle.cache.CachesFactory
|
import io.emeraldpay.dshackle.cache.CachesFactory
|
||||||
import io.emeraldpay.dshackle.config.CacheConfig
|
import io.emeraldpay.dshackle.config.CacheConfig
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
import io.emeraldpay.dshackle.reader.Reader
|
||||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
import io.emeraldpay.dshackle.upstream.Multistream
|
||||||
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||||
@@ -71,12 +71,12 @@ class TestingCommons {
|
|||||||
return new EthereumUpstreamMock(Chain.ETHEREUM, api, new DirectCallMethods(methods))
|
return new EthereumUpstreamMock(Chain.ETHEREUM, api, new DirectCallMethods(methods))
|
||||||
}
|
}
|
||||||
|
|
||||||
static AggregatedUpstream aggregatedUpstream(Reader<JsonRpcRequest, JsonRpcResponse> api) {
|
static Multistream aggregatedUpstream(Reader<JsonRpcRequest, JsonRpcResponse> api) {
|
||||||
return aggregatedUpstream(upstream(api))
|
return aggregatedUpstream(upstream(api))
|
||||||
}
|
}
|
||||||
|
|
||||||
static AggregatedUpstream aggregatedUpstream(EthereumUpstream up) {
|
static Multistream aggregatedUpstream(EthereumUpstream up) {
|
||||||
return new EthereumChainUpstream(Chain.ETHEREUM, [up], Caches.default(objectMapper()), objectMapper())
|
return new EthereumMultistream(Chain.ETHEREUM, [up], Caches.default(objectMapper()), objectMapper())
|
||||||
}
|
}
|
||||||
|
|
||||||
static CachesFactory emptyCaches() {
|
static CachesFactory emptyCaches() {
|
||||||
|
|||||||
@@ -19,14 +19,13 @@ import io.emeraldpay.dshackle.startup.UpstreamChange
|
|||||||
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class CurrentUpstreamsSpec extends Specification {
|
class CurrentMultistreamHolderSpec extends Specification {
|
||||||
|
|
||||||
def "add upstream"() {
|
def "add upstream"() {
|
||||||
setup:
|
setup:
|
||||||
def current = new CurrentUpstreams(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
def current = new CurrentMultistreamHolder(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
||||||
def up = new EthereumUpstreamMock("test", Chain.ETHEREUM, TestingCommons.api())
|
def up = new EthereumUpstreamMock("test", Chain.ETHEREUM, TestingCommons.api())
|
||||||
when:
|
when:
|
||||||
current.update(new UpstreamChange(Chain.ETHEREUM, up, UpstreamChange.ChangeType.ADDED))
|
current.update(new UpstreamChange(Chain.ETHEREUM, up, UpstreamChange.ChangeType.ADDED))
|
||||||
@@ -37,7 +36,7 @@ class CurrentUpstreamsSpec extends Specification {
|
|||||||
|
|
||||||
def "add multiple upstreams"() {
|
def "add multiple upstreams"() {
|
||||||
setup:
|
setup:
|
||||||
def current = new CurrentUpstreams(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
def current = new CurrentMultistreamHolder(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
||||||
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
|
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
|
||||||
def up2 = new EthereumUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
|
def up2 = new EthereumUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
|
||||||
def up3 = new EthereumUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
|
def up3 = new EthereumUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
|
||||||
@@ -53,7 +52,7 @@ class CurrentUpstreamsSpec extends Specification {
|
|||||||
|
|
||||||
def "remove upstream"() {
|
def "remove upstream"() {
|
||||||
setup:
|
setup:
|
||||||
def current = new CurrentUpstreams(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
def current = new CurrentMultistreamHolder(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
||||||
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
|
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
|
||||||
def up2 = new EthereumUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
|
def up2 = new EthereumUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
|
||||||
def up3 = new EthereumUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
|
def up3 = new EthereumUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
|
||||||
@@ -71,7 +70,7 @@ class CurrentUpstreamsSpec extends Specification {
|
|||||||
|
|
||||||
def "available after adding"() {
|
def "available after adding"() {
|
||||||
setup:
|
setup:
|
||||||
def current = new CurrentUpstreams(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
def current = new CurrentMultistreamHolder(TestingCommons.objectMapper(), TestingCommons.emptyCaches())
|
||||||
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
|
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
|
||||||
|
|
||||||
when:
|
when:
|
||||||
@@ -21,17 +21,17 @@ import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
|||||||
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class AggregatedUpstreamSpec extends Specification {
|
class MultistreamSpec extends Specification {
|
||||||
|
|
||||||
def "Aggregates methods"() {
|
def "Aggregates methods"() {
|
||||||
setup:
|
setup:
|
||||||
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test1", "eth_test2"]))
|
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test1", "eth_test2"]))
|
||||||
def up2 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test2", "eth_test3"]))
|
def up2 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test2", "eth_test3"]))
|
||||||
def aggr = new EthereumChainUpstream(Chain.ETHEREUM, [up1, up2], Caches.default(TestingCommons.objectMapper()), TestingCommons.objectMapper())
|
def aggr = new EthereumMultistream(Chain.ETHEREUM, [up1, up2], Caches.default(TestingCommons.objectMapper()), TestingCommons.objectMapper())
|
||||||
when:
|
when:
|
||||||
aggr.onUpstreamsUpdated()
|
aggr.onUpstreamsUpdated()
|
||||||
def act = aggr.getMethods()
|
def act = aggr.getMethods()
|
||||||
@@ -17,26 +17,18 @@ package io.emeraldpay.dshackle.upstream.ethereum
|
|||||||
|
|
||||||
import io.emeraldpay.dshackle.cache.BlocksMemCache
|
import io.emeraldpay.dshackle.cache.BlocksMemCache
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.cache.HeightCache
|
|
||||||
import io.emeraldpay.dshackle.cache.TxMemCache
|
import io.emeraldpay.dshackle.cache.TxMemCache
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.data.BlockId
|
import io.emeraldpay.dshackle.data.BlockId
|
||||||
import io.emeraldpay.dshackle.data.TxContainer
|
import io.emeraldpay.dshackle.data.TxContainer
|
||||||
import io.emeraldpay.dshackle.data.TxId
|
|
||||||
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.test.UpstreamsMock
|
import io.emeraldpay.dshackle.upstream.Multistream
|
||||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
|
||||||
import io.emeraldpay.dshackle.upstream.Head
|
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.Address
|
import io.infinitape.etherjar.domain.Address
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.domain.TransactionId
|
import io.infinitape.etherjar.domain.TransactionId
|
||||||
import io.infinitape.etherjar.domain.Wei
|
import io.infinitape.etherjar.domain.Wei
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
|
||||||
import io.infinitape.etherjar.rpc.RpcException
|
|
||||||
import io.infinitape.etherjar.rpc.RpcResponseError
|
|
||||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||||
import io.infinitape.etherjar.rpc.json.TransactionJson
|
import io.infinitape.etherjar.rpc.json.TransactionJson
|
||||||
import io.infinitape.etherjar.rpc.json.TransactionRefJson
|
import io.infinitape.etherjar.rpc.json.TransactionRefJson
|
||||||
@@ -44,7 +36,6 @@ import reactor.core.publisher.Mono
|
|||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.temporal.ChronoUnit
|
|
||||||
|
|
||||||
class EthereumReaderSpec extends Specification {
|
class EthereumReaderSpec extends Specification {
|
||||||
|
|
||||||
@@ -73,7 +64,7 @@ class EthereumReaderSpec extends Specification {
|
|||||||
.setBlockByHash(memCache)
|
.setBlockByHash(memCache)
|
||||||
.setObjectMapper(TestingCommons.objectMapper())
|
.setObjectMapper(TestingCommons.objectMapper())
|
||||||
.build()
|
.build()
|
||||||
def reader = new EthereumReader(Stub(AggregatedUpstream), caches, TestingCommons.objectMapper())
|
def reader = new EthereumReader(Stub(Multistream), caches, TestingCommons.objectMapper())
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def act = reader.blocksById().read(blockId).block()
|
def act = reader.blocksById().read(blockId).block()
|
||||||
@@ -135,7 +126,7 @@ class EthereumReaderSpec extends Specification {
|
|||||||
.setBlockByHash(memCache)
|
.setBlockByHash(memCache)
|
||||||
.setObjectMapper(TestingCommons.objectMapper())
|
.setObjectMapper(TestingCommons.objectMapper())
|
||||||
.build()
|
.build()
|
||||||
def reader = new EthereumReader(Stub(AggregatedUpstream), caches, TestingCommons.objectMapper())
|
def reader = new EthereumReader(Stub(Multistream), caches, TestingCommons.objectMapper())
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def act = reader.blocksByHash().read(blockJson.hash).block()
|
def act = reader.blocksByHash().read(blockJson.hash).block()
|
||||||
@@ -174,7 +165,7 @@ class EthereumReaderSpec extends Specification {
|
|||||||
.setTxByHash(memCache)
|
.setTxByHash(memCache)
|
||||||
.setObjectMapper(TestingCommons.objectMapper())
|
.setObjectMapper(TestingCommons.objectMapper())
|
||||||
.build()
|
.build()
|
||||||
def reader = new EthereumReader(Stub(AggregatedUpstream), caches, TestingCommons.objectMapper())
|
def reader = new EthereumReader(Stub(Multistream), caches, TestingCommons.objectMapper())
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def act = reader.txByHash().read(txJson.hash).block()
|
def act = reader.txByHash().read(txJson.hash).block()
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcGrpcClient
|
|||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.grpc.stub.StreamObserver
|
import io.grpc.stub.StreamObserver
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
|
||||||
import io.infinitape.etherjar.rpc.emerald.ReactorEmeraldClient
|
|
||||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user