Implement two way communication with Dero node.
- Implemented basic two way communication with the Dero node. The Bridge is listening for Dero node updates and requests the Block Height when receiving a Height update from the node. - Renamed Bridge to StargateBridge and added basic documentation. - Created model for DeroNode instances. We use only one node for now, but will add more down the line.
This commit is contained in:
parent
8b9727082a
commit
8189b590d3
4 changed files with 75 additions and 37 deletions
|
@ -5,19 +5,19 @@ import cafe.adriel.voyager.core.model.screenModelScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.IO
|
import kotlinx.coroutines.IO
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.agorise.shared.stargate.Bridge
|
import net.agorise.shared.stargate.StargateBridge
|
||||||
|
|
||||||
class ImportAccountScreenModel : ScreenModel {
|
class ImportAccountScreenModel : ScreenModel {
|
||||||
private val bridge = Bridge()
|
private val stargateBridge = StargateBridge()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
screenModelScope.launch(Dispatchers.IO) {
|
screenModelScope.launch(Dispatchers.IO) {
|
||||||
bridge.start()
|
stargateBridge.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDispose() {
|
override fun onDispose() {
|
||||||
super.onDispose()
|
super.onDispose()
|
||||||
bridge.stop()
|
stargateBridge.stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
package net.agorise.shared.stargate
|
|
||||||
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import io.ktor.client.engine.cio.CIO
|
|
||||||
import io.ktor.client.plugins.websocket.DefaultClientWebSocketSession
|
|
||||||
import io.ktor.client.plugins.websocket.WebSockets
|
|
||||||
import io.ktor.client.plugins.websocket.webSocket
|
|
||||||
import io.ktor.http.HttpMethod
|
|
||||||
import io.ktor.websocket.Frame
|
|
||||||
import io.ktor.websocket.readText
|
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
|
||||||
|
|
||||||
class Bridge {
|
|
||||||
private val client: HttpClient = HttpClient(CIO) { install(WebSockets) }
|
|
||||||
|
|
||||||
suspend fun start() {
|
|
||||||
client.webSocket(method = HttpMethod.Get, host = "node.derofoundation.org", port = 11012, path = "/ws") {
|
|
||||||
outputMessages()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stop() {
|
|
||||||
client.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun DefaultClientWebSocketSession.outputMessages() {
|
|
||||||
incoming.receiveAsFlow().collect { message ->
|
|
||||||
(message as? Frame.Text)?.let { textFrame ->
|
|
||||||
println(textFrame.readText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.agorise.shared.stargate
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Dero node
|
||||||
|
*
|
||||||
|
* @param host The host or base url of the node
|
||||||
|
* @param port The port of the node
|
||||||
|
* @param path The path of the node
|
||||||
|
*/
|
||||||
|
data class DeroNode(
|
||||||
|
val host: String,
|
||||||
|
val port: Int,
|
||||||
|
val path: String,
|
||||||
|
)
|
|
@ -0,0 +1,57 @@
|
||||||
|
package net.agorise.shared.stargate
|
||||||
|
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.engine.cio.CIO
|
||||||
|
import io.ktor.client.plugins.websocket.DefaultClientWebSocketSession
|
||||||
|
import io.ktor.client.plugins.websocket.WebSockets
|
||||||
|
import io.ktor.client.plugins.websocket.webSocket
|
||||||
|
import io.ktor.websocket.Frame
|
||||||
|
import io.ktor.websocket.readText
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bridge to communicate with the DERO Stargate RPC API: https://docs.dero.io/developer/RPC.html
|
||||||
|
*/
|
||||||
|
class StargateBridge {
|
||||||
|
private val foundationNode = DeroNode(host = "node.derofoundation.org", port = 11012, path = "/ws")
|
||||||
|
|
||||||
|
private val client: HttpClient = HttpClient(CIO) { install(WebSockets) }
|
||||||
|
|
||||||
|
private val rendezvousChannel = Channel<Boolean>()
|
||||||
|
|
||||||
|
private val blockCountRequest = "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"DERO.GetBlockCount\" }"
|
||||||
|
|
||||||
|
suspend fun start() {
|
||||||
|
val node = foundationNode
|
||||||
|
client.webSocket(host = node.host, port = node.port, path = node.path) {
|
||||||
|
writeMessages()
|
||||||
|
readMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
client.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun DefaultClientWebSocketSession.readMessages() {
|
||||||
|
incoming.receiveAsFlow().collect { message ->
|
||||||
|
(message as? Frame.Text)?.let { textFrame ->
|
||||||
|
val text = textFrame.readText()
|
||||||
|
println(text)
|
||||||
|
if (text.contains("\"method\":\"Block\"")) {
|
||||||
|
rendezvousChannel.send(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun DefaultClientWebSocketSession.writeMessages() {
|
||||||
|
rendezvousChannel.receiveAsFlow().onEach {
|
||||||
|
println("Prepared to send...")
|
||||||
|
outgoing.send(Frame.Text(blockCountRequest))
|
||||||
|
}.launchIn(this)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue