UNPKG

33.6 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = Object.setPrototypeOf ||
4 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6 return function (d, b) {
7 extendStatics(d, b);
8 function __() { this.constructor = d; }
9 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10 };
11})();
12var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13 return new (P || (P = Promise))(function (resolve, reject) {
14 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
17 step((generator = generator.apply(thisArg, _arguments || [])).next());
18 });
19};
20var __generator = (this && this.__generator) || function (thisArg, body) {
21 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
22 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
23 function verb(n) { return function (v) { return step([n, v]); }; }
24 function step(op) {
25 if (f) throw new TypeError("Generator is already executing.");
26 while (_) try {
27 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
28 if (y = 0, t) op = [op[0] & 2, t.value];
29 switch (op[0]) {
30 case 0: case 1: t = op; break;
31 case 4: _.label++; return { value: op[1], done: false };
32 case 5: _.label++; y = op[1]; op = [0]; continue;
33 case 7: op = _.ops.pop(); _.trys.pop(); continue;
34 default:
35 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
36 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
37 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
38 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
39 if (t[2]) _.ops.pop();
40 _.trys.pop(); continue;
41 }
42 op = body.call(thisArg, _);
43 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
44 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
45 }
46};
47var __importDefault = (this && this.__importDefault) || function (mod) {
48 return (mod && mod.__esModule) ? mod : { "default": mod };
49};
50Object.defineProperty(exports, "__esModule", { value: true });
51var debug_1 = __importDefault(require("debug"));
52var events_1 = __importDefault(require("events"));
53var retry_1 = __importDefault(require("retry"));
54var loom_pb_1 = require("./proto/loom_pb");
55var evm_pb_1 = require("./proto/evm_pb");
56var crypto_utils_1 = require("./crypto-utils");
57var address_1 = require("./address");
58var ws_rpc_client_1 = require("./internal/ws-rpc-client");
59var json_rpc_client_1 = require("./internal/json-rpc-client");
60var log = debug_1.default('client');
61var ClientEvent;
62(function (ClientEvent) {
63 /**
64 * Emitted when an event is received from a smart contract.
65 * Listener will receive IChainEventArgs.
66 */
67 ClientEvent["Contract"] = "contractEvent";
68 /**
69 * Emitted when an error occurs that can't be relayed by other means.
70 * Listener will receive IClientErrorEventArgs.
71 */
72 ClientEvent["Error"] = "error";
73 /**
74 * Emitted when a connection is established to the DAppChain.
75 * Listener will receive INetEventArgs.
76 */
77 ClientEvent["Connected"] = "connected";
78 /**
79 * Emitted when a connection with the DAppChain is closed.
80 * Listener will receive INetEventArgs.
81 */
82 ClientEvent["Disconnected"] = "disconnected";
83})(ClientEvent = exports.ClientEvent || (exports.ClientEvent = {}));
84var INVALID_TX_NONCE_ERROR = 'Invalid tx nonce';
85function isInvalidTxNonceError(err) {
86 return err instanceof Error && err.message === INVALID_TX_NONCE_ERROR;
87}
88exports.isInvalidTxNonceError = isInvalidTxNonceError;
89/**
90 * Writes to & reads from a Loom DAppChain.
91 *
92 * The client can listen to events emitted by smart contracts running on a DAppChain,
93 * there is currently only one type of event. The event subscription API matches the NodeJS
94 * EventEmitter API. For example...
95 *
96 * function subscribeToEvents(client: Client) {
97 * client.on(ClientEvent.Contract, (event: IChainEventArgs) => {
98 * // handle event
99 * }
100 * }
101 */
102var Client = /** @class */ (function (_super) {
103 __extends(Client, _super);
104 function Client(chainId, writeClient, readClient) {
105 var _this = _super.call(this) || this;
106 /** Middleware to apply to transactions before they are transmitted to the DAppChain. */
107 _this.txMiddleware = [];
108 /**
109 * The retry strategy that should be used to resend a tx when it's rejected because of a bad nonce.
110 * Default is a binary exponential retry strategy with 5 retries.
111 * To understand how to tweak the retry strategy see
112 * https://github.com/tim-kos/node-retry#retrytimeoutsoptions
113 */
114 _this.nonceRetryStrategy = {
115 retries: 5,
116 minTimeout: 500,
117 maxTimeout: 5000,
118 randomize: true
119 };
120 _this.chainId = chainId;
121 // TODO: basic validation of the URIs to ensure they have all required components.
122 _this._writeClient =
123 typeof writeClient === 'string' ? new ws_rpc_client_1.WSRPCClient(writeClient) : writeClient;
124 _this._writeClient.on(json_rpc_client_1.RPCClientEvent.Error, function (url, err) {
125 return _this._emitNetEvent(url, ClientEvent.Error, err);
126 });
127 _this._writeClient.on(json_rpc_client_1.RPCClientEvent.Connected, function (url) {
128 return _this._emitNetEvent(url, ClientEvent.Connected);
129 });
130 _this._writeClient.on(json_rpc_client_1.RPCClientEvent.Disconnected, function (url) {
131 return _this._emitNetEvent(url, ClientEvent.Disconnected);
132 });
133 if (!readClient || writeClient === readClient) {
134 _this._readClient = _this._writeClient;
135 }
136 else {
137 _this._readClient = typeof readClient === 'string' ? new ws_rpc_client_1.WSRPCClient(readClient) : readClient;
138 _this._readClient.on(json_rpc_client_1.RPCClientEvent.Error, function (url, err) {
139 return _this._emitNetEvent(url, ClientEvent.Error, err);
140 });
141 _this._readClient.on(json_rpc_client_1.RPCClientEvent.Connected, function (url) {
142 return _this._emitNetEvent(url, ClientEvent.Connected);
143 });
144 _this._readClient.on(json_rpc_client_1.RPCClientEvent.Disconnected, function (url) {
145 return _this._emitNetEvent(url, ClientEvent.Disconnected);
146 });
147 }
148 var emitContractEvent = function (url, event) {
149 return _this._emitContractEvent(url, event);
150 };
151 _this.on('newListener', function (event) {
152 if (event === ClientEvent.Contract && _this.listenerCount(ClientEvent.Contract) === 0) {
153 _this._readClient.on(json_rpc_client_1.RPCClientEvent.Message, emitContractEvent);
154 }
155 });
156 _this.on('removeListener', function (event) {
157 if (event === ClientEvent.Contract && _this.listenerCount(ClientEvent.Contract) === 0) {
158 _this._readClient.removeListener(json_rpc_client_1.RPCClientEvent.Message, emitContractEvent);
159 }
160 });
161 return _this;
162 }
163 Object.defineProperty(Client.prototype, "readUrl", {
164 get: function () {
165 return this._readClient.url;
166 },
167 enumerable: true,
168 configurable: true
169 });
170 Object.defineProperty(Client.prototype, "writeUrl", {
171 get: function () {
172 return this._writeClient.url;
173 },
174 enumerable: true,
175 configurable: true
176 });
177 /**
178 * Cleans up all underlying network resources.
179 * Once disconnected the client can no longer be used to interact with the DAppChain.
180 */
181 Client.prototype.disconnect = function () {
182 this.removeAllListeners();
183 this._writeClient.disconnect();
184 if (this._readClient && this._readClient != this._writeClient) {
185 this._readClient.disconnect();
186 }
187 };
188 /**
189 * Commits a transaction to the DAppChain.
190 *
191 * Consider using Contract.callAsync() instead.
192 *
193 * @param tx Transaction to commit.
194 * @param opts Options object.
195 * @param opts.middleware Middleware to apply before sending the tx to the DAppChain, setting this
196 * option will override the default set of middleware specified in
197 * the `Client.txMiddleware` property.
198 * @returns Result (if any) returned by the tx handler in the contract that processed the tx.
199 */
200 Client.prototype.commitTxAsync = function (tx, opts) {
201 var _this = this;
202 if (opts === void 0) { opts = {}; }
203 var _a = opts.middleware, middleware = _a === void 0 ? this.txMiddleware : _a;
204 var op = retry_1.default.operation(this.nonceRetryStrategy);
205 return new Promise(function (resolve, reject) {
206 op.attempt(function (currentAttempt) {
207 _this._commitTxAsync(tx, middleware)
208 .then(resolve)
209 .catch(function (err) {
210 if (err instanceof Error && err.message === INVALID_TX_NONCE_ERROR) {
211 if (!op.retry(err)) {
212 reject(err);
213 }
214 }
215 else {
216 op.stop();
217 reject(err);
218 }
219 });
220 });
221 });
222 };
223 Client.prototype._commitTxAsync = function (tx, middleware) {
224 return __awaiter(this, void 0, void 0, function () {
225 var txBytes, i, result;
226 return __generator(this, function (_a) {
227 switch (_a.label) {
228 case 0:
229 txBytes = tx.serializeBinary();
230 i = 0;
231 _a.label = 1;
232 case 1:
233 if (!(i < middleware.length)) return [3 /*break*/, 4];
234 return [4 /*yield*/, middleware[i].Handle(txBytes)];
235 case 2:
236 txBytes = _a.sent();
237 _a.label = 3;
238 case 3:
239 i++;
240 return [3 /*break*/, 1];
241 case 4: return [4 /*yield*/, this._writeClient.sendAsync('broadcast_tx_commit', [crypto_utils_1.Uint8ArrayToB64(txBytes)])];
242 case 5:
243 result = _a.sent();
244 if (result) {
245 if ((result.check_tx.code || 0) != 0) {
246 if (!result.check_tx.log) {
247 throw new Error("Failed to commit Tx: " + result.check_tx.code);
248 }
249 if (result.check_tx.code === 1 &&
250 result.check_tx.log === 'sequence number does not match') {
251 throw new Error(INVALID_TX_NONCE_ERROR);
252 }
253 throw new Error("Failed to commit Tx: " + result.check_tx.log);
254 }
255 if ((result.deliver_tx.code || 0) != 0) {
256 if (!result.deliver_tx.log) {
257 throw new Error("Failed to commit Tx: " + result.deliver_tx.code);
258 }
259 throw new Error("Failed to commit Tx: " + result.deliver_tx.log);
260 }
261 }
262 if (result.deliver_tx.data) {
263 return [2 /*return*/, crypto_utils_1.B64ToUint8Array(result.deliver_tx.data)];
264 }
265 return [2 /*return*/];
266 }
267 });
268 });
269 };
270 /**
271 * Queries the current state of a contract.
272 *
273 * Consider using Contract.staticCallAsync() instead.
274 */
275 Client.prototype.queryAsync = function (contract, query, vmType, caller) {
276 if (vmType === void 0) { vmType = loom_pb_1.VMType.PLUGIN; }
277 return __awaiter(this, void 0, void 0, function () {
278 var result;
279 return __generator(this, function (_a) {
280 switch (_a.label) {
281 case 0: return [4 /*yield*/, this._readClient.sendAsync('query', {
282 contract: contract.local.toString(),
283 query: query ? crypto_utils_1.Uint8ArrayToB64(query) : undefined,
284 vmType: vmType,
285 caller: caller ? caller.toString() : undefined
286 })];
287 case 1:
288 result = _a.sent();
289 if (result) {
290 return [2 /*return*/, crypto_utils_1.B64ToUint8Array(result)];
291 }
292 return [2 /*return*/];
293 }
294 });
295 });
296 };
297 /**
298 * Queries the receipt corresponding to a transaction hash
299 *
300 * @param txHash Transaction hash returned by call transaction.
301 * @return EvmTxReceipt The corresponding transaction receipt.
302 */
303 Client.prototype.getEvmTxReceiptAsync = function (txHash) {
304 return __awaiter(this, void 0, void 0, function () {
305 var result;
306 return __generator(this, function (_a) {
307 switch (_a.label) {
308 case 0: return [4 /*yield*/, this._readClient.sendAsync('evmtxreceipt', {
309 txHash: crypto_utils_1.Uint8ArrayToB64(txHash)
310 })];
311 case 1:
312 result = _a.sent();
313 if (result) {
314 return [2 /*return*/, evm_pb_1.EvmTxReceipt.deserializeBinary(crypto_utils_1.bufferToProtobufBytes(crypto_utils_1.B64ToUint8Array(result)))];
315 }
316 else {
317 return [2 /*return*/, null];
318 }
319 return [2 /*return*/];
320 }
321 });
322 });
323 };
324 /**
325 * Returns the information about a transaction requested by transaction hash
326 *
327 * @param txHash Transaction hash returned by call transaction.
328 * @return EvmTxObject The corresponding transaction object data.
329 */
330 Client.prototype.getEvmTxByHashAsync = function (txHash) {
331 return __awaiter(this, void 0, void 0, function () {
332 var result;
333 return __generator(this, function (_a) {
334 switch (_a.label) {
335 case 0: return [4 /*yield*/, this._readClient.sendAsync('getevmtransactionbyhash', {
336 txHash: crypto_utils_1.Uint8ArrayToB64(txHash)
337 })];
338 case 1:
339 result = _a.sent();
340 if (result) {
341 return [2 /*return*/, evm_pb_1.EvmTxObject.deserializeBinary(crypto_utils_1.bufferToProtobufBytes(crypto_utils_1.B64ToUint8Array(result)))];
342 }
343 else {
344 return [2 /*return*/, null];
345 }
346 return [2 /*return*/];
347 }
348 });
349 });
350 };
351 /**
352 * Queries the code corresponding to a contract
353 *
354 * @param contractAddress Contract address returned by deploy.
355 * @return Uint8Array The corresponding contract code
356 */
357 Client.prototype.getEvmCodeAsync = function (contractAddress) {
358 return __awaiter(this, void 0, void 0, function () {
359 var result;
360 return __generator(this, function (_a) {
361 switch (_a.label) {
362 case 0: return [4 /*yield*/, this._readClient.sendAsync('getevmcode', {
363 contract: contractAddress.toString()
364 })];
365 case 1:
366 result = _a.sent();
367 if (result) {
368 return [2 /*return*/, crypto_utils_1.B64ToUint8Array(result)];
369 }
370 else {
371 return [2 /*return*/, null];
372 }
373 return [2 /*return*/];
374 }
375 });
376 });
377 };
378 /**
379 * Queries logs with filter terms
380 *
381 * @param filter Filter terms
382 * @return Uint8Array The corresponding result of the filter
383 */
384 Client.prototype.getEvmLogsAsync = function (filterObject) {
385 return __awaiter(this, void 0, void 0, function () {
386 var filter, result;
387 return __generator(this, function (_a) {
388 switch (_a.label) {
389 case 0:
390 filter = JSON.stringify(filterObject);
391 log("Send filter " + filter + " to getlogs");
392 return [4 /*yield*/, this._readClient.sendAsync('getevmlogs', {
393 filter: filter
394 })];
395 case 1:
396 result = _a.sent();
397 if (result) {
398 return [2 /*return*/, crypto_utils_1.B64ToUint8Array(result)];
399 }
400 else {
401 return [2 /*return*/, null];
402 }
403 return [2 /*return*/];
404 }
405 });
406 });
407 };
408 /**
409 * Creates a new filter based on filter terms, to notify when the state changes
410 *
411 * The function getEVMNewFilterAsync works in the similar way of the RPC call eth_newFilter, for more
412 *
413 * Also for understand how filters works check https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter
414 *
415 * @param filter Filter terms
416 * @return Uint8Array The corresponding result of the filter
417 */
418 Client.prototype.newEvmFilterAsync = function (filterObject) {
419 return __awaiter(this, void 0, void 0, function () {
420 var filter, result;
421 return __generator(this, function (_a) {
422 switch (_a.label) {
423 case 0:
424 filter = JSON.stringify(filterObject);
425 log("Send filter " + filter + " to newfilter");
426 return [4 /*yield*/, this._readClient.sendAsync('newevmfilter', {
427 filter: filter
428 })];
429 case 1:
430 result = _a.sent();
431 if (result) {
432 return [2 /*return*/, result];
433 }
434 else {
435 return [2 /*return*/, null];
436 }
437 return [2 /*return*/];
438 }
439 });
440 });
441 };
442 /**
443 * Polling method for a filter, which returns an array of logs which occurred since last poll
444 *
445 * The ID used was requested from getEVMNewFilterChanges or getEVMNewBlockFilter
446 *
447 * @param id Id of filter previously created
448 * @return Uint8Array The corresponding result of the request for given id
449 */
450 Client.prototype.getEvmFilterChangesAsync = function (id) {
451 return __awaiter(this, void 0, void 0, function () {
452 var result, envelope;
453 return __generator(this, function (_a) {
454 switch (_a.label) {
455 case 0:
456 log("Get filter changes for " + JSON.stringify({ id: id }, null, 2));
457 return [4 /*yield*/, this._readClient.sendAsync('getevmfilterchanges', {
458 id: id
459 })];
460 case 1:
461 result = _a.sent();
462 if (result) {
463 envelope = evm_pb_1.EthFilterEnvelope.deserializeBinary(crypto_utils_1.bufferToProtobufBytes(result));
464 switch (envelope.getMessageCase()) {
465 case evm_pb_1.EthFilterEnvelope.MessageCase.ETH_BLOCK_HASH_LIST:
466 return [2 /*return*/, envelope.getEthBlockHashList()];
467 case evm_pb_1.EthFilterEnvelope.MessageCase.ETH_FILTER_LOG_LIST:
468 return [2 /*return*/, envelope.getEthFilterLogList()];
469 case evm_pb_1.EthFilterEnvelope.MessageCase.ETH_TX_HASH_LIST:
470 return [2 /*return*/, envelope.getEthTxHashList()];
471 case evm_pb_1.EthFilterEnvelope.MessageCase.MESSAGE_NOT_SET:
472 default:
473 return [2 /*return*/, null];
474 }
475 }
476 else {
477 return [2 /*return*/, null];
478 }
479 return [2 /*return*/];
480 }
481 });
482 });
483 };
484 /**
485 * Creates a filter in the node, to notify when a new block arrives
486 *
487 * In order to check if the state has changed, call getEVMFilterChangesAsync
488 *
489 * @return String Filter ID in hex format to be used later with getEVMFilterChangesAsync
490 */
491 Client.prototype.newBlockEvmFilterAsync = function () {
492 return __awaiter(this, void 0, void 0, function () {
493 var result;
494 return __generator(this, function (_a) {
495 switch (_a.label) {
496 case 0: return [4 /*yield*/, this._readClient.sendAsync('newblockevmfilter', {})];
497 case 1:
498 result = _a.sent();
499 if (result) {
500 return [2 /*return*/, result.toString()];
501 }
502 else {
503 return [2 /*return*/, null];
504 }
505 return [2 /*return*/];
506 }
507 });
508 });
509 };
510 /**
511 * Creates a filter in the node, to notify when new pending transactions arrive.
512 *
513 * In order to check if the state has changed, call getEVMFilterChangesAsync
514 *
515 * @return String Filter ID in hex format to be used later with getEVMFilterChangesAsync
516 */
517 Client.prototype.newPendingTransactionEvmFilterAsync = function () {
518 return __awaiter(this, void 0, void 0, function () {
519 var result;
520 return __generator(this, function (_a) {
521 switch (_a.label) {
522 case 0: return [4 /*yield*/, this._readClient.sendAsync('newpendingtransactionevmfilter', {})];
523 case 1:
524 result = _a.sent();
525 if (result) {
526 return [2 /*return*/, result.toString()];
527 }
528 else {
529 return [2 /*return*/, null];
530 }
531 return [2 /*return*/];
532 }
533 });
534 });
535 };
536 /**
537 * Uninstall/delete previously created filters
538 *
539 * The ID used was requested from getEVMNewFilterChanges or getEVMNewBlockFilter
540 *
541 * @param id Id of filter previously created
542 * @return boolean If true the filter is removed with success
543 */
544 Client.prototype.uninstallEvmFilterAsync = function (id) {
545 return this._readClient.sendAsync('uninstallevmfilter', {
546 id: id
547 });
548 };
549 /**
550 * Returns information about a block by block number.
551 *
552 * @param num Integer of a block number
553 * @param full If true it returns the full transaction objects, if false only the hashes of the transactions
554 */
555 Client.prototype.getEvmBlockByNumberAsync = function (num, full) {
556 if (full === void 0) { full = true; }
557 return __awaiter(this, void 0, void 0, function () {
558 var result;
559 return __generator(this, function (_a) {
560 switch (_a.label) {
561 case 0: return [4 /*yield*/, this._readClient.sendAsync('getevmblockbynumber', {
562 number: num,
563 full: full
564 })];
565 case 1:
566 result = _a.sent();
567 if (result) {
568 return [2 /*return*/, evm_pb_1.EthBlockInfo.deserializeBinary(crypto_utils_1.bufferToProtobufBytes(crypto_utils_1.B64ToUint8Array(result)))];
569 }
570 else {
571 return [2 /*return*/, null];
572 }
573 return [2 /*return*/];
574 }
575 });
576 });
577 };
578 /**
579 * Returns the information about a transaction requested by transaction hash.
580 *
581 * @param hash String with the hash of the transaction
582 * @param full If true it returns the full transaction objects, if false only the hashes of the transactions
583 */
584 Client.prototype.getEvmBlockByHashAsync = function (hashHexStr, full) {
585 if (full === void 0) { full = true; }
586 return __awaiter(this, void 0, void 0, function () {
587 var result;
588 return __generator(this, function (_a) {
589 switch (_a.label) {
590 case 0: return [4 /*yield*/, this._readClient.sendAsync('getevmblockbyhash', {
591 hash: Buffer.from(hashHexStr.slice(2), 'hex').toString('base64'),
592 full: full
593 })];
594 case 1:
595 result = _a.sent();
596 if (result) {
597 return [2 /*return*/, evm_pb_1.EthBlockInfo.deserializeBinary(crypto_utils_1.bufferToProtobufBytes(crypto_utils_1.B64ToUint8Array(result)))];
598 }
599 else {
600 return [2 /*return*/, null];
601 }
602 return [2 /*return*/];
603 }
604 });
605 });
606 };
607 /**
608 * It works by subscribing to particular events. The node will return a subscription id.
609 * For each event that matches the subscription a notification with relevant data is send
610 * together with the subscription id.
611 *
612 * Possible methods:
613 * * "NewHeads": Fires a notification each time a new header is appended to the chain
614 * * "Logs": Returns logs that are included in new imported blocks and match the given filter criteria
615 *
616 * Example of a "filter" (JSON String) with method "logs":
617 * {
618 * "address": "0xa520fe7702b96808f7bbc0d4a233ed1468216cfd",
619 * "topics": ["0x238a0cb8bb633d06981248b822e7bd33c2a35a6089241d099fa519e361cab902"]
620 * }
621 *
622 * @param method Method selected to the filter, can be "newHeads" or "logs"
623 * @param filter JSON string of the filter
624 */
625 Client.prototype.evmSubscribeAsync = function (method, filterObject) {
626 var filter = JSON.stringify(filterObject);
627 return this._readClient.sendAsync('evmsubscribe', {
628 method: method,
629 filter: filter
630 });
631 };
632 /**
633 * Subscriptions are cancelled method and the subscription id as first parameter.
634 * It returns a bool indicating if the subscription was cancelled successful.
635 *
636 * @param id Id of subscription previously created
637 * @return boolean If true the subscription is removed with success
638 */
639 Client.prototype.evmUnsubscribeAsync = function (id) {
640 return this._readClient.sendAsync('evmunsubscribe', {
641 id: id
642 });
643 };
644 /**
645 * Gets the number of the latest block
646 *
647 * @return The block height
648 */
649 Client.prototype.getBlockHeightAsync = function () {
650 return this._readClient.sendAsync('getblockheight', {});
651 };
652 /**
653 * Gets a nonce for the given public key.
654 *
655 * This should only be called by NonceTxMiddleware.
656 *
657 * @param key A hex encoded public key.
658 * @return The nonce.
659 */
660 Client.prototype.getNonceAsync = function (key) {
661 return __awaiter(this, void 0, void 0, function () {
662 var _a;
663 return __generator(this, function (_b) {
664 switch (_b.label) {
665 case 0:
666 _a = parseInt;
667 return [4 /*yield*/, this._readClient.sendAsync('nonce', { key: key })];
668 case 1: return [2 /*return*/, _a.apply(void 0, [_b.sent(), 10])];
669 }
670 });
671 });
672 };
673 /**
674 * Tries to resolve a contract name to an address.
675 *
676 * @param contractName Name of a smart contract on a Loom DAppChain.
677 * @returns Contract address, or null if a contract matching the given name wasn't found.
678 */
679 Client.prototype.getContractAddressAsync = function (contractName) {
680 return __awaiter(this, void 0, void 0, function () {
681 var addrStr;
682 return __generator(this, function (_a) {
683 switch (_a.label) {
684 case 0: return [4 /*yield*/, this._readClient.sendAsync('resolve', { name: contractName })];
685 case 1:
686 addrStr = _a.sent();
687 if (!addrStr) {
688 return [2 /*return*/, null];
689 }
690 return [2 /*return*/, address_1.Address.fromString(addrStr)];
691 }
692 });
693 });
694 };
695 Client.prototype._emitContractEvent = function (url, event) {
696 var error = event.error, result = event.result;
697 if (error) {
698 var eventArgs = { kind: ClientEvent.Error, url: url, error: error };
699 this.emit(ClientEvent.Error, eventArgs);
700 }
701 else if (result) {
702 log('Event', event.id, result);
703 // Ugh, no built-in JSON->Protobuf marshaller apparently
704 // https://github.com/google/protobuf/issues/1591 so gotta do this manually
705 var eventArgs = {
706 id: event.id,
707 kind: ClientEvent.Contract,
708 url: url,
709 contractAddress: new address_1.Address(result.address.chain_id, new address_1.LocalAddress(crypto_utils_1.B64ToUint8Array(result.address.local))),
710 callerAddress: new address_1.Address(result.caller.chain_id, new address_1.LocalAddress(crypto_utils_1.B64ToUint8Array(result.caller.local))),
711 blockHeight: result.block_height,
712 data: crypto_utils_1.B64ToUint8Array(result.encoded_body || '0x0'),
713 topics: result.topics,
714 transactionHash: result.tx_hash,
715 transactionHashBytes: result.tx_hash ? crypto_utils_1.B64ToUint8Array(result.tx_hash) : new Uint8Array([])
716 };
717 this.emit(ClientEvent.Contract, eventArgs);
718 }
719 };
720 Client.prototype._emitNetEvent = function (url, kind, error) {
721 if (kind === ClientEvent.Error) {
722 var eventArgs = { kind: kind, url: url, error: error };
723 this.emit(kind, eventArgs);
724 }
725 else {
726 var eventArgs = { kind: kind, url: url };
727 this.emit(kind, eventArgs);
728 }
729 };
730 return Client;
731}(events_1.default));
732exports.Client = Client;
733//# sourceMappingURL=client.js.map
\No newline at end of file