/**
 * Test Banner
 */

import { ResponseMiddleware, WSProvider, NewPendingTransactions, NewHeaders, LogSub, Syncing, Provider, HttpProvider, Messenger } from '@harmony-js/network';
import * as utils from '@harmony-js/utils';
import { assertObject, defaultConfig, HarmonyCore, Unit, isBech32Address, hexToNumber } from '@harmony-js/utils';
import * as crypto from '@harmony-js/crypto';
import { getAddress, fromBech32, HRP } from '@harmony-js/crypto';
import { TransactionFactory, Transaction } from '@harmony-js/transaction';
import { StakingTransaction, StakingFactory } from '@harmony-js/staking';
import { ContractFactory, Contract } from '@harmony-js/contract';
import { Wallet, Account, HDNode } from '@harmony-js/account';

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */

var extendStatics = function(d, b) {
    extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return extendStatics(d, b);
};

function __extends(d, b) {
    extendStatics(d, b);
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

var __assign = function() {
    __assign = Object.assign || function __assign(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};

function __decorate(decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
}

function __metadata(metadataKey, metadataValue) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

function __generator(thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            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;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
}

function __values(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}

function __read(o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
}

function __spread() {
    for (var ar = [], i = 0; i < arguments.length; i++)
        ar = ar.concat(__read(arguments[i]));
    return ar;
}

/**
 * ## About this package
 *
 * `@harmony-js/core` is collection of modules to guide user to interacte with harmony blockchian.
 *
 * Develops can use this package to:
 * - Create a `harmony` instance
 * - Create a `harmonyExtension` instance, which support fo `MathWallet`
 * - Get block and transaction by hash or blocknumber
 * - Send transaction
 * - Get balance of address
 *
 * ## How to use `@harmony-core`
 * ### Dependencies
 * - @harmony-js/core
 * - @harmony-js/utils
 *
 * ### Step 1: Initialize the Harmony instance
 * Before using harmony-core package, you should initialize the Harmony instance
 * ```javascript
 * // import or require Harmony class
 * const { Harmony } = require('@harmony-js/core');
 * // import or require settings
 * const { ChainID, ChainType } = require('@harmony-js/utils');
 *
 * // initialize the Harmony instance
 * const hmy = new Harmony(
 *   // rpc url
 *   'https://api.s0.b.hmny.io/',
 *   {
 *     // chainType set to Harmony
 *     chainType: ChainType.Harmony,
 *     // chainType set to HmyLocal
 *     chainId: ChainID.HmyLocal,
 *   },
 * );
 * ```
 *
 * ### Step 2: Use the instance to call specific functions
 * Example 1: get balance
 * ```javascript
 * // get balance
 * hmy.blockchain.getBalance({
 *   address: 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7',
 *   blockNumber: 'latest'
 * }).then((value) => {
 *   console.log(value.result);
 * });
 * ```
 *
 * Example 2: send transaction
 * ```
 * // add privateKey to wallet
 * const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
 * hmy.wallet.addByPrivateKey(privateKey);
 *
 * async function transfer() {
 *   const txn = hmy.transactions.newTx({
 *     //  token send to
 *     to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
 *     // amount to send
 *     value: '10000',
 *     // gas limit, you can use string
 *     gasLimit: '210000',
 *     // send token from shardID
 *     shardID: 0,
 *     // send token to toShardID
 *     toShardID: 0,
 *     // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
 *     gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
 *   });
 *
 *   // sign the transaction use wallet;
 *   const signedTxn = await hmy.wallet.signTransaction(txn);
 *   const txnHash = await hmy.blockchain.sendTransaction(signedTxn);
 *   console.log(txnHash.result);
 * }
 *
 * transfer();
 * ```
 *
 * @packageDocumentation
 * @module harmony-core
 */
var Blockchain = /** @class */ (function () {
    /**
     * @hidden
     */
    function Blockchain(messenger) {
        this.messenger = messenger;
    }
    /**
     * @hidden
     */
    Blockchain.prototype.setMessenger = function (messenger) {
        this.messenger = messenger;
    };
    /**
     *
     * @hidden
     */
    Blockchain.prototype.getRpcResult = function (result) {
        if (result instanceof ResponseMiddleware) {
            return result.getRaw;
        }
        else {
            return result;
        }
    };
    /**
     * Get the balance of an address at a given block.
     *
     * @param address the address to get the balance of.
     * @param blockNumber (option) If you pass this parameter it will not use the default block set with `DefaultBlockParams.latest`
     * @param shardID (option) If you pass this parameter it will not use the default block set with `this.messenger.currentShard`
     *
     * @returns The current balance for the given address in wei.
     *
     * @hint
     * ```
     * the third param `shardID` is binding with the endpoint
     * shard 0: localhost:9500
     * shard 1: localhost:9501
     * ```
     *
     * @example
     * ```javascript
     * hmy.blockchain.getBalance({
     *   address: 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7',
     *   blockNumber: 'latest'
     * }).then(value => {
     *   console.log(value.result);
     * });
     * ```
     */
    Blockchain.prototype.getBalance = function (_a) {
        var address = _a.address, _b = _a.blockNumber, blockNumber = _b === void 0 ? "latest" /* latest */ : _b, _c = _a.shardID, shardID = _c === void 0 ? this.messenger.currentShard : _c;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getBalance" /* GetBalance */, [getAddress(address).checksum, blockNumber], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _d.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns the current block number.
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @return `Promise` - The number of the most recent block.
     *
     * @hint
     * ```
     * the third param `shardID` is binding with the endpoint
     * shard 0: localhost:9500
     * shard 1: localhost:9501
     * ```
     *
     * @example
     * ```javascript
     * hmy.blockchain.getBlockNumber().then((value) => {
     *   console.log(value.result);
     * });
     * ```
     */
    Blockchain.prototype.getBlockNumber = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_blockNumber" /* BlockNumber */, [], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns a block matching the block Hash.
     *
     * @param blockHash the block hash
     * @param returnObject By default it is `true`, Features in development, IGNORE it!
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` - The block object
     *
     * @example
     * ```javascript
     * hmy.blockchain.getBlockByHash({
     *   blockHash: '0x9cd821b576efdff61280e8857ef218fb2cff8db0cf0fb27dfceef7237042b79e',
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getBlockByHash = function (_a) {
        var blockHash = _a.blockHash, _b = _a.returnObject, returnObject = _b === void 0 ? true : _b, _c = _a.shardID, shardID = _c === void 0 ? this.messenger.currentShard : _c;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getBlockByHash" /* GetBlockByHash */, [blockHash, returnObject], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _d.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns a block matching the block Number.
     *
     * @param blockNumber the block number
     * @param returnObject By default it is `true`, Features in development, IGNORE it!
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` - The block object
     *
     * @example
     * ```javascript
     * hmy.blockchain.getBlockByNumber({
     *   blockNumber: '0x89',
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getBlockByNumber = function (_a) {
        var _b = _a.blockNumber, blockNumber = _b === void 0 ? "latest" /* latest */ : _b, _c = _a.returnObject, returnObject = _c === void 0 ? true : _c, _d = _a.shardID, shardID = _d === void 0 ? this.messenger.currentShard : _d;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_e) {
                switch (_e.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getBlockByNumber" /* GetBlockByNumber */, [blockNumber, returnObject], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _e.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns the number of transaction in a given block.
     *
     * @param blockHash the block number Hash
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` -  The number of transactions in the given block.
     *
     * @example
     * ```javascript
     * hmy.blockchain.getBlockTransactionCountByHash({
     *   blockHash: '0x4142514a238157e7fe57b9d54abedb33943507fa15b3799954c273a12705ced1'
     * }).then((value) => {
     *   console.log(value):
     * });
     * ```
     */
    Blockchain.prototype.getBlockTransactionCountByHash = function (_a) {
        var blockHash = _a.blockHash, _b = _a.shardID, shardID = _b === void 0 ? this.messenger.currentShard : _b;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getBlockTransactionCountByHash" /* GetBlockTransactionCountByHash */, [blockHash], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _c.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns the number of transaction in a given block.
     *
     * @param blockNumber the block number Hash
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` -  The number of transactions in the given block.
     *
     * @example
     * ```javascript
     * hmy.blockchain.getBlockTransactionCountByNumber({
     *   blockNumber: '0x2403C'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getBlockTransactionCountByNumber = function (_a) {
        var blockNumber = _a.blockNumber, _b = _a.shardID, shardID = _b === void 0 ? this.messenger.currentShard : _b;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getBlockTransactionCountByNumber" /* GetBlockTransactionCountByNumber */, [blockNumber], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _c.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns a transaction based on a block hash and the transactions index position.
     *
     * @param blockHash the block number Hash
     * @param index The transactions index position. **Hex Number**
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` -  A transaction object
     *
     * @example
     * ```javascript
     * hmy.blockchain.getTransactionByBlockHashAndIndex({
     *   blockHash: '0x4142514a238157e7fe57b9d54abedb33943507fa15b3799954c273a12705ced1',
     *   index: '0x0'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getTransactionByBlockHashAndIndex = function (_a) {
        var blockHash = _a.blockHash, index = _a.index, _b = _a.shardID, shardID = _b === void 0 ? this.messenger.currentShard : _b;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getTransactionByBlockHashAndIndex" /* GetTransactionByBlockHashAndIndex */, [blockHash, index], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _c.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns a transaction based on a block number and the transactions index position.
     *
     * @param blockNumber the block number
     * @param index The transactions index position. **Hex Number**
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` -  A transaction object
     *
     * @example
     * ```javascript
     * hmy.blockchain.getTransactionByBlockNumberAndIndex({
     *   blockNumber: '0x2403C',
     *   index: '0x0'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getTransactionByBlockNumberAndIndex = function (_a) {
        var _b = _a.blockNumber, blockNumber = _b === void 0 ? "latest" /* latest */ : _b, index = _a.index, _c = _a.shardID, shardID = _c === void 0 ? this.messenger.currentShard : _c;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getTransactionByBlockNumberAndIndex" /* GetTransactionByBlockNumberAndIndex */, [blockNumber, index], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _d.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns a transaction matching the given transaction hash.
     *
     * @param txnHash The transaction hash
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` -  A transaction object
     *
     * @example
     * ```javascript
     * hmy.blockchain.getTransactionByHash({
     *   txnHash: '0x146a0cf7e8da45b44194207c4e7785564527059483b765f9a04424554443b224'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getTransactionByHash = function (_a) {
        var txnHash = _a.txnHash, _b = _a.shardID, shardID = _b === void 0 ? this.messenger.currentShard : _b;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getTransactionByHash" /* GetTransactionByHash */, [txnHash], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _c.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns the receipt of a transaction by transaction hash.
     *
     * @param txnHash The transaction hash
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` -  A transaction receipt object, or `null` when no receipt was found
     *
     * @example
     * ```javascript
     * hmy.blockchain.getTransactionReceipt({
     *   txnHash: '0x146a0cf7e8da45b44194207c4e7785564527059483b765f9a04424554443b224'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getTransactionReceipt = function (_a) {
        var txnHash = _a.txnHash, _b = _a.shardID, shardID = _b === void 0 ? this.messenger.currentShard : _b;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getTransactionReceipt" /* GetTransactionReceipt */, [txnHash], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _c.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get transaction recepit from cross shard transaction
     *
     * @param txnHash The transaction hash
     * @param shardID the shard id of receiver's address
     * @returns `Promise` -  A transaction receipt object, or `null` when no receipt was found
     *
     * @example
     * ```javascript
     * // This transaction sends from shard 0 to shard 1
     * hmy.blockchain.getCxReceiptByHash({
     *   txnHash: '0x7fae9252fbda68d718e610bc10cf2b5c6a9cafb42d4a6b9d6e392c77d587b9ea',
     *   shardID: 1,
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getCxReceiptByHash = function (_a) {
        var txnHash = _a.txnHash, shardID = _a.shardID;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getCXReceiptByHash" /* GetCXReceiptByHash */, [txnHash], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _b.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get the code at a specific address.
     *
     * @param address The address to get the code from (eg:smart contract)
     * @param blockNumber (OPTIONAL) If you pass this parameter it will not use the default block
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @return `Promise` - The data at given `address`
     *
     * @example
     * ```javascript
     * hmy.blockchain.getCode({
     *   address: '0x08AE1abFE01aEA60a47663bCe0794eCCD5763c19',
     *   blockNumber: 'latest'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getCode = function (_a) {
        var address = _a.address, _b = _a.blockNumber, blockNumber = _b === void 0 ? "latest" /* latest */ : _b, _c = _a.shardID, shardID = _c === void 0 ? this.messenger.currentShard : _c;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getCode" /* GetCode */, [getAddress(address).checksum, blockNumber], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _d.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get the number of peers connected to.
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` - number of peer count
     *
     * @example
     * ```javascript
     * hmy.blockchain.net_peerCount().then((value) => {
     *   console.log(value.result);
     * });
     * ```
     */
    Blockchain.prototype.net_peerCount = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("net_peerCount" /* PeerCount */, [], 'net', shardID)];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get the version of net.
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` - the current version.
     *
     * @example
     * ```javascript
     * hmy.blockchain.net_version().then((value) => {
     *   console.log(value.result);
     * });
     * ```
     */
    Blockchain.prototype.net_version = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("net_version" /* NetVersion */, [], 'net', shardID)];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get the protocal version.
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @returns `Promise` - the current protocol version.
     *
     * @example
     * ```javascript
     * hmy.blockchain.getProtocolVersion().then((value) => {
     *   console.log(value.result);
     * });
     * ```
     */
    Blockchain.prototype.getProtocolVersion = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_protocolVersion" /* ProtocolVersion */, [], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get the storage at a specific position of an address
     *
     * @param address The address to get the storage from
     * @param position The index position of the storage
     * @param blockNumber by default it's `latest`.
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     *
     * @example
     * ```javascript
     * hmy.blockchain.getStorageAt({
     *   address: 'one1d0kw95t6kkljmkk9vu0zv25jraut8ngv5vrs5g',
     *   position: '0x0'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getStorageAt = function (_a) {
        var address = _a.address, position = _a.position, _b = _a.blockNumber, blockNumber = _b === void 0 ? "latest" /* latest */ : _b, _c = _a.shardID, shardID = _c === void 0 ? this.messenger.currentShard : _c;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getStorageAt" /* GetStorageAt */, [getAddress(address).checksum, position, blockNumber], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _d.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get the numbers of transactions sent from this address.
     *
     * @param address The address to get the numbers of transactions from
     * @param blockNumber by default it's `latest`
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @return `Promise` - The number of transactions sent from the given address.
     *
     * @example
     * ```javascript
     * hmy.blockchain.getTransactionCount({
     *   address: "one1d0kw95t6kkljmkk9vu0zv25jraut8ngv5vrs5g"
     * }).then((value) => {
     *   console.log(value.result);
     * });
     * ```
     */
    Blockchain.prototype.getTransactionCount = function (_a) {
        var address = _a.address, _b = _a.blockNumber, blockNumber = _b === void 0 ? "latest" /* latest */ : _b, _c = _a.shardID, shardID = _c === void 0 ? this.messenger.currentShard : _c;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getTransactionCount" /* GetTransactionCount */, [getAddress(address).checksum, blockNumber], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _d.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Get the sharding structure of current network
     *
     * @return `Promise` - The sharding structure of current network.
     *
     * @example
     * ```javascript
     * hmy.blockchain.getShardingStructure().then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.getShardingStructure = function () {
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_getShardingStructure" /* GetShardingStructure */, [], this.messenger.chainPrefix)];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Sends a signed transaction to the network.
     *
     * @param transaction `Object` - The transaction object to send:
     * @return The **callbalck** will return the 32 bytes transaction hash
     *
     * @example
     * ```javascript
     * // add privateKey to wallet
     * const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
     * hmy.wallet.addByPrivateKey(privateKey);
     *
     * async function transfer() {
     *   const txn = hmy.transactions.newTx({
     *     //  token send to
     *     to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
     *     // amount to send
     *     value: '10000',
     *     // gas limit, you can use string
     *     gasLimit: '210000',
     *     // send token from shardID
     *     shardID: 0,
     *     // send token to toShardID
     *     toShardID: 0,
     *     // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
     *     gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
     *   });
     *
     *   // sign the transaction use wallet;
     *   const signedTxn = await hmy.wallet.signTransaction(txn);
     *   const txnHash = await hmy.blockchain.sendTransaction(signedTxn);
     *   console.log(txnHash.result);
     * }
     *
     * transfer();
     * ```
     */
    Blockchain.prototype.sendTransaction = function (transaction) {
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!transaction.isSigned() || !transaction) {
                            throw new Error('transaction is not signed or not exist');
                        }
                        return [4 /*yield*/, this.messenger.send("hmy_sendRawTransaction" /* SendRawTransaction */, [transaction.getRawTransaction()], this.messenger.chainPrefix, typeof transaction.txParams.shardID === 'string'
                                ? Number.parseInt(transaction.txParams.shardID, 10)
                                : transaction.txParams.shardID)];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Sends a raw transaction to the network.
     *
     * @param transaction `Object` - The transaction object to send:
     * @return The **callbalck** will return the 32 bytes transaction hash
     *
     * @example
     * ```javascript
     * // add privateKey to wallet
     * const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
     * hmy.wallet.addByPrivateKey(privateKey);
     *
     * async function transfer() {
     *   const txn = hmy.transactions.newTx({
     *     //  token send to
     *     to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
     *     // amount to send
     *     value: '10000',
     *     // gas limit, you can use string
     *     gasLimit: '210000',
     *     // send token from shardID
     *     shardID: 0,
     *     // send token to toShardID
     *     toShardID: 0,
     *     // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
     *     gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
     *   });
     *
     *   // sign the transaction use wallet;
     *   const signedTxn = await hmy.wallet.signTransaction(txn);
     *   recovered = signedTxn.recover(signedTxn.rawTransaction);
     *
     *   const txnHash = await hmy.blockchain.sendRawTransaction(recovered);
     *   console.log(txnHash);
     * }
     *
     * transfer();
     * ```
     */
    Blockchain.prototype.sendRawTransaction = function (transaction) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, txn, result;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!transaction.isSigned() || !transaction) {
                            throw new Error('transaction is not signed or not exist');
                        }
                        return [4 /*yield*/, transaction.sendTransaction()];
                    case 1:
                        _a = __read.apply(void 0, [_b.sent(), 2]), txn = _a[0], result = _a[1];
                        if (txn.isPending()) {
                            return [2 /*return*/, result];
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * send a transaction and check whether it exists
     *
     * @param transaction `Object` - The transaction object to send:
     * @return The **callbalck** will return the 32 bytes transaction hash
     *
     * @example
     * ```javascript
     * // add privateKey to wallet
     * const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
     * hmy.wallet.addByPrivateKey(privateKey);
     *
     * async function transfer() {
     *   const txn = hmy.transactions.newTx({
     *     //  token send to
     *     to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
     *     // amount to send
     *     value: '10000',
     *     // gas limit, you can use string
     *     gasLimit: '210000',
     *     // send token from shardID
     *     shardID: 0,
     *     // send token to toShardID
     *     toShardID: 0,
     *     // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
     *     gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
     *   });
     *
     *   // sign the transaction use wallet;
     *   const signedTxn = await hmy.wallet.signTransaction(txn);
     *   const txnHash = await hmy.blockchain.createObservedTransaction(signedTxn);
     *   console.log(txnHash);
     * }
     *
     * transfer();
     * ```
     */
    Blockchain.prototype.createObservedTransaction = function (transaction) {
        try {
            transaction.sendTransaction().then(function (response) {
                var _a = __read(response, 2), txReturned = _a[0], TranID = _a[1];
                txReturned.confirm(TranID).then(function (txConfirmed) {
                    transaction.emitter.resolve(txConfirmed);
                });
            });
            return transaction.emitter;
        }
        catch (err) {
            throw err;
        }
    };
    /**
     * send raw staking transaction
     *
     * @param staking
     * @ignore
     *
     * @warning
     * ```
     * At present, this function is not implement yet, will Coming soon!!!
     * ```
     */
    Blockchain.prototype.sendRawStakingTransaction = function (staking) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, txn, result;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!staking.isSigned() || !staking) {
                            throw new Error('staking transaction is not signed or not exist');
                        }
                        return [4 /*yield*/, staking.sendTransaction()];
                    case 1:
                        _a = __read.apply(void 0, [_b.sent(), 2]), txn = _a[0], result = _a[1];
                        if (txn.isPending()) {
                            return [2 /*return*/, result];
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * send raw staking transaction and check whether it exists
     *
     * @param staking
     * @ignore
     *
     * @warning
     * ```
     * At present, this function is not implement yet, will Coming soon!!!
     * ```
     */
    Blockchain.prototype.createObservedStakingTransaction = function (staking) {
        try {
            staking.sendTransaction().then(function (response) {
                var _a = __read(response, 2), txReturned = _a[0], TranID = _a[1];
                txReturned.confirm(TranID).then(function (txConfirmed) {
                    staking.emitter.resolve(txConfirmed);
                });
            });
            return staking.emitter;
        }
        catch (err) {
            throw err;
        }
    };
    /**
     * Executes a message call or transaction and returns the amount of the gas used.
     *
     * @param to the address will send to
     * @param data the data will send to that address
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @return `promise` -  the used gas for the simulated call/transaction.
     *
     * @warning
     * ```
     * At present, this function hmy_estimateGas is not implement yet, will Coming soon!!!
     * ```
     *
     * @example
     * ```javascript
     * hmy.blockchain.estimateGas({
     *   to: 'one1d0kw95t6kkljmkk9vu0zv25jraut8ngv5vrs5g',
     *   data: '0xc6888fa10000000000000000000000000000000000000000000000000000000000000003'
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.estimateGas = function (_a) {
        var to = _a.to, data = _a.data, _b = _a.shardID, shardID = _b === void 0 ? this.messenger.currentShard : _b;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_estimateGas" /* EstimateGas */, [{ to: getAddress(to).checksum, data: data }], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _c.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Returns the current gas price oracle. The gas price is determined by the last few blocks median gas price.
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     * @return `promise` - Number string of the current gas price in wei.
     *
     * @example
     * ```javascript
     * hmy.blockchain.gasPrice().then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.gasPrice = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_gasPrice" /* GasPrice */, [], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _a.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Executes a message call transaction,
     * which is directly executed in the VM of the node, but never mined into the blockchain.
     *
     * @param payload some data you want put into these fucntions
     * @param blockNumber by default it's `latest`
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     *
     * @example
     * ```javascript
     * hmy.blockchain.call({
     *   to: "0x08AE1abFE01aEA60a47663bCe0794eCCD5763c19",
     * }).then((value) => {
     *   console.log(value);
     * });
     * ```
     */
    Blockchain.prototype.call = function (_a) {
        var payload = _a.payload, _b = _a.blockNumber, blockNumber = _b === void 0 ? "latest" /* latest */ : _b, _c = _a.shardID, shardID = _c === void 0 ? this.messenger.currentShard : _c;
        return __awaiter(this, void 0, void 0, function () {
            var result;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0: return [4 /*yield*/, this.messenger.send("hmy_call" /* Call */, [payload, blockNumber], this.messenger.chainPrefix, shardID)];
                    case 1:
                        result = _d.sent();
                        return [2 /*return*/, this.getRpcResult(result)];
                }
            });
        });
    };
    /**
     * Return new pending Transactions
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     *
     * @example
     * ```javascript
     * const hmy = new Harmony(
     *   // rpc url
     *   'ws://api.s0.b.hmny.io/',
     *   {
     *     // chainType set to Harmony
     *     chainType: ChainType.Harmony,
     *     // chainType set to HmyLocal
     *     chainId: ChainID.HmyLocal,
     *   },
     * );
     *
     * const tmp = hmy.blockchain.newPendingTransactions();
     * console.log(tmp)
     * ```
     */
    Blockchain.prototype.newPendingTransactions = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        if (this.messenger.provider instanceof WSProvider) {
            return new NewPendingTransactions(this.messenger, shardID);
        }
        else {
            throw new Error('HttpProvider does not support this feature');
        }
    };
    /**
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     *
     * @example
     * ```javascript
     * const hmy = new Harmony(
     *   // rpc url
     *   'ws://api.s0.b.hmny.io/',
     *   {
     *     // chainType set to Harmony
     *     chainType: ChainType.Harmony,
     *     // chainType set to HmyLocal
     *     chainId: ChainID.HmyLocal,
     *   },
     * );
     *
     * const tmp = hmy.blockchain.newBlockHeaders();
     * console.log(tmp)
     * ```
     */
    Blockchain.prototype.newBlockHeaders = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        if (this.messenger.provider instanceof WSProvider) {
            return new NewHeaders(this.messenger, shardID);
        }
        else {
            throw new Error('HttpProvider does not support this feature');
        }
    };
    /**
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     *
     * @example
     * ```javascript
     * const hmy = new Harmony(
     *   // rpc url
     *   'ws://api.s0.b.hmny.io/',
     *   {
     *     // chainType set to Harmony
     *     chainType: ChainType.Harmony,
     *     // chainType set to HmyLocal
     *     chainId: ChainID.HmyLocal,
     *   },
     * );
     *
     * const tmp = hmy.blockchain.syncing();
     * console.log(tmp)
     * ```
     */
    Blockchain.prototype.syncing = function (shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        if (this.messenger.provider instanceof WSProvider) {
            return new Syncing(this.messenger, shardID);
        }
        else {
            throw new Error('HttpProvider does not support this feature');
        }
    };
    /**
     *
     * @param shardID `shardID` is binding with the endpoint, IGNORE it!
     *
     * @example
     * ```javascript
     * const hmy = new Harmony(
     *   // rpc url
     *   'ws://api.s0.b.hmny.io/',
     *   {
     *     // chainType set to Harmony
     *     chainType: ChainType.Harmony,
     *     // chainType set to HmyLocal
     *     chainId: ChainID.HmyLocal,
     *   },
     * );
     *
     * const tmp = hmy.blockchain.logs({
     *   from: '0x12'
     * });
     * console.log(tmp)
     * ```
     */
    Blockchain.prototype.logs = function (options, shardID) {
        if (shardID === void 0) { shardID = this.messenger.currentShard; }
        if (this.messenger.provider instanceof WSProvider) {
            return new LogSub(options, this.messenger, shardID);
        }
        else {
            throw new Error('HttpProvider does not support this feature');
        }
    };
    __decorate([
        assertObject({
            address: ['isValidAddress', "required" /* required */],
            blockNumber: ['isBlockNumber', "optional" /* optional */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getBalance", null);
    __decorate([
        assertObject({
            blockHash: ['isHash', "required" /* required */],
            returnObject: ['isBoolean', "optional" /* optional */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getBlockByHash", null);
    __decorate([
        assertObject({
            blockNumber: ['isBlockNumber', "optional" /* optional */],
            returnObject: ['isBoolean', "optional" /* optional */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getBlockByNumber", null);
    __decorate([
        assertObject({
            blockHash: ['isHash', "required" /* required */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getBlockTransactionCountByHash", null);
    __decorate([
        assertObject({
            blockNumber: ['isBlockNumber', "required" /* required */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getBlockTransactionCountByNumber", null);
    __decorate([
        assertObject({
            blockHash: ['isHash', "required" /* required */],
            index: ['isHex', "required" /* required */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getTransactionByBlockHashAndIndex", null);
    __decorate([
        assertObject({
            blockNumber: ['isBlockNumber', "optional" /* optional */],
            index: ['isHex', "required" /* required */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getTransactionByBlockNumberAndIndex", null);
    __decorate([
        assertObject({
            txnHash: ['isHash', "required" /* required */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getTransactionByHash", null);
    __decorate([
        assertObject({
            txnHash: ['isString', "required" /* required */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getTransactionReceipt", null);
    __decorate([
        assertObject({
            txnHash: ['isString', "required" /* required */],
            shardID: ['isNumber', "required" /* required */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getCxReceiptByHash", null);
    __decorate([
        assertObject({
            address: ['isValidAddress', "required" /* required */],
            blockNumber: ['isBlockNumber', "optional" /* optional */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getCode", null);
    __decorate([
        assertObject({
            address: ['isValidAddress', "required" /* required */],
            position: ['isHex', "required" /* required */],
            blockNumber: ['isBlockNumber', "optional" /* optional */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getStorageAt", null);
    __decorate([
        assertObject({
            address: ['isValidAddress', "required" /* required */],
            blockNumber: ['isBlockNumber', "optional" /* optional */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "getTransactionCount", null);
    __decorate([
        assertObject({
            to: ['isValidAddress', "optional" /* optional */],
            data: ['isHex', "optional" /* optional */],
            shardID: ['isNumber', "optional" /* optional */],
        }),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", Promise)
    ], Blockchain.prototype, "estimateGas", null);
    return Blockchain;
}());

/**
 * @packageDocumentation
 * @module harmony-core
 */
var Harmony = /** @class */ (function (_super) {
    __extends(Harmony, _super);
    /**
     * Create a harmony instance
     *
     * @param url The end-points of the hmy blockchain
     * @param config set up `ChainID` and `ChainType`, typically we can use the default values
     *
     * @example
     * ```
     * // import or require Harmony class
     * const { Harmony } = require('@harmony-js/core');
     *
     * // import or require settings
     * const { ChainID, ChainType } = require('@harmony-js/utils');
     *
     * // Initialize the Harmony instance
     * const hmy = new Harmony(
     *   // rpc url:
     *   // local: http://localhost:9500
     *   // testnet: https://api.s0.b.hmny.io/
     *   // mainnet: https://api.s0.t.hmny.io/
     *   'http://localhost:9500',
     *   {
     *     // chainType set to Harmony
     *     chainType: ChainType.Harmony,
     *     // chainType set to HmyLocal
     *     chainId: ChainID.HmyLocal,
     *   },
     * );
     * ```
     */
    function Harmony(url, config) {
        if (config === void 0) { config = {
            chainId: defaultConfig.Default.Chain_ID,
            chainType: defaultConfig.Default.Chain_Type,
        }; }
        var _this = _super.call(this, config.chainType, config.chainId) || this;
        /**@ignore*/
        _this.Modules = {
            HttpProvider: HttpProvider,
            WSProvider: WSProvider,
            Messenger: Messenger,
            Blockchain: Blockchain,
            TransactionFactory: TransactionFactory,
            StakingFactory: StakingFactory,
            Wallet: Wallet,
            Transaction: Transaction,
            StakingTransaction: StakingTransaction,
            Account: Account,
            Contract: Contract,
        };
        var providerUrl = config.chainUrl || url || defaultConfig.Default.Chain_URL;
        _this.provider = new Provider(providerUrl).provider;
        _this.messenger = new Messenger(_this.provider, _this.chainType, _this.chainId);
        _this.blockchain = new Blockchain(_this.messenger);
        _this.transactions = new TransactionFactory(_this.messenger);
        _this.stakings = new StakingFactory(_this.messenger);
        _this.wallet = new Wallet(_this.messenger);
        _this.contracts = new ContractFactory(_this.wallet);
        _this.crypto = crypto;
        _this.utils = utils;
        _this.defaultShardID = config.shardID;
        if (_this.defaultShardID !== undefined) {
            _this.setShardID(_this.defaultShardID);
        }
        return _this;
    }
    /**
     * Will change the provider for its module.
     *
     * @param provider a valid provider, you can replace it with your own working node
     *
     * @example
     * ```javascript
     * const tmp = hmy.setProvider('http://localhost:9500');
     * ```
     */
    Harmony.prototype.setProvider = function (provider) {
        this.provider = new Provider(provider).provider;
        this.messenger.setProvider(this.provider);
        this.setMessenger(this.messenger);
    };
    /**
     * set the chainID
     *
     * @hint
     * ```
     * Default = 0,
     * EthMainnet = 1,
      Morden = 2,
      Ropsten = 3,
      Rinkeby = 4,
      RootstockMainnet = 30,
      RootstockTestnet = 31,
      Kovan = 42,
      EtcMainnet = 61,
      EtcTestnet = 62,
      Geth = 1337,
      Ganache = 0,
      HmyMainnet = 1,
      HmyTestnet = 2,
      HmyLocal = 2,
      HmyPangaea = 3
     * ```
     * @param chainId
     *
     * @example
     * ```
     * hmy.setChainId(2);
     * ```
     */
    Harmony.prototype.setChainId = function (chainId) {
        this.chainId = chainId;
        this.messenger.setChainId(this.chainId);
        this.setMessenger(this.messenger);
    };
    /**
     * Change the Shard ID
     *
     * @example
     * ```
     * hmy.setShardID(2);
     * ```
     */
    Harmony.prototype.setShardID = function (shardID) {
        this.defaultShardID = shardID;
        this.messenger.setDefaultShardID(this.defaultShardID);
        this.setMessenger(this.messenger);
    };
    /**
     * set the chainType
     *
     * @param chainType `hmy` or `eth`
     *
     * @example
     * ```
     * // set chainType to hmy
     * hmy.setChainType('hmy');
     * // set chainType to eth
     * hmy.setChainType('eth');
     * ```
     */
    Harmony.prototype.setChainType = function (chainType) {
        this.chainType = chainType;
        this.messenger.setChainType(this.chainType);
        this.setMessenger(this.messenger);
    };
    /**
     * Set the sharding Structure
     *
     * @param shardingStructures The array of information of sharding structures
     *
     * @example
     * ```javascript
     * hmy.shardingStructures([
     *   {"current":true,"http":"http://127.0.0.1:9500",
     *    "shardID":0,"ws":"ws://127.0.0.1:9800"},
     *   {"current":false,"http":"http://127.0.0.1:9501",
     *    "shardID":1,"ws":"ws://127.0.0.1:9801"}
     * ]);
     * ```
     */
    Harmony.prototype.shardingStructures = function (shardingStructures) {
        var e_1, _a;
        try {
            for (var shardingStructures_1 = __values(shardingStructures), shardingStructures_1_1 = shardingStructures_1.next(); !shardingStructures_1_1.done; shardingStructures_1_1 = shardingStructures_1.next()) {
                var shard = shardingStructures_1_1.value;
                var shardID = typeof shard.shardID === 'string' ? Number.parseInt(shard.shardID, 10) : shard.shardID;
                this.messenger.shardProviders.set(shardID, {
                    current: shard.current !== undefined ? shard.current : false,
                    shardID: shardID,
                    http: shard.http,
                    ws: shard.ws,
                });
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (shardingStructures_1_1 && !shardingStructures_1_1.done && (_a = shardingStructures_1.return)) _a.call(shardingStructures_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        this.setMessenger(this.messenger);
    };
    /**@ignore*/
    Harmony.prototype.setMessenger = function (messenger) {
        this.blockchain.setMessenger(messenger);
        this.wallet.setMessenger(messenger);
        this.transactions.setMessenger(messenger);
        this.stakings.setMessenger(messenger);
    };
    return Harmony;
}(HarmonyCore));

/**
 * @packageDocumentation
 * @module harmony-core
 * @hidden
 */
var packageInfo = { version: '1.0.0' };
var TruffleProvider = /** @class */ (function (_super) {
    __extends(TruffleProvider, _super);
    function TruffleProvider(provider, hdOptions, chainOptions, transactionOptions) {
        if (provider === void 0) { provider = 'http://localhost:9500'; }
        if (hdOptions === void 0) { hdOptions = {
            menmonic: undefined,
            index: 0,
            addressCount: 1,
        }; }
        if (chainOptions === void 0) { chainOptions = {
            shardID: 0,
            chainType: "hmy" /* Harmony */,
            chainId: 2 /* HmyLocal */,
        }; }
        if (transactionOptions === void 0) { transactionOptions = {
            gasLimit: '10000000',
            gasPrice: '20000000000',
        }; }
        var _this = _super.call(this, provider, hdOptions.menmonic, hdOptions.index, hdOptions.addressCount, chainOptions.shardID, chainOptions.chainType, chainOptions.chainId, transactionOptions.gasLimit, transactionOptions.gasPrice) || this;
        _this.resolveResult = function (response) {
            var final = response.getRaw || response;
            delete final.req;
            delete final.responseType;
            return final;
        };
        _this.resolveCallback = function (err, res, callback) {
            try {
                if (err) {
                    callback(err);
                }
                var response = _this.resolveResult(res);
                callback(null, response);
            }
            catch (error) {
                throw error;
            }
        };
        return _this;
    }
    TruffleProvider.prototype.send = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return __awaiter(this, void 0, void 0, function () {
            var _a, newArgs, id, params, newMethod, callback, _b, accounts, txObj, rawTxn, result, result, result, result;
            var _this = this;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        _a = this.resolveArgs.apply(this, __spread(args)), newArgs = _a.newArgs, id = _a.id, params = _a.params, newMethod = _a.newMethod, callback = _a.callback;
                        _b = newMethod;
                        switch (_b) {
                            case 'hmy_accounts': return [3 /*break*/, 1];
                            case 'hmy_sendTransaction': return [3 /*break*/, 2];
                            case 'hmy_getTransactionReceipt': return [3 /*break*/, 5];
                            case 'net_version': return [3 /*break*/, 7];
                            case 'web3_clientVersion': return [3 /*break*/, 8];
                            case 'hmy_getBlockByNumber': return [3 /*break*/, 9];
                        }
                        return [3 /*break*/, 11];
                    case 1:
                        {
                            accounts = this.getAccounts();
                            callback(null, {
                                result: accounts,
                                id: id,
                                jsonrpc: '2.0',
                            });
                            return [2 /*return*/, {
                                    result: accounts,
                                    id: id,
                                    jsonrpc: '2.0',
                                }];
                            // break;
                        }
                        _c.label = 2;
                    case 2:
                        txObj = params[0];
                        return [4 /*yield*/, this.signTransaction(txObj)];
                    case 3:
                        rawTxn = _c.sent();
                        return [4 /*yield*/, this.provider.send({
                                id: id,
                                method: 'hmy_sendRawTransaction',
                                params: [rawTxn],
                                jsonrpc: '2.0',
                            }, function (err, res) { return _this.resolveCallback(err, res, callback); })];
                    case 4:
                        result = _c.sent();
                        return [2 /*return*/, this.resolveResult(result)];
                    case 5: return [4 /*yield*/, this.provider.send({
                            id: id,
                            method: 'hmy_getTransactionReceipt',
                            params: [params[0]],
                            jsonrpc: '2.0',
                        }, function (err, res) {
                            try {
                                if (err) {
                                    callback(err);
                                }
                                var response = _this.resolveResult(res);
                                if (response.result !== null) {
                                    response.result.status = '0x1';
                                }
                                callback(null, response);
                            }
                            catch (error) {
                                throw error;
                            }
                        })];
                    case 6:
                        result = _c.sent();
                        return [2 /*return*/, this.resolveResult(result)];
                    case 7:
                        {
                            callback(null, {
                                result: String(this.messenger.chainId),
                                id: id,
                                jsonrpc: '2.0',
                            });
                            return [2 /*return*/, {
                                    result: String(this.messenger.chainId),
                                    id: id,
                                    jsonrpc: '2.0',
                                }];
                        }
                        _c.label = 8;
                    case 8:
                        {
                            callback(null, {
                                result: "Harmony/" + packageInfo.version + "/@harmony-js",
                                id: id,
                                jsonrpc: '2.0',
                            });
                            return [2 /*return*/, {
                                    result: "Harmony/" + packageInfo.version + "/@harmony-js",
                                    id: id,
                                    jsonrpc: '2.0',
                                }];
                        }
                        _c.label = 9;
                    case 9: return [4 /*yield*/, this.provider.send(newArgs, function (err, res) {
                            try {
                                if (err) {
                                    callback(err);
                                }
                                var response = _this.resolveResult(res);
                                if (new Unit(response.result.gasLimit)
                                    .asWei()
                                    .toWei()
                                    .gt(new Unit(_this.gasLimit).asWei().toWei())) {
                                    response.result.gasLimit = "0x" + new Unit(_this.gasLimit)
                                        .asWei()
                                        .toWei()
                                        .toString('hex');
                                }
                                if (isBech32Address(response.result.miner)) {
                                    response.result.miner = fromBech32(response.result.miner, HRP);
                                }
                                callback(null, response);
                            }
                            catch (error) {
                                throw error;
                            }
                        })];
                    case 10:
                        result = _c.sent();
                        return [2 /*return*/, this.resolveResult(result)];
                    case 11: return [4 /*yield*/, this.provider.send(newArgs, function (err, res) { return _this.resolveCallback(err, res, callback); })];
                    case 12:
                        result = _c.sent();
                        return [2 /*return*/, this.resolveResult(result)];
                }
            });
        });
    };
    TruffleProvider.prototype.sendAsync = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return this.send.apply(this, __spread(args));
    };
    TruffleProvider.prototype.resolveArgs = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        var method = args[0].method;
        var params = args[0].params;
        var newMethod = method;
        if (method.startsWith('eth')) {
            newMethod = method.replace('eth', 'hmy');
        }
        args[0].method = newMethod;
        var id = args[0].id;
        return {
            newArgs: args[0],
            id: id,
            params: params,
            newMethod: newMethod,
            callback: args[1],
        };
    };
    return TruffleProvider;
}(HDNode));

/**
 * @packageDocumentation
 * @module harmony-core
 */
/** @hidden */
var ExtensionType;
(function (ExtensionType) {
    ExtensionType["MathWallet"] = "MathWallet";
    ExtensionType["OneWallet"] = "OneWallet";
})(ExtensionType || (ExtensionType = {}));
var HarmonyExtension = /** @class */ (function () {
    /**
     * Create an blockchain instance support wallet injection
     *
     * @param wallet could be MathWallet or OneWallet instance
     * @param config (optional), using default `Chain_Id` and `Chain_Type`
     *
     * @example
     * ```javascript
     * // Using Mathwallet instance
     * export const initEx = async() => {
     *   hmyEx = new HarmonyExtension(window.harmony);
     * }
     * // Using OneWallet instance
     * export const initEx = async() => {
     *   hmyEx = new HarmonyExtension(window.onewallet);
     * }
     * ```
     */
    function HarmonyExtension(wallet, config) {
        if (config === void 0) { config = {
            chainId: defaultConfig.Default.Chain_ID,
            chainType: defaultConfig.Default.Chain_Type,
        }; }
        this.extensionType = null;
        this.wallet = wallet;
        // check if it is mathwallet or onewallet
        this.isExtension(this.wallet);
        if (wallet.messenger) {
            this.provider = wallet.messenger.provider;
            this.messenger = wallet.messenger;
        }
        else {
            this.provider = new Provider(config.chainUrl || wallet.network.chain_url).provider;
            this.messenger = new Messenger(this.provider, config.chainType, config.chainId);
        }
        this.wallet.messenger = this.messenger;
        this.blockchain = new Blockchain(this.messenger);
        this.transactions = new TransactionFactory(this.messenger);
        this.contracts = new ContractFactory(this.wallet);
        this.crypto = crypto;
        this.utils = utils;
    }
    /**
     * Will change the provider for its module.
     *
     * @param provider a valid provider, you can replace it with your own working node
     *
     * @example
     * ```javascript
     * const tmp = hmyEx.setProvider('http://localhost:9500');
     * ```
     */
    HarmonyExtension.prototype.setProvider = function (provider) {
        this.provider = new Provider(provider).provider;
        this.messenger.setProvider(this.provider);
        this.setMessenger(this.messenger);
    };
    /**
     * Change the Shard ID
     *
     * @example
     * ```
     * hmyEx.setShardID(2);
     * ```
     */
    HarmonyExtension.prototype.setShardID = function (shardID) {
        this.defaultShardID = shardID;
        this.messenger.setDefaultShardID(this.defaultShardID);
        this.setMessenger(this.messenger);
    };
    HarmonyExtension.prototype.isExtension = function (wallet) {
        var _this = this;
        var isExtension = false;
        this.extensionType = null;
        if (wallet.isMathWallet || wallet.isOneWallet) {
            isExtension = true;
            if (wallet.isMathWallet)
                this.extensionType = ExtensionType.MathWallet;
            else
                this.extensionType = ExtensionType.OneWallet;
            // remake signTransaction of MathWallet or OneWallet
            var signTransaction_1 = this.wallet.signTransaction;
            this.wallet.signTransaction = function (transaction, updateNonce, encodeMode, blockNumber) {
                if (updateNonce === void 0) { updateNonce = true; }
                if (encodeMode === void 0) { encodeMode = 'rlp'; }
                if (blockNumber === void 0) { blockNumber = 'latest'; }
                return __awaiter(_this, void 0, void 0, function () {
                    var extensionAccount, nonce;
                    return __generator(this, function (_a) {
                        switch (_a.label) {
                            case 0: return [4 /*yield*/, this.wallet.getAccount()];
                            case 1:
                                extensionAccount = _a.sent();
                                if (!updateNonce) return [3 /*break*/, 3];
                                return [4 /*yield*/, this.messenger.send("hmy_getTransactionCount" /* GetTransactionCount */, [getAddress(extensionAccount.address).checksum, blockNumber], this.messenger.chainPrefix, typeof transaction.txParams.shardID === 'string'
                                        ? Number.parseInt(transaction.txParams.shardID, 10)
                                        : transaction.txParams.shardID)];
                            case 2:
                                nonce = _a.sent();
                                transaction.setParams(__assign(__assign({}, transaction.txParams), { from: getAddress(extensionAccount.address).bech32, nonce: Number.parseInt(hexToNumber(nonce.result), 10) }));
                                return [3 /*break*/, 4];
                            case 3:
                                transaction.setParams(__assign(__assign({}, transaction.txParams), { from: getAddress(extensionAccount.address).bech32 }));
                                _a.label = 4;
                            case 4: return [2 /*return*/, signTransaction_1(transaction, false, encodeMode, blockNumber)];
                        }
                    });
                });
            };
        }
        if (!isExtension) {
            throw new Error('Extension is not found');
        }
        return;
    };
    /**
     * Get the wallet account
     *
     * @example
     * ```javascript
     * const account = hmyEx.login();
     * console.log(account);
     * ```
     */
    HarmonyExtension.prototype.login = function () {
        return __awaiter(this, void 0, void 0, function () {
            var account;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.wallet.getAccount()];
                    case 1:
                        account = _a.sent();
                        // Use address
                        return [2 /*return*/, account];
                }
            });
        });
    };
    /**
     * Log out the wallet account
     *
     * @example
     * ```javascript
     * hmyEx.logout();
     * ```
     */
    HarmonyExtension.prototype.logout = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.wallet.forgetIdentity()];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Set the sharding Structure
     *
     * @param shardingStructures The array of information of sharding structures
     *
     * @example
     * ```javascript
     * hmyEx.shardingStructures([
     *   {"current":true,"http":"http://127.0.0.1:9500",
     *    "shardID":0,"ws":"ws://127.0.0.1:9800"},
     *   {"current":false,"http":"http://127.0.0.1:9501",
     *    "shardID":1,"ws":"ws://127.0.0.1:9801"}
     * ]);
     * ```
     */
    HarmonyExtension.prototype.shardingStructures = function (shardingStructures) {
        var e_1, _a;
        try {
            for (var shardingStructures_1 = __values(shardingStructures), shardingStructures_1_1 = shardingStructures_1.next(); !shardingStructures_1_1.done; shardingStructures_1_1 = shardingStructures_1.next()) {
                var shard = shardingStructures_1_1.value;
                var shardID = typeof shard.shardID === 'string' ? Number.parseInt(shard.shardID, 10) : shard.shardID;
                this.messenger.shardProviders.set(shardID, {
                    current: shard.current !== undefined ? shard.current : false,
                    shardID: shardID,
                    http: shard.http,
                    ws: shard.ws,
                });
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (shardingStructures_1_1 && !shardingStructures_1_1.done && (_a = shardingStructures_1.return)) _a.call(shardingStructures_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        this.setMessenger(this.messenger);
    };
    /**@ignore*/
    HarmonyExtension.prototype.setMessenger = function (messenger) {
        this.blockchain.setMessenger(messenger);
        this.wallet.messenger = messenger;
        this.transactions.setMessenger(messenger);
    };
    return HarmonyExtension;
}());

/**
 * @packageDocumentation
 * @module harmony-core
 * @hidden
 */
var UrlType;
(function (UrlType) {
    UrlType[UrlType["http"] = 0] = "http";
    UrlType[UrlType["ws"] = 1] = "ws";
})(UrlType || (UrlType = {}));

/**
 * @packageDocumentation
 * @module harmony-core
 * @hidden
 */

export { Harmony, Blockchain, TruffleProvider, ExtensionType, HarmonyExtension, UrlType };
//# sourceMappingURL=index.esm.js.map
