UNPKG

@colony/purser-software

Version:

A javascript library to interact with a software Ethereum wallet, based on the ethers.js library

297 lines (255 loc) 10.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.create = exports.open = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _wallet = require("ethers/wallet"); var _hdnode = require("ethers/utils/hdnode"); var _jsonWallet = require("ethers/utils/json-wallet"); var _helpers = require("@colony/purser-core/helpers"); var _utils = require("@colony/purser-core/utils"); var _defaults = require("@colony/purser-core/defaults"); var _class = _interopRequireDefault(require("./class")); var _defaults2 = require("./defaults"); var _messages = require("./messages"); /** * Open an existing wallet * Using either `mnemonic`, `private key` or `encrypted keystore` * * This will try to extract the private key from a mnemonic (if available), * and create a new SoftwareWallet instance using whichever key is available. * (the on passed in or the one extracted from the mnemonic). * * @TODO Reduce code repetition * * With some clever refactoring we might be able to only call the SoftwareWallet * constructor a single time for all three methods of opening the wallet * * @method open * * @param {string} password Optional password used to generate an encrypted keystore * @param {string} privateKey Private key to open the wallet with * @param {string} mnemonic Mnemonic string to open the wallet with * @param {string} keystore JSON formatted keystore string to open the wallet with. * Only works if you also send in a password * @param {number} chainId The id of the network to use, defaults to mainnet (1) * * All the above params are sent in as props of an {WalletArgumentsType} object. * * @return {WalletType} A new wallet object (or undefined) if somehwere along * the line an error is thrown. */ var open = /*#__PURE__*/ function () { var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee() { var argumentObject, password, privateKey, mnemonic, keystore, _argumentObject$chain, chainId, extractedPrivateKey, derivationPath, keystoreWallet, mnemonicWallet, privateKeyWallet, _args = arguments; return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: argumentObject = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}; /* * Validate the trasaction's object input */ (0, _helpers.userInputValidator)({ firstArgument: argumentObject, requiredEither: _defaults2.REQUIRED_PROPS.OPEN_WALLET }); password = argumentObject.password, privateKey = argumentObject.privateKey, mnemonic = argumentObject.mnemonic, keystore = argumentObject.keystore, _argumentObject$chain = argumentObject.chainId, chainId = _argumentObject$chain === void 0 ? _defaults.CHAIN_IDS.HOMESTEAD : _argumentObject$chain; /* * @TODO Re-add use ability to control derivation path * When opening the wallet. But only if this proves to be a needed feature. */ derivationPath = (0, _helpers.derivationPathSerializer)({ change: _defaults.PATH.CHANGE, addressIndex: _defaults.PATH.INDEX }); _context.prev = 4; if (!(keystore && (0, _jsonWallet.isSecretStorageWallet)(keystore) && password)) { _context.next = 13; break; } _context.next = 8; return _wallet.Wallet.fromEncryptedJson(keystore, password); case 8: keystoreWallet = _context.sent; /* * Set the keystore and password props on the instance object. * * So that we can make use of them inside the SoftwareWallet * constructor, as the Ethers Wallet instance object will * be passed down. * * @TODO Better passing of values * * This needs to be refactored to pass values to the SoftwareWallet * class in a less repetitious way */ keystoreWallet.keystore = keystore; keystoreWallet.password = password; keystoreWallet.chainId = chainId; return _context.abrupt("return", new _class.default(keystoreWallet)); case 13: /* * @TODO Detect if existing but not valid mnemonic, and warn the user */ if (mnemonic && (0, _hdnode.isValidMnemonic)(mnemonic)) { mnemonicWallet = (0, _hdnode.fromMnemonic)(mnemonic).derivePath(derivationPath); extractedPrivateKey = mnemonicWallet.privateKey; } /* * @TODO Detect if existing but not valid private key, and warn the user */ privateKeyWallet = new _wallet.Wallet(privateKey || extractedPrivateKey); /* * Set the mnemonic and password props on the instance object. * * So that we can make use of them inside the SoftwareWallet * constructor, as the Ethers Wallet instance object will * be passed down. * * @TODO Better passing of values * * This needs to be refactored to pass values to the SoftwareWallet * class in a less repetitious way */ privateKeyWallet.password = password; privateKeyWallet.chainId = chainId; /* * @NOTE mnemonic prop was renamed due to naming conflict with getter-only * ethers prop */ privateKeyWallet.originalMnemonic = mnemonic; return _context.abrupt("return", new _class.default(privateKeyWallet)); case 21: _context.prev = 21; _context.t0 = _context["catch"](4); throw new Error("".concat(_messages.staticMethods.open, " ").concat((0, _utils.objectToErrorString)({ password: password, privateKey: privateKey, mnemonic: mnemonic, keystore: keystore }), " Error: ").concat(_context.t0.message)); case 24: case "end": return _context.stop(); } } }, _callee, this, [[4, 21]]); })); return function open() { return _ref.apply(this, arguments); }; }(); /** * Create a new wallet. * * This will use EtherWallet's `createRandom()` (with defaults and entropy) * and use the resulting private key to instantiate a new SoftwareWallet. * * @method create * * @param {Uint8Array} entropy An unsigned 8bit integer Array to provide extra randomness * @param {string} password Optional password used to generate an encrypted keystore * @param {number} chainId The id of the network to use, defaults to mainnet (1) * * All the above params are sent in as props of an {WalletArgumentsType} object. * * @return {WalletType} A new wallet object */ exports.open = open; var create = /*#__PURE__*/ function () { var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee2() { var argumentObject, password, _argumentObject$entro, entropy, _argumentObject$chain2, chainId, basicWallet, _args2 = arguments; return _regenerator.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: argumentObject = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {}; /* * Validate the trasaction's object input */ (0, _helpers.userInputValidator)({ firstArgument: argumentObject }); password = argumentObject.password, _argumentObject$entro = argumentObject.entropy, entropy = _argumentObject$entro === void 0 ? (0, _utils.getRandomValues)(new Uint8Array(65536)) : _argumentObject$entro, _argumentObject$chain2 = argumentObject.chainId, chainId = _argumentObject$chain2 === void 0 ? _defaults.CHAIN_IDS.HOMESTEAD : _argumentObject$chain2; _context2.prev = 3; if (!entropy || entropy && !(entropy instanceof Uint8Array)) { (0, _utils.warning)(_messages.staticMethods.noEntrophy); basicWallet = _wallet.Wallet.createRandom(); } else { basicWallet = _wallet.Wallet.createRandom({ extraEntropy: entropy }); } /* * Set the password prop on the instance object. * * So that we can make use of them inside the SoftwareWallet * constructor, as the Ethers Wallet instance object will * be passed down. * * @TODO Better passing of values * * This needs to be refactored to pass values to the SoftwareWallet * class in a less repetitious way */ basicWallet.password = password; basicWallet.chainId = chainId; /* * @NOTE mnemonic prop was renamed due to naming conflict with getter-only * ethers prop */ basicWallet.originalMnemonic = basicWallet.mnemonic; return _context2.abrupt("return", new _class.default(basicWallet)); case 11: _context2.prev = 11; _context2.t0 = _context2["catch"](3); throw new Error("".concat(_messages.staticMethods.create, " Error: ").concat(_context2.t0.message)); case 14: case "end": return _context2.stop(); } } }, _callee2, this, [[3, 11]]); })); return function create() { return _ref2.apply(this, arguments); }; }(); exports.create = create; var softwareWallet = { open: open, create: create }; var _default = softwareWallet; exports.default = _default;