UNPKG

@colony/purser-core

Version:

A collection of helpers, utils, validators and normalizers to assist the individual purser modules

369 lines (320 loc) 12.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _utils = require("ethers/utils"); var _hdkey = _interopRequireDefault(require("hdkey")); var _validators = require("./validators"); var _normalizers = require("./normalizers"); var _messages = require("./messages"); var _defaults = require("./defaults"); var _types = require("./types"); var GETTERS = _defaults.DESCRIPTORS.GETTERS, SETTERS = _defaults.DESCRIPTORS.SETTERS, WALLET_PROPS = _defaults.DESCRIPTORS.WALLET_PROPS, GENERIC_PROPS = _defaults.DESCRIPTORS.GENERIC_PROPS; /* * "Private" (internal) variable(s). * * These are used as return values from getters which don't have an accompanying setter, * but we still want to set them internally. */ var internalPublicKey; var internalDerivationPath; /* * @TODO Support extra props * * Support the extra props required for the software wallet (privateKey, mnemonic, etc...) * Also, we need to find a way to extend both this and the `ethers` wallet class */ var GenericWallet = /*#__PURE__*/ function () { /* * Both `publicKey` and `derivationPath` are getters. */ /* * @TODO Add specific Flow types * * For the three main wallet methods */ function GenericWallet(_ref) { var _this = this; var publicKey = _ref.publicKey, chainCode = _ref.chainCode, rootDerivationPath = _ref.rootDerivationPath, _ref$addressCount = _ref.addressCount, addressCount = _ref$addressCount === void 0 ? 10 : _ref$addressCount, _ref$chainId = _ref.chainId, chainId = _ref$chainId === void 0 ? _defaults.CHAIN_IDS.HOMESTEAD : _ref$chainId; (0, _classCallCheck2.default)(this, GenericWallet); /* * Validate address count (this comes from the end user) */ (0, _validators.safeIntegerValidator)(addressCount); /* * Validate the `publicKey` and `chainCode` hex sequences. These come from * various external services, and we shouldn't trust them. */ (0, _validators.hexSequenceValidator)(publicKey); (0, _validators.hexSequenceValidator)(chainCode); /* * Derive the public key with the address index, so we can get the address */ var hdKey = new _hdkey.default(); /* * Sadly Flow doesn't have the correct types for node's Buffer Object */ /* $FlowFixMe */ hdKey.publicKey = Buffer.from(publicKey, _defaults.HEX_HASH_TYPE); /* * Sadly Flow doesn't have the correct types for node's Buffer Object */ /* $FlowFixMe */ hdKey.chainCode = Buffer.from(chainCode, _defaults.HEX_HASH_TYPE); var otherAddresses = Array.from( /* * We default to `1`, but this time, to prevent the case where the * user passes in the value `0` manually (which will break the array map) */ new Array(addressCount || 1), function (value, index) { var addressObject = {}; var derivationKey = hdKey.deriveChild(index); /* * Set this individual address's derivation path */ addressObject.derivationPath = rootDerivationPath.substr(-1) === _defaults.SPLITTER ? "".concat(rootDerivationPath).concat(index) : "".concat(rootDerivationPath).concat(_defaults.SPLITTER).concat(index); /* * This is the derrived public key, not the one originally fetched one */ var derivedPublicKey = derivationKey.publicKey.toString(_defaults.HEX_HASH_TYPE); addressObject.publicKey = (0, _normalizers.hexSequenceNormalizer)(derivedPublicKey); /* * Generate the address from the derived public key */ var addressFromPublicKey = (0, _utils.computeAddress)( /* * Sadly Flow doesn't have the correct types for node's Buffer Object */ /* $FlowFixMe */ derivationKey.publicKey); /* * Also validate the address that comes from the `HDKey` library. */ (0, _validators.addressValidator)(addressFromPublicKey); addressObject.address = (0, _normalizers.addressNormalizer)(addressFromPublicKey); return addressObject; }); /* * Set the "private" (internal) variables values */ internalPublicKey = otherAddresses[0].publicKey; internalDerivationPath = otherAddresses[0].derivationPath; /* * Set the Wallet Object's values * * We're using `defineProperties` instead of strait up assignment, so that * we can customize the prop's descriptors * * @TODO Reduce code repetition when setting Class props * * We do this here and in the software wallet, so it might make sense to * write a helper method for this. */ Object.defineProperties(this, { address: Object.assign({}, { value: otherAddresses[0].address }, SETTERS), chainId: Object.assign({}, { value: chainId }, WALLET_PROPS), type: Object.assign({}, { value: _types.TYPE_GENERIC }, GENERIC_PROPS), subtype: Object.assign({}, { value: _types.SUBTYPE_GENERIC }, GENERIC_PROPS), /** * Set the default address/public key/path one of the (other) addresses from the array. * This is usefull since most methods (sign, signMessage) use this props as defaults. * * There's an argument to be made here that we can derive new addresses only when this * method gets called. * * This would be helpful to offload the initial cost of deriving a number * of `addressCount` addresses. * * On the other hand, if we do this, we won't be able to show the user what * addresses are available up front. * * @method setDefaultAddress * * @param {number} addressIndex The address index from the array * * @return {Promise<boolean>} True if it was able to set it, false otherwise */ setDefaultAddress: Object.assign({}, { /* * @TODO Accept both number and object as argument * To make the arguments consistent across the wallet instance methods */ value: function () { var _value = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee() { var addressIndex, _args = arguments; return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: addressIndex = _args.length > 0 && _args[0] !== undefined ? _args[0] : 0; (0, _validators.safeIntegerValidator)(addressIndex); if (!(addressIndex >= 0 && addressIndex < otherAddresses.length)) { _context.next = 7; break; } /* * Address count will always be at least `1` (the first derived address). * * This method is useful (can be used) only when the user generated more than * one address when instantiating the Wallet. */ _this.address = otherAddresses[addressIndex].address; internalPublicKey = otherAddresses[addressIndex].publicKey; internalDerivationPath = otherAddresses[addressIndex].derivationPath; return _context.abrupt("return", true); case 7: throw new Error("".concat(_messages.genericClass.addressIndexOutsideRange, ": index (").concat(addressIndex, ") count (").concat(addressCount, ")")); case 8: case "end": return _context.stop(); } } }, _callee, this); })); return function value() { return _value.apply(this, arguments); }; }() }, WALLET_PROPS), /* * These are just a placeholder static methods. They should be replaced (or deleted at least) * with methods that actually has some functionality. */ sign: Object.assign({}, { value: function () { var _value2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee2() { return _regenerator.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: case "end": return _context2.stop(); } } }, _callee2, this); })); return function value() { return _value2.apply(this, arguments); }; }() }, GENERIC_PROPS), signMessage: Object.assign({}, { value: function () { var _value3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee3() { return _regenerator.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: case "end": return _context3.stop(); } } }, _callee3, this); })); return function value() { return _value3.apply(this, arguments); }; }() }, GENERIC_PROPS), verifyMessage: Object.assign({}, { value: function () { var _value4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee4() { return _regenerator.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: case "end": return _context4.stop(); } } }, _callee4, this); })); return function value() { return _value4.apply(this, arguments); }; }() }, GENERIC_PROPS) }); /* * The `otherAddresses` prop is only available if we have more than one. * * Otherwise it's pointless since it just repeats information (first index * is also the default one). */ if (addressCount > 1) { Object.defineProperty(this, 'otherAddresses', Object.assign({}, { /* * Map out the publicKey and derivation path from the `otherAddresses` * array that gets assigned to the Wallet instance. * * The user should only have access to `the publicKey` and `derivationPath` from the * default account (set via `setDefaultAddress()`) */ value: otherAddresses.map(function (_ref2) { var address = _ref2.address; return address; }) }, WALLET_PROPS)); } } /* * Public Key Getter */ /* eslint-disable-next-line class-methods-use-this */ (0, _createClass2.default)(GenericWallet, [{ key: "publicKey", get: function get() { return Promise.resolve(internalPublicKey); } /* eslint-disable-next-line class-methods-use-this */ }, { key: "derivationPath", get: function get() { return Promise.resolve(internalDerivationPath); } }]); return GenericWallet; }(); /* * We need to use `defineProperties` to make props enumerable. * When adding them via a `Class` getter/setter it will prevent that by default */ exports.default = GenericWallet; Object.defineProperties(GenericWallet.prototype, { publicKey: GETTERS, derivationPath: GETTERS });