From 5472c34fd3ad4328d8de347c65801718ff970d3b Mon Sep 17 00:00:00 2001 From: MK <53529533+magiziz@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:02:54 +0000 Subject: [PATCH] chore: show alert error for forbidden analytics event (#3692) Co-authored-by: tomiir --- .changeset/tricky-spies-reply.md | 23 ++++++++++++++ packages/common/index.ts | 1 + packages/common/src/utils/ConstantsUtil.ts | 3 +- packages/common/src/utils/SafeLocalStorage.ts | 2 +- .../core/src/controllers/EventsController.ts | 29 +++++++++++++++-- .../tests/controllers/ApiController.test.ts | 1 + .../controllers/EventsController.test.ts | 31 +++++++++++++++++-- packages/core/vitest.config.ts | 6 +++- 8 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 .changeset/tricky-spies-reply.md diff --git a/.changeset/tricky-spies-reply.md b/.changeset/tricky-spies-reply.md new file mode 100644 index 0000000000..aa12296974 --- /dev/null +++ b/.changeset/tricky-spies-reply.md @@ -0,0 +1,23 @@ +--- +'@reown/appkit-common': patch +'@reown/appkit-core': patch +'@reown/appkit-adapter-bitcoin': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-cli': patch +'@reown/appkit-experimental': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-siwx': patch +'@reown/appkit-ui': patch +'@reown/appkit-wallet': patch +'@reown/appkit-wallet-button': patch +--- + + Added an alert error if the analytics event fails with a forbidden status. diff --git a/packages/common/index.ts b/packages/common/index.ts index 9d9953dca7..ccb5a328f4 100644 --- a/packages/common/index.ts +++ b/packages/common/index.ts @@ -12,6 +12,7 @@ export { ParseUtil } from './src/utils/ParseUtil.js' export { SafeLocalStorage, SafeLocalStorageKeys, + isSafe, type SafeLocalStorageKey, getSafeConnectorIdKey } from './src/utils/SafeLocalStorage.js' diff --git a/packages/common/src/utils/ConstantsUtil.ts b/packages/common/src/utils/ConstantsUtil.ts index 16e14931df..ca46c73d1f 100644 --- a/packages/common/src/utils/ConstantsUtil.ts +++ b/packages/common/src/utils/ConstantsUtil.ts @@ -51,7 +51,8 @@ export const ConstantsUtil = { '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9' ], HTTP_STATUS_CODES: { - SERVICE_UNAVAILABLE: 503 + SERVICE_UNAVAILABLE: 503, + FORBIDDEN: 403 }, UNSUPPORTED_NETWORK_NAME: 'Unknown Network' } as const diff --git a/packages/common/src/utils/SafeLocalStorage.ts b/packages/common/src/utils/SafeLocalStorage.ts index efa7a8e04d..1b50c328c1 100644 --- a/packages/common/src/utils/SafeLocalStorage.ts +++ b/packages/common/src/utils/SafeLocalStorage.ts @@ -74,6 +74,6 @@ export const SafeLocalStorage = { } } -function isSafe(): boolean { +export function isSafe(): boolean { return typeof window !== 'undefined' && typeof localStorage !== 'undefined' } diff --git a/packages/core/src/controllers/EventsController.ts b/packages/core/src/controllers/EventsController.ts index 927e6c30c9..97a331932e 100644 --- a/packages/core/src/controllers/EventsController.ts +++ b/packages/core/src/controllers/EventsController.ts @@ -1,8 +1,11 @@ import { proxy, subscribe as sub } from 'valtio/vanilla' +import { ConstantsUtil, isSafe } from '@reown/appkit-common' + import { CoreHelperUtil } from '../utils/CoreHelperUtil.js' import { FetchUtil } from '../utils/FetchUtil.js' import type { Event } from '../utils/TypeUtil.js' +import { AlertController } from './AlertController.js' import { OptionsController } from './OptionsController.js' // -- Helpers ------------------------------------------- // @@ -13,12 +16,14 @@ const excluded = ['MODAL_CREATED'] // -- Types --------------------------------------------- // export interface EventsControllerState { timestamp: number + reportedErrors: Record data: Event } // -- State --------------------------------------------- // const state = proxy({ timestamp: Date.now(), + reportedErrors: {}, data: { type: 'track', event: 'MODAL_CREATED' @@ -60,8 +65,28 @@ export const EventsController = { props: payload.data } }) - } catch { - // Catch silently + + state.reportedErrors['FORBIDDEN'] = false + } catch (err) { + const isForbiddenError = + err instanceof Error && + err.cause instanceof Response && + err.cause.status === ConstantsUtil.HTTP_STATUS_CODES.FORBIDDEN && + !state.reportedErrors['FORBIDDEN'] + + if (isForbiddenError) { + AlertController.open( + { + shortMessage: 'Invalid App Configuration', + longMessage: `Origin ${ + isSafe() ? window.origin : 'uknown' + } not found on Allowlist - update configuration on cloud.reown.com` + }, + 'error' + ) + + state.reportedErrors['FORBIDDEN'] = true + } } }, diff --git a/packages/core/tests/controllers/ApiController.test.ts b/packages/core/tests/controllers/ApiController.test.ts index e0790d9a22..de7eefdf03 100644 --- a/packages/core/tests/controllers/ApiController.test.ts +++ b/packages/core/tests/controllers/ApiController.test.ts @@ -76,6 +76,7 @@ const networks = [ // -- Tests -------------------------------------------------------------------- beforeAll(() => { + global.URL.createObjectURL = vi.fn((file: Blob) => `blob:${file}`) ChainController.initialize( [ { diff --git a/packages/core/tests/controllers/EventsController.test.ts b/packages/core/tests/controllers/EventsController.test.ts index bff4edf649..c88a2cb539 100644 --- a/packages/core/tests/controllers/EventsController.test.ts +++ b/packages/core/tests/controllers/EventsController.test.ts @@ -1,6 +1,8 @@ -import { describe, expect, it } from 'vitest' +import { describe, expect, it, vi } from 'vitest' -import { EventsController } from '../../exports/index.js' +import { ConstantsUtil } from '@reown/appkit-common' + +import { AlertController, EventsController, FetchUtil } from '../../exports/index.js' // -- Setup -------------------------------------------------------------------- const event = { type: 'track', event: 'MODAL_CLOSE', properties: { connected: true } } as const @@ -19,4 +21,29 @@ describe('EventsController', () => { EventsController.sendEvent(event) expect(EventsController.state.data).toEqual(event) }) + + it('should trigger an alert error if the analytics event fails with a forbidden status', async () => { + const error = new Error('forbidden') + error.cause = new Response(null, { + status: ConstantsUtil.HTTP_STATUS_CODES.FORBIDDEN + }) + + vi.spyOn(AlertController, 'open') + vi.spyOn(FetchUtil.prototype, 'post').mockRejectedValue(error) + + await EventsController._sendAnalyticsEvent({ + ...EventsController.state, + data: { type: 'track', event: 'MODAL_CLOSE', properties: { connected: true } } + }) + + expect(AlertController.open).toHaveBeenCalledWith( + { + shortMessage: 'Invalid App Configuration', + longMessage: expect.stringContaining('not found on Allowlist') + }, + 'error' + ) + + expect(EventsController.state.reportedErrors['FORBIDDEN']).toBe(true) + }) }) diff --git a/packages/core/vitest.config.ts b/packages/core/vitest.config.ts index 73c4c1171f..63cc63385e 100644 --- a/packages/core/vitest.config.ts +++ b/packages/core/vitest.config.ts @@ -1,3 +1,7 @@ import { defineProject } from 'vitest/config' -export default defineProject({}) +export default defineProject({ + test: { + environment: 'jsdom' + } +})