@colony/purser-metamask
Version:
A javascript library to interact with a Metamask based Ethereum wallet
212 lines (189 loc) • 6.28 kB
JavaScript
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import Web3Instance from 'web3';
import { warning } from '@colony/purser-core/utils';
import MetamaskWallet from './class';
import { methodCaller, getInpageProvider, detect as detectHelper, setStateEventObserver } from './helpers';
import { staticMethods as messages } from './messages';
/**
* Open the Metamask Wallet instance
*
* @method open
*
* @return {WalletType} The wallet object resulted by instantiating the class
* (Object is wrapped in a promise).
*/
export var open =
/*#__PURE__*/
function () {
var _ref = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee() {
var addressAfterEnable, _ref2, _ref3, legacyProvider;
return _regeneratorRuntime.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 Web3Instance(global.ethereum);
/*
* Enable it
*/
_context.next = 5;
return global.ethereum.enable();
case 5:
_ref2 = _context.sent;
_ref3 = _slicedToArray(_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
*/
warning(messages.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 = getInpageProvider();
legacyProvider.enable();
/*
* Inject the web3 provider (overwrite the current one)
*/
global.web3 = new Web3Instance(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", methodCaller(function () {
var _getInpageProvider = getInpageProvider(),
state = _getInpageProvider.publicConfigStore._state;
return new MetamaskWallet({
/*
* 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.metamaskNotAvailable));
case 12:
_context.prev = 12;
_context.t0 = _context["catch"](0);
throw new Error(messages.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.
*/
export var detect =
/*#__PURE__*/
function () {
var _ref4 = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee2() {
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
return _context2.abrupt("return", detectHelper());
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
*/
export var accountChangeHook =
/*#__PURE__*/
function () {
var _ref5 = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee3(callback) {
return _regeneratorRuntime.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)
*/
detectHelper();
_context3.prev = 1;
return _context3.abrupt("return", setStateEventObserver(callback));
case 5:
_context3.prev = 5;
_context3.t0 = _context3["catch"](1);
throw new Error(messages.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
*/
var metamaskWallet = {
open: open,
detect: detect,
accountChangeHook: accountChangeHook
};
export default metamaskWallet;