Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/plugins/Claim/src/SiteAdaptor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const site: Plugin.SiteAdaptor.Definition = {
iconFilterColor: 'rgba(240, 51, 51, 0.3)',
category: 'dapp',
entryWalletConnectedNotRequired: true,
hiddenInList: true,
},
],
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import { Icons } from '@masknet/icons'
import type { Plugin } from '@masknet/plugin-infra'
import { resolveTCOLink } from '@masknet/plugin-infra/dom/context'
import { makeStyles, ShadowRootPopper } from '@masknet/theme'
import { Link } from '@mui/material'
import { useQuery } from '@tanstack/react-query'
import { memo } from 'react'
import { PluginScamRPC } from '../../messages.js'
import { usePopoverControl } from './usePopoverControl.js'
import { WarningCard } from './WarningCard.js'
import { SecurityProvider } from '../../constants.js'
import { GoPlusLabs } from '@masknet/web3-providers'
import { extractAddresses } from '../../utils.js'
import { useDetectAddress } from '../hooks/useDetectAddress.js'
import { AddressTag } from './TextModifier.js'
import { useCheckLink } from '../hooks/useCheckLink.js'

const useStyles = makeStyles()((theme) => ({
link: {
Expand All @@ -37,40 +32,12 @@ const useStyles = makeStyles()((theme) => ({
},
}))

function isTCO(url: string | null) {
if (!url) return false
return url.startsWith('https://t.co/')
}

export const LinkModifier = memo<PropsOf<Plugin.SiteAdaptor.Definition['LinkModifier']>>(function LinkModifier({
fallback,
...props
}) {
const { classes } = useStyles()
const { data } = useQuery({
queryKey: ['scam-warning', 'check-link', props.href, props.children],
queryFn: async () => {
const resolvedLink = isTCO(props.href) ? await resolveTCOLink(props.href) : props.href
if (!resolvedLink) return { isScam: false }
const result = await GoPlusLabs.checkIsPhishingSite(resolvedLink)
if (result)
return {
isScam: result,
provider: SecurityProvider.GoPlus,
resolvedLink,
}
const isEllipsis = props.children.endsWith('…')
// We assume that the link contains only one address
const address = isEllipsis ? extractAddresses(resolvedLink, true)[0] : undefined

return {
isScam: await PluginScamRPC.checkUrl(resolvedLink),
provider: SecurityProvider.ScamSniffer,
resolvedLink,
address,
}
},
})
const { data } = useCheckLink(props.href, props.children)
const { data: detected } = useDetectAddress(data?.address, data?.isScam === false)
const { open, anchorEl, iconRef, onMouseEnter, onMouseLeave } = usePopoverControl()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function useCheckLink(link: string, text: string) {
}
const isEllipsis = text.endsWith('…')
// We assume that the link contains only one address
const address = isEllipsis ? extractAddresses(resolvedLink)[0] : undefined
const address = isEllipsis ? extractAddresses(resolvedLink, true)[0] : undefined

return {
isScam: await PluginScamRPC.checkUrl(resolvedLink),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function useDetectAddress(address: string | null | undefined, enabled = t
}
if (isTronAddress(address))
return {
isScam: GoPlusLabs.checkIfAddressIsScam('tron', address),
isScam: await GoPlusLabs.checkIfAddressIsScam('tron', address),
provider: SecurityProvider.GoPlus,
}
return { isScam: false, provider: null }
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/ScamWarning/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { EVM_ADDRESS, SOLANA_ADDRESS } from '@masknet/plugin-scam-warning'
import { EXIST_EVM_ADDRESS, EXIST_SOLANA_ADDRESS, EXIST_TRON_ADDRESS, TRON_ADDRESS } from './constants.js'

export function isTronAddress(address: string) {
return !!address.match(address)
return !!address.match(TRON_ADDRESS)
}

export function extractAddresses(text: string, exist = false) {
Expand Down
17 changes: 8 additions & 9 deletions packages/web3-shared/solana/src/helpers/address.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import bs58 from 'bs58'
import { memoize } from 'lodash-es'
import * as Web3 from /* webpackDefer: true */ '@solana/web3.js'
import { getEnumAsArray } from '@masknet/kit'
import { isSameAddress } from '@masknet/web3-shared-base'
import { NetworkPluginID, createLookupTableResolver } from '@masknet/shared-base'
import { ChainId, NetworkType, ProviderType, SchemaType } from '../types.js'
import { isSameAddress } from '@masknet/web3-shared-base'
import * as Web3 from /* webpackDefer: true */ '@solana/web3.js'
import bs58 from 'bs58'
import { memoize } from 'lodash-es'
import { getTokenConstant } from '../constants/constants.js'
import { ZERO_ADDRESS } from '../constants/primitives.js'
import { isTronAddress } from './isTronAddress.js'
import { ChainId, NetworkType, ProviderType, SchemaType } from '../types.js'

export function encodePublicKey(key: Web3.PublicKey) {
return key.toBase58()
Expand All @@ -20,7 +19,7 @@ export function decodeAddress(initData: string | Buffer | Uint8Array) {
}

export function formatAddress(address: string, size = 0) {
if (!isValidAddress(address, false)) return address
if (!isValidAddress(address)) return address
if (size === 0 || size >= 22) return address
return `${address.slice(0, Math.max(0, size))}...${address.slice(-size)}`
}
Expand All @@ -42,12 +41,12 @@ export function formatTokenId(tokenId = '', size_ = 4) {
return `#${head}...${tail}`
}

export function isValidAddress(address?: string, strict?: boolean): address is string {
export function isValidAddress(address?: string): address is string {
const length = address?.length
if (!length || length < 32 || length > 44) return false
try {
const buffer = bs58.decode(address)
return strict === false ? true : Web3.PublicKey.isOnCurve(buffer) && !isTronAddress(address)
return buffer.byteLength === 32
} catch {
return false
}
Expand Down
19 changes: 9 additions & 10 deletions packages/web3-shared/solana/tests/address.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { describe, test, expect } from 'vitest'
import { describe, expect, test } from 'vitest'
import { isValidAddress } from '../src/helpers/address.js'

describe('Solana address utilities', () => {
test.each<[address: string, strict: boolean | undefined, result: boolean]>([
['EZXbaV3', undefined, false],
['EZXbaV3Lntre7DdvRyxmQoEk8cpMvfY8v2eC3qP9ntZUEZXbaV3Lntre7DdvRyxmQoEk8cpMvfY8v2eC3qP9ntZU', undefined, false],
['EZXbaV3Lntre7DdvRyxmQoEk8cpMvfY8v2eC3qP9ntZU', undefined, true],
['5afERTeXF8diWPy5P8AP2EkmcCFGkV9Z7LeSo9fpjcuf', undefined, false],
['5afERTeXF8diWPy5P8AP2EkmcCFGkV9Z7LeSo9fpjcuf', false, true],
['TPpADS2avP3rKgUcjZgnQNw5oMhjW2J6Za', true, false],
])('isValidAddress(%s)', (address, strict, result) => {
expect(isValidAddress(address, strict)).toBe(result)
test.each<[address: string, result: boolean]>([
['EZXbaV3', false],
['EZXbaV3Lntre7DdvRyxmQoEk8cpMvfY8v2eC3qP9ntZUEZXbaV3Lntre7DdvRyxmQoEk8cpMvfY8v2eC3qP9ntZU', false],
['EZXbaV3Lntre7DdvRyxmQoEk8cpMvfY8v2eC3qP9ntZU', true],
['5afERTeXF8diWPy5P8AP2EkmcCFGkV9Z7LeSo9fpjcuf', true],
['TPpADS2avP3rKgUcjZgnQNw5oMhjW2J6Za', false],
])('isValidAddress(%s)', (address, result) => {
expect(isValidAddress(address)).toBe(result)
})
})