@xelis/sdk 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/create_esm_pkg.js +13 -0
  2. package/dist/cjs/config.js +38 -0
  3. package/dist/cjs/daemon/rpc.js +143 -0
  4. package/dist/cjs/daemon/types.js +74 -0
  5. package/dist/cjs/daemon/websocket.js +236 -0
  6. package/dist/cjs/lib/rpc.js +89 -0
  7. package/dist/cjs/lib/types.js +2 -0
  8. package/dist/cjs/lib/websocket.js +283 -0
  9. package/dist/cjs/react/daemon.js +176 -0
  10. package/dist/cjs/wallet/rpc.js +131 -0
  11. package/dist/cjs/wallet/types.js +29 -0
  12. package/dist/cjs/wallet/websocket.js +92 -0
  13. package/dist/cjs/xswd/types.js +9 -0
  14. package/dist/cjs/xswd/websocket.js +38 -0
  15. package/dist/esm/config.js +35 -0
  16. package/dist/esm/daemon/rpc.js +140 -0
  17. package/dist/esm/daemon/websocket.js +233 -0
  18. package/dist/esm/lib/rpc.js +86 -0
  19. package/dist/esm/lib/websocket.js +277 -0
  20. package/dist/esm/package.json +1 -0
  21. package/dist/esm/react/daemon.js +144 -0
  22. package/dist/esm/wallet/rpc.js +128 -0
  23. package/dist/esm/wallet/websocket.js +89 -0
  24. package/dist/esm/xswd/websocket.js +35 -0
  25. package/jest.config.js +6 -0
  26. package/package.json +12 -3
  27. package/tsconfig.cjs.json +7 -0
  28. package/tsconfig.esm.json +7 -0
  29. package/tsconfig.json +17 -0
  30. package/tsconfig.types.json +8 -0
  31. package/config.js +0 -25
  32. package/daemon/rpc.js +0 -119
  33. package/daemon/websocket.js +0 -171
  34. package/lib/rpc.js +0 -38
  35. package/lib/websocket.js +0 -202
  36. package/react/daemon.js +0 -82
  37. package/wallet/rpc.js +0 -67
  38. package/wallet/websocket.js +0 -66
  39. package/xswd/websocket.js +0 -16
  40. /package/{daemon → dist/esm/daemon}/types.js +0 -0
  41. /package/{lib → dist/esm/lib}/types.js +0 -0
  42. /package/{wallet → dist/esm/wallet}/types.js +0 -0
  43. /package/{xswd → dist/esm/xswd}/types.js +0 -0
  44. /package/{config.d.ts → dist/types/config.d.ts} +0 -0
  45. /package/{daemon → dist/types/daemon}/rpc.d.ts +0 -0
  46. /package/{daemon → dist/types/daemon}/types.d.ts +0 -0
  47. /package/{daemon → dist/types/daemon}/websocket.d.ts +0 -0
  48. /package/{lib → dist/types/lib}/rpc.d.ts +0 -0
  49. /package/{lib → dist/types/lib}/types.d.ts +0 -0
  50. /package/{lib → dist/types/lib}/websocket.d.ts +0 -0
  51. /package/{react → dist/types/react}/daemon.d.ts +0 -0
  52. /package/{wallet → dist/types/wallet}/rpc.d.ts +0 -0
  53. /package/{wallet → dist/types/wallet}/types.d.ts +0 -0
  54. /package/{wallet → dist/types/wallet}/websocket.d.ts +0 -0
  55. /package/{xswd → dist/types/xswd}/types.d.ts +0 -0
  56. /package/{xswd → dist/types/xswd}/websocket.d.ts +0 -0
package/jest.config.js ADDED
@@ -0,0 +1,6 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ testMatch: ['**/*.spec.ts'],
6
+ }
package/package.json CHANGED
@@ -1,7 +1,15 @@
1
1
  {
2
- "version": "0.7.0",
2
+ "version": "0.8.0",
3
3
  "name": "@xelis/sdk",
4
4
  "description": "Xelis software development kit for JS",
5
+ "exports": {
6
+ "./*": {
7
+ "types": "./dist/types/*.d.ts",
8
+ "require": "./dist/cjs/*.js",
9
+ "import": "./dist/esm/*.js",
10
+ "default": "./dist/esm/*.js"
11
+ }
12
+ },
5
13
  "repository": {
6
14
  "type": "git",
7
15
  "url": "git+https://github.com/xelis-project/xelis-js-sdk"
@@ -9,8 +17,9 @@
9
17
  "homepage": "https://github.com/xelis-project/xelis-js-sdk#readme",
10
18
  "scripts": {
11
19
  "test": "jest",
12
- "build": "rm -rf ./dist && npx tsc --declaration && cp package.json README.md LICENSE ./dist",
13
- "publish-npm": "npm run build && cd ./dist && npm publish"
20
+ "compile": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json ./tsconfig.types.json",
21
+ "clean": "rm -rf ./dist",
22
+ "build": "npm run clean && npm run compile && node create_esm_pkg.js"
14
23
  },
15
24
  "devDependencies": {
16
25
  "@types/jest": "^29.4.0",
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist/cjs",
5
+ "module": "commonjs"
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist/esm",
5
+ "module": "ES2015"
6
+ }
7
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "jsx": "react",
4
+ "moduleResolution": "node",
5
+ "outDir": "./dist",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true
9
+ },
10
+ "include": [
11
+ "./src/**/*"
12
+ ],
13
+ "exclude": [
14
+ "node_modules",
15
+ "**/*.spec.ts"
16
+ ]
17
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist/types",
5
+ "declaration": true,
6
+ "emitDeclarationOnly": true
7
+ }
8
+ }
package/config.js DELETED
@@ -1,25 +0,0 @@
1
- export const DAEMON_RPC_PORT = `8080`;
2
- export const WALLET_RPC_PORT = `8081`;
3
- export const XSWD_PORT = `44325`;
4
- export const MAINNET_NODE_URL = `node.xelis.io`;
5
- export const TESTNET_NODE_URL = `testnet-node.xelis.io`;
6
- export const LOCAL_NODE_URL = `127.0.0.1:${DAEMON_RPC_PORT}`;
7
- export const MAINNET_NODE_RPC = `https://${MAINNET_NODE_URL}/json_rpc`;
8
- export const TESTNET_NODE_RPC = `https://${TESTNET_NODE_URL}/json_rpc`;
9
- export const LOCAL_NODE_RPC = `http://${LOCAL_NODE_URL}/json_rpc`;
10
- export const MAINNET_NODE_WS = `wss://${MAINNET_NODE_URL}/json_rpc`;
11
- export const TESTNET_NODE_WS = `wss://${TESTNET_NODE_URL}/json_rpc`;
12
- export const LOCAL_NODE_WS = `ws://${LOCAL_NODE_URL}/json_rpc`;
13
- export const LOCAL_WALLET_URL = `127.0.0.1:${WALLET_RPC_PORT}`;
14
- export const LOCAL_WALLET_RPC = `http://${LOCAL_WALLET_URL}/json_rpc`;
15
- export const LOCAL_WALLET_WS = `ws://${LOCAL_WALLET_URL}/json_rpc`;
16
- export const LOCAL_XSWD_URL = `127.0.0.1:${XSWD_PORT}`;
17
- export const LOCAL_XSWD_WS = `ws://${LOCAL_XSWD_URL}/xswd`;
18
- export default {
19
- MAINNET_NODE_URL, TESTNET_NODE_URL,
20
- MAINNET_NODE_RPC, TESTNET_NODE_RPC, LOCAL_NODE_RPC,
21
- MAINNET_NODE_WS, TESTNET_NODE_WS, LOCAL_NODE_WS,
22
- DAEMON_RPC_PORT, WALLET_RPC_PORT, XSWD_PORT,
23
- LOCAL_WALLET_URL, LOCAL_WALLET_RPC, LOCAL_WALLET_WS,
24
- LOCAL_XSWD_URL, LOCAL_XSWD_WS
25
- };
package/daemon/rpc.js DELETED
@@ -1,119 +0,0 @@
1
- import { RPCMethod } from './types';
2
- import { RPC as BaseRPC } from '../lib/rpc';
3
- export class RPC extends BaseRPC {
4
- getVersion() {
5
- return this.post(RPCMethod.GetVersion);
6
- }
7
- getHeight() {
8
- return this.post(RPCMethod.GetHeight);
9
- }
10
- getTopoHeight() {
11
- return this.post(RPCMethod.GetTopoHeight);
12
- }
13
- getStableHeight() {
14
- return this.post(RPCMethod.GetStableHeight);
15
- }
16
- getBlockTemplate(address) {
17
- return this.post(RPCMethod.GetBlockTemplate, { address });
18
- }
19
- getBlockAtTopoHeight(params) {
20
- return this.post(RPCMethod.GetBlockAtTopoHeight, params);
21
- }
22
- getBlocksAtHeight(params) {
23
- return this.post(RPCMethod.GetBlocksAtHeight, params);
24
- }
25
- getBlockByHash(params) {
26
- return this.post(RPCMethod.GetBlockByHash, params);
27
- }
28
- getTopBlock(params) {
29
- return this.post(RPCMethod.GetTopBlock, params);
30
- }
31
- submitBlock(blockTemplate) {
32
- return this.post(RPCMethod.SubmitBlock, { block_template: blockTemplate });
33
- }
34
- getBalance(params) {
35
- return this.post(RPCMethod.GetBalance, params);
36
- }
37
- hasBalance(params) {
38
- return this.post(RPCMethod.HasBalance, params);
39
- }
40
- getBalanceAtTopoHeight(params) {
41
- return this.post(RPCMethod.GetBalanceAtTopoHeight, params);
42
- }
43
- getInfo() {
44
- return this.post(RPCMethod.GetInfo);
45
- }
46
- getNonce(params) {
47
- return this.post(RPCMethod.GetNonce, params);
48
- }
49
- hasNonce(params) {
50
- return this.post(RPCMethod.HasNonce, params);
51
- }
52
- getNonceAtTopoheight(params) {
53
- return this.post(RPCMethod.GetNonceAtTopoheight, params);
54
- }
55
- getAsset(params) {
56
- return this.post(RPCMethod.GetAsset, params);
57
- }
58
- getAssets() {
59
- return this.post(RPCMethod.GetAssets);
60
- }
61
- countAssets() {
62
- return this.post(RPCMethod.CountAssets);
63
- }
64
- countAccounts() {
65
- return this.post(RPCMethod.CountAccounts);
66
- }
67
- countTransactions() {
68
- return this.post(RPCMethod.CountTransactions);
69
- }
70
- submitTransaction(hexData) {
71
- return this.post(RPCMethod.SubmitTransaction, { data: hexData });
72
- }
73
- getTransaction(hash) {
74
- return this.post(RPCMethod.GetTransaction, { hash });
75
- }
76
- p2pStatus() {
77
- return this.post(RPCMethod.P2PStatus);
78
- }
79
- getPeers() {
80
- return this.post(RPCMethod.GetPeers);
81
- }
82
- getMemPool() {
83
- return this.post(RPCMethod.GetMempool);
84
- }
85
- getTips() {
86
- return this.post(RPCMethod.GetTips);
87
- }
88
- getDAGOrder(params) {
89
- return this.post(RPCMethod.GetDAGOrder, params);
90
- }
91
- getBlocksRangeByTopoheight(params) {
92
- return this.post(RPCMethod.GetBlocksRangeByTopoheight, params);
93
- }
94
- getBlocksRangeByHeight(params) {
95
- return this.post(RPCMethod.GetBlocksRangeByHeight, params);
96
- }
97
- getTransactions(txHashes) {
98
- return this.post(RPCMethod.GetTransactions, { tx_hashes: txHashes });
99
- }
100
- getAccountHistory(params) {
101
- return this.post(RPCMethod.GetAccountHistory, params);
102
- }
103
- getAccountAssets(address) {
104
- return this.post(RPCMethod.GetAccountAssets, { address });
105
- }
106
- getAccounts(params) {
107
- return this.post(RPCMethod.GetAccounts, params);
108
- }
109
- isTxExecutedInBlock(params) {
110
- return this.post(RPCMethod.IsTxExecutedInBlock, params);
111
- }
112
- getDevFeeThresholds() {
113
- return this.post(RPCMethod.GetDevFeeThresholds);
114
- }
115
- getSizeOnDisk() {
116
- return this.post(RPCMethod.GetSizeOnDisk);
117
- }
118
- }
119
- export default RPC;
@@ -1,171 +0,0 @@
1
- import { RPCEvent, RPCMethod } from './types';
2
- import { WS as BaseWS } from '../lib/websocket';
3
- export class DaemonMethods {
4
- constructor(ws, prefix = "") {
5
- this.ws = ws;
6
- this.prefix = prefix;
7
- }
8
- async listenEvent(event, onData) {
9
- return this.ws.listenEvent(this.prefix + event, onData);
10
- }
11
- dataCall(method, params) {
12
- return this.ws.dataCall(this.prefix + method, params);
13
- }
14
- onNewBlock(onData) {
15
- return this.listenEvent(RPCEvent.NewBlock, onData);
16
- }
17
- onTransactionAddedInMempool(onData) {
18
- return this.listenEvent(RPCEvent.TransactionAddedInMempool, onData);
19
- }
20
- onTransactionExecuted(onData) {
21
- return this.listenEvent(RPCEvent.TransactionExecuted, onData);
22
- }
23
- onBlockOrdered(onData) {
24
- return this.listenEvent(RPCEvent.BlockOrdered, onData);
25
- }
26
- onPeerConnected(onData) {
27
- return this.listenEvent(RPCEvent.PeerConnected, onData);
28
- }
29
- onPeerDisconnected(onData) {
30
- return this.listenEvent(RPCEvent.PeerDisconnected, onData);
31
- }
32
- onPeerPeerListUpdated(onData) {
33
- return this.listenEvent(RPCEvent.PeerPeerListUpdated, onData);
34
- }
35
- onPeerPeerDisconnected(onData) {
36
- return this.listenEvent(RPCEvent.PeerPeerDisconnected, onData);
37
- }
38
- onPeerStateUpdated(onData) {
39
- return this.listenEvent(RPCEvent.PeerStateUpdated, onData);
40
- }
41
- onNewAsset(onData) {
42
- return this.listenEvent(RPCEvent.NewAsset, onData);
43
- }
44
- onBlockOrphaned(onData) {
45
- return this.listenEvent(RPCEvent.BlockOrphaned, onData);
46
- }
47
- onTransactionOrphaned(onData) {
48
- return this.listenEvent(RPCEvent.TransactionOrphaned, onData);
49
- }
50
- onStableHeightChanged(onData) {
51
- return this.listenEvent(RPCEvent.StableHeightChanged, onData);
52
- }
53
- getVersion() {
54
- return this.dataCall(RPCMethod.GetVersion);
55
- }
56
- getHeight() {
57
- return this.dataCall(RPCMethod.GetHeight);
58
- }
59
- getTopoHeight() {
60
- return this.dataCall(RPCMethod.GetTopoHeight);
61
- }
62
- getStableHeight() {
63
- return this.dataCall(RPCMethod.GetStableHeight);
64
- }
65
- getBlockTemplate(address) {
66
- return this.dataCall(RPCMethod.GetBlockTemplate, { address });
67
- }
68
- getBlockAtTopoHeight(params) {
69
- return this.dataCall(RPCMethod.GetBlockAtTopoHeight, params);
70
- }
71
- getBlocksAtHeight(params) {
72
- return this.dataCall(RPCMethod.GetBlocksAtHeight, params);
73
- }
74
- getBlockByHash(params) {
75
- return this.dataCall(RPCMethod.GetBlockByHash, params);
76
- }
77
- getTopBlock(params) {
78
- return this.dataCall(RPCMethod.GetTopBlock, params);
79
- }
80
- submitBlock(blockTemplate) {
81
- return this.dataCall(RPCMethod.SubmitBlock, { block_template: blockTemplate });
82
- }
83
- getBalance(params) {
84
- return this.dataCall(RPCMethod.GetBalance, params);
85
- }
86
- hasBalance(params) {
87
- return this.dataCall(RPCMethod.HasBalance, params);
88
- }
89
- getBalanceAtTopoHeight(params) {
90
- return this.dataCall(RPCMethod.GetBalanceAtTopoHeight, params);
91
- }
92
- getInfo() {
93
- return this.dataCall(RPCMethod.GetInfo);
94
- }
95
- getNonce(params) {
96
- return this.dataCall(RPCMethod.GetNonce, params);
97
- }
98
- hasNonce(params) {
99
- return this.dataCall(RPCMethod.HasNonce, params);
100
- }
101
- getAsset(params) {
102
- return this.dataCall(RPCMethod.GetAsset, params);
103
- }
104
- getAssets() {
105
- return this.dataCall(RPCMethod.GetAssets);
106
- }
107
- countAssets() {
108
- return this.dataCall(RPCMethod.CountAssets);
109
- }
110
- countAccounts() {
111
- return this.dataCall(RPCMethod.CountAccounts);
112
- }
113
- countTransactions() {
114
- return this.dataCall(RPCMethod.CountTransactions);
115
- }
116
- submitTransaction(hexData) {
117
- return this.dataCall(RPCMethod.SubmitTransaction, { data: hexData });
118
- }
119
- getTransaction(hash) {
120
- return this.dataCall(RPCMethod.GetTransaction, { hash });
121
- }
122
- p2pStatus() {
123
- return this.dataCall(RPCMethod.P2PStatus);
124
- }
125
- getPeers() {
126
- return this.dataCall(RPCMethod.GetPeers);
127
- }
128
- getMemPool() {
129
- return this.dataCall(RPCMethod.GetMempool);
130
- }
131
- getTips() {
132
- return this.dataCall(RPCMethod.GetTips);
133
- }
134
- getDAGOrder(params) {
135
- return this.dataCall(RPCMethod.GetDAGOrder, params);
136
- }
137
- getBlocksRangeByTopoheight(params) {
138
- return this.dataCall(RPCMethod.GetBlocksRangeByTopoheight, params);
139
- }
140
- getBlocksRangeByHeight(params) {
141
- return this.dataCall(RPCMethod.GetBlocksRangeByHeight, params);
142
- }
143
- getTransactions(txHashes) {
144
- return this.dataCall(RPCMethod.GetTransactions, { tx_hashes: txHashes });
145
- }
146
- getAccountHistory(params) {
147
- return this.dataCall(RPCMethod.GetAccountHistory, params);
148
- }
149
- getAccountAssets(address) {
150
- return this.dataCall(RPCMethod.GetAccountAssets, { address });
151
- }
152
- getAccounts(params) {
153
- return this.dataCall(RPCMethod.GetAccounts, params);
154
- }
155
- isTxExecutedInBlock(params) {
156
- return this.dataCall(RPCMethod.IsTxExecutedInBlock, params);
157
- }
158
- getDevFeeThresholds() {
159
- return this.dataCall(RPCMethod.GetDevFeeThresholds);
160
- }
161
- getSizeOnDisk() {
162
- return this.dataCall(RPCMethod.GetSizeOnDisk);
163
- }
164
- }
165
- export class WS extends BaseWS {
166
- constructor() {
167
- super();
168
- this.methods = new DaemonMethods(this);
169
- }
170
- }
171
- export default WS;
package/lib/rpc.js DELETED
@@ -1,38 +0,0 @@
1
- export class RPC {
2
- constructor(endpoint) {
3
- this.endpoint = endpoint;
4
- this.timeout = 3000;
5
- }
6
- async post(method, params, headers) {
7
- try {
8
- const controller = new AbortController();
9
- const body = JSON.stringify({ id: 1, jsonrpc: '2.0', method: method, params });
10
- const timeoutId = setTimeout(() => {
11
- controller.abort();
12
- }, this.timeout);
13
- headers = headers || new Headers();
14
- headers.set(`Content-Type`, `application/json`);
15
- const res = await fetch(this.endpoint, {
16
- headers,
17
- method: `POST`,
18
- body,
19
- signal: controller.signal
20
- });
21
- clearTimeout(timeoutId);
22
- if (res.ok) {
23
- const data = await res.json();
24
- if (data.error) {
25
- return Promise.reject(new Error(data.error.message));
26
- }
27
- return Promise.resolve(data);
28
- }
29
- else {
30
- return Promise.reject(new Error(`${res.status} - ${res.statusText}`));
31
- }
32
- }
33
- catch (err) {
34
- console.log(err);
35
- return Promise.reject(err);
36
- }
37
- }
38
- }
package/lib/websocket.js DELETED
@@ -1,202 +0,0 @@
1
- import WebSocket from 'isomorphic-ws';
2
- import to from 'await-to-js';
3
- export class WS {
4
- constructor(options) {
5
- this.connectionTries = 0;
6
- this.methodIdIncrement = 0;
7
- this.endpoint = "";
8
- this.timeout = 15000; // default to 15s
9
- this.events = {};
10
- this.unsubscribeSuspense = 1000;
11
- this.maxConnectionTries = 3;
12
- this.reconnectOnConnectionLoss = true;
13
- this.options = options;
14
- }
15
- connect(endpoint) {
16
- // force disconnect if already connected
17
- if (this.socket && this.socket.readyState === WebSocket.OPEN) {
18
- this.socket.close();
19
- }
20
- this.events = {};
21
- this.connectionTries = 0;
22
- return new Promise((resolve, reject) => {
23
- this.socket = new WebSocket(endpoint, this.options);
24
- this.endpoint = endpoint;
25
- this.socket.addEventListener(`open`, (event) => {
26
- resolve(event);
27
- });
28
- this.socket.addEventListener(`close`, (event) => {
29
- if (this.reconnectOnConnectionLoss && !event.wasClean) {
30
- this.tryReconnect();
31
- reject(new Error(`Unhandled close. Reconnecting...`));
32
- }
33
- else {
34
- reject(event);
35
- }
36
- });
37
- this.socket.addEventListener(`error`, (err) => {
38
- reject(err);
39
- });
40
- });
41
- }
42
- tryReconnect() {
43
- this.connectionTries++;
44
- if (this.connectionTries > this.maxConnectionTries) {
45
- return;
46
- }
47
- this.socket = new WebSocket(this.endpoint, this.options);
48
- this.socket.addEventListener(`open`, () => {
49
- this.connectionTries = 0;
50
- });
51
- this.socket.addEventListener(`close`, (event) => {
52
- this.tryReconnect();
53
- });
54
- }
55
- close() {
56
- if (!this.socket)
57
- return;
58
- this.socket.close();
59
- }
60
- clearEvent(event) {
61
- this.events[event].listeners.forEach(listener => {
62
- this.socket && this.socket.removeEventListener(`message`, listener);
63
- });
64
- Reflect.deleteProperty(this.events, event);
65
- }
66
- async closeAllListens(event) {
67
- if (this.events[event]) {
68
- const [err, _] = await to(this.call(`unsubscribe`, { notify: event }));
69
- if (err)
70
- return Promise.reject(err);
71
- this.clearEvent(event);
72
- }
73
- return Promise.resolve();
74
- }
75
- async listenEvent(event, onData) {
76
- const onMessage = (msgEvent) => {
77
- if (this.events[event]) {
78
- const { id } = this.events[event];
79
- if (typeof msgEvent.data === `string`) {
80
- try {
81
- const data = JSON.parse(msgEvent.data);
82
- if (data.id === id) {
83
- if (data.error) {
84
- onData(msgEvent, undefined, new Error(data.error.message));
85
- }
86
- else {
87
- onData(msgEvent, data.result, undefined);
88
- }
89
- }
90
- }
91
- catch (_a) {
92
- // can't parse json -- do nothing
93
- }
94
- }
95
- }
96
- };
97
- if (this.events[event]) {
98
- const { unsubscribeTimeoutId } = this.events[event];
99
- if (unsubscribeTimeoutId) {
100
- // clear timeout to unsubscribe
101
- // because we got a new registered event and want to cancel the pending unsubscribe grace period
102
- clearTimeout(unsubscribeTimeoutId);
103
- }
104
- this.events[event].listeners.push(onMessage);
105
- }
106
- else {
107
- // important if multiple listenEvent are called without await at least we store listener before getting id
108
- this.events[event] = { listeners: [onMessage] };
109
- const [err, res] = await to(this.call(`subscribe`, { notify: event }));
110
- if (err) {
111
- this.clearEvent(event);
112
- return Promise.reject(err);
113
- }
114
- this.events[event].id = res.id;
115
- }
116
- this.socket && this.socket.addEventListener(`message`, onMessage);
117
- const closeListen = () => {
118
- const eventData = this.events[event];
119
- if (eventData) {
120
- const listeners = eventData.listeners;
121
- for (let i = 0; i < listeners.length; i++) {
122
- if (listeners[i] === onMessage) {
123
- listeners.splice(i, 1);
124
- break;
125
- }
126
- }
127
- // no more listener so we unsubscribe from daemon websocket if socket still open
128
- if (listeners.length === 0) {
129
- if (this.socket && this.socket.readyState === WebSocket.OPEN) {
130
- // we use a grace period to unsubscribe (mostly because of react useEffect and avoid unecessary subscribe)
131
- this.events[event].unsubscribeTimeoutId = setTimeout(async () => {
132
- this.call(`unsubscribe`, { notify: event });
133
- Reflect.deleteProperty(this.events, event);
134
- }, this.unsubscribeSuspense);
135
- }
136
- else {
137
- // socket is closed so we don't send unsubscribe and no grace period delete right away
138
- Reflect.deleteProperty(this.events, event);
139
- }
140
- }
141
- }
142
- this.socket && this.socket.removeEventListener(`message`, onMessage);
143
- return Promise.resolve();
144
- };
145
- return Promise.resolve(closeListen);
146
- }
147
- call(method, params, overwriteData) {
148
- return new Promise((resolve, reject) => {
149
- if (!this.socket)
150
- return reject(new Error(`Socket is not initialized.`));
151
- if (this.socket.readyState !== WebSocket.OPEN)
152
- return reject(new Error(`Can't send msg. Socket is not opened.`));
153
- let requestMethod = this.createRequestMethod(method, params);
154
- // for XSWD we want to send the application data without request method wrapping
155
- if (overwriteData) {
156
- requestMethod.id = null;
157
- requestMethod.data = overwriteData;
158
- }
159
- let timeoutId = null;
160
- const onMessage = (msgEvent) => {
161
- if (typeof msgEvent.data === `string`) {
162
- const data = JSON.parse(msgEvent.data);
163
- if (data.id === requestMethod.id) {
164
- clearTimeout(timeoutId);
165
- this.socket && this.socket.removeEventListener(`message`, onMessage);
166
- if (data.error)
167
- return reject(new Error(data.error.message));
168
- else
169
- resolve(data);
170
- }
171
- }
172
- };
173
- // make sure you listen before sending data
174
- this.socket && this.socket.addEventListener(`message`, onMessage); // we don't use { once: true } option because of timeout feature
175
- if (this.timeout > 0) {
176
- timeoutId = setTimeout(() => {
177
- this.socket && this.socket.removeEventListener(`message`, onMessage);
178
- reject(new Error(`timeout`));
179
- }, this.timeout);
180
- }
181
- if (this.socket && this.socket.readyState === WebSocket.OPEN) {
182
- this.socket.send(requestMethod.data);
183
- }
184
- });
185
- }
186
- dataCall(method, params) {
187
- return new Promise(async (resolve, reject) => {
188
- const [err, res] = await to(this.call(method, params));
189
- if (err)
190
- return reject(err);
191
- return resolve(res.result);
192
- });
193
- }
194
- createRequestMethod(method, params) {
195
- const id = this.methodIdIncrement++;
196
- const request = { id: id, jsonrpc: `2.0`, method };
197
- if (params)
198
- request.params = params;
199
- const data = JSON.stringify(request);
200
- return { data, id };
201
- }
202
- }