@xelis/sdk 0.3.3 → 0.4.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.
- package/daemon/rpc.d.ts +30 -30
- package/daemon/rpc.js +34 -49
- package/daemon/websocket.d.ts +6 -20
- package/daemon/websocket.js +34 -193
- package/lib/rpc.d.ts +6 -0
- package/lib/rpc.js +24 -0
- package/{daemon → lib}/types.d.ts +63 -10
- package/lib/types.js +51 -0
- package/lib/websocket.d.ts +22 -0
- package/lib/websocket.js +171 -0
- package/package.json +1 -2
- package/react/{context.d.ts → daemon.d.ts} +1 -1
- package/wallet/rpc.d.ts +15 -0
- package/wallet/rpc.js +35 -0
- package/wallet/websocket.d.ts +16 -0
- package/wallet/websocket.js +38 -0
- package/daemon/types.js +0 -35
- package/dist +0 -44
- /package/react/{context.js → daemon.js} +0 -0
package/daemon/rpc.d.ts
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import { Balance, Block, TopoHeightRangeParams, GetInfoResult, HeightRangeParams, GetLastBalanceResult, P2PStatusResult,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
import { Balance, Block, TopoHeightRangeParams, GetInfoResult, HeightRangeParams, GetLastBalanceResult, P2PStatusResult, Transaction, GetLastBalanceParams, GetBalanceAtTopoHeightParams, GetAccountsParams, GetBlockAtTopoHeightParams, GetBlockByHashParams, GetBlocksAtHeightParams, GetTopBlockParams } from '../lib/types';
|
|
2
|
+
import { RPC as BaseRPC } from '../lib/rpc';
|
|
3
|
+
declare class RPC extends BaseRPC {
|
|
4
|
+
getVersion(): Promise<import("../lib/types").RPCResponse<string>>;
|
|
5
|
+
getInfo(): Promise<import("../lib/types").RPCResponse<GetInfoResult>>;
|
|
6
|
+
getHeight(): Promise<import("../lib/types").RPCResponse<number>>;
|
|
7
|
+
getTopoHeight(): Promise<import("../lib/types").RPCResponse<number>>;
|
|
8
|
+
getStableHeight(): Promise<import("../lib/types").RPCResponse<number>>;
|
|
9
|
+
getBlockTemplate(address: string): Promise<import("../lib/types").RPCResponse<string>>;
|
|
10
|
+
getBlockAtTopoHeight(params: GetBlockAtTopoHeightParams): Promise<import("../lib/types").RPCResponse<Block>>;
|
|
11
|
+
getBlocksAtHeight(params: GetBlocksAtHeightParams): Promise<import("../lib/types").RPCResponse<Block[]>>;
|
|
12
|
+
getBlockByHash(params: GetBlockByHashParams): Promise<import("../lib/types").RPCResponse<Block>>;
|
|
13
|
+
getTopBlock(params: GetTopBlockParams): Promise<import("../lib/types").RPCResponse<Block>>;
|
|
14
|
+
getNonce(address: string): Promise<import("../lib/types").RPCResponse<number>>;
|
|
15
|
+
getLastBalance(params: GetLastBalanceParams): Promise<import("../lib/types").RPCResponse<GetLastBalanceResult>>;
|
|
16
|
+
getBalanceAtTopoHeight(params: GetBalanceAtTopoHeightParams): Promise<import("../lib/types").RPCResponse<Balance>>;
|
|
17
|
+
getAssets(): Promise<import("../lib/types").RPCResponse<string[]>>;
|
|
18
|
+
countTransactions(): Promise<import("../lib/types").RPCResponse<number>>;
|
|
19
|
+
countAssets(): Promise<import("../lib/types").RPCResponse<number>>;
|
|
20
|
+
getTips(): Promise<import("../lib/types").RPCResponse<string[]>>;
|
|
21
|
+
p2pStatus(): Promise<import("../lib/types").RPCResponse<P2PStatusResult>>;
|
|
22
|
+
getDAGOrder(params: TopoHeightRangeParams): Promise<import("../lib/types").RPCResponse<string[]>>;
|
|
23
|
+
getMemPool(): Promise<import("../lib/types").RPCResponse<Transaction[]>>;
|
|
24
|
+
getTransaction(hash: string): Promise<import("../lib/types").RPCResponse<Transaction>>;
|
|
25
|
+
getTransactions(txHashes: string[]): Promise<import("../lib/types").RPCResponse<Transaction[]>>;
|
|
26
|
+
getBlocksRangeByTopoheight(params: TopoHeightRangeParams): Promise<import("../lib/types").RPCResponse<Block[]>>;
|
|
27
|
+
getBlocksRangeByHeight(params: HeightRangeParams): Promise<import("../lib/types").RPCResponse<Block[]>>;
|
|
28
|
+
getAccounts(params: GetAccountsParams): Promise<import("../lib/types").RPCResponse<string[]>>;
|
|
29
|
+
submitBlock(blockTemplate: string): Promise<import("../lib/types").RPCResponse<boolean>>;
|
|
30
|
+
submitTransaction(hexData: string): Promise<import("../lib/types").RPCResponse<boolean>>;
|
|
31
31
|
}
|
|
32
32
|
export default RPC;
|
package/daemon/rpc.js
CHANGED
|
@@ -1,101 +1,86 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
this.endpoint = endpoint;
|
|
5
|
-
}
|
|
6
|
-
async fetch(method, params) {
|
|
7
|
-
try {
|
|
8
|
-
const body = JSON.stringify({ id: 1, jsonrpc: '2.0', method: method, params });
|
|
9
|
-
const res = await fetch(this.endpoint, { method: `POST`, body });
|
|
10
|
-
if (res.ok) {
|
|
11
|
-
const data = await res.json();
|
|
12
|
-
if (data.error) {
|
|
13
|
-
return Promise.reject(new Error(data.error.message));
|
|
14
|
-
}
|
|
15
|
-
return Promise.resolve(data);
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
return Promise.reject(new Error(`${res.status} - ${res.statusText}`));
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
catch (err) {
|
|
22
|
-
return Promise.reject(err);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
1
|
+
import { DaemonRPCMethod } from '../lib/types';
|
|
2
|
+
import { RPC as BaseRPC } from '../lib/rpc';
|
|
3
|
+
class RPC extends BaseRPC {
|
|
25
4
|
getVersion() {
|
|
26
|
-
return this.
|
|
5
|
+
return this.post(DaemonRPCMethod.GetVersion);
|
|
27
6
|
}
|
|
28
7
|
getInfo() {
|
|
29
|
-
return this.
|
|
8
|
+
return this.post(DaemonRPCMethod.GetInfo);
|
|
30
9
|
}
|
|
31
10
|
getHeight() {
|
|
32
|
-
return this.
|
|
11
|
+
return this.post(DaemonRPCMethod.GetHeight);
|
|
33
12
|
}
|
|
34
13
|
getTopoHeight() {
|
|
35
|
-
return this.
|
|
14
|
+
return this.post(DaemonRPCMethod.GetTopoHeight);
|
|
36
15
|
}
|
|
37
16
|
getStableHeight() {
|
|
38
|
-
return this.
|
|
17
|
+
return this.post(DaemonRPCMethod.GetStableHeight);
|
|
39
18
|
}
|
|
40
19
|
getBlockTemplate(address) {
|
|
41
|
-
return this.
|
|
20
|
+
return this.post(DaemonRPCMethod.GetBlockTemplate, { address });
|
|
42
21
|
}
|
|
43
22
|
getBlockAtTopoHeight(params) {
|
|
44
|
-
return this.
|
|
23
|
+
return this.post(DaemonRPCMethod.GetBlockAtTopoHeight, params);
|
|
45
24
|
}
|
|
46
25
|
getBlocksAtHeight(params) {
|
|
47
|
-
return this.
|
|
26
|
+
return this.post(DaemonRPCMethod.GetBlocksAtHeight, params);
|
|
48
27
|
}
|
|
49
28
|
getBlockByHash(params) {
|
|
50
|
-
return this.
|
|
29
|
+
return this.post(DaemonRPCMethod.GetBlockByHash, params);
|
|
51
30
|
}
|
|
52
31
|
getTopBlock(params) {
|
|
53
|
-
return this.
|
|
32
|
+
return this.post(DaemonRPCMethod.GetTopBlock, params);
|
|
54
33
|
}
|
|
55
34
|
getNonce(address) {
|
|
56
|
-
return this.
|
|
35
|
+
return this.post(DaemonRPCMethod.GetNonce, { address });
|
|
57
36
|
}
|
|
58
37
|
getLastBalance(params) {
|
|
59
|
-
return this.
|
|
38
|
+
return this.post(DaemonRPCMethod.GetLastBalance, params);
|
|
60
39
|
}
|
|
61
40
|
getBalanceAtTopoHeight(params) {
|
|
62
|
-
return this.
|
|
41
|
+
return this.post(DaemonRPCMethod.GetBalanceAtTopoHeight, params);
|
|
63
42
|
}
|
|
64
43
|
getAssets() {
|
|
65
|
-
return this.
|
|
44
|
+
return this.post(DaemonRPCMethod.GetAssets);
|
|
66
45
|
}
|
|
67
46
|
countTransactions() {
|
|
68
|
-
return this.
|
|
47
|
+
return this.post(DaemonRPCMethod.CountTransactions);
|
|
69
48
|
}
|
|
70
49
|
countAssets() {
|
|
71
|
-
return this.
|
|
50
|
+
return this.post(DaemonRPCMethod.CountAssets);
|
|
72
51
|
}
|
|
73
52
|
getTips() {
|
|
74
|
-
return this.
|
|
53
|
+
return this.post(DaemonRPCMethod.GetTips);
|
|
75
54
|
}
|
|
76
55
|
p2pStatus() {
|
|
77
|
-
return this.
|
|
56
|
+
return this.post(DaemonRPCMethod.P2PStatus);
|
|
78
57
|
}
|
|
79
58
|
getDAGOrder(params) {
|
|
80
|
-
return this.
|
|
59
|
+
return this.post(DaemonRPCMethod.GetDAGOrder, params);
|
|
81
60
|
}
|
|
82
61
|
getMemPool() {
|
|
83
|
-
return this.
|
|
62
|
+
return this.post(DaemonRPCMethod.GetMempool);
|
|
84
63
|
}
|
|
85
64
|
getTransaction(hash) {
|
|
86
|
-
return this.
|
|
65
|
+
return this.post(DaemonRPCMethod.GetTransaction, { hash });
|
|
87
66
|
}
|
|
88
67
|
getTransactions(txHashes) {
|
|
89
|
-
return this.
|
|
68
|
+
return this.post(DaemonRPCMethod.GetTransactions, { tx_hashes: txHashes });
|
|
90
69
|
}
|
|
91
70
|
getBlocksRangeByTopoheight(params) {
|
|
92
|
-
return this.
|
|
71
|
+
return this.post(DaemonRPCMethod.GetBlocksRangeByTopoheight, params);
|
|
93
72
|
}
|
|
94
73
|
getBlocksRangeByHeight(params) {
|
|
95
|
-
return this.
|
|
74
|
+
return this.post(DaemonRPCMethod.GetBlocksRangeByHeight, params);
|
|
96
75
|
}
|
|
97
76
|
getAccounts(params) {
|
|
98
|
-
return this.
|
|
77
|
+
return this.post(DaemonRPCMethod.GetAccounts, params);
|
|
78
|
+
}
|
|
79
|
+
submitBlock(blockTemplate) {
|
|
80
|
+
return this.post(DaemonRPCMethod.SubmitBlock, { block_template: blockTemplate });
|
|
81
|
+
}
|
|
82
|
+
submitTransaction(hexData) {
|
|
83
|
+
return this.post(DaemonRPCMethod.SubmitTransaction, { data: hexData });
|
|
99
84
|
}
|
|
100
85
|
}
|
|
101
86
|
export default RPC;
|
package/daemon/websocket.d.ts
CHANGED
|
@@ -1,28 +1,12 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { MessageEvent } from 'ws';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
declare class WS {
|
|
6
|
-
endpoint: string;
|
|
7
|
-
socket?: WebSocket;
|
|
8
|
-
timeout: number;
|
|
9
|
-
connected: boolean;
|
|
10
|
-
unsubscribeSuspense: number;
|
|
11
|
-
private events;
|
|
12
|
-
constructor();
|
|
13
|
-
connect(endpoint: string): Promise<unknown>;
|
|
14
|
-
close(code?: number | undefined, data?: string | Buffer | undefined): void;
|
|
15
|
-
onClose(cb: (event: WebSocket.CloseEvent) => void): void;
|
|
16
|
-
onError(cb: (err: WebSocket.ErrorEvent) => void): void;
|
|
17
|
-
private clearEvent;
|
|
18
|
-
closeAllListens(event: RPCEvent): Promise<void>;
|
|
19
|
-
listenEvent<T>(event: RPCEvent, onData: (msgEvent: MessageEvent, data?: T, err?: Error) => void): Promise<() => Promise<void>>;
|
|
2
|
+
import { Block, GetInfoResult, RPCEventResult, Transaction, TopoHeightRangeParams, P2PStatusResult, Balance, GetBalanceAtTopoHeightParams, GetLastBalanceResult, HeightRangeParams, BlockOrdered, GetLastBalanceParams, GetAccountsParams, GetBlockAtTopoHeightParams, GetBlockByHashParams, GetBlocksAtHeightParams, GetTopBlockParams } from '../lib/types';
|
|
3
|
+
import { WS as BaseWS } from '../lib/websocket';
|
|
4
|
+
declare class WS extends BaseWS {
|
|
20
5
|
onNewBlock(onData: (msgEvent: MessageEvent, data?: Block & RPCEventResult, err?: Error) => void): Promise<() => Promise<void>>;
|
|
21
6
|
onTransactionAddedInMempool(onData: (msgEvent: MessageEvent, data?: Transaction & RPCEventResult, err?: Error) => void): Promise<() => Promise<void>>;
|
|
22
7
|
onTransactionExecuted(onData: (msgEvent: MessageEvent, data?: Transaction & RPCEventResult, err?: Error) => void): Promise<() => Promise<void>>;
|
|
23
8
|
onBlockOrdered(onData: (msgEvent: MessageEvent, data?: BlockOrdered & RPCEventResult, err?: Error) => void): Promise<() => Promise<void>>;
|
|
24
|
-
|
|
25
|
-
dataCall<T>(method: string, params?: any): Promise<T>;
|
|
9
|
+
getVersion(): Promise<string>;
|
|
26
10
|
getInfo(): Promise<GetInfoResult>;
|
|
27
11
|
getHeight(): Promise<number>;
|
|
28
12
|
getTopoHeight(): Promise<number>;
|
|
@@ -46,5 +30,7 @@ declare class WS {
|
|
|
46
30
|
getBlocksRangeByTopoheight(params: TopoHeightRangeParams): Promise<Block[]>;
|
|
47
31
|
getBlocksRangeByHeight(params: HeightRangeParams): Promise<Block[]>;
|
|
48
32
|
getAccounts(params: GetAccountsParams): Promise<string[]>;
|
|
33
|
+
submitBlock(blockTemplate: string): Promise<boolean>;
|
|
34
|
+
submitTransaction(hexData: string): Promise<boolean>;
|
|
49
35
|
}
|
|
50
36
|
export default WS;
|
package/daemon/websocket.js
CHANGED
|
@@ -1,140 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
function createRequestMethod(method, params) {
|
|
5
|
-
const id = Math.floor(Date.now() * Math.random());
|
|
6
|
-
const request = { id: id, jsonrpc: `2.0`, method };
|
|
7
|
-
if (params)
|
|
8
|
-
request.params = params;
|
|
9
|
-
const data = JSON.stringify(request);
|
|
10
|
-
return { data, id };
|
|
11
|
-
}
|
|
12
|
-
class WS {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.endpoint = "";
|
|
15
|
-
this.timeout = 3000;
|
|
16
|
-
this.connected = false;
|
|
17
|
-
this.events = {};
|
|
18
|
-
this.unsubscribeSuspense = 1000;
|
|
19
|
-
}
|
|
20
|
-
connect(endpoint) {
|
|
21
|
-
if (this.socket && this.socket.readyState !== WebSocket.CLOSED) {
|
|
22
|
-
this.socket.close();
|
|
23
|
-
}
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
this.socket = new WebSocket(endpoint);
|
|
26
|
-
this.endpoint = endpoint;
|
|
27
|
-
this.socket.addEventListener(`open`, (event) => {
|
|
28
|
-
this.connected = true;
|
|
29
|
-
resolve(event);
|
|
30
|
-
});
|
|
31
|
-
this.socket.addEventListener(`close`, () => {
|
|
32
|
-
this.connected = false;
|
|
33
|
-
reject();
|
|
34
|
-
});
|
|
35
|
-
this.socket.addEventListener(`error`, (err) => {
|
|
36
|
-
this.connected = false;
|
|
37
|
-
reject(err);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
close(code, data) {
|
|
42
|
-
this.socket && this.socket.close(code, data);
|
|
43
|
-
}
|
|
44
|
-
onClose(cb) {
|
|
45
|
-
if (!this.socket)
|
|
46
|
-
return;
|
|
47
|
-
this.socket.addEventListener(`close`, (event) => {
|
|
48
|
-
cb(event);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
onError(cb) {
|
|
52
|
-
if (!this.socket)
|
|
53
|
-
return;
|
|
54
|
-
this.socket.addEventListener(`error`, (err) => {
|
|
55
|
-
cb(err);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
clearEvent(event) {
|
|
59
|
-
this.events[event].listeners.forEach(listener => {
|
|
60
|
-
this.socket && this.socket.removeEventListener(`message`, listener);
|
|
61
|
-
});
|
|
62
|
-
Reflect.deleteProperty(this.events, event);
|
|
63
|
-
}
|
|
64
|
-
async closeAllListens(event) {
|
|
65
|
-
if (this.events[event]) {
|
|
66
|
-
const [err, _] = await to(this.call(`unsubscribe`, { notify: event }));
|
|
67
|
-
if (err)
|
|
68
|
-
return Promise.reject(err);
|
|
69
|
-
this.clearEvent(event);
|
|
70
|
-
}
|
|
71
|
-
return Promise.resolve();
|
|
72
|
-
}
|
|
73
|
-
async listenEvent(event, onData) {
|
|
74
|
-
const onMessage = (msgEvent) => {
|
|
75
|
-
if (this.events[event]) {
|
|
76
|
-
const { id } = this.events[event];
|
|
77
|
-
if (typeof msgEvent.data === `string`) {
|
|
78
|
-
try {
|
|
79
|
-
const data = JSON.parse(msgEvent.data);
|
|
80
|
-
if (data.id === id) {
|
|
81
|
-
if (data.error) {
|
|
82
|
-
onData(msgEvent, undefined, new Error(data.error.message));
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
onData(msgEvent, data.result, undefined);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
catch (_a) {
|
|
90
|
-
// can't parse json -- do nothing
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
if (this.events[event]) {
|
|
96
|
-
const { unsubscribeTimeoutId } = this.events[event];
|
|
97
|
-
if (unsubscribeTimeoutId) {
|
|
98
|
-
// clear timeout to unsubscribe
|
|
99
|
-
// because we got a new registered event and want to cancel the pending unsubscribe grace period
|
|
100
|
-
clearTimeout(unsubscribeTimeoutId);
|
|
101
|
-
}
|
|
102
|
-
this.events[event].listeners.push(onMessage);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
// important if multiple listenEvent are called without await atleast we store listener before getting id
|
|
106
|
-
this.events[event] = { listeners: [onMessage] };
|
|
107
|
-
const [err, res] = await to(this.call(`subscribe`, { notify: event }));
|
|
108
|
-
if (err) {
|
|
109
|
-
this.clearEvent(event);
|
|
110
|
-
return Promise.reject(err);
|
|
111
|
-
}
|
|
112
|
-
this.events[event].id = res.id;
|
|
113
|
-
}
|
|
114
|
-
this.socket && this.socket.addEventListener(`message`, onMessage);
|
|
115
|
-
const closeListen = () => {
|
|
116
|
-
const eventData = this.events[event];
|
|
117
|
-
if (eventData) {
|
|
118
|
-
const listeners = eventData.listeners;
|
|
119
|
-
for (let i = 0; i < listeners.length; i++) {
|
|
120
|
-
if (listeners[i] === onMessage) {
|
|
121
|
-
listeners.splice(i, 1);
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
if (listeners.length === 0) {
|
|
126
|
-
this.events[event].unsubscribeTimeoutId = setTimeout(async () => {
|
|
127
|
-
// no more listener so we unsubscribe from daemon websocket
|
|
128
|
-
this.call(`unsubscribe`, { notify: event });
|
|
129
|
-
Reflect.deleteProperty(this.events, event);
|
|
130
|
-
}, this.unsubscribeSuspense);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
this.socket && this.socket.removeEventListener(`message`, onMessage);
|
|
134
|
-
return Promise.resolve();
|
|
135
|
-
};
|
|
136
|
-
return Promise.resolve(closeListen);
|
|
137
|
-
}
|
|
1
|
+
import { RPCEvent, DaemonRPCMethod } from '../lib/types';
|
|
2
|
+
import { WS as BaseWS } from '../lib/websocket';
|
|
3
|
+
class WS extends BaseWS {
|
|
138
4
|
onNewBlock(onData) {
|
|
139
5
|
return this.listenEvent(RPCEvent.NewBlock, onData);
|
|
140
6
|
}
|
|
@@ -147,108 +13,83 @@ class WS {
|
|
|
147
13
|
onBlockOrdered(onData) {
|
|
148
14
|
return this.listenEvent(RPCEvent.BlockOrdered, onData);
|
|
149
15
|
}
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
-
const { data, id } = createRequestMethod(method, params);
|
|
153
|
-
let timeoutId = null;
|
|
154
|
-
const onMessage = (msgEvent) => {
|
|
155
|
-
if (typeof msgEvent.data === `string`) {
|
|
156
|
-
const data = JSON.parse(msgEvent.data);
|
|
157
|
-
if (data.id === id) {
|
|
158
|
-
clearTimeout(timeoutId);
|
|
159
|
-
this.socket && this.socket.removeEventListener(`message`, onMessage);
|
|
160
|
-
if (data.error)
|
|
161
|
-
return reject(new Error(data.error.message));
|
|
162
|
-
else
|
|
163
|
-
resolve(data);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
// make sure you listen before sending data
|
|
168
|
-
this.socket && this.socket.addEventListener(`message`, onMessage); // we don't use { once: true } option because of timeout feature
|
|
169
|
-
timeoutId = setTimeout(() => {
|
|
170
|
-
this.socket && this.socket.removeEventListener(`message`, onMessage);
|
|
171
|
-
reject(new Error(`timeout`));
|
|
172
|
-
}, this.timeout);
|
|
173
|
-
this.socket && this.socket.send(data);
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
dataCall(method, params) {
|
|
177
|
-
return new Promise(async (resolve, reject) => {
|
|
178
|
-
const [err, res] = await to(this.call(method, params));
|
|
179
|
-
if (err)
|
|
180
|
-
return reject(err);
|
|
181
|
-
return resolve(res.result);
|
|
182
|
-
});
|
|
16
|
+
getVersion() {
|
|
17
|
+
return this.dataCall(DaemonRPCMethod.GetVersion);
|
|
183
18
|
}
|
|
184
19
|
getInfo() {
|
|
185
|
-
return this.dataCall(
|
|
20
|
+
return this.dataCall(DaemonRPCMethod.GetInfo);
|
|
186
21
|
}
|
|
187
22
|
getHeight() {
|
|
188
|
-
return this.dataCall(
|
|
23
|
+
return this.dataCall(DaemonRPCMethod.GetHeight);
|
|
189
24
|
}
|
|
190
25
|
getTopoHeight() {
|
|
191
|
-
return this.dataCall(
|
|
26
|
+
return this.dataCall(DaemonRPCMethod.GetTopoHeight);
|
|
192
27
|
}
|
|
193
28
|
getStableHeight() {
|
|
194
|
-
return this.dataCall(
|
|
29
|
+
return this.dataCall(DaemonRPCMethod.GetStableHeight);
|
|
195
30
|
}
|
|
196
31
|
getBlockTemplate(address) {
|
|
197
|
-
return this.dataCall(
|
|
32
|
+
return this.dataCall(DaemonRPCMethod.GetBlockTemplate, { address });
|
|
198
33
|
}
|
|
199
34
|
getBlockAtTopoHeight(params) {
|
|
200
|
-
return this.dataCall(
|
|
35
|
+
return this.dataCall(DaemonRPCMethod.GetBlockAtTopoHeight, params);
|
|
201
36
|
}
|
|
202
37
|
getBlocksAtHeight(params) {
|
|
203
|
-
return this.dataCall(
|
|
38
|
+
return this.dataCall(DaemonRPCMethod.GetBlocksAtHeight, params);
|
|
204
39
|
}
|
|
205
40
|
getBlockByHash(params) {
|
|
206
|
-
return this.dataCall(
|
|
41
|
+
return this.dataCall(DaemonRPCMethod.GetBlockByHash, params);
|
|
207
42
|
}
|
|
208
43
|
getTopBlock(params) {
|
|
209
|
-
return this.dataCall(
|
|
44
|
+
return this.dataCall(DaemonRPCMethod.GetTopBlock, params);
|
|
210
45
|
}
|
|
211
46
|
getNonce(address) {
|
|
212
|
-
return this.dataCall(
|
|
47
|
+
return this.dataCall(DaemonRPCMethod.GetNonce, { address });
|
|
213
48
|
}
|
|
214
49
|
getLastBalance(params) {
|
|
215
|
-
return this.dataCall(
|
|
50
|
+
return this.dataCall(DaemonRPCMethod.GetLastBalance, params);
|
|
216
51
|
}
|
|
217
52
|
getBalanceAtTopoHeight(params) {
|
|
218
|
-
return this.dataCall(
|
|
53
|
+
return this.dataCall(DaemonRPCMethod.GetBalanceAtTopoHeight, params);
|
|
219
54
|
}
|
|
220
55
|
getAssets() {
|
|
221
|
-
return this.dataCall(
|
|
56
|
+
return this.dataCall(DaemonRPCMethod.GetAssets);
|
|
222
57
|
}
|
|
223
58
|
countTransactions() {
|
|
224
|
-
return this.dataCall(
|
|
59
|
+
return this.dataCall(DaemonRPCMethod.CountTransactions);
|
|
225
60
|
}
|
|
226
61
|
getTips() {
|
|
227
|
-
return this.dataCall(
|
|
62
|
+
return this.dataCall(DaemonRPCMethod.GetTips);
|
|
228
63
|
}
|
|
229
64
|
p2pStatus() {
|
|
230
|
-
return this.dataCall(
|
|
65
|
+
return this.dataCall(DaemonRPCMethod.P2PStatus);
|
|
231
66
|
}
|
|
232
67
|
getDAGOrder(params) {
|
|
233
|
-
return this.dataCall(
|
|
68
|
+
return this.dataCall(DaemonRPCMethod.GetDAGOrder, params);
|
|
234
69
|
}
|
|
235
70
|
getMemPool() {
|
|
236
|
-
return this.dataCall(
|
|
71
|
+
return this.dataCall(DaemonRPCMethod.GetMempool);
|
|
237
72
|
}
|
|
238
73
|
getTransaction(hash) {
|
|
239
|
-
return this.dataCall(
|
|
74
|
+
return this.dataCall(DaemonRPCMethod.GetTransaction, { hash });
|
|
240
75
|
}
|
|
241
76
|
getTransactions(txHashes) {
|
|
242
|
-
return this.dataCall(
|
|
77
|
+
return this.dataCall(DaemonRPCMethod.GetTransactions, { tx_hashes: txHashes });
|
|
243
78
|
}
|
|
244
79
|
getBlocksRangeByTopoheight(params) {
|
|
245
|
-
return this.dataCall(
|
|
80
|
+
return this.dataCall(DaemonRPCMethod.GetBlocksRangeByTopoheight, params);
|
|
246
81
|
}
|
|
247
82
|
getBlocksRangeByHeight(params) {
|
|
248
|
-
return this.dataCall(
|
|
83
|
+
return this.dataCall(DaemonRPCMethod.GetBlocksRangeByHeight, params);
|
|
249
84
|
}
|
|
250
85
|
getAccounts(params) {
|
|
251
|
-
return this.dataCall(
|
|
86
|
+
return this.dataCall(DaemonRPCMethod.GetAccounts, params);
|
|
87
|
+
}
|
|
88
|
+
submitBlock(blockTemplate) {
|
|
89
|
+
return this.dataCall(DaemonRPCMethod.SubmitBlock, { block_template: blockTemplate });
|
|
90
|
+
}
|
|
91
|
+
submitTransaction(hexData) {
|
|
92
|
+
return this.dataCall(DaemonRPCMethod.SubmitTransaction, { data: hexData });
|
|
252
93
|
}
|
|
253
94
|
}
|
|
254
95
|
export default WS;
|
package/lib/rpc.d.ts
ADDED
package/lib/rpc.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class RPC {
|
|
2
|
+
constructor(endpoint) {
|
|
3
|
+
this.endpoint = endpoint;
|
|
4
|
+
}
|
|
5
|
+
async post(method, params) {
|
|
6
|
+
try {
|
|
7
|
+
const body = JSON.stringify({ id: 1, jsonrpc: '2.0', method: method, params });
|
|
8
|
+
const res = await fetch(this.endpoint, { method: `POST`, body });
|
|
9
|
+
if (res.ok) {
|
|
10
|
+
const data = await res.json();
|
|
11
|
+
if (data.error) {
|
|
12
|
+
return Promise.reject(new Error(data.error.message));
|
|
13
|
+
}
|
|
14
|
+
return Promise.resolve(data);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return Promise.reject(new Error(`${res.status} - ${res.statusText}`));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
return Promise.reject(err);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -88,17 +88,27 @@ export interface BlockOrdered {
|
|
|
88
88
|
block_hash: string;
|
|
89
89
|
block_type: string;
|
|
90
90
|
}
|
|
91
|
+
export interface Transfer {
|
|
92
|
+
amount: number;
|
|
93
|
+
asset: string;
|
|
94
|
+
extra_data?: any;
|
|
95
|
+
to: string;
|
|
96
|
+
}
|
|
97
|
+
export interface TransactionData {
|
|
98
|
+
transfers: Transfer[];
|
|
99
|
+
burn: {
|
|
100
|
+
asset: string;
|
|
101
|
+
amount: number;
|
|
102
|
+
};
|
|
103
|
+
call_contract: {
|
|
104
|
+
contract: string;
|
|
105
|
+
};
|
|
106
|
+
deploy_contract: string;
|
|
107
|
+
}
|
|
91
108
|
export interface Transaction {
|
|
92
109
|
hash: string;
|
|
93
110
|
blocks: string[];
|
|
94
|
-
data:
|
|
95
|
-
Transfer: {
|
|
96
|
-
amount: number;
|
|
97
|
-
asset: string;
|
|
98
|
-
extra_data: any;
|
|
99
|
-
to: string;
|
|
100
|
-
}[];
|
|
101
|
-
};
|
|
111
|
+
data: TransactionData;
|
|
102
112
|
fee: number;
|
|
103
113
|
nonce: number;
|
|
104
114
|
owner: string;
|
|
@@ -125,7 +135,48 @@ export interface GetBlockByHashParams {
|
|
|
125
135
|
export interface GetTopBlockParams {
|
|
126
136
|
include_txs?: boolean;
|
|
127
137
|
}
|
|
128
|
-
export
|
|
138
|
+
export interface GetAddressParams {
|
|
139
|
+
integrated_data?: string;
|
|
140
|
+
}
|
|
141
|
+
export interface SplitAddressParams {
|
|
142
|
+
address: string;
|
|
143
|
+
}
|
|
144
|
+
export interface SplitAddressResult {
|
|
145
|
+
address: string;
|
|
146
|
+
integrated_data: string;
|
|
147
|
+
}
|
|
148
|
+
export interface BuildTransactionParams {
|
|
149
|
+
tx_type: TransactionData;
|
|
150
|
+
broadcast: boolean;
|
|
151
|
+
fee?: number;
|
|
152
|
+
}
|
|
153
|
+
export interface BuildTransactionResult {
|
|
154
|
+
hash: string;
|
|
155
|
+
data: Transaction;
|
|
156
|
+
}
|
|
157
|
+
export interface ListTransactionParams {
|
|
158
|
+
min_topoheight?: number;
|
|
159
|
+
max_topoheight?: number;
|
|
160
|
+
address?: string;
|
|
161
|
+
accept_incoming?: boolean;
|
|
162
|
+
accept_outgoing?: boolean;
|
|
163
|
+
accept_coinbase?: boolean;
|
|
164
|
+
accept_burn?: boolean;
|
|
165
|
+
}
|
|
166
|
+
export declare enum WalletRPCMethod {
|
|
167
|
+
GetVersion = "get_version",
|
|
168
|
+
GetNetwork = "get_network",
|
|
169
|
+
GetNonce = "get_nonce",
|
|
170
|
+
GetTopoheight = "get_topoheight",
|
|
171
|
+
GetAddress = "get_address",
|
|
172
|
+
SplitAddress = "split_address",
|
|
173
|
+
GetBalance = "get_balance",
|
|
174
|
+
GetTrackedAssets = "get_tracked_assets",
|
|
175
|
+
GetTransaction = "get_transaction",
|
|
176
|
+
BuildTransaction = "build_transaction",
|
|
177
|
+
ListTransactions = "list_transactions"
|
|
178
|
+
}
|
|
179
|
+
export declare enum DaemonRPCMethod {
|
|
129
180
|
GetVersion = "get_version",
|
|
130
181
|
GetInfo = "get_info",
|
|
131
182
|
GetHeight = "get_height",
|
|
@@ -150,7 +201,9 @@ export declare enum RPCMethod {
|
|
|
150
201
|
GetTransactions = "get_transactions",
|
|
151
202
|
GetBlocksRangeByTopoheight = "get_blocks_range_by_topoheight",
|
|
152
203
|
GetBlocksRangeByHeight = "get_blocks_range_by_height",
|
|
153
|
-
GetAccounts = "get_accounts"
|
|
204
|
+
GetAccounts = "get_accounts",
|
|
205
|
+
SubmitBlock = "submit_block",
|
|
206
|
+
SubmitTransaction = "submit_transaction"
|
|
154
207
|
}
|
|
155
208
|
export declare enum RPCEvent {
|
|
156
209
|
NewBlock = "NewBlock",
|
package/lib/types.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export var WalletRPCMethod;
|
|
2
|
+
(function (WalletRPCMethod) {
|
|
3
|
+
WalletRPCMethod["GetVersion"] = "get_version";
|
|
4
|
+
WalletRPCMethod["GetNetwork"] = "get_network";
|
|
5
|
+
WalletRPCMethod["GetNonce"] = "get_nonce";
|
|
6
|
+
WalletRPCMethod["GetTopoheight"] = "get_topoheight";
|
|
7
|
+
WalletRPCMethod["GetAddress"] = "get_address";
|
|
8
|
+
WalletRPCMethod["SplitAddress"] = "split_address";
|
|
9
|
+
WalletRPCMethod["GetBalance"] = "get_balance";
|
|
10
|
+
WalletRPCMethod["GetTrackedAssets"] = "get_tracked_assets";
|
|
11
|
+
WalletRPCMethod["GetTransaction"] = "get_transaction";
|
|
12
|
+
WalletRPCMethod["BuildTransaction"] = "build_transaction";
|
|
13
|
+
WalletRPCMethod["ListTransactions"] = "list_transactions";
|
|
14
|
+
})(WalletRPCMethod || (WalletRPCMethod = {}));
|
|
15
|
+
export var DaemonRPCMethod;
|
|
16
|
+
(function (DaemonRPCMethod) {
|
|
17
|
+
DaemonRPCMethod["GetVersion"] = "get_version";
|
|
18
|
+
DaemonRPCMethod["GetInfo"] = "get_info";
|
|
19
|
+
DaemonRPCMethod["GetHeight"] = "get_height";
|
|
20
|
+
DaemonRPCMethod["GetTopoHeight"] = "get_topoheight";
|
|
21
|
+
DaemonRPCMethod["GetStableHeight"] = "get_stableheight";
|
|
22
|
+
DaemonRPCMethod["GetBlockTemplate"] = "get_block_template";
|
|
23
|
+
DaemonRPCMethod["GetBlockAtTopoHeight"] = "get_block_at_topoheight";
|
|
24
|
+
DaemonRPCMethod["GetBlocksAtHeight"] = "get_blocks_at_height";
|
|
25
|
+
DaemonRPCMethod["GetBlockByHash"] = "get_block_by_hash";
|
|
26
|
+
DaemonRPCMethod["GetTopBlock"] = "get_top_block";
|
|
27
|
+
DaemonRPCMethod["GetNonce"] = "get_nonce";
|
|
28
|
+
DaemonRPCMethod["GetLastBalance"] = "get_last_balance";
|
|
29
|
+
DaemonRPCMethod["GetBalanceAtTopoHeight"] = "get_balance_at_topoheight";
|
|
30
|
+
DaemonRPCMethod["GetAssets"] = "get_assets";
|
|
31
|
+
DaemonRPCMethod["CountAssets"] = "count_assets";
|
|
32
|
+
DaemonRPCMethod["CountTransactions"] = "count_transactions";
|
|
33
|
+
DaemonRPCMethod["GetTips"] = "get_tips";
|
|
34
|
+
DaemonRPCMethod["P2PStatus"] = "p2p_status";
|
|
35
|
+
DaemonRPCMethod["GetDAGOrder"] = "get_dag_order";
|
|
36
|
+
DaemonRPCMethod["GetMempool"] = "get_mempool";
|
|
37
|
+
DaemonRPCMethod["GetTransaction"] = "get_transaction";
|
|
38
|
+
DaemonRPCMethod["GetTransactions"] = "get_transactions";
|
|
39
|
+
DaemonRPCMethod["GetBlocksRangeByTopoheight"] = "get_blocks_range_by_topoheight";
|
|
40
|
+
DaemonRPCMethod["GetBlocksRangeByHeight"] = "get_blocks_range_by_height";
|
|
41
|
+
DaemonRPCMethod["GetAccounts"] = "get_accounts";
|
|
42
|
+
DaemonRPCMethod["SubmitBlock"] = "submit_block";
|
|
43
|
+
DaemonRPCMethod["SubmitTransaction"] = "submit_transaction";
|
|
44
|
+
})(DaemonRPCMethod || (DaemonRPCMethod = {}));
|
|
45
|
+
export var RPCEvent;
|
|
46
|
+
(function (RPCEvent) {
|
|
47
|
+
RPCEvent["NewBlock"] = "NewBlock";
|
|
48
|
+
RPCEvent["TransactionAddedInMempool"] = "TransactionAddedInMempool";
|
|
49
|
+
RPCEvent["TransactionExecuted"] = "TransactionExecuted";
|
|
50
|
+
RPCEvent["BlockOrdered"] = "BlockOrdered";
|
|
51
|
+
})(RPCEvent || (RPCEvent = {}));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { MessageEvent } from 'ws';
|
|
3
|
+
import WebSocket from 'isomorphic-ws';
|
|
4
|
+
import { RPCResponse, RPCEvent, RPCEventResult } from './types';
|
|
5
|
+
export declare class WS {
|
|
6
|
+
endpoint: string;
|
|
7
|
+
socket?: WebSocket;
|
|
8
|
+
timeout: number;
|
|
9
|
+
connected: boolean;
|
|
10
|
+
unsubscribeSuspense: number;
|
|
11
|
+
private events;
|
|
12
|
+
constructor();
|
|
13
|
+
connect(endpoint: string): Promise<unknown>;
|
|
14
|
+
close(code?: number | undefined, data?: string | Buffer | undefined): void;
|
|
15
|
+
onClose(cb: (event: WebSocket.CloseEvent) => void): void;
|
|
16
|
+
onError(cb: (err: WebSocket.ErrorEvent) => void): void;
|
|
17
|
+
private clearEvent;
|
|
18
|
+
closeAllListens(event: RPCEvent): Promise<void>;
|
|
19
|
+
listenEvent<T>(event: RPCEvent, onData: (msgEvent: MessageEvent, data?: T & RPCEventResult, err?: Error) => void): Promise<() => Promise<void>>;
|
|
20
|
+
call<T>(method: string, params?: any): Promise<RPCResponse<T>>;
|
|
21
|
+
dataCall<T>(method: string, params?: any): Promise<T>;
|
|
22
|
+
}
|
package/lib/websocket.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import WebSocket from 'isomorphic-ws';
|
|
2
|
+
import to from 'await-to-js';
|
|
3
|
+
function createRequestMethod(method, params) {
|
|
4
|
+
const id = Math.floor(Date.now() * Math.random());
|
|
5
|
+
const request = { id: id, jsonrpc: `2.0`, method };
|
|
6
|
+
if (params)
|
|
7
|
+
request.params = params;
|
|
8
|
+
const data = JSON.stringify(request);
|
|
9
|
+
return { data, id };
|
|
10
|
+
}
|
|
11
|
+
export class WS {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.endpoint = "";
|
|
14
|
+
this.timeout = 3000;
|
|
15
|
+
this.connected = false;
|
|
16
|
+
this.events = {};
|
|
17
|
+
this.unsubscribeSuspense = 1000;
|
|
18
|
+
}
|
|
19
|
+
connect(endpoint) {
|
|
20
|
+
if (this.socket && this.socket.readyState !== WebSocket.CLOSED) {
|
|
21
|
+
this.socket.close();
|
|
22
|
+
}
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
this.socket = new WebSocket(endpoint);
|
|
25
|
+
this.endpoint = endpoint;
|
|
26
|
+
this.socket.addEventListener(`open`, (event) => {
|
|
27
|
+
this.connected = true;
|
|
28
|
+
resolve(event);
|
|
29
|
+
});
|
|
30
|
+
this.socket.addEventListener(`close`, () => {
|
|
31
|
+
this.connected = false;
|
|
32
|
+
reject();
|
|
33
|
+
});
|
|
34
|
+
this.socket.addEventListener(`error`, (err) => {
|
|
35
|
+
this.connected = false;
|
|
36
|
+
reject(err);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
close(code, data) {
|
|
41
|
+
this.socket && this.socket.close(code, data);
|
|
42
|
+
}
|
|
43
|
+
onClose(cb) {
|
|
44
|
+
if (!this.socket)
|
|
45
|
+
return;
|
|
46
|
+
this.socket.addEventListener(`close`, (event) => {
|
|
47
|
+
cb(event);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
onError(cb) {
|
|
51
|
+
if (!this.socket)
|
|
52
|
+
return;
|
|
53
|
+
this.socket.addEventListener(`error`, (err) => {
|
|
54
|
+
cb(err);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
clearEvent(event) {
|
|
58
|
+
this.events[event].listeners.forEach(listener => {
|
|
59
|
+
this.socket && this.socket.removeEventListener(`message`, listener);
|
|
60
|
+
});
|
|
61
|
+
Reflect.deleteProperty(this.events, event);
|
|
62
|
+
}
|
|
63
|
+
async closeAllListens(event) {
|
|
64
|
+
if (this.events[event]) {
|
|
65
|
+
const [err, _] = await to(this.call(`unsubscribe`, { notify: event }));
|
|
66
|
+
if (err)
|
|
67
|
+
return Promise.reject(err);
|
|
68
|
+
this.clearEvent(event);
|
|
69
|
+
}
|
|
70
|
+
return Promise.resolve();
|
|
71
|
+
}
|
|
72
|
+
async listenEvent(event, onData) {
|
|
73
|
+
const onMessage = (msgEvent) => {
|
|
74
|
+
if (this.events[event]) {
|
|
75
|
+
const { id } = this.events[event];
|
|
76
|
+
if (typeof msgEvent.data === `string`) {
|
|
77
|
+
try {
|
|
78
|
+
const data = JSON.parse(msgEvent.data);
|
|
79
|
+
if (data.id === id) {
|
|
80
|
+
if (data.error) {
|
|
81
|
+
onData(msgEvent, undefined, new Error(data.error.message));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
onData(msgEvent, data.result, undefined);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (_a) {
|
|
89
|
+
// can't parse json -- do nothing
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
if (this.events[event]) {
|
|
95
|
+
const { unsubscribeTimeoutId } = this.events[event];
|
|
96
|
+
if (unsubscribeTimeoutId) {
|
|
97
|
+
// clear timeout to unsubscribe
|
|
98
|
+
// because we got a new registered event and want to cancel the pending unsubscribe grace period
|
|
99
|
+
clearTimeout(unsubscribeTimeoutId);
|
|
100
|
+
}
|
|
101
|
+
this.events[event].listeners.push(onMessage);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// important if multiple listenEvent are called without await atleast we store listener before getting id
|
|
105
|
+
this.events[event] = { listeners: [onMessage] };
|
|
106
|
+
const [err, res] = await to(this.call(`subscribe`, { notify: event }));
|
|
107
|
+
if (err) {
|
|
108
|
+
this.clearEvent(event);
|
|
109
|
+
return Promise.reject(err);
|
|
110
|
+
}
|
|
111
|
+
this.events[event].id = res.id;
|
|
112
|
+
}
|
|
113
|
+
this.socket && this.socket.addEventListener(`message`, onMessage);
|
|
114
|
+
const closeListen = () => {
|
|
115
|
+
const eventData = this.events[event];
|
|
116
|
+
if (eventData) {
|
|
117
|
+
const listeners = eventData.listeners;
|
|
118
|
+
for (let i = 0; i < listeners.length; i++) {
|
|
119
|
+
if (listeners[i] === onMessage) {
|
|
120
|
+
listeners.splice(i, 1);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (listeners.length === 0) {
|
|
125
|
+
this.events[event].unsubscribeTimeoutId = setTimeout(async () => {
|
|
126
|
+
// no more listener so we unsubscribe from daemon websocket
|
|
127
|
+
this.call(`unsubscribe`, { notify: event });
|
|
128
|
+
Reflect.deleteProperty(this.events, event);
|
|
129
|
+
}, this.unsubscribeSuspense);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
this.socket && this.socket.removeEventListener(`message`, onMessage);
|
|
133
|
+
return Promise.resolve();
|
|
134
|
+
};
|
|
135
|
+
return Promise.resolve(closeListen);
|
|
136
|
+
}
|
|
137
|
+
call(method, params) {
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
const { data, id } = createRequestMethod(method, params);
|
|
140
|
+
let timeoutId = null;
|
|
141
|
+
const onMessage = (msgEvent) => {
|
|
142
|
+
if (typeof msgEvent.data === `string`) {
|
|
143
|
+
const data = JSON.parse(msgEvent.data);
|
|
144
|
+
if (data.id === id) {
|
|
145
|
+
clearTimeout(timeoutId);
|
|
146
|
+
this.socket && this.socket.removeEventListener(`message`, onMessage);
|
|
147
|
+
if (data.error)
|
|
148
|
+
return reject(new Error(data.error.message));
|
|
149
|
+
else
|
|
150
|
+
resolve(data);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
// make sure you listen before sending data
|
|
155
|
+
this.socket && this.socket.addEventListener(`message`, onMessage); // we don't use { once: true } option because of timeout feature
|
|
156
|
+
timeoutId = setTimeout(() => {
|
|
157
|
+
this.socket && this.socket.removeEventListener(`message`, onMessage);
|
|
158
|
+
reject(new Error(`timeout`));
|
|
159
|
+
}, this.timeout);
|
|
160
|
+
this.socket && this.socket.send(data);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
dataCall(method, params) {
|
|
164
|
+
return new Promise(async (resolve, reject) => {
|
|
165
|
+
const [err, res] = await to(this.call(method, params));
|
|
166
|
+
if (err)
|
|
167
|
+
return reject(err);
|
|
168
|
+
return resolve(res.result);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.4.0",
|
|
3
3
|
"name": "@xelis/sdk",
|
|
4
4
|
"description": "Xelis software development kit for JS",
|
|
5
5
|
"repository": {
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"test": "jest",
|
|
12
12
|
"build": "npx tsc --declaration && cp package.json ./dist && cp README.md ./dist",
|
|
13
|
-
"prepublishOnly": "npm run build",
|
|
14
13
|
"publish": "cd ./dist && npm publish"
|
|
15
14
|
},
|
|
16
15
|
"devDependencies": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import { MessageEvent } from 'ws';
|
|
3
3
|
import DaemonWS from '../daemon/websocket';
|
|
4
|
-
import { RPCEvent } from '../
|
|
4
|
+
import { RPCEvent } from '../lib/types';
|
|
5
5
|
interface NodeSocket {
|
|
6
6
|
daemon: DaemonWS;
|
|
7
7
|
loading: boolean;
|
package/wallet/rpc.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Transaction, GetAddressParams, SplitAddressParams, SplitAddressResult, BuildTransactionParams, BuildTransactionResult, ListTransactionParams } from '../lib/types';
|
|
2
|
+
import { RPC as BaseRPC } from '../lib/rpc';
|
|
3
|
+
declare class RPC extends BaseRPC {
|
|
4
|
+
getVersion(): Promise<import("../lib/types").RPCResponse<string>>;
|
|
5
|
+
getNonce(): Promise<import("../lib/types").RPCResponse<number>>;
|
|
6
|
+
getTopoheight(): Promise<import("../lib/types").RPCResponse<number>>;
|
|
7
|
+
getAddress(params?: GetAddressParams): Promise<import("../lib/types").RPCResponse<string>>;
|
|
8
|
+
splitAddress(params: SplitAddressParams): Promise<import("../lib/types").RPCResponse<SplitAddressResult>>;
|
|
9
|
+
getBalance(asset?: string): Promise<import("../lib/types").RPCResponse<number>>;
|
|
10
|
+
getTrackedAssets(): Promise<import("../lib/types").RPCResponse<string[]>>;
|
|
11
|
+
getTransaction(hash: string): Promise<import("../lib/types").RPCResponse<Transaction>>;
|
|
12
|
+
buildTransaction(params: BuildTransactionParams): Promise<import("../lib/types").RPCResponse<BuildTransactionResult>>;
|
|
13
|
+
listTransactions(params?: ListTransactionParams): Promise<import("../lib/types").RPCResponse<Transaction[]>>;
|
|
14
|
+
}
|
|
15
|
+
export default RPC;
|
package/wallet/rpc.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { WalletRPCMethod } from '../lib/types';
|
|
2
|
+
import { RPC as BaseRPC } from '../lib/rpc';
|
|
3
|
+
class RPC extends BaseRPC {
|
|
4
|
+
getVersion() {
|
|
5
|
+
return this.post(WalletRPCMethod.GetVersion);
|
|
6
|
+
}
|
|
7
|
+
getNonce() {
|
|
8
|
+
return this.post(WalletRPCMethod.GetNonce);
|
|
9
|
+
}
|
|
10
|
+
getTopoheight() {
|
|
11
|
+
return this.post(WalletRPCMethod.GetTopoheight);
|
|
12
|
+
}
|
|
13
|
+
getAddress(params) {
|
|
14
|
+
return this.post(WalletRPCMethod.GetAddress, params);
|
|
15
|
+
}
|
|
16
|
+
splitAddress(params) {
|
|
17
|
+
return this.post(WalletRPCMethod.SplitAddress, params);
|
|
18
|
+
}
|
|
19
|
+
getBalance(asset) {
|
|
20
|
+
return this.post(WalletRPCMethod.GetBalance, { asset });
|
|
21
|
+
}
|
|
22
|
+
getTrackedAssets() {
|
|
23
|
+
return this.post(WalletRPCMethod.GetTrackedAssets);
|
|
24
|
+
}
|
|
25
|
+
getTransaction(hash) {
|
|
26
|
+
return this.post(WalletRPCMethod.GetTransaction, { hash });
|
|
27
|
+
}
|
|
28
|
+
buildTransaction(params) {
|
|
29
|
+
return this.post(WalletRPCMethod.BuildTransaction, params);
|
|
30
|
+
}
|
|
31
|
+
listTransactions(params) {
|
|
32
|
+
return this.post(WalletRPCMethod.ListTransactions, params);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export default RPC;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { WS as BaseWS } from '../lib/websocket';
|
|
2
|
+
import { BuildTransactionParams, BuildTransactionResult, GetAddressParams, ListTransactionParams, SplitAddressParams, SplitAddressResult, Transaction } from '../lib/types';
|
|
3
|
+
declare class WS extends BaseWS {
|
|
4
|
+
getVersion(): Promise<string>;
|
|
5
|
+
getNetwork(): Promise<string>;
|
|
6
|
+
getNonce(): Promise<number>;
|
|
7
|
+
getTopoheight(): Promise<number>;
|
|
8
|
+
getAddress(params?: GetAddressParams): Promise<string>;
|
|
9
|
+
splitAddress(params: SplitAddressParams): Promise<SplitAddressResult>;
|
|
10
|
+
getBalance(asset?: string): Promise<number>;
|
|
11
|
+
getTrackedAssets(): Promise<string[]>;
|
|
12
|
+
getTransaction(hash: string): Promise<Transaction>;
|
|
13
|
+
buildTransaction(params: BuildTransactionParams): Promise<BuildTransactionResult>;
|
|
14
|
+
listTransactions(params?: ListTransactionParams): Promise<Transaction[]>;
|
|
15
|
+
}
|
|
16
|
+
export default WS;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { WS as BaseWS } from '../lib/websocket';
|
|
2
|
+
import { WalletRPCMethod } from '../lib/types';
|
|
3
|
+
class WS extends BaseWS {
|
|
4
|
+
getVersion() {
|
|
5
|
+
return this.dataCall(WalletRPCMethod.GetVersion);
|
|
6
|
+
}
|
|
7
|
+
getNetwork() {
|
|
8
|
+
return this.dataCall(WalletRPCMethod.GetNetwork);
|
|
9
|
+
}
|
|
10
|
+
getNonce() {
|
|
11
|
+
return this.dataCall(WalletRPCMethod.GetNonce);
|
|
12
|
+
}
|
|
13
|
+
getTopoheight() {
|
|
14
|
+
return this.dataCall(WalletRPCMethod.GetTopoheight);
|
|
15
|
+
}
|
|
16
|
+
getAddress(params) {
|
|
17
|
+
return this.dataCall(WalletRPCMethod.GetAddress, params);
|
|
18
|
+
}
|
|
19
|
+
splitAddress(params) {
|
|
20
|
+
return this.dataCall(WalletRPCMethod.SplitAddress, params);
|
|
21
|
+
}
|
|
22
|
+
getBalance(asset) {
|
|
23
|
+
return this.dataCall(WalletRPCMethod.GetBalance, { asset });
|
|
24
|
+
}
|
|
25
|
+
getTrackedAssets() {
|
|
26
|
+
return this.dataCall(WalletRPCMethod.GetTrackedAssets);
|
|
27
|
+
}
|
|
28
|
+
getTransaction(hash) {
|
|
29
|
+
return this.dataCall(WalletRPCMethod.GetTransaction, { hash });
|
|
30
|
+
}
|
|
31
|
+
buildTransaction(params) {
|
|
32
|
+
return this.dataCall(WalletRPCMethod.BuildTransaction, params);
|
|
33
|
+
}
|
|
34
|
+
listTransactions(params) {
|
|
35
|
+
return this.dataCall(WalletRPCMethod.GetTransaction, params);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export default WS;
|
package/daemon/types.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export var RPCMethod;
|
|
2
|
-
(function (RPCMethod) {
|
|
3
|
-
RPCMethod["GetVersion"] = "get_version";
|
|
4
|
-
RPCMethod["GetInfo"] = "get_info";
|
|
5
|
-
RPCMethod["GetHeight"] = "get_height";
|
|
6
|
-
RPCMethod["GetTopoHeight"] = "get_topoheight";
|
|
7
|
-
RPCMethod["GetStableHeight"] = "get_stableheight";
|
|
8
|
-
RPCMethod["GetBlockTemplate"] = "get_block_template";
|
|
9
|
-
RPCMethod["GetBlockAtTopoHeight"] = "get_block_at_topoheight";
|
|
10
|
-
RPCMethod["GetBlocksAtHeight"] = "get_blocks_at_height";
|
|
11
|
-
RPCMethod["GetBlockByHash"] = "get_block_by_hash";
|
|
12
|
-
RPCMethod["GetTopBlock"] = "get_top_block";
|
|
13
|
-
RPCMethod["GetNonce"] = "get_nonce";
|
|
14
|
-
RPCMethod["GetLastBalance"] = "get_last_balance";
|
|
15
|
-
RPCMethod["GetBalanceAtTopoHeight"] = "get_balance_at_topoheight";
|
|
16
|
-
RPCMethod["GetAssets"] = "get_assets";
|
|
17
|
-
RPCMethod["CountAssets"] = "count_assets";
|
|
18
|
-
RPCMethod["CountTransactions"] = "count_transactions";
|
|
19
|
-
RPCMethod["GetTips"] = "get_tips";
|
|
20
|
-
RPCMethod["P2PStatus"] = "p2p_status";
|
|
21
|
-
RPCMethod["GetDAGOrder"] = "get_dag_order";
|
|
22
|
-
RPCMethod["GetMempool"] = "get_mempool";
|
|
23
|
-
RPCMethod["GetTransaction"] = "get_transaction";
|
|
24
|
-
RPCMethod["GetTransactions"] = "get_transactions";
|
|
25
|
-
RPCMethod["GetBlocksRangeByTopoheight"] = "get_blocks_range_by_topoheight";
|
|
26
|
-
RPCMethod["GetBlocksRangeByHeight"] = "get_blocks_range_by_height";
|
|
27
|
-
RPCMethod["GetAccounts"] = "get_accounts";
|
|
28
|
-
})(RPCMethod || (RPCMethod = {}));
|
|
29
|
-
export var RPCEvent;
|
|
30
|
-
(function (RPCEvent) {
|
|
31
|
-
RPCEvent["NewBlock"] = "NewBlock";
|
|
32
|
-
RPCEvent["TransactionAddedInMempool"] = "TransactionAddedInMempool";
|
|
33
|
-
RPCEvent["TransactionExecuted"] = "TransactionExecuted";
|
|
34
|
-
RPCEvent["BlockOrdered"] = "BlockOrdered";
|
|
35
|
-
})(RPCEvent || (RPCEvent = {}));
|
package/dist
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# XELIS-JS-SDK
|
|
2
|
-
|
|
3
|
-
Xelis software development kit for JS.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
Install library with NPM.
|
|
8
|
-
|
|
9
|
-
`npm i @xelis/sdk`
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
Import library and start working :).
|
|
14
|
-
|
|
15
|
-
Use http/rpc connection.
|
|
16
|
-
|
|
17
|
-
```js
|
|
18
|
-
import { DEV_NODE_RPC } from '@xelis/sdk/config/nodes'
|
|
19
|
-
import DaemonRPC from '@xelis/sdk/daemon/rpc'
|
|
20
|
-
|
|
21
|
-
const main = async () => {
|
|
22
|
-
const daemonRPC = new DaemonRPC(DEV_NODE_RPC)
|
|
23
|
-
const info = await daemonRPC.getInfo()
|
|
24
|
-
console.log(info)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
main()
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Use websocket connection.
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
import { DEV_NODE_RPC } from '@xelis/sdk/config/nodes'
|
|
34
|
-
import DaemonWS from '@xelis/sdk/daemon/websocket'
|
|
35
|
-
|
|
36
|
-
const main = async () => {
|
|
37
|
-
const daemonWS = new DaemonWS()
|
|
38
|
-
await daemonWS.connect(DEV_NODE_RPC)
|
|
39
|
-
const info = await daemonWS.getInfo()
|
|
40
|
-
console.log(info)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
main()
|
|
44
|
-
```
|
|
File without changes
|