UNPKG

@harmony-js/account

Version:

account and wallet for harmony

522 lines 21.3 kB
"use strict"; /** * @packageDocumentation * @module harmony-account */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Wallet = void 0; var tslib_1 = require("tslib"); var crypto_1 = require("@harmony-js/crypto"); var utils_1 = require("@harmony-js/utils"); var account_1 = require("./account"); var utils_2 = require("./utils"); var Wallet = /** @class */ (function () { /** * @example * ``` * const { Wallet } = require('@harmony-js/account'); * const { HttpProvider, Messenger } = require('@harmony-js/network'); * const { ChainType, ChainID } = require('@harmony-js/utils'); * * // create a custom messenger * const customMessenger = new Messenger( * new HttpProvider('http://localhost:9500'), * ChainType.Harmony, // if you are connected to Harmony's blockchain * ChainID.HmyLocal, // check if the chainId is correct * ) * * const wallet = new Wallet(customMessenger); * ``` */ function Wallet(messenger) { if (messenger === void 0) { messenger = utils_2.defaultMessenger; } /** * @hidden */ this.accountMap = new Map(); this.messenger = messenger; } // static method generate Mnemonic Wallet.generateMnemonic = function () { return crypto_1.bip39.generateMnemonic(); }; Object.defineProperty(Wallet.prototype, "accounts", { /** * get acounts addresses * * @return {string[]} accounts addresses * * @example * ```javascript * const wallet = new Wallet(customMessenger); * const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'; * wallet.addByPrivateKey(key_1); * * console.log(wallet.accounts); * ``` */ get: function () { return tslib_1.__spread(this.accountMap.keys()); }, enumerable: false, configurable: true }); Object.defineProperty(Wallet.prototype, "signer", { /** * get the signer of the account, by default, using the first account * * @example * ```javascript * const wallet = new Wallet(customMessenger); * const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'; * wallet.addByPrivateKey(key_1); * * console.log(wallet.signer) * ``` */ get: function () { if (this.defaultSigner) { return this.getAccount(this.defaultSigner); } else if (!this.defaultSigner && this.accounts.length > 0) { this.setSigner(this.accounts[0]); return this.getAccount(this.accounts[0]); } else { return undefined; } }, enumerable: false, configurable: true }); /** * @function newMnemonic * @memberof Wallet * @return {string} Mnemonics */ Wallet.prototype.newMnemonic = function () { return Wallet.generateMnemonic(); }; /** * Add account using Mnemonic phrases * @param {string} phrase - Mnemonic phrase * @param {index} index - index to hdKey root * * @example * ```javascript * const mnemonic_1 = 'urge clog right example dish drill card maximum mix bachelor section select'; * const wallet = new Wallet(customMessenger); * wallet.addByMnemonic(mnemonic_1); * * console.log(wallet.accounts); * ``` */ Wallet.prototype.addByMnemonic = function (phrase, index) { if (index === void 0) { index = 0; } if (!this.isValidMnemonic(phrase)) { throw new Error("Invalid mnemonic phrase: " + phrase); } var seed = crypto_1.bip39.mnemonicToSeed(phrase); var hdKey = crypto_1.hdkey.fromMasterSeed(seed); // TODO:hdkey should apply to Harmony's settings var path = this.messenger.chainType === utils_1.ChainType.Harmony ? '1023' : '60'; var childKey = hdKey.derive("m/44'/" + path + "'/0'/0/" + index); var privateKey = childKey.privateKey.toString('hex'); return this.addByPrivateKey(privateKey); }; /** * Add an account using privateKey * * @param {string} privateKey - privateKey to add * @return {Account} return added Account * * @example * ```javascript * const wallet = new Wallet(customMessenger); * const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'; * console.log(wallet.addByPrivateKey(key_1)); * ``` */ Wallet.prototype.addByPrivateKey = function (privateKey) { try { var newAcc = account_1.Account.add(privateKey); newAcc.setMessenger(this.messenger); if (newAcc.address) { this.accountMap.set(newAcc.address, newAcc); if (!this.defaultSigner) { this.setSigner(newAcc.address); } return newAcc; } else { throw new Error('add account failed'); } } catch (error) { throw error; } }; /** * Add an account using privateKey * @param {string} keyStore - keystore jsonString to add * @param {string} password - password to decrypt the file * @return {Account} return added Account */ Wallet.prototype.addByKeyStore = function (keyStore, password) { return tslib_1.__awaiter(this, void 0, void 0, function () { var newAcc, result, error_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); newAcc = new account_1.Account(undefined); return [4 /*yield*/, newAcc.fromFile(keyStore, password)]; case 1: result = _a.sent(); result.setMessenger(this.messenger); if (result.address) { this.accountMap.set(result.address, result); if (!this.defaultSigner) { this.setSigner(result.address); } return [2 /*return*/, result]; } else { throw new Error('add account failed'); } return [3 /*break*/, 3]; case 2: error_1 = _a.sent(); throw error_1; case 3: return [2 /*return*/]; } }); }); }; /** * create a new account using Mnemonic * @return {Account} {description} * * @example * ```javascript * console.log(wallet.accounts); * wallet.createAccount(); * wallet.createAccount(); * * console.log(wallet.accounts); * ```` */ Wallet.prototype.createAccount = function (password, options) { return tslib_1.__awaiter(this, void 0, void 0, function () { var prv, acc, encrypted; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: prv = crypto_1.generatePrivateKey(); acc = this.addByPrivateKey(prv); if (!(acc.address && password)) return [3 /*break*/, 2]; return [4 /*yield*/, this.encryptAccount(acc.address, password, options)]; case 1: encrypted = _a.sent(); return [2 /*return*/, encrypted]; case 2: if (acc.address && !password) { return [2 /*return*/, acc]; } else { throw new Error('create acount failed'); } _a.label = 3; case 3: return [2 /*return*/]; } }); }); }; /** * To encrypt an account that lives in the wallet. * if encrypted, returns original one, if not found, throw error * @param {string} address - address in accounts * @param {string} password - string that used to encrypt * @param {EncryptOptions} options - encryption options * @return {Promise<Account>} * * @example * ```javascript * const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'; * wallet.addByPrivateKey(key_1); * wallet.encryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345').then((value) => { * console.log(value); * }) * ``` */ Wallet.prototype.encryptAccount = function (address, password, options) { return tslib_1.__awaiter(this, void 0, void 0, function () { var foundAcc, error_2; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 4, , 5]); foundAcc = this.getAccount(address); if (!(foundAcc && foundAcc.privateKey && utils_1.isPrivateKey(foundAcc.privateKey))) return [3 /*break*/, 2]; return [4 /*yield*/, foundAcc.toFile(password, options)]; case 1: _a.sent(); return [2 /*return*/, foundAcc]; case 2: if (foundAcc && foundAcc.privateKey && !utils_1.isPrivateKey(foundAcc.privateKey)) { return [2 /*return*/, foundAcc]; } else { throw new Error('encrypt account failed'); } _a.label = 3; case 3: return [3 /*break*/, 5]; case 4: error_2 = _a.sent(); throw error_2; case 5: return [2 /*return*/]; } }); }); }; /** * To decrypt an account that lives in the wallet,if not encrypted, return original, * if not found, throw error * @param {string} address - address in accounts * @param {string} password - string that used to encrypt * @return {Promise<Account>} * * @example * ```javascript * const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'; * wallet.addByPrivateKey(key_1); * wallet.encryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345') * .then(() => { * wallet.decryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345') * .then((value) =>{ * console.log(value); * }); * }); * ``` */ Wallet.prototype.decryptAccount = function (address, password) { return tslib_1.__awaiter(this, void 0, void 0, function () { var foundAcc, error_3; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 4, , 5]); foundAcc = this.getAccount(address); if (!(foundAcc && foundAcc.privateKey && !utils_1.isPrivateKey(foundAcc.privateKey))) return [3 /*break*/, 2]; return [4 /*yield*/, foundAcc.fromFile(foundAcc.privateKey, password)]; case 1: _a.sent(); return [2 /*return*/, foundAcc]; case 2: if (foundAcc && foundAcc.privateKey && utils_1.isPrivateKey(foundAcc.privateKey)) { foundAcc.encrypted = false; return [2 /*return*/, foundAcc]; } else { throw new Error('decrypt account failed'); } _a.label = 3; case 3: return [3 /*break*/, 5]; case 4: error_3 = _a.sent(); throw error_3; case 5: return [2 /*return*/]; } }); }); }; /** * Get Account instance using address as param * @param {string} address - address hex * @return {Account} Account instance which lives in Wallet * * @example * ``` * const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'; * wallet.addByPrivateKey(key_1); * console.log(wallet.getAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7')); * ``` */ Wallet.prototype.getAccount = function (address) { return this.accountMap.get(crypto_1.getAddress(address).basicHex); }; /** * @function removeAccount * @memberof Wallet * @description remove Account using address as param * @param {string} address: - address hex */ Wallet.prototype.removeAccount = function (address) { this.accountMap.delete(crypto_1.getAddress(address).basicHex); if (this.defaultSigner === address) { this.defaultSigner = undefined; } }; /** * Set Customer Messenage * @param messenger * * @example * ```javascript * const customMessenger = new Messenger( * new HttpProvider('https://api.s0.b.hmny.io'), * ChainType.Harmony, // if you are connected to Harmony's blockchain * ChainID.HmyLocal, // check if the chainId is correct * ) * const wallet = new Wallet(); * wallet.setMessenger(customMessenger); * console.log(wallet.messenger); * ``` */ Wallet.prototype.setMessenger = function (messenger) { this.messenger = messenger; }; /** * Set signer * * @param address one of the address in the accounts */ Wallet.prototype.setSigner = function (address) { if (!utils_1.isAddress(address) && !this.getAccount(address)) { throw new Error('could not set signer'); } this.defaultSigner = address; }; Wallet.prototype.signTransaction = function (transaction, account, // tslint:disable-next-line: no-unnecessary-initializer password, updateNonce, encodeMode, blockNumber) { if (account === void 0) { account = this.signer; } if (password === void 0) { password = undefined; } if (updateNonce === void 0) { updateNonce = true; } if (encodeMode === void 0) { encodeMode = 'rlp'; } if (blockNumber === void 0) { blockNumber = 'latest'; } return tslib_1.__awaiter(this, void 0, void 0, function () { var toSignWith, decrypted, signed, error_4, signed, error_5; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: toSignWith = account || this.signer; if (!toSignWith) { throw new Error('no signer found or did not provide correct account'); } if (!(toSignWith instanceof account_1.Account && toSignWith.encrypted && toSignWith.address)) return [3 /*break*/, 7]; if (!password) { throw new Error('must provide password to further execution'); } _a.label = 1; case 1: _a.trys.push([1, 5, , 6]); return [4 /*yield*/, this.decryptAccount(toSignWith.address, password)]; case 2: decrypted = _a.sent(); return [4 /*yield*/, decrypted.signTransaction(transaction, updateNonce, encodeMode, blockNumber)]; case 3: signed = _a.sent(); return [4 /*yield*/, this.encryptAccount(toSignWith.address, password)]; case 4: _a.sent(); return [2 /*return*/, signed]; case 5: error_4 = _a.sent(); throw error_4; case 6: return [3 /*break*/, 13]; case 7: if (!(toSignWith instanceof account_1.Account && !toSignWith.encrypted && toSignWith.address)) return [3 /*break*/, 12]; _a.label = 8; case 8: _a.trys.push([8, 10, , 11]); return [4 /*yield*/, toSignWith.signTransaction(transaction, updateNonce, encodeMode, blockNumber)]; case 9: signed = _a.sent(); return [2 /*return*/, signed]; case 10: error_5 = _a.sent(); throw error_5; case 11: return [3 /*break*/, 13]; case 12: throw new Error('sign transaction failed'); case 13: return [2 /*return*/]; } }); }); }; Wallet.prototype.signStaking = function (staking, account, // tslint:disable-next-line: no-unnecessary-initializer password, updateNonce, encodeMode, blockNumber, shardID) { if (account === void 0) { account = this.signer; } if (password === void 0) { password = undefined; } if (updateNonce === void 0) { updateNonce = true; } if (encodeMode === void 0) { encodeMode = 'rlp'; } if (blockNumber === void 0) { blockNumber = 'latest'; } if (shardID === void 0) { shardID = this.messenger.currentShard; } return tslib_1.__awaiter(this, void 0, void 0, function () { var toSignWith, decrypted, signed, error_6, signed, error_7; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: toSignWith = account || this.signer; if (!toSignWith) { throw new Error('no signer found or did not provide correct account'); } if (!(toSignWith instanceof account_1.Account && toSignWith.encrypted && toSignWith.address)) return [3 /*break*/, 7]; if (!password) { throw new Error('must provide password to further execution'); } _a.label = 1; case 1: _a.trys.push([1, 5, , 6]); return [4 /*yield*/, this.decryptAccount(toSignWith.address, password)]; case 2: decrypted = _a.sent(); return [4 /*yield*/, decrypted.signStaking(staking, updateNonce, encodeMode, blockNumber, shardID)]; case 3: signed = _a.sent(); return [4 /*yield*/, this.encryptAccount(toSignWith.address, password)]; case 4: _a.sent(); return [2 /*return*/, signed]; case 5: error_6 = _a.sent(); throw error_6; case 6: return [3 /*break*/, 13]; case 7: if (!(toSignWith instanceof account_1.Account && !toSignWith.encrypted && toSignWith.address)) return [3 /*break*/, 12]; _a.label = 8; case 8: _a.trys.push([8, 10, , 11]); return [4 /*yield*/, toSignWith.signStaking(staking, updateNonce, encodeMode, blockNumber, shardID)]; case 9: signed = _a.sent(); return [2 /*return*/, signed]; case 10: error_7 = _a.sent(); throw error_7; case 11: return [3 /*break*/, 13]; case 12: throw new Error('sign transaction failed'); case 13: return [2 /*return*/]; } }); }); }; /** * @function isValidMnemonic * @memberof Wallet * @description check if Mnemonic is valid * @param {string} phrase - Mnemonic phrase * @return {boolean} * @ignore */ Wallet.prototype.isValidMnemonic = function (phrase) { if (phrase.trim().split(/\s+/g).length < 12) { return false; } return crypto_1.bip39.validateMnemonic(phrase); }; return Wallet; }()); exports.Wallet = Wallet; //# sourceMappingURL=wallet.js.map