UNPKG

@airgap/beacon-dapp

Version:

Use this package on your dApp to instanciate a DAppClient object and communicate to wallets.

703 lines • 27.7 kB
import { closeAlert, openAlert, openBugReport, closeToast, openToast } from '@airgap/beacon-dapp'; import { BeaconErrorType } from '@airgap/beacon-types'; import { UnknownBeaconError, Logger, getError // EncryptPayloadResponseOutput, // EncryptionOperation } from '@airgap/beacon-core'; import { shortenString } from './utils/shorten-string'; import { isMobile, isMobileOS } from '@airgap/beacon-ui'; const logger = new Logger('BeaconEvents'); const SUCCESS_TIMER = 5 * 1000; /** * The different events that can be emitted by the beacon-sdk */ export var BeaconEvent; (function (BeaconEvent) { BeaconEvent["PERMISSION_REQUEST_SENT"] = "PERMISSION_REQUEST_SENT"; BeaconEvent["PERMISSION_REQUEST_SUCCESS"] = "PERMISSION_REQUEST_SUCCESS"; BeaconEvent["PERMISSION_REQUEST_ERROR"] = "PERMISSION_REQUEST_ERROR"; BeaconEvent["PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT"] = "PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT"; BeaconEvent["PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS"] = "PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS"; BeaconEvent["PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR"] = "PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR"; BeaconEvent["SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT"] = "SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT"; BeaconEvent["SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS"] = "SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS"; BeaconEvent["SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR"] = "SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR"; BeaconEvent["OPERATION_REQUEST_SENT"] = "OPERATION_REQUEST_SENT"; BeaconEvent["OPERATION_REQUEST_SUCCESS"] = "OPERATION_REQUEST_SUCCESS"; BeaconEvent["OPERATION_REQUEST_ERROR"] = "OPERATION_REQUEST_ERROR"; BeaconEvent["SIGN_REQUEST_SENT"] = "SIGN_REQUEST_SENT"; BeaconEvent["SIGN_REQUEST_SUCCESS"] = "SIGN_REQUEST_SUCCESS"; BeaconEvent["SIGN_REQUEST_ERROR"] = "SIGN_REQUEST_ERROR"; BeaconEvent["BLOCKCHAIN_REQUEST_SUCCESS"] = "BLOCKCHAIN_REQUEST_SUCCESS"; // TODO: ENCRYPTION // ENCRYPT_REQUEST_SENT = 'ENCRYPT_REQUEST_SENT', // ENCRYPT_REQUEST_SUCCESS = 'ENCRYPT_REQUEST_SUCCESS', // ENCRYPT_REQUEST_ERROR = 'ENCRYPT_REQUEST_ERROR', BeaconEvent["BROADCAST_REQUEST_SENT"] = "BROADCAST_REQUEST_SENT"; BeaconEvent["BROADCAST_REQUEST_SUCCESS"] = "BROADCAST_REQUEST_SUCCESS"; BeaconEvent["BROADCAST_REQUEST_ERROR"] = "BROADCAST_REQUEST_ERROR"; BeaconEvent["ACKNOWLEDGE_RECEIVED"] = "ACKNOWLEDGE_RECEIVED"; BeaconEvent["LOCAL_RATE_LIMIT_REACHED"] = "LOCAL_RATE_LIMIT_REACHED"; BeaconEvent["NO_PERMISSIONS"] = "NO_PERMISSIONS"; BeaconEvent["ACTIVE_ACCOUNT_SET"] = "ACTIVE_ACCOUNT_SET"; BeaconEvent["ACTIVE_TRANSPORT_SET"] = "ACTIVE_TRANSPORT_SET"; BeaconEvent["SHOW_PREPARE"] = "SHOW_PREPARE"; BeaconEvent["HIDE_UI"] = "HIDE_UI"; BeaconEvent["INVALID_ACTIVE_ACCOUNT_STATE"] = "INVALID_ACTIVE_ACCOUNT_STATE"; BeaconEvent["INVALID_ACCOUNT_DEACTIVATED"] = "INVALID_ACCOUNT_DEACTIVATED"; BeaconEvent["PAIR_INIT"] = "PAIR_INIT"; BeaconEvent["PAIR_SUCCESS"] = "PAIR_SUCCESS"; BeaconEvent["CHANNEL_CLOSED"] = "CHANNEL_CLOSED"; BeaconEvent["GENERIC_ERROR"] = "GENERIC_ERROR"; BeaconEvent["OPEN_BUG_REPORT"] = "OPEN_BUG_REPORT"; BeaconEvent["RELAYER_ERROR"] = "RELAYER_ERROR"; BeaconEvent["INTERNAL_ERROR"] = "INTERNAL_ERROR"; BeaconEvent["UNKNOWN"] = "UNKNOWN"; })(BeaconEvent || (BeaconEvent = {})); /** * Show a "Request sent" toast */ const showSentToast = async (data) => { let openWalletAction; const actions = []; if (data.walletInfo.deeplink) { if (data.walletInfo.type === 'web' || (data.walletInfo.type === 'mobile' && isMobile(window)) || (data.walletInfo.type === 'desktop' && !isMobile(window))) { const link = data.walletInfo.deeplink; openWalletAction = async () => { const a = document.createElement('a'); a.setAttribute('rel', 'noopener'); a.setAttribute('href', link); a.setAttribute('target', '_blank'); a.dispatchEvent(new MouseEvent('click', { view: window, bubbles: true, cancelable: true })); }; } } actions.push({ text: `No answer from your wallet received yet. Please make sure the wallet is open.`, isBold: true }); actions.push({ text: 'Wallet not receiving request?', actionText: 'Reset Connection', actionCallback: async () => { closeToast(); // eslint-disable-next-line @typescript-eslint/unbound-method const resetCallback = data.extraInfo.resetCallback; if (resetCallback) { logger.log('showSentToast', 'resetCallback invoked'); await resetCallback(); } } }); actions.push({ text: 'Do you wish to report a bug?', actionText: 'Open', actionCallback: async () => { closeToast(); openBugReport(); } }); openToast({ body: `Request sent to\u00A0 {{wallet}}`, walletInfo: data.walletInfo, state: 'loading', timer: isMobileOS(window) ? SUCCESS_TIMER : 0, actions, openWalletAction }); }; const showAcknowledgedToast = async (data) => { openToast({ body: 'Awaiting confirmation in\u00A0 {{wallet}}', state: 'acknowledge', walletInfo: data.walletInfo }); }; const showPrepare = async (data) => { const text = data.walletInfo ? `Preparing Request for\u00A0 {{wallet}}...` : 'Preparing Request...'; openToast({ body: text, state: 'prepare', walletInfo: data.walletInfo }); }; const hideUI = (elements) => { if (elements?.includes('alert')) { closeAlert(); } if (elements?.includes('toast') || !elements) { closeToast(); } }; /** * Show a "No Permission" alert */ const showNoPermissionAlert = async () => { openAlert({ title: 'No Permission', body: 'Please allow the wallet to handle this type of request.' }); }; /** * Show an "Invalid state" alert */ const showInvalidActiveAccountState = async () => { openAlert({ title: 'Invalid state', body: `An active account has been received, but no active subscription was found for BeaconEvent.ACTIVE_ACCOUNT_SET. For more information, visit: https://docs.walletbeacon.io/guides/migration-guide` }); }; /** * Show an "account deactivated" error alert */ const showInvalidAccountDeactivated = async () => { await openAlert({ title: 'Error', body: `Your session has expired. Please pair with your wallet again.` }); }; /** * Show an "Invalid state" alert */ const showGenericErrorAlert = async (errorMessage) => { openAlert({ title: `${errorMessage}`, body: 'Please try again. If this problem persists please send us a bug report.', buttons: [ { label: 'Send Report', type: 'primary', onClick: () => openBugReport() } ] }); }; /** * Show an error toast * * @param beaconError The beacon error */ const showErrorToast = async (response, buttons) => { const error = response.errorResponse.errorType ? getError(response.errorResponse.errorType, response.errorResponse.errorData) : new UnknownBeaconError(); const actions = [ { text: error.title, isBold: true } ]; if (response.errorResponse.errorType === BeaconErrorType.TRANSACTION_INVALID_ERROR && response.errorResponse.errorData) { const err = response.errorResponse.errorData; const errorMessages = response.errorMessages; let hasHumandReadableError = false; if (err[0]?.contract_handle && errorMessages && errorMessages?.[err[0].contract_handle]) { const errCode = err[1]?.with?.int ?? err[1]?.with?.string; const contractErrors = errorMessages?.[err[0].contract_handle]; if (errCode && contractErrors?.[errCode]) { actions.push({ text: contractErrors?.[errCode], isBold: true }); hasHumandReadableError = true; } } if (!hasHumandReadableError) { actions.push({ text: error.description }); } actions.push({ text: '', actionText: 'Show Details', actionCallback: async () => { closeToast(); openAlert({ title: error.title, // eslint-disable-next-line @typescript-eslint/unbound-method body: error.fullDescription.description, data: error.fullDescription.data, buttons }); } }); } openToast({ body: `{{wallet}}\u00A0 has returned an error`, timer: response.errorResponse.errorType === BeaconErrorType.ABORTED_ERROR ? SUCCESS_TIMER : undefined, state: 'finished', walletInfo: response.walletInfo, actions }); }; /** * Show a rate limit reached toast */ const showRateLimitReached = async () => { openAlert({ title: 'Error', body: 'Rate limit reached. Please slow down', buttons: [{ text: 'Done', style: 'outline' }], timer: 3000 }); }; /** * Show a "connection successful" alert for 1.5 seconds */ const showExtensionConnectedAlert = () => { closeAlert(); }; const showBugReportForm = async () => { await openBugReport(); }; const showRelayerErrorAlert = async () => { openAlert({ title: 'Error', body: `Failed to connect to the relayer. Please check that your system time is synchronized with the current time and reload the page.`, buttons: [{ text: 'Done', style: 'outline' }], timer: 1500 }); }; /** * Show a "channel closed" alert for 1.5 seconds */ const showChannelClosedAlert = async () => { // openAlert({ // title: 'Channel closed', // body: `Your peer has closed the connection.`, // buttons: [{ text: 'Done', style: 'outline' }], // timer: 1500 // }) }; const showInternalErrorAlert = async (data) => { const buttons = [...(data.buttons ?? [])]; buttons.push({ text: 'Done', style: 'outline' }); const alertConfig = { title: 'Internal Error', body: data.text, buttons }; openAlert(alertConfig); }; /** * Show a connect alert with QR code * * @param data The data that is emitted by the PAIR_INIT event */ const showPairAlert = async (data) => { logger.log('showPairAlert'); const alertConfig = { title: 'Choose your preferred wallet', body: `<p></p>`, pairingPayload: { p2pSyncCode: data.p2pPeerInfo, walletConnectSyncCode: data.walletConnectPeerInfo, postmessageSyncCode: data.postmessagePeerInfo, networkType: data.networkType }, // eslint-disable-next-line @typescript-eslint/unbound-method closeButtonCallback: data.abortedHandler, disclaimerText: data.disclaimerText, analytics: data.analytics, featuredWallets: data.featuredWallets, substratePairing: data.substratePairing }; openAlert(alertConfig); }; /** * Show a "Permission Granted" alert * * @param data The data that is emitted by the PERMISSION_REQUEST_SUCCESS event */ const showPermissionSuccessAlert = async (data) => { const { output } = data; const actions = [ { text: 'Address', actionText: shortenString(output.address), isBold: true } ]; if (output.network.type !== 'substrate') { actions.push({ text: 'Network', actionText: `${output.network.type}` }); actions.push({ text: 'Permissions', actionText: output.scopes.join(', ') }); } openToast({ body: `{{wallet}}\u00A0 has granted permission`, timer: SUCCESS_TIMER, walletInfo: data.walletInfo, state: 'finished', actions }); }; const showProofOfEventChallengeSuccessAlert = async (data) => { const { output } = data; openToast({ body: `{{wallet}}\u00A0 has ${output.isAccepted ? 'accepted' : 'refused'} the challenge`, timer: SUCCESS_TIMER, walletInfo: data.walletInfo, state: 'finished', actions: output.isAccepted ? [ { text: `Payload hash: ${output.payloadHash}`, actionText: 'Copy to clipboard', actionCallback: async () => { navigator.clipboard.writeText(output.payloadHash).then(() => { logger.log('showSignSuccessAlert', 'Copying to clipboard was successful!'); }, (err) => { logger.error('showSignSuccessAlert', 'Could not copy text to clipboard: ', err); }); closeToast(); } } ] : [] }); }; const showSimulatedProofOfEventChallengeSuccessAlert = async (data) => { const { output } = data; openToast({ body: !output.errorMessage ? `{{wallet}}\u00A0 has returned the list of operation` : `{{wallet}}\u00A0 has returned an error`, timer: SUCCESS_TIMER, walletInfo: data.walletInfo, state: 'finished', actions: !output.errorMessage ? [ { text: 'Operation list', actionText: 'Copy to clipboard', actionCallback: async () => { navigator.clipboard.writeText(output.operationsList).then(() => { logger.log('showSignSuccessAlert', 'Copying to clipboard was successful!'); }, (err) => { logger.error('showSignSuccessAlert', 'Could not copy text to clipboard: ', err); }); closeToast(); } } ] : [{ text: 'Error message', actionText: output.errorMessage }] }); }; /** * Show an "Operation Broadcasted" alert * * @param data The data that is emitted by the OPERATION_REQUEST_SUCCESS event */ const showOperationSuccessAlert = async (data) => { const { account, output, blockExplorer } = data; openToast({ body: `{{wallet}}\u00A0 successfully submitted operation`, timer: SUCCESS_TIMER, state: 'finished', walletInfo: data.walletInfo, actions: [ { text: shortenString(output.transactionHash), isBold: true, actionText: `Open Blockexplorer`, actionLogo: 'external', actionCallback: async () => { const link = await blockExplorer.getTransactionLink(output.transactionHash, account.network); window.open(link, '_blank', 'noopener'); closeToast(); } } ] }); }; /** * Show a "Transaction Signed" alert * * @param data The data that is emitted by the SIGN_REQUEST_SUCCESS event */ const showSignSuccessAlert = async (data) => { const output = data.output; openToast({ body: `{{wallet}}\u00A0 successfully signed payload`, timer: SUCCESS_TIMER, state: 'finished', walletInfo: data.walletInfo, actions: [ { text: `Signature: ${shortenString(output.signature)}`, actionText: 'Copy to clipboard', actionCallback: async () => { navigator.clipboard.writeText(output.signature).then(() => { logger.log('showSignSuccessAlert', 'Copying to clipboard was successful!'); }, (err) => { logger.error('showSignSuccessAlert', 'Could not copy text to clipboard: ', err); }); closeToast(); } } ] }); }; /** * Show a "Transaction Signed" alert * * @param data The data that is emitted by the ENCRYPT_REQUEST_SUCCESS event */ // TODO: ENCRYPTION // const showEncryptSuccessAlert = async ( // data: BeaconEventType[BeaconEvent.ENCRYPT_REQUEST_SUCCESS] // ): Promise<void> => { // const output = data.output // openToast({ // body: `{{wallet}}\u00A0 successfully ${ // data.output.cryptoOperation === EncryptionOperation.ENCRYPT ? 'encrypted' : 'decrypted' // } payload`, // timer: SUCCESS_TIMER, // state: 'finished', // walletInfo: data.walletInfo, // actions: [ // { // text: `Payload: <strong>${shortenString(output.payload)}</strong>`, // actionText: 'Copy to clipboard', // actionCallback: async (): Promise<void> => { // navigator.clipboard.writeText(output.payload).then( // () => { // logger.log('showSignSuccessAlert', 'Copying to clipboard was successful!') // }, // (err) => { // logger.error('showSignSuccessAlert', 'Could not copy text to clipboard: ', err) // } // ) // closeToast() // } // } // ] // }) // } const showBlockchainRequestSuccessToast = async (data) => { openToast({ body: `{{wallet}}\u00A0 request successfully executed`, timer: SUCCESS_TIMER, state: 'finished', walletInfo: data.walletInfo }); }; /** * Show a "Broadcasted" alert * * @param data The data that is emitted by the BROADCAST_REQUEST_SUCCESS event */ const showBroadcastSuccessAlert = async (data) => { const { network, output, blockExplorer } = data; openToast({ body: `{{wallet}}\u00A0 successfully injected operation`, timer: SUCCESS_TIMER, state: 'finished', walletInfo: data.walletInfo, actions: [ { text: shortenString(output.transactionHash), isBold: true, actionText: `Open Blockexplorer`, actionLogo: 'external', actionCallback: async () => { const link = await blockExplorer.getTransactionLink(output.transactionHash, network); window.open(link, '_blank', 'noopener'); closeToast(); } } ] }); }; const emptyHandler = () => async () => { // }; /** * The default event handlers */ export const defaultEventCallbacks = { [BeaconEvent.PERMISSION_REQUEST_SENT]: showSentToast, [BeaconEvent.PERMISSION_REQUEST_SUCCESS]: showPermissionSuccessAlert, [BeaconEvent.PERMISSION_REQUEST_ERROR]: showErrorToast, [BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT]: showSentToast, [BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS]: showProofOfEventChallengeSuccessAlert, [BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR]: showErrorToast, [BeaconEvent.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT]: showSentToast, [BeaconEvent.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS]: showSimulatedProofOfEventChallengeSuccessAlert, [BeaconEvent.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR]: showErrorToast, [BeaconEvent.OPERATION_REQUEST_SENT]: showSentToast, [BeaconEvent.OPERATION_REQUEST_SUCCESS]: showOperationSuccessAlert, [BeaconEvent.OPERATION_REQUEST_ERROR]: showErrorToast, [BeaconEvent.SIGN_REQUEST_SENT]: showSentToast, [BeaconEvent.SIGN_REQUEST_SUCCESS]: showSignSuccessAlert, [BeaconEvent.SIGN_REQUEST_ERROR]: showErrorToast, // TODO: ENCRYPTION // [BeaconEvent.ENCRYPT_REQUEST_SENT]: showSentToast, // [BeaconEvent.ENCRYPT_REQUEST_SUCCESS]: showEncryptSuccessAlert, // [BeaconEvent.ENCRYPT_REQUEST_ERROR]: showErrorToast, [BeaconEvent.BROADCAST_REQUEST_SENT]: showSentToast, [BeaconEvent.BROADCAST_REQUEST_SUCCESS]: showBroadcastSuccessAlert, [BeaconEvent.BROADCAST_REQUEST_ERROR]: showErrorToast, [BeaconEvent.ACKNOWLEDGE_RECEIVED]: showAcknowledgedToast, [BeaconEvent.LOCAL_RATE_LIMIT_REACHED]: showRateLimitReached, [BeaconEvent.NO_PERMISSIONS]: showNoPermissionAlert, [BeaconEvent.ACTIVE_ACCOUNT_SET]: emptyHandler(), [BeaconEvent.ACTIVE_TRANSPORT_SET]: emptyHandler(), [BeaconEvent.INVALID_ACTIVE_ACCOUNT_STATE]: showInvalidActiveAccountState, [BeaconEvent.GENERIC_ERROR]: showGenericErrorAlert, [BeaconEvent.INVALID_ACCOUNT_DEACTIVATED]: showInvalidAccountDeactivated, [BeaconEvent.SHOW_PREPARE]: showPrepare, [BeaconEvent.HIDE_UI]: hideUI, [BeaconEvent.PAIR_INIT]: showPairAlert, [BeaconEvent.PAIR_SUCCESS]: showExtensionConnectedAlert, [BeaconEvent.OPEN_BUG_REPORT]: showBugReportForm, [BeaconEvent.RELAYER_ERROR]: showRelayerErrorAlert, [BeaconEvent.CHANNEL_CLOSED]: showChannelClosedAlert, [BeaconEvent.INTERNAL_ERROR]: showInternalErrorAlert, [BeaconEvent.BLOCKCHAIN_REQUEST_SUCCESS]: showBlockchainRequestSuccessToast, [BeaconEvent.UNKNOWN]: emptyHandler() }; /** * @internalapi * * Handles beacon events */ export class BeaconEventHandler { callbackMap = { [BeaconEvent.PERMISSION_REQUEST_SENT]: [defaultEventCallbacks.PERMISSION_REQUEST_SENT], [BeaconEvent.PERMISSION_REQUEST_SUCCESS]: [defaultEventCallbacks.PERMISSION_REQUEST_SUCCESS], [BeaconEvent.PERMISSION_REQUEST_ERROR]: [defaultEventCallbacks.PERMISSION_REQUEST_ERROR], [BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT]: [ defaultEventCallbacks.PERMISSION_REQUEST_SENT ], [BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS]: [ defaultEventCallbacks.PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS ], [BeaconEvent.PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR]: [ defaultEventCallbacks.PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR ], [BeaconEvent.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT]: [ defaultEventCallbacks.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SENT ], [BeaconEvent.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS]: [ defaultEventCallbacks.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_SUCCESS ], [BeaconEvent.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR]: [ defaultEventCallbacks.SIMULATED_PROOF_OF_EVENT_CHALLENGE_REQUEST_ERROR ], [BeaconEvent.OPERATION_REQUEST_SENT]: [defaultEventCallbacks.OPERATION_REQUEST_SENT], [BeaconEvent.OPERATION_REQUEST_SUCCESS]: [defaultEventCallbacks.OPERATION_REQUEST_SUCCESS], [BeaconEvent.OPERATION_REQUEST_ERROR]: [defaultEventCallbacks.OPERATION_REQUEST_ERROR], [BeaconEvent.SIGN_REQUEST_SENT]: [defaultEventCallbacks.SIGN_REQUEST_SENT], [BeaconEvent.SIGN_REQUEST_SUCCESS]: [defaultEventCallbacks.SIGN_REQUEST_SUCCESS], [BeaconEvent.SIGN_REQUEST_ERROR]: [defaultEventCallbacks.SIGN_REQUEST_ERROR], // TODO: ENCRYPTION // [BeaconEvent.ENCRYPT_REQUEST_SENT]: [defaultEventCallbacks.ENCRYPT_REQUEST_SENT], // [BeaconEvent.ENCRYPT_REQUEST_SUCCESS]: [defaultEventCallbacks.ENCRYPT_REQUEST_SUCCESS], // [BeaconEvent.ENCRYPT_REQUEST_ERROR]: [defaultEventCallbacks.ENCRYPT_REQUEST_ERROR], [BeaconEvent.BROADCAST_REQUEST_SENT]: [defaultEventCallbacks.BROADCAST_REQUEST_SENT], [BeaconEvent.BROADCAST_REQUEST_SUCCESS]: [defaultEventCallbacks.BROADCAST_REQUEST_SUCCESS], [BeaconEvent.BROADCAST_REQUEST_ERROR]: [defaultEventCallbacks.BROADCAST_REQUEST_ERROR], [BeaconEvent.BLOCKCHAIN_REQUEST_SUCCESS]: [defaultEventCallbacks.BLOCKCHAIN_REQUEST_SUCCESS], [BeaconEvent.ACKNOWLEDGE_RECEIVED]: [defaultEventCallbacks.ACKNOWLEDGE_RECEIVED], [BeaconEvent.LOCAL_RATE_LIMIT_REACHED]: [defaultEventCallbacks.LOCAL_RATE_LIMIT_REACHED], [BeaconEvent.NO_PERMISSIONS]: [defaultEventCallbacks.NO_PERMISSIONS], [BeaconEvent.ACTIVE_ACCOUNT_SET]: [defaultEventCallbacks.ACTIVE_ACCOUNT_SET], [BeaconEvent.ACTIVE_TRANSPORT_SET]: [defaultEventCallbacks.ACTIVE_TRANSPORT_SET], [BeaconEvent.INVALID_ACTIVE_ACCOUNT_STATE]: [ defaultEventCallbacks.INVALID_ACTIVE_ACCOUNT_STATE ], [BeaconEvent.GENERIC_ERROR]: [showGenericErrorAlert], [BeaconEvent.INVALID_ACCOUNT_DEACTIVATED]: [defaultEventCallbacks.INVALID_ACCOUNT_DEACTIVATED], [BeaconEvent.SHOW_PREPARE]: [defaultEventCallbacks.SHOW_PREPARE], [BeaconEvent.HIDE_UI]: [defaultEventCallbacks.HIDE_UI], [BeaconEvent.PAIR_INIT]: [defaultEventCallbacks.PAIR_INIT], [BeaconEvent.PAIR_SUCCESS]: [defaultEventCallbacks.PAIR_SUCCESS], [BeaconEvent.OPEN_BUG_REPORT]: [showBugReportForm], [BeaconEvent.CHANNEL_CLOSED]: [defaultEventCallbacks.CHANNEL_CLOSED], [BeaconEvent.INTERNAL_ERROR]: [defaultEventCallbacks.INTERNAL_ERROR], [BeaconEvent.RELAYER_ERROR]: [defaultEventCallbacks.RELAYER_ERROR], [BeaconEvent.UNKNOWN]: [defaultEventCallbacks.UNKNOWN] }; constructor(eventsToOverride = {}, overrideAll) { if (overrideAll) { this.setAllHandlers(); } this.overrideDefaults(eventsToOverride); } /** * A method to subscribe to a specific beacon event and register a callback * * @param event The event being emitted * @param eventCallback The callback that will be invoked */ async on(event, eventCallback) { const listeners = this.callbackMap[event] || []; listeners.push(eventCallback); this.callbackMap[event] = listeners; } /** * Emit a beacon event * * @param event The event being emitted * @param data The data to be emit */ async emit(event, data, eventCallback) { const listeners = this.callbackMap[event]; if (listeners && listeners.length > 0) { listeners.forEach(async (listener) => { try { await listener(data, eventCallback); } catch (listenerError) { logger.error(`error handling event ${event}`, listenerError); } }); } } /** * Override beacon event default callbacks. This can be used to disable default alert/toast behaviour * * @param eventsToOverride An object with the events to override */ overrideDefaults(eventsToOverride) { Object.keys(eventsToOverride).forEach((untypedEvent) => { const eventType = untypedEvent; const event = eventsToOverride[eventType]; if (event) { this.callbackMap[eventType] = [event.handler]; } }); } /** * Set all event callbacks to a specific handler. */ setAllHandlers(handler) { Object.keys(this.callbackMap).forEach((untypedEvent) => { const eventType = untypedEvent; this.callbackMap[eventType] = []; if (handler) { this.callbackMap[eventType].push(handler); } else { this.callbackMap[eventType].push((...data) => { logger.log(untypedEvent, ...data); }); } }); } } //# sourceMappingURL=events.js.map