UNPKG

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