From df288f522a733e049df1d227e566a6d4bde43820 Mon Sep 17 00:00:00 2001
From: abtestingalpha <104046418+abtestingalpha@users.noreply.github.com>
Date: Mon, 15 Jul 2024 10:23:15 -0400
Subject: [PATCH] feat(synapse-interface): Dest address screener middleware
(#2870)
* Adds destination address middleware screening check
* Changes screenAddress to async/await
* Moves bl check into screenAddress
---
.../DestinationAddressInput.tsx | 2 +
.../contexts/SegmentAnalyticsProvider.tsx | 11 ++--
.../contexts/UserProvider.tsx | 12 ++---
.../pages/state-managed-bridge/index.tsx | 9 ++++
.../store/destinationAddressMiddleware.ts | 15 ++++++
packages/synapse-interface/store/store.ts | 3 +-
.../synapse-interface/utils/screenAddress.ts | 53 ++++++++++++-------
7 files changed, 73 insertions(+), 32 deletions(-)
create mode 100644 packages/synapse-interface/store/destinationAddressMiddleware.ts
diff --git a/packages/synapse-interface/components/StateManagedBridge/DestinationAddressInput.tsx b/packages/synapse-interface/components/StateManagedBridge/DestinationAddressInput.tsx
index 345a76dc4e..a88965cf7a 100644
--- a/packages/synapse-interface/components/StateManagedBridge/DestinationAddressInput.tsx
+++ b/packages/synapse-interface/components/StateManagedBridge/DestinationAddressInput.tsx
@@ -220,6 +220,8 @@ export const DestinationAddressInput = ({
const adjustInputSize = () => {
const addressInput: HTMLElement = document.getElementById('address-input')
+ if (!addressInput) return
+
if (isInputFocused || isInputInvalid) {
addressInput.style.width = '12rem'
} else if (inputValue.length > 0) {
diff --git a/packages/synapse-interface/contexts/SegmentAnalyticsProvider.tsx b/packages/synapse-interface/contexts/SegmentAnalyticsProvider.tsx
index ff069ef3f9..34977c8605 100644
--- a/packages/synapse-interface/contexts/SegmentAnalyticsProvider.tsx
+++ b/packages/synapse-interface/contexts/SegmentAnalyticsProvider.tsx
@@ -2,7 +2,6 @@ import { AnalyticsBrowser } from '@segment/analytics-next'
import { getAccount } from '@wagmi/core'
import { createContext, useContext } from 'react'
-import { isBlacklisted } from '@/utils/isBlacklisted'
import { screenAddress } from '@/utils/screenAddress'
import { wagmiConfig } from '@/wagmiConfig'
@@ -24,12 +23,10 @@ export const segmentAnalyticsEvent = (
const { address } = getAccount(wagmiConfig)
- if (isBlacklisted(address)) {
- document.body = document.createElement('body')
- } else {
- if (screen) {
- screenAddress(address)
- }
+ if (screen && address) {
+ screenAddress(address).catch((error) => {
+ console.error('Error screening address:', error)
+ })
}
const enrichedEventData = {
diff --git a/packages/synapse-interface/contexts/UserProvider.tsx b/packages/synapse-interface/contexts/UserProvider.tsx
index 769b7b0e02..6476d8e19e 100644
--- a/packages/synapse-interface/contexts/UserProvider.tsx
+++ b/packages/synapse-interface/contexts/UserProvider.tsx
@@ -8,7 +8,6 @@ import { setSwapChainId } from '@/slices/swap/reducer'
import { fetchAndStorePortfolioBalances } from '@/slices/portfolio/hooks'
import { useAppDispatch } from '@/store/hooks'
import { resetPortfolioState } from '@/slices/portfolio/actions'
-import { isBlacklisted } from '@/utils/isBlacklisted'
import { screenAddress } from '@/utils/screenAddress'
const WalletStatusContext = createContext(undefined)
@@ -85,11 +84,12 @@ export const UserProvider = ({ children }) => {
useEffect(() => {
if (address) {
- if (!isBlacklisted(address)) {
- screenAddress(address)
- } else {
- document.body = document.createElement('body')
- }
+ ;(async () => {
+ const isRisky = await screenAddress(address)
+ if (isRisky) {
+ return
+ }
+ })()
}
}, [address])
diff --git a/packages/synapse-interface/pages/state-managed-bridge/index.tsx b/packages/synapse-interface/pages/state-managed-bridge/index.tsx
index 46befb6311..99183e76da 100644
--- a/packages/synapse-interface/pages/state-managed-bridge/index.tsx
+++ b/packages/synapse-interface/pages/state-managed-bridge/index.tsx
@@ -73,6 +73,7 @@ import {
} from '@/components/Maintenance/Maintenance'
import { wagmiConfig } from '@/wagmiConfig'
import { useStaleQuoteUpdater } from '@/utils/hooks/useStaleQuoteUpdater'
+import { screenAddress } from '@/utils/screenAddress'
const StateManagedBridge = () => {
const { address } = useAccount()
@@ -349,6 +350,14 @@ const StateManagedBridge = () => {
const executeBridge = async () => {
let pendingPopup: any
+
+ if (destinationAddress) {
+ const isRisky = await screenAddress(destinationAddress)
+ if (isRisky) {
+ return
+ }
+ }
+
segmentAnalyticsEvent(
`[Bridge] initiates bridge`,
{
diff --git a/packages/synapse-interface/store/destinationAddressMiddleware.ts b/packages/synapse-interface/store/destinationAddressMiddleware.ts
new file mode 100644
index 0000000000..0b412f8b25
--- /dev/null
+++ b/packages/synapse-interface/store/destinationAddressMiddleware.ts
@@ -0,0 +1,15 @@
+import { Middleware } from '@reduxjs/toolkit'
+
+import { screenAddress } from '@/utils/screenAddress'
+import { setDestinationAddress } from '@/slices/bridge/reducer'
+
+export const destinationAddressMiddleware: Middleware =
+ (_store) => (next) => async (action) => {
+ if (setDestinationAddress.match(action) && action.payload !== null) {
+ const isRisky = await screenAddress(action.payload)
+ if (isRisky) {
+ return
+ }
+ }
+ return next(action)
+ }
diff --git a/packages/synapse-interface/store/store.ts b/packages/synapse-interface/store/store.ts
index 33606768e3..28a84a9ccc 100644
--- a/packages/synapse-interface/store/store.ts
+++ b/packages/synapse-interface/store/store.ts
@@ -6,6 +6,7 @@ import { api } from '@/slices/api/slice'
import { segmentAnalyticsEvent } from '@/contexts/SegmentAnalyticsProvider'
import { storageKey, persistConfig, persistedReducer } from './reducer'
import { resetReduxCache } from '@/slices/application/actions'
+import { destinationAddressMiddleware } from '@/store/destinationAddressMiddleware'
const checkVersionAndResetCache = (): boolean => {
if (typeof window !== 'undefined') {
@@ -27,7 +28,7 @@ export const store = configureStore({
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
- }).concat(api.middleware),
+ }).concat(api.middleware, destinationAddressMiddleware),
})
if (checkVersionAndResetCache()) {
diff --git a/packages/synapse-interface/utils/screenAddress.ts b/packages/synapse-interface/utils/screenAddress.ts
index c849571fd6..571d574ca5 100644
--- a/packages/synapse-interface/utils/screenAddress.ts
+++ b/packages/synapse-interface/utils/screenAddress.ts
@@ -1,25 +1,42 @@
import { Address } from 'viem'
-import { GlobalEventEmitter } from '@/utils/globalEventEmitter'
import { DISCORD_URL } from '@/constants/urls'
+import { GlobalEventEmitter } from '@/utils/globalEventEmitter'
+import { isBlacklisted } from '@/utils/isBlacklisted'
+
+const createRiskDetectedEvent = (address: Address | string) => {
+ return new CustomEvent('riskDetected', {
+ detail: {
+ message: `This address ${address} has been flagged for being associated with illicit activities. If you think this is a mistake, please contact support.`,
+ },
+ })
+}
-export const screenAddress = (address: Address | string) => {
+export const screenAddress = async (
+ address: Address | string
+): Promise => {
const url = `https://screener.omnirpc.io/fe/address/${address}`
- fetch(url, {
- method: 'GET',
- })
- .then((response) => response.json())
- .then(({ risk }) => {
- if (risk) {
- const event = new CustomEvent('riskDetected', {
- detail: {
- message: `This address has been flagged for being associated with illicit activities. If you think this is a mistake, please contact support.`,
- },
- })
-
- GlobalEventEmitter.dispatchEvent(event)
- }
- })
- .catch((error) => console.error('Error:', error))
+ if (isBlacklisted(address)) {
+ const event = createRiskDetectedEvent(address)
+
+ GlobalEventEmitter.dispatchEvent(event)
+ return true
+ }
+
+ try {
+ const response = await fetch(url, { method: 'GET' })
+ const { risk } = await response.json()
+
+ if (risk) {
+ const event = createRiskDetectedEvent(address)
+
+ GlobalEventEmitter.dispatchEvent(event)
+ return true
+ }
+ return false
+ } catch (error) {
+ console.error('Error:', error)
+ return false
+ }
}