UNPKG

@colony/purser-metamask

Version:

A javascript library to interact with a Metamask based Ethereum wallet

234 lines (197 loc) 6.34 kB
import _regeneratorRuntime from "@babel/runtime/regenerator"; import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator"; import { helpers as messages } from './messages'; /* * @TODO Add isModern() helper method to detect the new version of Metamask */ /** * Detect the Metmask Extensaion * * @method detect * * @return {boolean} If it's available it will return true, otherwise it will throw */ export var detect = /*#__PURE__*/ function () { var _ref = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee() { return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (!global.ethereum) { _context.next = 16; break; } _context.t0 = global.ethereum.isUnlocked; if (!_context.t0) { _context.next = 6; break; } _context.next = 5; return global.ethereum.isUnlocked(); case 5: _context.t0 = !_context.sent; case 6: if (!_context.t0) { _context.next = 8; break; } throw new Error(messages.isLocked); case 8: _context.t1 = global.ethereum.isEnabled; if (!_context.t1) { _context.next = 13; break; } _context.next = 12; return global.ethereum.isEnabled(); case 12: _context.t1 = !_context.sent; case 13: if (!_context.t1) { _context.next = 15; break; } throw new Error(messages.notEnabled); case 15: return _context.abrupt("return", true); case 16: if (!(!global.ethereum && global.web3)) { _context.next = 24; break; } if (!(!global.web3.currentProvider || !global.web3.currentProvider.publicConfigStore)) { _context.next = 19; break; } throw new Error(messages.noInpageProvider); case 19: if (global.web3.currentProvider.publicConfigStore._state) { _context.next = 21; break; } throw new Error(messages.noProviderState); case 21: if (global.web3.currentProvider.publicConfigStore._state.selectedAddress) { _context.next = 23; break; } throw new Error(messages.notEnabled); case 23: return _context.abrupt("return", true); case 24: throw new Error(messages.noExtension); case 25: case "end": return _context.stop(); } } }, _callee, this); })); return function detect() { return _ref.apply(this, arguments); }; }(); /** * Helper method that wraps a method passed as an argument and first checks * for Metamask's availablity before calling it. * * This is basically a wrapper, so that we can cut down on code repetition, since * this pattern repeats itself every time we try to access the in-page proxy. * * @method methodCaller * * @param {Function} callback The method to call, if Metamask is available * @param {string} errorMessage Optional error message to show to use * (in case Metamask is not available) * * @return {any} It returns the result of the callback execution */ export var methodCaller = /*#__PURE__*/ function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee2(callback) { var errorMessage, _args2 = arguments; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: errorMessage = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : ''; _context2.prev = 1; _context2.next = 4; return metamaskHelpers.detect(); case 4: return _context2.abrupt("return", callback()); case 7: _context2.prev = 7; _context2.t0 = _context2["catch"](1); throw new Error("".concat(errorMessage).concat(errorMessage ? ' ' : '', "Error: ").concat(_context2.t0.message)); case 10: case "end": return _context2.stop(); } } }, _callee2, this, [[1, 7]]); })); return function methodCaller(_x) { return _ref2.apply(this, arguments); }; }(); /** * If the Metamask injected instance is available, get the in-page provider * * @method getInpageProvider * * @return {Object} The `MetamaskInpageProvider` object instance */ export var getInpageProvider = function getInpageProvider() { /* * We need this little go-around trick to mock just one export of * the module, while leaving the rest of the module intact so we can test it * * See: https://github.com/facebook/jest/issues/936 */ if (global.ethereum) { return global.ethereum; } return global.web3.currentProvider; }; /** * Add a new observer method to Metamask's state update events * * @method setStateEventObserver * * @param {Function} observer Function to add the state events update array * * @return {number} the length of the state events update array */ export var setStateEventObserver = function setStateEventObserver(observer) { var _metamaskHelpers$getI = /* * We need this little go-around trick to mock just one export of * the module, while leaving the rest of the module intact so we can test it * * See: https://github.com/facebook/jest/issues/936 */ /* eslint-disable-next-line no-use-before-define */ metamaskHelpers.getInpageProvider(), stateEvents = _metamaskHelpers$getI.publicConfigStore._events; return stateEvents.update.push(observer); }; /* * This default export is only here to help us with testing, otherwise * it wound't be needed */ var metamaskHelpers = { detect: detect, methodCaller: methodCaller, getInpageProvider: getInpageProvider, setStateEventObserver: setStateEventObserver }; export default metamaskHelpers;