Add hyperliquid native tx labels for routing (#713)
* Add hyperliquid native tx labels for routing
This commit is contained in:
@@ -11,6 +11,7 @@ import io.emeraldpay.dshackle.upstream.Upstream
|
|||||||
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
|
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
const val ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
|
const val ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
|
||||||
|
|
||||||
@@ -22,13 +23,15 @@ class EthereumUpstreamSettingsDetector(
|
|||||||
private val notArchived = upstream
|
private val notArchived = upstream
|
||||||
.getLabels()
|
.getLabels()
|
||||||
.find { it.getOrDefault("archive", "") == "false" } != null
|
.find { it.getOrDefault("archive", "") == "false" } != null
|
||||||
|
private var detectCounter = AtomicInteger(1)
|
||||||
override fun internalDetectLabels(): Flux<Pair<String, String>> {
|
override fun internalDetectLabels(): Flux<Pair<String, String>> {
|
||||||
|
detectCounter.incrementAndGet()
|
||||||
return Flux.merge(
|
return Flux.merge(
|
||||||
detectNodeType(),
|
detectNodeType(),
|
||||||
detectArchiveNode(notArchived),
|
detectArchiveNode(notArchived),
|
||||||
detectGasLabels(),
|
detectGasLabels(),
|
||||||
detectFlashBlocks(),
|
detectFlashBlocks(),
|
||||||
|
detectHlNativeTx(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +123,81 @@ class EthereumUpstreamSettingsDetector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Some clients on hyperliquid don't include system topup transactions, set either one of labels
|
||||||
|
*/
|
||||||
|
private fun detectHlNativeTx(): Flux<Pair<String, String>> {
|
||||||
|
// Only run HL native tx detection on Hyperliquid chains
|
||||||
|
if (chain != Chain.HYPERLIQUID__MAINNET && chain != Chain.HYPERLIQUID__TESTNET) {
|
||||||
|
return Flux.empty()
|
||||||
|
}
|
||||||
|
if (detectCounter.get() % 5 != 1) {
|
||||||
|
return Flux.empty() // reduce frequency of detection
|
||||||
|
}
|
||||||
|
val blocksToCheck = 300 // as of now, native tx occurs about once in 30 blocks on average, have 10x leeway here...
|
||||||
|
return upstream.getIngressReader().read(
|
||||||
|
ChainRequest(
|
||||||
|
"eth_blockNumber",
|
||||||
|
ListParams(),
|
||||||
|
),
|
||||||
|
).flatMap {
|
||||||
|
it.requireResult()
|
||||||
|
}.flatMapMany { latestBlockBytes ->
|
||||||
|
val latestBlockHex = String(latestBlockBytes).trim().replace("\"", "")
|
||||||
|
val latestBlockNumber = latestBlockHex.drop(2).toBigInteger(16)
|
||||||
|
val blockChecks = (0L until blocksToCheck).map { offset ->
|
||||||
|
val blockNumber = latestBlockNumber - offset.toBigInteger()
|
||||||
|
val blockHex = "0x" + blockNumber.toString(16)
|
||||||
|
upstream.getIngressReader().read(
|
||||||
|
ChainRequest(
|
||||||
|
"eth_getBlockReceipts",
|
||||||
|
ListParams(blockHex),
|
||||||
|
),
|
||||||
|
).flatMap {
|
||||||
|
it.requireResult()
|
||||||
|
}.flatMap { receiptsBytes ->
|
||||||
|
val receiptsJson = Global.objectMapper.readValue(receiptsBytes, JsonNode::class.java)
|
||||||
|
var foundHlNativeTx = false
|
||||||
|
if (receiptsJson.isArray) {
|
||||||
|
receiptsJson.forEach { receipt ->
|
||||||
|
val from = receipt.get("from")?.asText()
|
||||||
|
if (from == "0x2222222222222222222222222222222222222222") { // system topup transaction
|
||||||
|
foundHlNativeTx = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mono.just(foundHlNativeTx)
|
||||||
|
}.onErrorResume {
|
||||||
|
log.error("${upstream.getId()} Error during HL native tx detection: ${it.message}")
|
||||||
|
Mono.empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Flux.fromIterable(blockChecks)
|
||||||
|
.flatMap { it }
|
||||||
|
.any { it }
|
||||||
|
.flatMapMany { hasHlNativeTx ->
|
||||||
|
if (hasHlNativeTx) {
|
||||||
|
Flux.fromIterable(
|
||||||
|
listOf(
|
||||||
|
Pair("include_hl_native_tx", "true"),
|
||||||
|
Pair("exclude_hl_native_tx", "false"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Flux.fromIterable(
|
||||||
|
listOf(
|
||||||
|
Pair("include_hl_native_tx", "false"),
|
||||||
|
Pair("exclude_hl_native_tx", "true"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.onErrorResume {
|
||||||
|
log.error("${upstream.getId()} Can't determine HL native tx status: ${it.message}")
|
||||||
|
Flux.empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun detectArchiveNode(notArchived: Boolean): Mono<Pair<String, String>> {
|
private fun detectArchiveNode(notArchived: Boolean): Mono<Pair<String, String>> {
|
||||||
if (notArchived) {
|
if (notArchived) {
|
||||||
return Mono.empty()
|
return Mono.empty()
|
||||||
|
|||||||
Reference in New Issue
Block a user