@colony/purser-metamask
Version:
A javascript library to interact with a Metamask based Ethereum wallet
237 lines (199 loc) • 6.87 kB
JavaScript
;
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;