UNPKG

@metamask/eth-ledger-bridge-keyring

Version:

A MetaMask compatible keyring, for ledger hardware wallets

176 lines 10 kB
"use strict"; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _LedgerIframeBridge_instances, _LedgerIframeBridge_opts, _LedgerIframeBridge_messageResponseHandles, _LedgerIframeBridge_deviceActionMessage, _LedgerIframeBridge_setupIframe, _LedgerIframeBridge_getOrigin, _LedgerIframeBridge_eventListener, _LedgerIframeBridge_sendMessage, _LedgerIframeBridge_validateConfiguration; Object.defineProperty(exports, "__esModule", { value: true }); exports.LedgerIframeBridge = exports.IFrameMessageAction = void 0; const utils_1 = require("@metamask/utils"); const LEDGER_IFRAME_ID = 'LEDGER-IFRAME'; const IFRAME_MESSAGE_TIMEOUT = 4000; var IFrameMessageAction; (function (IFrameMessageAction) { IFrameMessageAction["LedgerIsIframeReady"] = "ledger-is-iframe-ready"; IFrameMessageAction["LedgerConnectionChange"] = "ledger-connection-change"; IFrameMessageAction["LedgerUnlock"] = "ledger-unlock"; IFrameMessageAction["LedgerMakeApp"] = "ledger-make-app"; IFrameMessageAction["LedgerUpdateTransport"] = "ledger-update-transport"; IFrameMessageAction["LedgerSignTransaction"] = "ledger-sign-transaction"; IFrameMessageAction["LedgerSignPersonalMessage"] = "ledger-sign-personal-message"; IFrameMessageAction["LedgerSignTypedData"] = "ledger-sign-typed-data"; })(IFrameMessageAction || (exports.IFrameMessageAction = IFrameMessageAction = {})); class LedgerIframeBridge { constructor(opts = { bridgeUrl: 'https://metamask.github.io/eth-ledger-bridge-keyring', }) { _LedgerIframeBridge_instances.add(this); this.iframeLoaded = false; _LedgerIframeBridge_opts.set(this, void 0); this.isDeviceConnected = false; this.currentMessageId = 0; _LedgerIframeBridge_messageResponseHandles.set(this, new Map()); __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_validateConfiguration).call(this, opts); __classPrivateFieldSet(this, _LedgerIframeBridge_opts, { bridgeUrl: opts?.bridgeUrl, }, "f"); } async init() { await __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_setupIframe).call(this, __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f").bridgeUrl); this.eventListener = __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_eventListener).bind(this, __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f").bridgeUrl); window.addEventListener('message', this.eventListener); } async destroy() { if (this.eventListener) { window.removeEventListener('message', this.eventListener); } } async getOptions() { return __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f"); } async setOptions(opts) { __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_validateConfiguration).call(this, opts); if (__classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f")?.bridgeUrl !== opts.bridgeUrl) { __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f").bridgeUrl = opts.bridgeUrl; await this.destroy(); await this.init(); } } async attemptMakeApp() { const response = await __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_sendMessage).call(this, { action: IFrameMessageAction.LedgerMakeApp, }, { timeout: IFRAME_MESSAGE_TIMEOUT }); if ('success' in response && response.success) { return true; } else if ('error' in response) { // Assuming this is using an `Error` type: throw response.error; } else { throw new Error('Unknown error occurred'); } } async updateTransportMethod(transportType) { if (!this.iframeLoaded) { throw new Error('The iframe is not loaded yet'); } const response = await __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_sendMessage).call(this, { action: IFrameMessageAction.LedgerUpdateTransport, params: { transportType }, }, { timeout: IFRAME_MESSAGE_TIMEOUT }); if ('success' in response && response.success) { return true; } throw new Error('Ledger transport could not be updated'); } async getPublicKey(params) { return __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_deviceActionMessage).call(this, IFrameMessageAction.LedgerUnlock, params); } async deviceSignTransaction(params) { return __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_deviceActionMessage).call(this, IFrameMessageAction.LedgerSignTransaction, params); } async deviceSignMessage(params) { return __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_deviceActionMessage).call(this, IFrameMessageAction.LedgerSignPersonalMessage, params); } async deviceSignTypedData(params) { return __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_deviceActionMessage).call(this, IFrameMessageAction.LedgerSignTypedData, params); } } exports.LedgerIframeBridge = LedgerIframeBridge; _LedgerIframeBridge_opts = new WeakMap(), _LedgerIframeBridge_messageResponseHandles = new WeakMap(), _LedgerIframeBridge_instances = new WeakSet(), _LedgerIframeBridge_deviceActionMessage = async function _LedgerIframeBridge_deviceActionMessage(...[action, params]) { const response = await __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_sendMessage).call(this, { action, params }); if ('payload' in response && response.payload) { if ('success' in response && response.success) { return response.payload; } if ('error' in response.payload) { throw response.payload.error; } } throw new Error('Unknown error occurred'); }, _LedgerIframeBridge_setupIframe = async function _LedgerIframeBridge_setupIframe(bridgeUrl) { return new Promise((resolve) => { this.iframe = document.createElement('iframe'); this.iframe.src = bridgeUrl; this.iframe.allow = `hid 'src'`; this.iframe.onload = async () => { this.iframeLoaded = true; resolve(); }; document.head.appendChild(this.iframe); }); }, _LedgerIframeBridge_getOrigin = function _LedgerIframeBridge_getOrigin(bridgeUrl) { const tmp = bridgeUrl.split('/'); tmp.splice(-1, 1); return tmp.join('/'); }, _LedgerIframeBridge_eventListener = function _LedgerIframeBridge_eventListener(bridgeUrl, eventMessage) { const { origin, data } = eventMessage; if (origin !== __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_getOrigin).call(this, bridgeUrl)) { return; } if (data) { const messageResponseHandle = __classPrivateFieldGet(this, _LedgerIframeBridge_messageResponseHandles, "f").get(data.messageId); if (messageResponseHandle) { messageResponseHandle.resolve(data); __classPrivateFieldGet(this, _LedgerIframeBridge_messageResponseHandles, "f").delete(data.messageId); } else if (data.action === IFrameMessageAction.LedgerConnectionChange) { this.isDeviceConnected = data.payload.connected; } } }, _LedgerIframeBridge_sendMessage = async function _LedgerIframeBridge_sendMessage(message, { timeout } = {}) { this.currentMessageId += 1; const postMsg = { ...message, messageId: this.currentMessageId, target: LEDGER_IFRAME_ID, }; const messageResponseHandle = (0, utils_1.createDeferredPromise)(); __classPrivateFieldGet(this, _LedgerIframeBridge_messageResponseHandles, "f").set(this.currentMessageId, messageResponseHandle); if (!this.iframeLoaded || !this.iframe?.contentWindow) { throw new Error('The iframe is not loaded yet'); } if (timeout) { setTimeout(() => { if (__classPrivateFieldGet(this, _LedgerIframeBridge_messageResponseHandles, "f").has(postMsg.messageId)) { __classPrivateFieldGet(this, _LedgerIframeBridge_messageResponseHandles, "f").delete(postMsg.messageId); messageResponseHandle.reject(new Error('Ledger iframe message timeout')); } }, timeout); } this.iframe.contentWindow.postMessage(postMsg, '*'); return messageResponseHandle.promise; }, _LedgerIframeBridge_validateConfiguration = function _LedgerIframeBridge_validateConfiguration(opts) { if (typeof opts.bridgeUrl !== 'string' || opts.bridgeUrl.length === 0) { throw new Error('bridgeURL is not a valid URL'); } }; //# sourceMappingURL=ledger-iframe-bridge.cjs.map