UNPKG

@ledgerhq/live-common

Version:
108 lines 4.21 kB
import { of } from "rxjs"; import { scan, catchError, tap } from "rxjs/operators"; import { useEffect, useState } from "react"; import { log } from "@ledgerhq/logs"; import { TransportStatusError } from "@ledgerhq/errors"; import { TransactionRefusedOnDevice } from "../../errors"; import { getMainAccount } from "../../account"; import { getAccountBridge } from "../../bridge"; import { createAction as createAppAction } from "./app"; const mapResult = ({ device, signedOperation, transactionSignError, }) => { if (signedOperation && device) { return { signedOperation, device, }; } if (transactionSignError) { return { transactionSignError, }; } return null; }; const initialState = { signedOperation: null, deviceSignatureRequested: false, deviceStreamingProgress: null, transactionSignError: null, transactionChecksOptInTriggered: false, transactionChecksOptIn: null, }; const reducer = (state, e) => { switch (e.type) { case "error": { const { error } = e; const transactionSignError = error instanceof TransportStatusError && error.statusCode === 0x6985 ? new TransactionRefusedOnDevice() : error; return { ...initialState, transactionSignError }; } case "signed": return { ...state, signedOperation: e.signedOperation }; case "device-signature-requested": return { ...state, deviceSignatureRequested: true }; case "device-signature-granted": return { ...state, deviceSignatureRequested: false }; case "device-streaming": return { ...state, deviceStreamingProgress: e.progress }; case "transaction-checks-opt-in-triggered": return { ...state, transactionChecksOptInTriggered: true }; case "transaction-checks-opt-in": return { ...state, transactionChecksOptIn: true }; case "transaction-checks-opt-out": return { ...state, transactionChecksOptIn: false }; default: return state; } }; export const createAction = (connectAppExec) => { const useHook = (reduxDevice, { account, parentAccount, transaction, broadcast, appName, dependencies, requireLatestFirmware, manifestId, manifestName, }) => { const mainAccount = getMainAccount(account, parentAccount); const appState = createAppAction(connectAppExec).useHook(reduxDevice, { account: mainAccount, appName, dependencies, requireLatestFirmware, }); const { device, opened, inWrongDeviceForAccount, error } = appState; const [state, setState] = useState(initialState); useEffect(() => { if (!device || !opened || inWrongDeviceForAccount || error) { setState(initialState); return; } const bridge = getAccountBridge(mainAccount); const sub = bridge .signRawOperation({ account: mainAccount, transaction, deviceId: device.deviceId, deviceModelId: device.modelId, broadcast, }) .pipe(catchError(error => of({ type: "error", error, })), tap((e) => log("actions-transaction-event", e.type, e)), scan(reducer, initialState)) .subscribe((x) => setState(x)); return () => { sub.unsubscribe(); }; }, [device, mainAccount, transaction, broadcast, opened, inWrongDeviceForAccount, error]); return { ...appState, ...state, manifestId, manifestName, deviceStreamingProgress: state.signedOperation || state.transactionSignError ? null // when good app is opened, we start the progress so it doesn't "blink" : state.deviceStreamingProgress || (appState.opened ? 0 : null), }; }; return { useHook, mapResult, }; }; //# sourceMappingURL=rawTransaction.js.map