problem: doesn't return ERC20 balance

This commit is contained in:
Igor Artamonov
2022-01-20 22:06:35 -05:00
parent 438ee1dfe9
commit 88fecff429
4 changed files with 58 additions and 1 deletions

View File

@@ -21,5 +21,9 @@ import org.reactivestreams.Publisher
interface ApiSource : Publisher<Upstream> {
fun resolve()
/**
* Must be called before actual use, it spins off control flow of the API Source
*/
fun request(tries: Int)
}

View File

@@ -35,6 +35,7 @@ import kotlin.math.min
import kotlin.math.pow
import kotlin.math.roundToLong
import kotlin.random.Random
import org.slf4j.LoggerFactory
class FilteredApis(
val chain: Chain,
@@ -49,6 +50,8 @@ class FilteredApis(
) : ApiSource {
companion object {
private val log = LoggerFactory.getLogger(FilteredApis::class.java)
private const val DEFAULT_DELAY_STEP = 100
private const val MAX_WAIT_MILLIS = 5000L
@@ -86,6 +89,7 @@ class FilteredApis(
private val secondaryUpstreams: List<Upstream>
private val standardWithFallback: List<Upstream>
private var started = false
private val control = Sinks.many().unicast().onBackpressureBuffer<Boolean>()
init {
@@ -176,6 +180,12 @@ class FilteredApis(
result.filter { up -> up.isAvailable() && matcher.matches(up) }
.zipWith(control.asFlux())
.map { it.t1 }
.doOnSubscribe {
if (!started) {
// in addition to subscription the FilteredAPI should use request() method to prepare the control flow
log.warn("API Source subscribed before preparing a request")
}
}
.subscribe(subscriber)
}
@@ -184,6 +194,7 @@ class FilteredApis(
}
override fun request(tries: Int) {
started = true
// TODO check the buffer size before submitting
repeat(tries) {
control.tryEmitNext(true)

View File

@@ -15,6 +15,7 @@
*/
package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.upstream.ApiSource
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
@@ -41,10 +42,18 @@ open class ERC20Balance {
return upstreams
// use only up-to-date upstreams
.getApiSource(Selector.HeightMatcher(upstreams.getHead().getCurrentHeight() ?: 0))
.let { Flux.from(it) }
.let { getBalance(it, token, address) }
}
open fun getBalance(apis: ApiSource, token: ERC20Token, address: Address): Mono<BigInteger> {
apis.request(1)
return Flux.from(apis)
.flatMap {
getBalance(it.cast(EthereumUpstream::class.java), token, address)
}
.doOnNext {
apis.resolve()
}
.next()
}