UNPKG

@colony/purser-metamask

Version:

A javascript library to interact with a Metamask based Ethereum wallet

237 lines (199 loc) 6.87 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.accountChangeHook = exports.detect = exports.open = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _web = _interopRequireDefault(require("web3")); var _utils = require("@colony/purser-core/utils"); var _class = _interopRequireDefault(require("./class")); var _helpers = require("./helpers"); var _messages = require("./messages"); /** * Open the Metamask Wallet instance * * @method open * * @return {WalletType} The wallet object resulted by instantiating the class * (Object is wrapped in a promise). */ var open = /*#__PURE__*/ function () { var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee() { var addressAfterEnable, _ref2, _ref3, legacyProvider; return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.prev = 0; if (!global.ethereum) { _context.next = 8; break; } /* * Inject the web3 provider */ global.web3 = new _web.default(global.ethereum); /* * Enable it */ _context.next = 5; return global.ethereum.enable(); case 5: _ref2 = _context.sent; _ref3 = (0, _slicedToArray2.default)(_ref2, 1); addressAfterEnable = _ref3[0]; case 8: /* * We're on the legacy version of Metamask */ if (!global.ethereum && global.web3) { /* * Warn the user about legacy mode * * @TODO Remove legacy metmask version messages * After an adequate amount of time has passed */ (0, _utils.warning)(_messages.staticMethods.legacyMode); /* * Enable it * * @NOTE There's an argument to be made here that it's dangerous to use * the `getInpageProvider()` helper before using `detect()` */ legacyProvider = (0, _helpers.getInpageProvider)(); legacyProvider.enable(); /* * Inject the web3 provider (overwrite the current one) */ global.web3 = new _web.default(legacyProvider); } /* * Everything functions the same since the Web3 instance is now in place * (Granted, it's now using the 1.x.x version) */ return _context.abrupt("return", (0, _helpers.methodCaller)(function () { var _getInpageProvider = (0, _helpers.getInpageProvider)(), state = _getInpageProvider.publicConfigStore._state; return new _class.default({ /* * The EIP-1102 mode uses the address we got after enabling (and getting * the users's permission), while the legacy mode get the address from * the state */ address: addressAfterEnable || state.selectedAddress }); }, _messages.staticMethods.metamaskNotAvailable)); case 12: _context.prev = 12; _context.t0 = _context["catch"](0); throw new Error(_messages.staticMethods.didNotAuthorize); case 15: case "end": return _context.stop(); } } }, _callee, this, [[0, 12]]); })); return function open() { return _ref.apply(this, arguments); }; }(); /** * Check if Metamask's injected web3 proxy instance is available in the * global object. * * Makes use of the `detect()` helper, basically it's a wrapper * that exposes it from the module. * * @method detect * * @return {boolean} Only returns true if it's available, otherwise it will throw. */ exports.open = open; var detect = /*#__PURE__*/ function () { var _ref4 = (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: return _context2.abrupt("return", (0, _helpers.detect)()); case 1: case "end": return _context2.stop(); } } }, _callee2, this); })); return function detect() { return _ref4.apply(this, arguments); }; }(); /** * Hook into Metamask's state events observers array to be able to act on account * changes from the UI * * It's a wrapper around the `setStateEventObserver()` helper method * * @method accountChangeHook * * @param {Function} callback Function to add the state events update array * It receives the state object as an only argument * * @return {Promise<void>} Does not return noting */ exports.detect = detect; var accountChangeHook = /*#__PURE__*/ function () { var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee3(callback) { return _regenerator.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: /* * If detect fails, it will throw, with a message explaining the problem * (Most likely Metamask will be locked, so we won't be able to get to * the state observer via the in-page provider) */ (0, _helpers.detect)(); _context3.prev = 1; return _context3.abrupt("return", (0, _helpers.setStateEventObserver)(callback)); case 5: _context3.prev = 5; _context3.t0 = _context3["catch"](1); throw new Error(_messages.staticMethods.cannotAddHook); case 8: case "end": return _context3.stop(); } } }, _callee3, this, [[1, 5]]); })); return function accountChangeHook(_x) { return _ref5.apply(this, arguments); }; }(); /* * @NOTE There's an argument to be made here to expose the new version */ exports.accountChangeHook = accountChangeHook; var metamaskWallet = { open: open, detect: detect, accountChangeHook: accountChangeHook }; var _default = metamaskWallet; exports.default = _default;