Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into 529-remove-deprecated-rpc
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/com/limechain/Main.java
#	src/main/java/com/limechain/rpc/RpcClient.java
  • Loading branch information
Zurcusa committed Sep 19, 2024
2 parents 02ae840 + 03e28d1 commit 08f3029
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 4 deletions.
8 changes: 8 additions & 0 deletions src/main/java/com/limechain/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@

public class Main {

private static final String WS_RPC = "wsRpc";

private static final DivLogger log = new DivLogger();

public static void main(String[] args) {
exportHttpRpc(RpcClient::sendRpcRequest, JSString.valueOf(HTTP_RPC));
exportWsRpc(new WsRpcClientImpl(), JSString.valueOf(WS_RPC));

log.log("Starting LimeChain node...");

RpcApp rpcApp = new RpcApp();
Expand All @@ -24,4 +29,7 @@ public static void main(String[] args) {
client.start();
log.log(Level.INFO, "\uD83D\uDE80Started light client!");
}

@JSBody(params = {"c", "apiName"}, script = "window[apiName] = c;")
private static native void exportWsRpc(WsRpcClient c, JSString apiName);
}
16 changes: 16 additions & 0 deletions src/main/java/com/limechain/rpc/WebsocketState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.limechain.rpc;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum WebsocketState {

CONNECTING(0),
OPEN(1),
CLOSING(2),
CLOSED(3);

private final int intValue;
}
14 changes: 14 additions & 0 deletions src/main/java/com/limechain/rpc/WsRpcClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.limechain.rpc;

import org.teavm.jso.JSObject;
import org.teavm.jso.core.JSString;

/**
* TeaVM overlay interface for a client used to communicate with a full node's RPC server.
*/
public interface WsRpcClient extends JSObject {

void send(JSString rpcString);

String nextResponse();
}
89 changes: 89 additions & 0 deletions src/main/java/com/limechain/rpc/WsRpcClientImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.limechain.rpc;

import com.limechain.constants.RpcConstants;
import lombok.SneakyThrows;
import lombok.extern.java.Log;
import org.teavm.jso.browser.Window;
import org.teavm.jso.core.JSString;
import org.teavm.jso.websocket.WebSocket;

import java.util.ArrayDeque;
import java.util.Queue;

/**
* The implementation of {@link WsRpcClient}. Uses a native JS Websocket implementation.
*/
@Log
public class WsRpcClientImpl implements WsRpcClient {

private static final int WS_OPEN_WAIT_MS = 50;

private WebSocket ws;
private final Queue<String> responseQueue;

public WsRpcClientImpl() {
responseQueue = new ArrayDeque<>();
openWebsocketConnection();
}

private void openWebsocketConnection() {
log.info("Initializing RPC websocket connection...");
//TODO change when configuring chain.
ws = new WebSocket(RpcConstants.POLKADOT_WS_RPC);
initHandlers();
}

private void initHandlers() {
ws.onClose(e -> {
log.info("RPC websocket connection was closed.");
log.info("Retrying connection...");
Window.setTimeout(this::openWebsocketConnection, 1000);
});

ws.onError(e -> {
log.warning("There was an error in the RPC websocket connection. Closing connection...");
ws.close();
});

ws.onOpen(e -> log.info("Websocket connection is open."));
ws.onMessage(e -> responseQueue.offer(e.getDataAsString()));
}

/**
* Waits for the current ws connection to be in an opened state then sends an RPC request to the full node.
*/
@Override
public void send(JSString rpcString) {
new Thread(() -> {
handleSocketState();
ws.send(rpcString.stringValue());
}).start();
}

/**
* Handles the state of the websocket when sending a message. If the connection is in a closing (2) or a closed (3)
* state the client throws an error.
*/
@SneakyThrows
private void handleSocketState() {
int startState = ws.getReadyState();
int openedState = WebsocketState.OPEN.getIntValue();

while (startState != openedState) {
if (startState > openedState) {
throw new Exception("Calling function of a closed websocket is prohibited.");
}

Thread.sleep(WS_OPEN_WAIT_MS);
startState = ws.getReadyState();
}
}

/**
* Polls the first item in the queue and returns it as a string.
*/
@Override
public String nextResponse() {
return responseQueue.poll();
}
}
8 changes: 4 additions & 4 deletions src/main/java/com/limechain/utils/json/JsonParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ private Object parseNumber() {

private boolean isValidNumberChar() {
return (Character.isDigit(json.charAt(index))
|| json.charAt(index) == '-'
|| json.charAt(index) == '.'
|| json.charAt(index) == 'e'
|| json.charAt(index) == 'E');
|| json.charAt(index) == '-'
|| json.charAt(index) == '.'
|| json.charAt(index) == 'e'
|| json.charAt(index) == 'E');
}

private void skipWhitespace() {
Expand Down

0 comments on commit 08f3029

Please sign in to comment.