190 lines
5.6 KiB
JavaScript
190 lines
5.6 KiB
JavaScript
import { isBrowser, getLocation, getQueryString, detectEnv, appendToQueryString, } from "@walletconnect/utils";
|
|
import NetworkMonitor from "./network";
|
|
const WS = typeof global.WebSocket !== "undefined" ? global.WebSocket : require("ws");
|
|
class SocketTransport {
|
|
constructor(opts) {
|
|
this.opts = opts;
|
|
this._queue = [];
|
|
this._events = [];
|
|
this._subscriptions = [];
|
|
this._protocol = opts.protocol;
|
|
this._version = opts.version;
|
|
this._url = "";
|
|
this._netMonitor = null;
|
|
this._socket = null;
|
|
this._nextSocket = null;
|
|
this._subscriptions = opts.subscriptions || [];
|
|
this._netMonitor = opts.netMonitor || new NetworkMonitor();
|
|
if (!opts.url || typeof opts.url !== "string") {
|
|
throw new Error("Missing or invalid WebSocket url");
|
|
}
|
|
this._url = opts.url;
|
|
this._netMonitor.on("online", () => this._socketCreate());
|
|
}
|
|
set readyState(value) {
|
|
}
|
|
get readyState() {
|
|
return this._socket ? this._socket.readyState : -1;
|
|
}
|
|
set connecting(value) {
|
|
}
|
|
get connecting() {
|
|
return this.readyState === 0;
|
|
}
|
|
set connected(value) {
|
|
}
|
|
get connected() {
|
|
return this.readyState === 1;
|
|
}
|
|
set closing(value) {
|
|
}
|
|
get closing() {
|
|
return this.readyState === 2;
|
|
}
|
|
set closed(value) {
|
|
}
|
|
get closed() {
|
|
return this.readyState === 3;
|
|
}
|
|
open() {
|
|
this._socketCreate();
|
|
}
|
|
close() {
|
|
this._socketClose();
|
|
}
|
|
send(message, topic, silent) {
|
|
if (!topic || typeof topic !== "string") {
|
|
throw new Error("Missing or invalid topic field");
|
|
}
|
|
this._socketSend({
|
|
topic: topic,
|
|
type: "pub",
|
|
payload: message,
|
|
silent: !!silent,
|
|
});
|
|
}
|
|
subscribe(topic) {
|
|
this._socketSend({
|
|
topic: topic,
|
|
type: "sub",
|
|
payload: "",
|
|
silent: true,
|
|
});
|
|
}
|
|
on(event, callback) {
|
|
this._events.push({ event, callback });
|
|
}
|
|
_socketCreate() {
|
|
if (this._nextSocket) {
|
|
return;
|
|
}
|
|
const url = getWebSocketUrl(this._url, this._protocol, this._version);
|
|
this._nextSocket = new WS(url);
|
|
if (!this._nextSocket) {
|
|
throw new Error("Failed to create socket");
|
|
}
|
|
this._nextSocket.onmessage = (event) => this._socketReceive(event);
|
|
this._nextSocket.onopen = () => this._socketOpen();
|
|
this._nextSocket.onerror = (event) => this._socketError(event);
|
|
this._nextSocket.onclose = () => {
|
|
setTimeout(() => {
|
|
this._nextSocket = null;
|
|
this._socketCreate();
|
|
}, 1000);
|
|
};
|
|
}
|
|
_socketOpen() {
|
|
this._socketClose();
|
|
this._socket = this._nextSocket;
|
|
this._nextSocket = null;
|
|
this._queueSubscriptions();
|
|
this._pushQueue();
|
|
}
|
|
_socketClose() {
|
|
if (this._socket) {
|
|
this._socket.onclose = () => {
|
|
};
|
|
this._socket.close();
|
|
}
|
|
}
|
|
_socketSend(socketMessage) {
|
|
const message = JSON.stringify(socketMessage);
|
|
if (this._socket && this._socket.readyState === 1) {
|
|
this._socket.send(message);
|
|
}
|
|
else {
|
|
this._setToQueue(socketMessage);
|
|
this._socketCreate();
|
|
}
|
|
}
|
|
async _socketReceive(event) {
|
|
let socketMessage;
|
|
try {
|
|
socketMessage = JSON.parse(event.data);
|
|
}
|
|
catch (error) {
|
|
return;
|
|
}
|
|
this._socketSend({
|
|
topic: socketMessage.topic,
|
|
type: "ack",
|
|
payload: "",
|
|
silent: true,
|
|
});
|
|
if (this._socket && this._socket.readyState === 1) {
|
|
const events = this._events.filter(event => event.event === "message");
|
|
if (events && events.length) {
|
|
events.forEach(event => event.callback(socketMessage));
|
|
}
|
|
}
|
|
}
|
|
_socketError(e) {
|
|
const events = this._events.filter(event => event.event === "error");
|
|
if (events && events.length) {
|
|
events.forEach(event => event.callback(e));
|
|
}
|
|
}
|
|
_queueSubscriptions() {
|
|
const subscriptions = this._subscriptions;
|
|
subscriptions.forEach((topic) => this._queue.push({
|
|
topic: topic,
|
|
type: "sub",
|
|
payload: "",
|
|
silent: true,
|
|
}));
|
|
this._subscriptions = this.opts.subscriptions || [];
|
|
}
|
|
_setToQueue(socketMessage) {
|
|
this._queue.push(socketMessage);
|
|
}
|
|
_pushQueue() {
|
|
const queue = this._queue;
|
|
queue.forEach((socketMessage) => this._socketSend(socketMessage));
|
|
this._queue = [];
|
|
}
|
|
}
|
|
function getWebSocketUrl(_url, protocol, version) {
|
|
var _a, _b;
|
|
const url = _url.startsWith("https")
|
|
? _url.replace("https", "wss")
|
|
: _url.startsWith("http")
|
|
? _url.replace("http", "ws")
|
|
: _url;
|
|
const splitUrl = url.split("?");
|
|
const params = isBrowser()
|
|
? {
|
|
protocol,
|
|
version,
|
|
env: "browser",
|
|
host: ((_a = getLocation()) === null || _a === void 0 ? void 0 : _a.host) || "",
|
|
}
|
|
: {
|
|
protocol,
|
|
version,
|
|
env: ((_b = detectEnv()) === null || _b === void 0 ? void 0 : _b.name) || "",
|
|
};
|
|
const queryString = appendToQueryString(getQueryString(splitUrl[1] || ""), params);
|
|
return splitUrl[0] + "?" + queryString;
|
|
}
|
|
export default SocketTransport;
|
|
//# sourceMappingURL=index.js.map
|