UNPKG

@ledgerhq/live-common

Version:
144 lines 6.06 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAction = exports.signMessageExec = exports.prepareMessageToSign = void 0; const errors_1 = require("@ledgerhq/errors"); const logs_1 = require("@ledgerhq/logs"); const invariant_1 = __importDefault(require("invariant")); const react_1 = require("react"); const rxjs_1 = require("rxjs"); const wallet_api_acre_module_1 = require("@ledgerhq/wallet-api-acre-module"); const hw_signMessage_1 = __importDefault(require("../../generated/hw-signMessage")); const app_1 = require("../actions/app"); const deviceAccess_1 = require("../deviceAccess"); const ACRESetup_1 = require("../../families/bitcoin/ACRESetup"); const account_1 = require("../../account"); const prepareMessageToSign = (account, message) => { const utf8Message = Buffer.from(message, "hex").toString(); if (!hw_signMessage_1.default[account.currency.family]) { throw new Error("Crypto does not support signMessage"); } if ("prepareMessageToSign" in hw_signMessage_1.default[account.currency.family]) { return hw_signMessage_1.default[account.currency.family].prepareMessageToSign({ account, message: utf8Message, }); } // Default implementation return { message: utf8Message }; }; exports.prepareMessageToSign = prepareMessageToSign; const signMessage = (transport, account, opts) => { const { currency } = account; let signMessage = hw_signMessage_1.default[currency.family].signMessage; if ("type" in opts) { switch (opts.type) { case wallet_api_acre_module_1.AcreMessageType.Withdraw: signMessage = ACRESetup_1.messageSigner.signWithdraw; break; case wallet_api_acre_module_1.AcreMessageType.SignIn: signMessage = ACRESetup_1.messageSigner.signIn; break; default: signMessage = ACRESetup_1.messageSigner.signMessage; break; } } (0, invariant_1.default)(signMessage, `signMessage is not implemented for ${currency.id}`); return signMessage(transport, account, opts) .then(result => { const path = "path" in opts && opts.path ? opts.path : account.freshAddressPath; (0, logs_1.log)("hw", `signMessage ${currency.id} on ${path} with message [${opts.message}]`, result); return result; }) .catch(e => { const path = "path" in opts && opts.path ? opts.path : account.freshAddressPath; (0, logs_1.log)("hw", `signMessage ${currency.id} on ${path} FAILED ${String(e)}`); if (e && e.name === "TransportStatusError") { if (e.statusCode === 0x6985 || e.statusCode === 0x5501) { throw new errors_1.UserRefusedAddress(); } } throw e; }); }; const signMessageExec = ({ request, deviceId }) => { if (!request.account) { throw new Error("account is required"); } const { type } = (0, account_1.decodeAccountId)(request.account.id); if (type === "mock") { return (0, rxjs_1.from)(Promise.resolve({ signature: "mockedSignature", })); } const result = (0, deviceAccess_1.withDevice)(deviceId)(transport => (0, rxjs_1.from)(signMessage(transport, request.account, request.message))); return result; }; exports.signMessageExec = signMessageExec; const initialState = { signMessageRequested: null, signMessageError: null, signMessageResult: null, }; const createAction = (connectAppExec, signMessage = exports.signMessageExec) => { const useHook = (reduxDevice, request) => { const appState = (0, app_1.createAction)(connectAppExec).useHook(reduxDevice, { appName: request.appName, dependencies: request.dependencies, account: request.isACRE ? undefined : request.account, // Bypass derivation check with ACRE as we can use other addresses than the freshest }); const { device, opened, inWrongDeviceForAccount, error } = appState; const [state, setState] = (0, react_1.useState)({ ...initialState, signMessageRequested: request.message, }); const signedFired = (0, react_1.useRef)(undefined); const sign = (0, react_1.useCallback)(async () => { let result; if (!device) { setState({ ...initialState, signMessageError: new Error("no Device"), }); return; } try { result = await (0, rxjs_1.firstValueFrom)(signMessage({ request, deviceId: device.deviceId, })); } catch (e) { if (e.name === "UserRefusedAddress") { e.name = "UserRefusedOnDevice"; e.message = "UserRefusedOnDevice"; } return setState({ ...initialState, signMessageError: e }); } setState({ ...initialState, signMessageResult: result?.signature }); }, [device, request]); (0, react_1.useEffect)(() => { if (!device || !opened || inWrongDeviceForAccount || error) { return; } if (state.signMessageRequested && !signedFired.current) { signedFired.current = true; sign(); } }, [device, opened, inWrongDeviceForAccount, error, sign, state.signMessageRequested]); return { ...appState, ...state }; }; return { useHook, mapResult: (state) => ({ signature: state.signMessageResult, error: state.signMessageError, }), }; }; exports.createAction = createAction; exports.default = signMessage; //# sourceMappingURL=index.js.map