@tchain/tcabci-read-js-client 2.7.12 → 2.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.
- package/README.md +62 -46
- package/block.d.ts +19 -10
- package/block.js +39 -41
- package/breaker.d.ts +5 -1
- package/breaker.js +47 -44
- package/bytea.d.ts +1 -0
- package/bytea.js +16 -0
- package/callback.d.ts +12 -7
- package/client.d.ts +170 -119
- package/client.js +465 -315
- package/errors.d.ts +16 -2
- package/errors.js +5 -1
- package/http.d.ts +31 -6
- package/http.js +286 -51
- package/message.d.ts +48 -45
- package/message.js +77 -53
- package/package.json +22 -17
- package/transaction.d.ts +178 -92
- package/transaction.js +96 -69
- package/types.d.ts +60 -0
- package/util.d.ts +4 -0
- package/util.js +20 -6
- package/validation.d.ts +28 -0
- package/validation.js +155 -0
- package/websocket.d.ts +35 -15
- package/websocket.js +129 -43
- package/websocketOptions.d.ts +48 -10
- package/websocketOptions.js +53 -23
package/client.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addresses as validateAddresses,
|
|
3
|
+
signedData as validateSignedData,
|
|
4
|
+
endpoint,
|
|
5
|
+
closeCode,
|
|
6
|
+
rfc3339Timestamp
|
|
7
|
+
} from './validation.js'
|
|
1
8
|
import {
|
|
2
9
|
ALREADY_CONNECTED,
|
|
3
10
|
BLOCK_NOT_FOUND,
|
|
@@ -25,7 +32,7 @@ import { HTTP } from './http.js'
|
|
|
25
32
|
|
|
26
33
|
/**
|
|
27
34
|
* @callback SuccessCallback
|
|
28
|
-
* @param {
|
|
35
|
+
* @param {Event} event
|
|
29
36
|
* @return void
|
|
30
37
|
*/
|
|
31
38
|
|
|
@@ -50,14 +57,16 @@ import { HTTP } from './http.js'
|
|
|
50
57
|
*/
|
|
51
58
|
|
|
52
59
|
export default class TCaBCIClient {
|
|
53
|
-
_httpClient
|
|
60
|
+
_httpClient
|
|
61
|
+
_startPromise = null
|
|
62
|
+
_generation = 0
|
|
54
63
|
_subscribed = false
|
|
55
64
|
_subscribedAddresses = []
|
|
56
65
|
_SubscribedSignedData = {}
|
|
57
66
|
_connected = false
|
|
58
67
|
_chainName = 'transferchain'
|
|
59
68
|
_chainVersion = 'v1'
|
|
60
|
-
_version = `v2.
|
|
69
|
+
_version = `v2.8.0`
|
|
61
70
|
/**
|
|
62
71
|
* @type {?SuccessCallback}
|
|
63
72
|
*/
|
|
@@ -88,40 +97,66 @@ export default class TCaBCIClient {
|
|
|
88
97
|
_readNodeWSAddress = READ_NODE_WS_ADDRESS
|
|
89
98
|
|
|
90
99
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* @param {
|
|
94
|
-
* @param {
|
|
100
|
+
* Create an HTTP/WebSocket client. Start initiates connection setup;
|
|
101
|
+
* SetSuccessCallback reports when the socket is OPEN.
|
|
102
|
+
* @param {string[]} [readNodeAddresses=[]] HTTP and WS endpoints, or defaults.
|
|
103
|
+
* @param {import('./types.js').WebSocketConstructor} [wsLibrary=globalThis.WebSocket]
|
|
104
|
+
* @param {string|null} [chainName=null]
|
|
105
|
+
* @param {string|null} [chainVersion=null]
|
|
106
|
+
* @param {import('./types.js').ClientOptions} [options={}] Limits and TLS policy.
|
|
95
107
|
*/
|
|
96
108
|
constructor(
|
|
97
109
|
readNodeAddresses = [],
|
|
98
|
-
wsLibrary,
|
|
110
|
+
wsLibrary = globalThis.WebSocket,
|
|
99
111
|
chainName = null,
|
|
100
|
-
chainVersion = null
|
|
112
|
+
chainVersion = null,
|
|
113
|
+
options = {}
|
|
101
114
|
) {
|
|
102
115
|
if (!wsLibrary) throw new Error(INVALID_ARGUMENTS)
|
|
103
|
-
this._wsLibrary = wsLibrary
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
if (!readNodeAddresses[0].startsWith('http'))
|
|
107
|
-
throw new Error(INVALID_ARGUMENTS)
|
|
108
|
-
if (!readNodeAddresses[1].startsWith('ws'))
|
|
109
|
-
throw new Error(INVALID_ARGUMENTS)
|
|
117
|
+
this._wsLibrary = wsLibrary
|
|
110
118
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
if (
|
|
120
|
+
!Array.isArray(readNodeAddresses) ||
|
|
121
|
+
![0, 2].includes(readNodeAddresses.length)
|
|
122
|
+
)
|
|
123
|
+
throw new Error(INVALID_ARGUMENTS)
|
|
124
|
+
|
|
125
|
+
if (readNodeAddresses.length === 2) {
|
|
126
|
+
this._readNodeAddress = endpoint(
|
|
127
|
+
readNodeAddresses[0],
|
|
128
|
+
['https:', 'http:'],
|
|
129
|
+
options.allowInsecure
|
|
130
|
+
).href
|
|
131
|
+
this._readNodeWSAddress = endpoint(
|
|
132
|
+
readNodeAddresses[1],
|
|
133
|
+
['wss:', 'ws:'],
|
|
134
|
+
options.allowInsecure
|
|
135
|
+
).href
|
|
114
136
|
}
|
|
115
137
|
|
|
138
|
+
this._httpClient = new HTTP(this._readNodeAddress, options)
|
|
116
139
|
this._options = new Options(this._readNodeWSAddress)
|
|
117
|
-
|
|
140
|
+
.setAllowInsecure(options.allowInsecure)
|
|
141
|
+
.setCustomWS(this._wsLibrary)
|
|
142
|
+
|
|
143
|
+
if (typeof options.maxMessageBytes !== 'undefined')
|
|
144
|
+
this._options.setMaxMessageBytes(options.maxMessageBytes)
|
|
145
|
+
|
|
146
|
+
if (typeof options.maxEnqueuedMessages !== 'undefined')
|
|
147
|
+
this._options.setMaxEnqueuedMessages(options.maxEnqueuedMessages)
|
|
148
|
+
|
|
149
|
+
if (typeof options.maxPendingCallbacks !== 'undefined')
|
|
150
|
+
this._options.setMaxPendingCallbacks(options.maxPendingCallbacks)
|
|
118
151
|
|
|
119
152
|
if (chainName) this._chainName = chainName
|
|
153
|
+
|
|
120
154
|
if (chainVersion) this._chainVersion = chainVersion
|
|
121
155
|
}
|
|
122
156
|
|
|
123
157
|
SetDebug(debug) {
|
|
124
158
|
this._options.setDebug(debug)
|
|
159
|
+
|
|
125
160
|
return this
|
|
126
161
|
}
|
|
127
162
|
|
|
@@ -130,6 +165,9 @@ export default class TCaBCIClient {
|
|
|
130
165
|
* @return {TCaBCIClient}
|
|
131
166
|
*/
|
|
132
167
|
SetSuccessCallback(cb) {
|
|
168
|
+
if (cb !== null && typeof cb !== 'function')
|
|
169
|
+
throw new TypeError('Invalid callback')
|
|
170
|
+
|
|
133
171
|
this._successCb = cb
|
|
134
172
|
|
|
135
173
|
return this
|
|
@@ -140,6 +178,9 @@ export default class TCaBCIClient {
|
|
|
140
178
|
* @return {TCaBCIClient}
|
|
141
179
|
*/
|
|
142
180
|
SetErrorCallback(cb) {
|
|
181
|
+
if (cb !== null && typeof cb !== 'function')
|
|
182
|
+
throw new TypeError('Invalid callback')
|
|
183
|
+
|
|
143
184
|
this._errorCb = cb
|
|
144
185
|
|
|
145
186
|
return this
|
|
@@ -150,6 +191,9 @@ export default class TCaBCIClient {
|
|
|
150
191
|
* @return {TCaBCIClient}
|
|
151
192
|
*/
|
|
152
193
|
SetCloseCallback(cb) {
|
|
194
|
+
if (cb !== null && typeof cb !== 'function')
|
|
195
|
+
throw new TypeError('Invalid callback')
|
|
196
|
+
|
|
153
197
|
this._closeCb = cb
|
|
154
198
|
|
|
155
199
|
return this
|
|
@@ -160,6 +204,9 @@ export default class TCaBCIClient {
|
|
|
160
204
|
* @return {TCaBCIClient}
|
|
161
205
|
*/
|
|
162
206
|
SetListenCallback(cb) {
|
|
207
|
+
if (cb !== null && typeof cb !== 'function')
|
|
208
|
+
throw new TypeError('Invalid callback')
|
|
209
|
+
|
|
163
210
|
this._listenCb = cb
|
|
164
211
|
|
|
165
212
|
return this
|
|
@@ -173,42 +220,55 @@ export default class TCaBCIClient {
|
|
|
173
220
|
return this._subscribed
|
|
174
221
|
}
|
|
175
222
|
|
|
223
|
+
/** @returns {ReadonlyArray<string>} Frozen address copy. */
|
|
176
224
|
get SubscribeAddresses() {
|
|
177
|
-
return this._subscribedAddresses
|
|
225
|
+
return Object.freeze([...this._subscribedAddresses])
|
|
178
226
|
}
|
|
179
227
|
|
|
228
|
+
/** @returns {Readonly<Record<string, string>>} Frozen proof copy. */
|
|
180
229
|
get SubscribedSignedData() {
|
|
181
|
-
return this._SubscribedSignedData
|
|
230
|
+
return Object.freeze({ ...this._SubscribedSignedData })
|
|
182
231
|
}
|
|
183
232
|
|
|
184
233
|
get Socket() {
|
|
185
234
|
return this._ws
|
|
186
235
|
}
|
|
187
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Stop the old socket and initiate a replacement connection.
|
|
239
|
+
* @param {number} [code=1000]
|
|
240
|
+
* @returns {Promise<TCaBCIClient>}
|
|
241
|
+
*/
|
|
188
242
|
async Reconnect(code = 1000) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
243
|
+
const stopping = this._disconnect(code),
|
|
244
|
+
generation = this._generation
|
|
245
|
+
|
|
246
|
+
await stopping
|
|
247
|
+
|
|
248
|
+
if (generation !== this._generation) return this
|
|
192
249
|
|
|
193
250
|
await this._connect()
|
|
194
251
|
|
|
195
252
|
return this
|
|
196
253
|
}
|
|
197
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Initiate one shared connection attempt; does not await the OPEN event.
|
|
257
|
+
* @returns {Promise<TWebSocket>}
|
|
258
|
+
*/
|
|
198
259
|
async Start() {
|
|
199
260
|
return this._connect()
|
|
200
261
|
}
|
|
201
262
|
|
|
202
263
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
264
|
+
* Idempotently stop sockets, abort HTTP and release subscription state.
|
|
265
|
+
* Application callbacks remain registered for reuse; Dispose releases them.
|
|
266
|
+
* Caller-owned buffers are never zeroed or frozen.
|
|
267
|
+
* @param {number} [code=1000]
|
|
268
|
+
* @returns {Promise<TCaBCIClient>}
|
|
206
269
|
*/
|
|
207
270
|
async Stop(code = 1000) {
|
|
208
|
-
|
|
209
|
-
throw new Error(NOT_CONNECTED)
|
|
210
|
-
}
|
|
211
|
-
|
|
271
|
+
this._httpClient.abort()
|
|
212
272
|
await this._disconnect(code)
|
|
213
273
|
this._setConnected(false)
|
|
214
274
|
this._setSubscribed(false)
|
|
@@ -216,69 +276,56 @@ export default class TCaBCIClient {
|
|
|
216
276
|
return this
|
|
217
277
|
}
|
|
218
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Return a detached, frozen status snapshot.
|
|
281
|
+
* @returns {Readonly<import('./client.js').ClientStatus>}
|
|
282
|
+
*/
|
|
219
283
|
Status() {
|
|
220
|
-
return {
|
|
284
|
+
return Object.freeze({
|
|
221
285
|
chain_name: this._chainName,
|
|
222
286
|
chain_version: this._chainVersion,
|
|
223
287
|
connected: this._connected,
|
|
224
288
|
subscribed: this._subscribed
|
|
225
|
-
}
|
|
289
|
+
})
|
|
226
290
|
}
|
|
227
291
|
|
|
228
292
|
/**
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
* @
|
|
233
|
-
* @
|
|
293
|
+
* Subscribe to at most 251 unique addresses, each at most 2048 characters.
|
|
294
|
+
* The combined active address list is bounded. Proof maps are copied;
|
|
295
|
+
* caller objects remain mutable. ACK updates IsSubscribed asynchronously.
|
|
296
|
+
* @param {readonly string[]} addresses
|
|
297
|
+
* @param {Readonly<Record<string, string>>} signedData
|
|
298
|
+
* @param {readonly string[]|null} [txTypes=null]
|
|
299
|
+
* @returns {TCaBCIClient}
|
|
234
300
|
*/
|
|
235
301
|
Subscribe(addresses, signedData, txTypes = null) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
throw new Error(INVALID_ARGUMENT_WITH_CS('txTypes'))
|
|
247
|
-
|
|
248
|
-
for (let i = 0; i < txTypes.length; i++) {
|
|
249
|
-
if (!TX_TYPE_LIST.includes(txTypes[i]))
|
|
250
|
-
throw new Error(INVALID_ARGUMENT_WITH_CS('txType ', txTypes[i]))
|
|
251
|
-
}
|
|
252
|
-
}
|
|
302
|
+
const requested = validateAddresses(addresses),
|
|
303
|
+
proof = validateSignedData(signedData)
|
|
304
|
+
|
|
305
|
+
if (
|
|
306
|
+
txTypes !== null &&
|
|
307
|
+
(!Array.isArray(txTypes) ||
|
|
308
|
+
txTypes.length > TX_TYPE_LIST.length ||
|
|
309
|
+
txTypes.some((type) => !TX_TYPE_LIST.includes(type)))
|
|
310
|
+
)
|
|
311
|
+
throw new Error(INVALID_ARGUMENT_WITH_CS('txTypes'))
|
|
253
312
|
|
|
254
313
|
if (!this.IsConnected()) throw new Error(NOT_CONNECTED)
|
|
255
314
|
|
|
256
|
-
const addrs = [
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
addrs.push(...addresses)
|
|
260
|
-
|
|
261
|
-
if (this.SubscribeAddresses.length > 0) {
|
|
262
|
-
let newAddress = []
|
|
263
|
-
|
|
264
|
-
for (let i = 0; i < addresses.length; i++) {
|
|
265
|
-
if (this.SubscribeAddresses.indexOf(addresses[i]) === -1) {
|
|
266
|
-
newAddress.push(addresses[i])
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
addrs.push(...newAddress)
|
|
270
|
-
}
|
|
315
|
+
const addrs = validateAddresses([
|
|
316
|
+
...new Set([...this._subscribedAddresses, ...requested])
|
|
317
|
+
])
|
|
271
318
|
|
|
272
319
|
this._ws.send(
|
|
273
320
|
new Message({
|
|
274
321
|
isWeb: true,
|
|
275
322
|
type: SUBSCRIBEMessage,
|
|
276
323
|
addrs: addrs,
|
|
277
|
-
signedData:
|
|
324
|
+
signedData: proof,
|
|
278
325
|
txTypes
|
|
279
326
|
}).ToJSON()
|
|
280
327
|
)
|
|
281
|
-
this._setSubscribeAddresses(addrs
|
|
328
|
+
this._setSubscribeAddresses(addrs)._setSubscribeSignedData(proof)
|
|
282
329
|
|
|
283
330
|
return this
|
|
284
331
|
}
|
|
@@ -290,108 +337,122 @@ export default class TCaBCIClient {
|
|
|
290
337
|
if (!this.IsSubscribed()) {
|
|
291
338
|
throw new Error(NOT_SUBSCRIBED)
|
|
292
339
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
this._ws.send(
|
|
343
|
+
new Message({
|
|
344
|
+
isWeb: true,
|
|
345
|
+
type: UNSUBSCRIBEMessage,
|
|
346
|
+
addrs: this.SubscribeAddresses
|
|
347
|
+
}).ToJSON()
|
|
348
|
+
)
|
|
349
|
+
} finally {
|
|
350
|
+
this._clearSubscription()
|
|
351
|
+
}
|
|
303
352
|
|
|
304
353
|
return this
|
|
305
354
|
}
|
|
306
355
|
|
|
307
356
|
/**
|
|
308
|
-
*
|
|
309
|
-
* @param {
|
|
310
|
-
* @
|
|
311
|
-
* @
|
|
357
|
+
* Read the latest block; query values are URL-encoded.
|
|
358
|
+
* @param {string|null} [chainName=null]
|
|
359
|
+
* @param {string|null} [chainVersion=null]
|
|
360
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
361
|
+
* @returns {Promise<Readonly<Awaited<ReturnType<import('./client.js').default['LastBlock']>>>>} Frozen result; nested snapshots are readonly.
|
|
312
362
|
*/
|
|
313
|
-
LastBlock(chainName = null, chainVersion = null) {
|
|
314
|
-
return this.
|
|
315
|
-
.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
.then(res => {
|
|
322
|
-
return {
|
|
323
|
-
blocks: [],
|
|
324
|
-
info: {
|
|
325
|
-
chainName: chainName,
|
|
326
|
-
chainVersion: chainVersion,
|
|
363
|
+
LastBlock(chainName = null, chainVersion = null, requestOptions = {}) {
|
|
364
|
+
return this._request(
|
|
365
|
+
`/v1/blocks?chain_name=${encodeURIComponent(chainName ?? this._chainName)}&chain_version=${encodeURIComponent(chainVersion ?? this._chainVersion)}&limit=1&offset=0`,
|
|
366
|
+
{
|
|
367
|
+
method: 'GET'
|
|
368
|
+
},
|
|
369
|
+
requestOptions
|
|
370
|
+
)
|
|
371
|
+
.then((res) => {
|
|
372
|
+
return Object.freeze({
|
|
373
|
+
blocks: Object.freeze([]),
|
|
374
|
+
info: Object.freeze({
|
|
375
|
+
chainName: chainName ?? this._chainName,
|
|
376
|
+
chainVersion: chainVersion ?? this._chainVersion,
|
|
327
377
|
hash: res.data.hash,
|
|
328
378
|
height: res.data.height,
|
|
329
379
|
txs: res.data.txs,
|
|
330
|
-
createdAt: new Date(res.data.inserted_at)
|
|
331
|
-
},
|
|
380
|
+
createdAt: new Date(rfc3339Timestamp(res.data.inserted_at))
|
|
381
|
+
}),
|
|
332
382
|
total_count: res.total_count
|
|
333
|
-
}
|
|
383
|
+
})
|
|
334
384
|
})
|
|
335
|
-
.catch(e => this._httpClient.handleError(e, new Error(BLOCK_NOT_FOUND)))
|
|
385
|
+
.catch((e) => this._httpClient.handleError(e, new Error(BLOCK_NOT_FOUND)))
|
|
336
386
|
}
|
|
337
387
|
|
|
338
388
|
/**
|
|
389
|
+
* Read a transaction. Signature headers are never followed across redirects.
|
|
339
390
|
* @param {string} id
|
|
340
391
|
* @param {string} signature
|
|
341
|
-
* @
|
|
392
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
393
|
+
* @returns {Promise<Readonly<{tx: Readonly<Transaction>}>>} Frozen result; nested snapshots are readonly.
|
|
342
394
|
*/
|
|
343
|
-
Tx(id, signature) {
|
|
344
|
-
if (
|
|
395
|
+
Tx(id, signature, requestOptions = {}) {
|
|
396
|
+
if (
|
|
397
|
+
!id ||
|
|
398
|
+
id === '.' ||
|
|
399
|
+
id === '..' ||
|
|
400
|
+
typeof id !== 'string' ||
|
|
401
|
+
typeof signature !== 'string' ||
|
|
402
|
+
!signature.length
|
|
403
|
+
) {
|
|
345
404
|
return Promise.reject(new Error(INVALID_ARGUMENTS))
|
|
346
405
|
}
|
|
347
406
|
|
|
348
|
-
return this.
|
|
349
|
-
|
|
407
|
+
return this._request(
|
|
408
|
+
`/v1/tx/${encodeURIComponent(id)}`,
|
|
409
|
+
{
|
|
350
410
|
method: 'GET',
|
|
351
411
|
headers: { 'X-Signature': signature }
|
|
352
|
-
}
|
|
353
|
-
|
|
412
|
+
},
|
|
413
|
+
requestOptions
|
|
414
|
+
)
|
|
415
|
+
.then((res) => {
|
|
354
416
|
const { transaction, error } = Transaction.FromObject(res.data)
|
|
417
|
+
|
|
355
418
|
if (error) return Promise.reject(error)
|
|
356
419
|
|
|
357
|
-
return { tx: transaction }
|
|
420
|
+
return Object.freeze({ tx: transaction })
|
|
358
421
|
})
|
|
359
|
-
.catch(e => this._httpClient.handleError(e))
|
|
422
|
+
.catch((e) => this._httpClient.handleError(e))
|
|
360
423
|
}
|
|
361
424
|
|
|
362
425
|
/**
|
|
363
|
-
*
|
|
364
|
-
* @param {
|
|
365
|
-
* @param {
|
|
366
|
-
* @
|
|
367
|
-
* @param {?Array<string>} types
|
|
368
|
-
* @param {?string} chainName
|
|
369
|
-
* @param {?string} chainVersion
|
|
370
|
-
* @return {Promise<{
|
|
371
|
-
* chain_name: string,
|
|
372
|
-
* chain_version: string,
|
|
373
|
-
* first_block_height: number,
|
|
374
|
-
* first_transaction: Transaction,
|
|
375
|
-
* last_block_height: number,
|
|
376
|
-
* last_transaction: Transaction,
|
|
377
|
-
* total_count: number,
|
|
378
|
-
* }>}
|
|
426
|
+
* Read transaction data with cancellation and a total request deadline.
|
|
427
|
+
* @param {import('./client.js').TxQuery} query
|
|
428
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
429
|
+
* @returns {Promise<Readonly<Awaited<ReturnType<import('./client.js').default['TxSummary']>>>>} Frozen result; nested snapshots are readonly.
|
|
379
430
|
*/
|
|
380
|
-
TxSummary(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
431
|
+
TxSummary(
|
|
432
|
+
{
|
|
433
|
+
recipientAddrs,
|
|
434
|
+
senderAddrs,
|
|
435
|
+
signedData,
|
|
436
|
+
typ,
|
|
437
|
+
types = null,
|
|
438
|
+
chainName = null,
|
|
439
|
+
chainVersion = null
|
|
440
|
+
},
|
|
441
|
+
requestOptions = {}
|
|
442
|
+
) {
|
|
389
443
|
if (!recipientAddrs && !senderAddrs) {
|
|
390
444
|
return Promise.reject(new Error(INVALID_ARGUMENTS))
|
|
391
445
|
}
|
|
392
446
|
|
|
393
|
-
|
|
394
|
-
|
|
447
|
+
if (recipientAddrs) recipientAddrs = validateAddresses(recipientAddrs)
|
|
448
|
+
|
|
449
|
+
if (senderAddrs) senderAddrs = validateAddresses(senderAddrs)
|
|
450
|
+
|
|
451
|
+
if (signedData) signedData = validateSignedData(signedData)
|
|
452
|
+
|
|
453
|
+
return this._request(
|
|
454
|
+
'/v1/tx_summary',
|
|
455
|
+
{
|
|
395
456
|
method: 'POST',
|
|
396
457
|
body: JSON.stringify({
|
|
397
458
|
chain_name: chainName ?? this._chainName,
|
|
@@ -401,15 +462,19 @@ export default class TCaBCIClient {
|
|
|
401
462
|
signed_addrs: signedData,
|
|
402
463
|
...(types ? { types: types } : { typ: typ })
|
|
403
464
|
})
|
|
404
|
-
}
|
|
405
|
-
|
|
465
|
+
},
|
|
466
|
+
requestOptions
|
|
467
|
+
)
|
|
468
|
+
.then((res) => {
|
|
406
469
|
let firstTransaction, lastTransaction
|
|
407
470
|
|
|
408
471
|
if (res.data.first_transaction) {
|
|
409
472
|
const { transaction, error } = Transaction.FromObject(
|
|
410
473
|
res.data.first_transaction
|
|
411
474
|
)
|
|
475
|
+
|
|
412
476
|
if (error) return Promise.reject(error)
|
|
477
|
+
|
|
413
478
|
firstTransaction = transaction
|
|
414
479
|
}
|
|
415
480
|
|
|
@@ -417,11 +482,13 @@ export default class TCaBCIClient {
|
|
|
417
482
|
const { transaction, error: errorTwo } = Transaction.FromObject(
|
|
418
483
|
res.data.last_transaction
|
|
419
484
|
)
|
|
485
|
+
|
|
420
486
|
if (errorTwo) return Promise.reject(errorTwo)
|
|
487
|
+
|
|
421
488
|
lastTransaction = transaction
|
|
422
489
|
}
|
|
423
490
|
|
|
424
|
-
return {
|
|
491
|
+
return Object.freeze({
|
|
425
492
|
chain_name: res.data.chain_name,
|
|
426
493
|
chain_version: res.data.chain_version,
|
|
427
494
|
first_block_height: res.data.first_block_height,
|
|
@@ -429,50 +496,47 @@ export default class TCaBCIClient {
|
|
|
429
496
|
last_block_height: res.data.last_block_height,
|
|
430
497
|
last_transaction: lastTransaction,
|
|
431
498
|
total_count: res.total_count
|
|
432
|
-
}
|
|
499
|
+
})
|
|
433
500
|
})
|
|
434
|
-
.catch(e => this._httpClient.handleError(e))
|
|
501
|
+
.catch((e) => this._httpClient.handleError(e))
|
|
435
502
|
}
|
|
436
503
|
|
|
437
504
|
/**
|
|
438
|
-
*
|
|
439
|
-
* @param {
|
|
440
|
-
* @param {
|
|
441
|
-
* @
|
|
442
|
-
* @param {?Array<string>} recipientAddrs
|
|
443
|
-
* @param {?Array<string>} senderAddrs
|
|
444
|
-
* @param {?Object} signedData
|
|
445
|
-
* @param {?Array<string>} hashes
|
|
446
|
-
* @param {string} typ
|
|
447
|
-
* @param {?Array<string>} types
|
|
448
|
-
* @param {number} limit
|
|
449
|
-
* @param {number} offset
|
|
450
|
-
* @param {string} orderField
|
|
451
|
-
* @param {string} orderBy
|
|
452
|
-
* @param {?string} chainName
|
|
453
|
-
* @param {?string} chainVersion
|
|
454
|
-
* @return {Promise<{txs: Transaction[], total_count: number}>}
|
|
505
|
+
* Read transaction data with cancellation and a total request deadline.
|
|
506
|
+
* @param {import('./client.js').TxSearchQuery} query
|
|
507
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
508
|
+
* @returns {Promise<Readonly<Awaited<ReturnType<import('./client.js').default['TxSearch']>>>>} Frozen result; nested snapshots are readonly.
|
|
455
509
|
*/
|
|
456
|
-
TxSearch(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
510
|
+
TxSearch(
|
|
511
|
+
{
|
|
512
|
+
heightOperator,
|
|
513
|
+
height,
|
|
514
|
+
maxHeight,
|
|
515
|
+
lastOrder,
|
|
516
|
+
recipientAddrs,
|
|
517
|
+
senderAddrs,
|
|
518
|
+
signedData,
|
|
519
|
+
hashes,
|
|
520
|
+
typ,
|
|
521
|
+
types,
|
|
522
|
+
limit,
|
|
523
|
+
offset,
|
|
524
|
+
orderField,
|
|
525
|
+
orderBy,
|
|
526
|
+
chainName = null,
|
|
527
|
+
chainVersion = null
|
|
528
|
+
},
|
|
529
|
+
requestOptions = {}
|
|
530
|
+
) {
|
|
531
|
+
if (recipientAddrs) recipientAddrs = validateAddresses(recipientAddrs)
|
|
532
|
+
|
|
533
|
+
if (senderAddrs) senderAddrs = validateAddresses(senderAddrs)
|
|
534
|
+
|
|
535
|
+
if (signedData) signedData = validateSignedData(signedData)
|
|
536
|
+
|
|
537
|
+
return this._request(
|
|
538
|
+
'/v1/tx_search/p',
|
|
539
|
+
{
|
|
476
540
|
method: 'POST',
|
|
477
541
|
body: JSON.stringify({
|
|
478
542
|
chain_name: chainName ?? this._chainName,
|
|
@@ -490,45 +554,38 @@ export default class TCaBCIClient {
|
|
|
490
554
|
...(orderBy ? { order_by: orderBy } : {}),
|
|
491
555
|
...(types ? { types: types } : typ ? { typ: typ } : {})
|
|
492
556
|
})
|
|
493
|
-
}
|
|
494
|
-
|
|
557
|
+
},
|
|
558
|
+
requestOptions
|
|
559
|
+
)
|
|
560
|
+
.then((res) => {
|
|
495
561
|
const data = []
|
|
496
562
|
|
|
497
563
|
for (const _data of res.data) {
|
|
498
564
|
const { transaction, error } = Transaction.FromObject(_data)
|
|
565
|
+
|
|
499
566
|
if (error) return Promise.reject(error)
|
|
567
|
+
|
|
500
568
|
data.push(transaction)
|
|
501
569
|
}
|
|
502
570
|
|
|
503
|
-
return {
|
|
504
|
-
txs: data,
|
|
571
|
+
return Object.freeze({
|
|
572
|
+
txs: Object.freeze(data),
|
|
505
573
|
total_count: res.total_count
|
|
506
|
-
}
|
|
574
|
+
})
|
|
507
575
|
})
|
|
508
|
-
.catch(e => this._httpClient.handleError(e))
|
|
576
|
+
.catch((e) => this._httpClient.handleError(e))
|
|
509
577
|
}
|
|
510
578
|
|
|
511
579
|
/**
|
|
512
|
-
*
|
|
513
|
-
* @param {
|
|
514
|
-
* @param {
|
|
515
|
-
* @
|
|
516
|
-
* @param {string} sender_addr
|
|
517
|
-
* @param {string} recipient_addr
|
|
518
|
-
* @param {string} sign
|
|
519
|
-
* @param {number} fee
|
|
520
|
-
* @return {Promise<any>}
|
|
580
|
+
* Publish once: automatic retries are disabled to avoid duplicate writes.
|
|
581
|
+
* @param {import('./client.js').BroadcastInput} input
|
|
582
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
583
|
+
* @returns {Promise<Readonly<{data: import('./types.js').JSONValue}>>} Frozen result; nested snapshots are readonly.
|
|
521
584
|
*/
|
|
522
|
-
BroadcastCommit(
|
|
523
|
-
id,
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
data,
|
|
527
|
-
sender_addr,
|
|
528
|
-
recipient_addr,
|
|
529
|
-
sign,
|
|
530
|
-
fee
|
|
531
|
-
}) {
|
|
585
|
+
BroadcastCommit(
|
|
586
|
+
{ id, version, type, data, sender_addr, recipient_addr, sign, fee },
|
|
587
|
+
requestOptions = {}
|
|
588
|
+
) {
|
|
532
589
|
return this.broadcast(
|
|
533
590
|
{
|
|
534
591
|
id,
|
|
@@ -541,35 +598,32 @@ export default class TCaBCIClient {
|
|
|
541
598
|
fee
|
|
542
599
|
},
|
|
543
600
|
false,
|
|
544
|
-
true
|
|
601
|
+
true,
|
|
602
|
+
requestOptions
|
|
545
603
|
)
|
|
546
604
|
}
|
|
547
605
|
|
|
548
606
|
/**
|
|
549
|
-
*
|
|
550
|
-
* @param {
|
|
551
|
-
* @param {
|
|
552
|
-
* @
|
|
553
|
-
* @param {?string} additional_data
|
|
554
|
-
* @param {?string} cipher_data
|
|
555
|
-
* @param {string} sender_addr
|
|
556
|
-
* @param {string} recipient_addr
|
|
557
|
-
* @param {string} sign
|
|
558
|
-
* @param {number} fee
|
|
559
|
-
* @return {Promise<any>}
|
|
607
|
+
* Publish once: automatic retries are disabled to avoid duplicate writes.
|
|
608
|
+
* @param {import('./client.js').BroadcastInput} input
|
|
609
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
610
|
+
* @returns {Promise<Readonly<{data: import('./types.js').JSONValue}>>} Frozen result; nested snapshots are readonly.
|
|
560
611
|
*/
|
|
561
|
-
BroadcastSync(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
612
|
+
BroadcastSync(
|
|
613
|
+
{
|
|
614
|
+
id,
|
|
615
|
+
version,
|
|
616
|
+
type,
|
|
617
|
+
data,
|
|
618
|
+
additional_data = null,
|
|
619
|
+
cipher_data = null,
|
|
620
|
+
sender_addr,
|
|
621
|
+
recipient_addr,
|
|
622
|
+
sign,
|
|
623
|
+
fee
|
|
624
|
+
},
|
|
625
|
+
requestOptions = {}
|
|
626
|
+
) {
|
|
573
627
|
return this.broadcast(
|
|
574
628
|
{
|
|
575
629
|
id,
|
|
@@ -584,35 +638,32 @@ export default class TCaBCIClient {
|
|
|
584
638
|
fee
|
|
585
639
|
},
|
|
586
640
|
true,
|
|
587
|
-
false
|
|
641
|
+
false,
|
|
642
|
+
requestOptions
|
|
588
643
|
)
|
|
589
644
|
}
|
|
590
645
|
|
|
591
646
|
/**
|
|
592
|
-
*
|
|
593
|
-
* @param {
|
|
594
|
-
* @param {
|
|
595
|
-
* @
|
|
596
|
-
* @param {?string} additional_data
|
|
597
|
-
* @param {?string} cipher_data
|
|
598
|
-
* @param {string} sender_addr
|
|
599
|
-
* @param {string} recipient_addr
|
|
600
|
-
* @param {string} sign
|
|
601
|
-
* @param {number} fee
|
|
602
|
-
* @return {Promise<any>}
|
|
647
|
+
* Publish once: automatic retries are disabled to avoid duplicate writes.
|
|
648
|
+
* @param {import('./client.js').BroadcastInput} input
|
|
649
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
650
|
+
* @returns {Promise<Readonly<{data: import('./types.js').JSONValue}>>} Frozen result; nested snapshots are readonly.
|
|
603
651
|
*/
|
|
604
|
-
Broadcast(
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
652
|
+
Broadcast(
|
|
653
|
+
{
|
|
654
|
+
id,
|
|
655
|
+
version,
|
|
656
|
+
type,
|
|
657
|
+
data,
|
|
658
|
+
additional_data = null,
|
|
659
|
+
cipher_data = null,
|
|
660
|
+
sender_addr,
|
|
661
|
+
recipient_addr,
|
|
662
|
+
sign,
|
|
663
|
+
fee
|
|
664
|
+
},
|
|
665
|
+
requestOptions = {}
|
|
666
|
+
) {
|
|
616
667
|
return this.broadcast(
|
|
617
668
|
{
|
|
618
669
|
id,
|
|
@@ -627,10 +678,19 @@ export default class TCaBCIClient {
|
|
|
627
678
|
fee
|
|
628
679
|
},
|
|
629
680
|
false,
|
|
630
|
-
false
|
|
681
|
+
false,
|
|
682
|
+
requestOptions
|
|
631
683
|
)
|
|
632
684
|
}
|
|
633
685
|
|
|
686
|
+
/**
|
|
687
|
+
* Internal/public legacy broadcast entry; never retries a write.
|
|
688
|
+
* @param {import('./client.js').BroadcastInput} input
|
|
689
|
+
* @param {boolean} [sync=false]
|
|
690
|
+
* @param {boolean} [commit=false]
|
|
691
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
692
|
+
* @returns {Promise<Readonly<{data: import('./types.js').JSONValue}>>} Frozen result; nested snapshots are readonly.
|
|
693
|
+
*/
|
|
634
694
|
broadcast(
|
|
635
695
|
{
|
|
636
696
|
id,
|
|
@@ -645,14 +705,30 @@ export default class TCaBCIClient {
|
|
|
645
705
|
fee
|
|
646
706
|
},
|
|
647
707
|
sync = false,
|
|
648
|
-
commit = false
|
|
708
|
+
commit = false,
|
|
709
|
+
requestOptions = {}
|
|
649
710
|
) {
|
|
650
711
|
if (!TX_TYPE_LIST.includes(type)) {
|
|
651
712
|
throw new Error(TRANSACTION_TYPE_NOT_VALID)
|
|
652
713
|
}
|
|
653
714
|
|
|
654
|
-
|
|
655
|
-
|
|
715
|
+
validateAddresses([sender_addr, recipient_addr])
|
|
716
|
+
|
|
717
|
+
if (
|
|
718
|
+
typeof id !== 'string' ||
|
|
719
|
+
!id.length ||
|
|
720
|
+
typeof sign !== 'string' ||
|
|
721
|
+
!sign.length ||
|
|
722
|
+
!Number.isSafeInteger(version) ||
|
|
723
|
+
version < 0 ||
|
|
724
|
+
!Number.isFinite(fee) ||
|
|
725
|
+
fee < 0
|
|
726
|
+
)
|
|
727
|
+
throw new Error(INVALID_ARGUMENTS)
|
|
728
|
+
|
|
729
|
+
return this._request(
|
|
730
|
+
commit ? '/v1/tx/commit' : sync ? '/v1/tx/sync' : '/v1/tx',
|
|
731
|
+
{
|
|
656
732
|
method: 'POST',
|
|
657
733
|
body: JSON.stringify({
|
|
658
734
|
id,
|
|
@@ -666,11 +742,13 @@ export default class TCaBCIClient {
|
|
|
666
742
|
sign,
|
|
667
743
|
fee
|
|
668
744
|
})
|
|
745
|
+
},
|
|
746
|
+
requestOptions
|
|
747
|
+
)
|
|
748
|
+
.then((res) => {
|
|
749
|
+
return Object.freeze({ data: res.data })
|
|
669
750
|
})
|
|
670
|
-
.
|
|
671
|
-
return { data: res.data }
|
|
672
|
-
})
|
|
673
|
-
.catch(e =>
|
|
751
|
+
.catch((e) =>
|
|
674
752
|
this._httpClient.handleError(e, {
|
|
675
753
|
400: new Error(TRANSACTION_NOT_BROADCAST)
|
|
676
754
|
})
|
|
@@ -678,86 +756,144 @@ export default class TCaBCIClient {
|
|
|
678
756
|
}
|
|
679
757
|
|
|
680
758
|
/**
|
|
681
|
-
*
|
|
682
|
-
* @param {
|
|
683
|
-
* @param {
|
|
684
|
-
* @param {
|
|
685
|
-
* @param {
|
|
686
|
-
* @
|
|
687
|
-
* @
|
|
759
|
+
* Read a bounded address batch (1..251 entries; 1..2048 chars per address).
|
|
760
|
+
* @param {readonly string[]} [addresses=[]]
|
|
761
|
+
* @param {Readonly<Record<string, string>>} [signedData={}]
|
|
762
|
+
* @param {number|null} [maxHeight=null]
|
|
763
|
+
* @param {string|null} [chainName=null]
|
|
764
|
+
* @param {string|null} [chainVersion=null]
|
|
765
|
+
* @param {import('./types.js').RequestOptions} [requestOptions={}]
|
|
766
|
+
* @returns {Promise<import('./types.js').JSONValue>} Recursively readonly JSON snapshot.
|
|
688
767
|
*/
|
|
689
768
|
Bulk(
|
|
690
769
|
addresses = [],
|
|
691
770
|
signedData = {},
|
|
692
771
|
maxHeight = null,
|
|
693
772
|
chainName = null,
|
|
694
|
-
chainVersion = null
|
|
773
|
+
chainVersion = null,
|
|
774
|
+
requestOptions = {}
|
|
695
775
|
) {
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
776
|
+
addresses = validateAddresses(addresses)
|
|
777
|
+
signedData = validateSignedData(signedData)
|
|
778
|
+
|
|
779
|
+
return this._request(
|
|
780
|
+
'/v1/bulk_tx',
|
|
781
|
+
{
|
|
782
|
+
method: 'POST',
|
|
783
|
+
body: JSON.stringify({
|
|
784
|
+
chain_name: chainName ?? this._chainName,
|
|
785
|
+
chain_version: chainVersion ?? this._chainVersion,
|
|
786
|
+
addresses: addresses,
|
|
787
|
+
signed_addrs: signedData,
|
|
788
|
+
...(maxHeight ? { max_height: maxHeight } : {})
|
|
789
|
+
})
|
|
790
|
+
},
|
|
791
|
+
requestOptions
|
|
792
|
+
)
|
|
706
793
|
}
|
|
707
794
|
|
|
708
795
|
/**
|
|
709
796
|
* @return {Promise<TWebSocket>}
|
|
710
797
|
*/
|
|
711
798
|
async _connect() {
|
|
712
|
-
if (this.IsConnected())
|
|
713
|
-
|
|
714
|
-
|
|
799
|
+
if (this.IsConnected()) throw new Error(ALREADY_CONNECTED)
|
|
800
|
+
|
|
801
|
+
if (this._startPromise) return this._startPromise
|
|
802
|
+
|
|
803
|
+
if (this._ws) return this._ws
|
|
715
804
|
|
|
716
|
-
|
|
805
|
+
const generation = this._generation,
|
|
806
|
+
ws = new TWebSocket(this._options)
|
|
807
|
+
|
|
808
|
+
this._ws = ws
|
|
809
|
+
|
|
810
|
+
const current = () => generation === this._generation && this._ws === ws
|
|
811
|
+
|
|
812
|
+
ws.addErrorListener((e) => {
|
|
813
|
+
if (!current()) return
|
|
717
814
|
|
|
718
|
-
this._ws.addErrorListener(e => {
|
|
719
815
|
this._setConnected(false)
|
|
720
|
-
this.
|
|
721
|
-
this._setSubscribeAddresses([], false)
|
|
722
|
-
this._setSubscribeSignedData({})
|
|
816
|
+
this._clearSubscription()
|
|
723
817
|
this._callErrorCallback(e)
|
|
724
818
|
})
|
|
819
|
+
ws.addOpenListener((e) => {
|
|
820
|
+
if (!current()) return
|
|
725
821
|
|
|
726
|
-
this._ws.addOpenListener(e => {
|
|
727
822
|
this._setConnected(true)
|
|
728
823
|
this._callSuccessCallback(e)
|
|
729
824
|
})
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
this._callListenCallback(message.data)
|
|
825
|
+
ws.addMessageListener((message) => {
|
|
826
|
+
if (current()) this._callListenCallback(message.data)
|
|
733
827
|
})
|
|
828
|
+
ws.addCloseListener((e) => {
|
|
829
|
+
if (!current()) return
|
|
734
830
|
|
|
735
|
-
this._ws.addCloseListener(e => {
|
|
736
831
|
this._setConnected(false)
|
|
737
|
-
this.
|
|
738
|
-
|
|
739
|
-
this.
|
|
832
|
+
this._clearSubscription()
|
|
833
|
+
|
|
834
|
+
if (!ws.active) this._ws = null
|
|
835
|
+
|
|
740
836
|
this._callCloseCallback(e)
|
|
741
837
|
})
|
|
742
838
|
|
|
743
|
-
|
|
839
|
+
const start = ws.connect()
|
|
840
|
+
|
|
841
|
+
this._startPromise = start
|
|
842
|
+
|
|
843
|
+
try {
|
|
844
|
+
return await start
|
|
845
|
+
} catch {
|
|
846
|
+
if (current()) await this._disconnect()
|
|
847
|
+
|
|
848
|
+
throw new Error('Connection failed')
|
|
849
|
+
} finally {
|
|
850
|
+
if (this._startPromise === start) this._startPromise = null
|
|
851
|
+
}
|
|
744
852
|
}
|
|
745
853
|
|
|
746
|
-
/**
|
|
747
|
-
* @param {?number} code
|
|
748
|
-
* @return {Promise<TCaBCIClient>}
|
|
749
|
-
*/
|
|
750
854
|
async _disconnect(code = 1000) {
|
|
751
|
-
|
|
752
|
-
await this._ws.disconnect(code)
|
|
855
|
+
code = closeCode(code)
|
|
753
856
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
857
|
+
const ws = this._ws
|
|
858
|
+
|
|
859
|
+
this._generation++
|
|
860
|
+
this._ws = null
|
|
861
|
+
this._startPromise = null
|
|
862
|
+
this._setConnected(false)
|
|
863
|
+
this._clearSubscription()
|
|
864
|
+
await ws?.disconnect(code)
|
|
757
865
|
|
|
758
866
|
return this
|
|
759
867
|
}
|
|
760
868
|
|
|
869
|
+
_clearSubscription() {
|
|
870
|
+
this._setSubscribed(false)
|
|
871
|
+
this._setSubscribeAddresses([])
|
|
872
|
+
this._setSubscribeSignedData({})
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Stop all work and release application callback references.
|
|
877
|
+
* @returns {Promise<TCaBCIClient>}
|
|
878
|
+
*/
|
|
879
|
+
async Dispose() {
|
|
880
|
+
await this.Stop()
|
|
881
|
+
this._successCb = null
|
|
882
|
+
this._errorCb = null
|
|
883
|
+
this._closeCb = null
|
|
884
|
+
this._listenCb = null
|
|
885
|
+
|
|
886
|
+
return this
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
_request(uri, req, options = {}) {
|
|
890
|
+
const readOnly =
|
|
891
|
+
req.method === 'GET' ||
|
|
892
|
+
['/v1/tx_summary', '/v1/tx_search/p', '/v1/bulk_tx'].includes(uri)
|
|
893
|
+
|
|
894
|
+
return this._httpClient.request(uri, req, { ...options, retry: readOnly })
|
|
895
|
+
}
|
|
896
|
+
|
|
761
897
|
_setSubscribed(value) {
|
|
762
898
|
this._subscribed = value
|
|
763
899
|
}
|
|
@@ -773,11 +909,14 @@ export default class TCaBCIClient {
|
|
|
773
909
|
*/
|
|
774
910
|
_setSubscribeAddresses(addresses, push = false) {
|
|
775
911
|
if (push) {
|
|
776
|
-
this._subscribedAddresses
|
|
912
|
+
this._subscribedAddresses = [
|
|
913
|
+
...new Set([...this._subscribedAddresses, ...addresses])
|
|
914
|
+
]
|
|
777
915
|
|
|
778
916
|
return this
|
|
779
917
|
}
|
|
780
|
-
|
|
918
|
+
|
|
919
|
+
this._subscribedAddresses = [...addresses]
|
|
781
920
|
|
|
782
921
|
return this
|
|
783
922
|
}
|
|
@@ -787,7 +926,7 @@ export default class TCaBCIClient {
|
|
|
787
926
|
* @return {TCaBCIClient}
|
|
788
927
|
*/
|
|
789
928
|
_setSubscribeSignedData(signedData) {
|
|
790
|
-
this._SubscribedSignedData = signedData
|
|
929
|
+
this._SubscribedSignedData = { ...signedData }
|
|
791
930
|
|
|
792
931
|
return this
|
|
793
932
|
}
|
|
@@ -808,41 +947,52 @@ export default class TCaBCIClient {
|
|
|
808
947
|
let msg
|
|
809
948
|
|
|
810
949
|
const { transaction, error: e1 } = Transaction.FromJSON(message)
|
|
950
|
+
|
|
811
951
|
if (e1) {
|
|
812
952
|
const { message: _msg, error: e2 } = Message.FromJSON(message)
|
|
953
|
+
|
|
813
954
|
if (e2) {
|
|
814
955
|
this._callErrorCallback(e2)
|
|
956
|
+
|
|
815
957
|
return
|
|
816
958
|
}
|
|
817
959
|
|
|
818
|
-
switch (_msg.
|
|
960
|
+
switch (_msg.Type) {
|
|
819
961
|
case MBlock:
|
|
820
|
-
msg = Block.FromObject(_msg.
|
|
962
|
+
msg = Block.FromObject(_msg.Data)
|
|
963
|
+
|
|
821
964
|
if (msg.error) {
|
|
822
965
|
this._callErrorCallback(msg.error)
|
|
966
|
+
|
|
823
967
|
return
|
|
824
968
|
}
|
|
825
969
|
|
|
826
970
|
if (this._listenCb) this._listenCb(msg.block, null, null)
|
|
971
|
+
|
|
827
972
|
break
|
|
828
973
|
case MTransaction:
|
|
829
|
-
msg = Transaction.FromObject(_msg.
|
|
974
|
+
msg = Transaction.FromObject(_msg.Data)
|
|
975
|
+
|
|
830
976
|
if (msg.error) {
|
|
831
977
|
this._callErrorCallback(msg.error)
|
|
978
|
+
|
|
832
979
|
return
|
|
833
980
|
}
|
|
834
981
|
|
|
835
982
|
if (this._listenCb) this._listenCb(null, msg.transaction, null)
|
|
983
|
+
|
|
836
984
|
break
|
|
837
985
|
case Subscription:
|
|
838
|
-
if (
|
|
986
|
+
if (_msg.State === OK) {
|
|
839
987
|
this._setSubscribed(true)
|
|
840
988
|
} else {
|
|
841
|
-
this.
|
|
989
|
+
this._clearSubscription()
|
|
842
990
|
}
|
|
991
|
+
|
|
843
992
|
break
|
|
844
993
|
default:
|
|
845
994
|
if (this._listenCb) this._listenCb(null, null, _msg)
|
|
995
|
+
|
|
846
996
|
break
|
|
847
997
|
}
|
|
848
998
|
} else {
|