@tchain/tcabci-read-js-client 1.0.4 → 1.0.6
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/README.md +3 -0
- package/client.js +97 -71
- package/client_test.js +45 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,6 +18,9 @@ $ npm i @tchain/tcabci-read-js-client
|
|
|
18
18
|
const tcAbciClient = require("@tchain/tcabci-read-js-client")
|
|
19
19
|
|
|
20
20
|
const client = new tcAbciClient()
|
|
21
|
+
// OR
|
|
22
|
+
const client = new tcAbciClient(['https://read-node-01.transferchain.io',
|
|
23
|
+
'wss://read-node-01.transferchain.io/ws'])
|
|
21
24
|
|
|
22
25
|
client.Start()
|
|
23
26
|
|
package/client.js
CHANGED
|
@@ -15,20 +15,27 @@ const {toJSON} = require("./util")
|
|
|
15
15
|
const axios = require("axios")
|
|
16
16
|
|
|
17
17
|
class TCAbciClient {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
subscribed = false
|
|
19
|
+
subscribedAddresses = []
|
|
20
|
+
connected = false
|
|
21
|
+
version = "v0.1.0"
|
|
22
|
+
retrieverCount = 0
|
|
22
23
|
errorCb = null
|
|
23
24
|
listenCb = null
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
ws = null
|
|
26
|
+
httpClient = null
|
|
27
|
+
readNodeAddress = READ_NODE_ADDRESS
|
|
28
|
+
readNodeWSAddress = READ_NODE_WS_ADDRESS
|
|
26
29
|
|
|
27
|
-
constructor() {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
constructor(readNodeAddresses = []) {
|
|
31
|
+
if (readNodeAddresses.length === 2) {
|
|
32
|
+
this.readNodeAddress = readNodeAddresses[0]
|
|
33
|
+
this.readNodeWSAddress = readNodeAddresses[1]
|
|
34
|
+
}
|
|
35
|
+
this.httpClient = axios.create({
|
|
36
|
+
baseURL: this.readNodeAddress,
|
|
30
37
|
timeout: 10000,
|
|
31
|
-
headers: {'Client': `tcabaci-read-js-client${this
|
|
38
|
+
headers: {'Client': `tcabaci-read-js-client${this.version}`}
|
|
32
39
|
})
|
|
33
40
|
}
|
|
34
41
|
|
|
@@ -39,48 +46,21 @@ class TCAbciClient {
|
|
|
39
46
|
this.listenCb = cb
|
|
40
47
|
}
|
|
41
48
|
Start() {
|
|
42
|
-
return
|
|
43
|
-
if (this.#getConnected()) {
|
|
44
|
-
reject(ALREADY_CONNECTED)
|
|
45
|
-
}
|
|
46
|
-
const wsClient = this.#wsClient()
|
|
47
|
-
this.#ws = new wsClient(READ_NODE_WS_ADDRESS)
|
|
48
|
-
|
|
49
|
-
this.#ws.onerror = (event) => {
|
|
50
|
-
this.#setConnected(false)
|
|
51
|
-
if (this.errorCb) {
|
|
52
|
-
this.errorCb(event.error)
|
|
53
|
-
}
|
|
54
|
-
reject(event)
|
|
55
|
-
}
|
|
56
|
-
this.#ws.onopen = (event) => {
|
|
57
|
-
this.#setConnected(true)
|
|
58
|
-
resolve(event)
|
|
59
|
-
}
|
|
60
|
-
this.#ws.onmessage = (message) => {
|
|
61
|
-
if (message.data === "OK" && message.data.length < 10) {
|
|
62
|
-
return { status: message.data }
|
|
63
|
-
}
|
|
64
|
-
if (this.listenCb) {
|
|
65
|
-
this.listenCb(toJSON(message.data))
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
})
|
|
49
|
+
return this.connect()
|
|
70
50
|
}
|
|
71
51
|
Stop() {
|
|
72
|
-
if (!this
|
|
52
|
+
if (!this.getConnected()) {
|
|
73
53
|
throw NOT_CONNECTED
|
|
74
54
|
}
|
|
75
|
-
this
|
|
76
|
-
this
|
|
77
|
-
this
|
|
55
|
+
this.ws.close()
|
|
56
|
+
this.setConnected(false)
|
|
57
|
+
this.setSubscribed(false)
|
|
78
58
|
}
|
|
79
59
|
Subscribe(addresses) {
|
|
80
60
|
if (!Array.isArray(addresses)) {
|
|
81
61
|
throw INVALID_ARGUMENTS
|
|
82
62
|
}
|
|
83
|
-
if (!this
|
|
63
|
+
if (!this.getConnected()) {
|
|
84
64
|
throw NOT_CONNECTED
|
|
85
65
|
}
|
|
86
66
|
let addrs = []
|
|
@@ -88,37 +68,37 @@ class TCAbciClient {
|
|
|
88
68
|
throw ADDRESSES_IS_EMPTY
|
|
89
69
|
}
|
|
90
70
|
addrs = addresses
|
|
91
|
-
if (this
|
|
71
|
+
if (this.getSubscribeAddresses().length > 0) {
|
|
92
72
|
let newAddress = []
|
|
93
73
|
for (let i = 0; i < addresses.length; i++) {
|
|
94
|
-
if (this
|
|
74
|
+
if (this.getSubscribeAddresses().indexOf(addresses[i]) === -1 ){
|
|
95
75
|
newAddress.push(addresses[i])
|
|
96
76
|
}
|
|
97
77
|
}
|
|
98
78
|
addrs = newAddress
|
|
99
79
|
}
|
|
100
80
|
const message = new Message(true, MESSAGE_TYPE.SUBSCRIBE, addrs)
|
|
101
|
-
this
|
|
102
|
-
this
|
|
103
|
-
this
|
|
81
|
+
this.ws.send(message.ToJSONString())
|
|
82
|
+
this.setSubscribeAddresses(addrs, true)
|
|
83
|
+
this.setSubscribed(true)
|
|
104
84
|
}
|
|
105
85
|
Unsubscribe() {
|
|
106
|
-
if (!this
|
|
86
|
+
if (!this.getSubscribed()) {
|
|
107
87
|
throw NOT_SUBSCRIBED
|
|
108
88
|
}
|
|
109
|
-
this
|
|
110
|
-
this
|
|
111
|
-
this
|
|
89
|
+
this.ws.send(new Message(true, MESSAGE_TYPE.UNSUBSCRIBE, this.getSubscribeAddresses()).ToJSONString())
|
|
90
|
+
this.setSubscribed(false)
|
|
91
|
+
this.setSubscribeAddresses([])
|
|
112
92
|
}
|
|
113
93
|
LastBlock() {
|
|
114
|
-
return this
|
|
94
|
+
return this.httpClient.get("/v1/blocks?limit=1&offset=0")
|
|
115
95
|
.then(res => { return { blocks: res.data.data, total_count: res.data.total_count } } )
|
|
116
96
|
.catch(e => {
|
|
117
97
|
throw BLOCK_NOT_FOUND
|
|
118
98
|
})
|
|
119
99
|
}
|
|
120
100
|
TxSearch({heightOperator, height, recipientAddrs, senderAddrs, hashes, typ, limit, offset, orderField, orderBy}) {
|
|
121
|
-
return this
|
|
101
|
+
return this.httpClient.post(
|
|
122
102
|
"/v1/tx_search/p",
|
|
123
103
|
{
|
|
124
104
|
height: `${heightOperator} ${height}`,
|
|
@@ -143,8 +123,8 @@ class TCAbciClient {
|
|
|
143
123
|
}
|
|
144
124
|
Status() {
|
|
145
125
|
return {
|
|
146
|
-
connected: this
|
|
147
|
-
subscribed: this
|
|
126
|
+
connected: this.connected,
|
|
127
|
+
subscribed: this.subscribed,
|
|
148
128
|
}
|
|
149
129
|
}
|
|
150
130
|
Broadcast({id, version, type, data, sender_addr, recipient_addr, sign, fee}) {
|
|
@@ -152,7 +132,7 @@ class TCAbciClient {
|
|
|
152
132
|
throw TRANSACTION_TYPE_NOT_VALID
|
|
153
133
|
}
|
|
154
134
|
|
|
155
|
-
return this
|
|
135
|
+
return this.httpClient.post(
|
|
156
136
|
"/v1/broadcast",
|
|
157
137
|
{
|
|
158
138
|
id,
|
|
@@ -168,34 +148,80 @@ class TCAbciClient {
|
|
|
168
148
|
.catch(e => { throw TRANSACTION_NOT_BROADCAST })
|
|
169
149
|
}
|
|
170
150
|
|
|
171
|
-
|
|
151
|
+
Disconnect(code = 1000) {
|
|
152
|
+
if (this.getConnected()) {
|
|
153
|
+
this.ws.close(code)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
connect() {
|
|
158
|
+
return new Promise((resolve, reject) => {
|
|
159
|
+
if (this.getConnected()) {
|
|
160
|
+
reject(ALREADY_CONNECTED)
|
|
161
|
+
}
|
|
162
|
+
const wsClient = this.wsClient()
|
|
163
|
+
this.ws = new wsClient(this.readNodeWSAddress)
|
|
164
|
+
|
|
165
|
+
this.ws.onerror = (event) => {
|
|
166
|
+
this.setConnected(false)
|
|
167
|
+
if (this.errorCb) {
|
|
168
|
+
this.errorCb(event.error)
|
|
169
|
+
}
|
|
170
|
+
reject(event)
|
|
171
|
+
}
|
|
172
|
+
this.ws.onopen = (event) => {
|
|
173
|
+
this.setConnected(true)
|
|
174
|
+
this.retrieverCount = 0
|
|
175
|
+
resolve(event)
|
|
176
|
+
}
|
|
177
|
+
this.ws.onmessage = (message) => {
|
|
178
|
+
if (message.data === "OK" && message.data.length < 10) {
|
|
179
|
+
return { status: message.data }
|
|
180
|
+
}
|
|
181
|
+
if (this.listenCb) {
|
|
182
|
+
this.listenCb(toJSON(message.data))
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
this.ws.onclose = (event) => {
|
|
186
|
+
this.setConnected(false)
|
|
187
|
+
if (event.code !== 1000 && this.retrieverCount <= 10) {
|
|
188
|
+
this.retrieverCount++
|
|
189
|
+
setTimeout(() => {
|
|
190
|
+
this.connect().catch(() => {})
|
|
191
|
+
}, 3000)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
wsClient() {
|
|
172
198
|
if (typeof window !== "undefined") {
|
|
173
199
|
return window.WebSocket
|
|
174
200
|
}
|
|
175
201
|
const { WebSocket } = require("ws")
|
|
176
202
|
return WebSocket
|
|
177
203
|
}
|
|
178
|
-
|
|
179
|
-
return this
|
|
204
|
+
getConnected() {
|
|
205
|
+
return this.connected
|
|
180
206
|
}
|
|
181
|
-
|
|
182
|
-
this
|
|
207
|
+
setConnected(value) {
|
|
208
|
+
this.connected = value
|
|
183
209
|
}
|
|
184
|
-
|
|
185
|
-
return this
|
|
210
|
+
getSubscribed() {
|
|
211
|
+
return this.subscribed
|
|
186
212
|
}
|
|
187
|
-
|
|
188
|
-
this
|
|
213
|
+
setSubscribed(value) {
|
|
214
|
+
this.subscribed = value
|
|
189
215
|
}
|
|
190
|
-
|
|
191
|
-
return this
|
|
216
|
+
getSubscribeAddresses() {
|
|
217
|
+
return this.subscribedAddresses
|
|
192
218
|
}
|
|
193
|
-
|
|
219
|
+
setSubscribeAddresses(addresses, push = false) {
|
|
194
220
|
if (push) {
|
|
195
|
-
this
|
|
221
|
+
this.subscribedAddresses.push(...addresses)
|
|
196
222
|
return
|
|
197
223
|
}
|
|
198
|
-
this
|
|
224
|
+
this.subscribedAddresses = addresses
|
|
199
225
|
}
|
|
200
226
|
}
|
|
201
227
|
|
package/client_test.js
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
const tcAbciClient = require("./client")
|
|
2
2
|
const unitJS = require("unit.js")
|
|
3
|
-
const {INVALID_ARGUMENTS, INVALID_URL, TRANSACTION_TYPE_NOT_VALID} = require("./errors")
|
|
4
|
-
const { TX_TYPE } = require("./constants")
|
|
3
|
+
const {INVALID_ARGUMENTS, INVALID_URL, TRANSACTION_TYPE_NOT_VALID, TRANSACTION_NOT_BROADCAST} = require("./errors")
|
|
4
|
+
const { TX_TYPE, READ_NODE_ADDRESS, READ_NODE_WS_ADDRESS} = require("./constants")
|
|
5
5
|
const {randomString} = require("./util")
|
|
6
6
|
|
|
7
7
|
describe("TCAbciClient TESTS", () => {
|
|
8
8
|
|
|
9
|
+
it('should start with valid parameters and read node addresses',(done) => {
|
|
10
|
+
const client = new tcAbciClient([READ_NODE_ADDRESS, READ_NODE_WS_ADDRESS])
|
|
11
|
+
client.Start()
|
|
12
|
+
.then(() => {
|
|
13
|
+
const { connected, subscribed } = client.Status()
|
|
14
|
+
unitJS.assert.equal(connected, true)
|
|
15
|
+
unitJS.assert.equal(subscribed, false)
|
|
16
|
+
done()
|
|
17
|
+
})
|
|
18
|
+
.catch(err => {
|
|
19
|
+
done(err)
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
9
23
|
it('should start with valid parameters',(done) => {
|
|
10
24
|
const client = new tcAbciClient()
|
|
11
25
|
client.Start()
|
|
@@ -20,6 +34,33 @@ describe("TCAbciClient TESTS", () => {
|
|
|
20
34
|
})
|
|
21
35
|
})
|
|
22
36
|
|
|
37
|
+
it('should reconnect with start and valid parameters',(done) => {
|
|
38
|
+
const client = new tcAbciClient()
|
|
39
|
+
client.Start()
|
|
40
|
+
.then(() => {
|
|
41
|
+
const { connected, subscribed } = client.Status()
|
|
42
|
+
unitJS.assert.equal(connected, true)
|
|
43
|
+
unitJS.assert.equal(subscribed, false)
|
|
44
|
+
|
|
45
|
+
client.Disconnect(1003)
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
const { connected: c2, subscribed: b2} = client.Status()
|
|
48
|
+
unitJS.assert.equal(c2, false)
|
|
49
|
+
unitJS.assert.equal(b2, false)
|
|
50
|
+
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
const { connected, subscribed } = client.Status()
|
|
53
|
+
unitJS.assert.equal(connected, true)
|
|
54
|
+
unitJS.assert.equal(subscribed, false)
|
|
55
|
+
done()
|
|
56
|
+
}, 3100)
|
|
57
|
+
}, 1000)
|
|
58
|
+
})
|
|
59
|
+
.catch(err => {
|
|
60
|
+
done(err)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
23
64
|
it('should subscribe with valid parameters',(done) => {
|
|
24
65
|
const client = new tcAbciClient()
|
|
25
66
|
client.Start()
|
|
@@ -121,7 +162,8 @@ describe("TCAbciClient TESTS", () => {
|
|
|
121
162
|
done()
|
|
122
163
|
})
|
|
123
164
|
.catch(err => {
|
|
124
|
-
|
|
165
|
+
unitJS.assert.equal(TRANSACTION_NOT_BROADCAST, err)
|
|
166
|
+
done()
|
|
125
167
|
})
|
|
126
168
|
})
|
|
127
169
|
|