Skip to content

Commit f8c268c

Browse files
guanbinruiUncleBillzhouhanseng
authored
[Release] Hotfix 2.20.1 => 2.20.2 (patch) (#9630)
* chore: bump version to 2.20.2 * fix: mf-4191 mf-4192 update firefly(MaskX) sources allowed list (#9631) mf-4191 mf-4192 * fix(trending): price change default 24h (#9636) * fix: avatar realm render conflict (#9637) * fix: avatar realm render conflict * fix: avatar realm render conflict * fix: mf-4197 verify twiter handle by address (#9633) * fix: mf-4185 add more icons for address (#9638) --------- Co-authored-by: UncleBill <[email protected]> Co-authored-by: Hancheng Zhou <[email protected]>
1 parent 6e13011 commit f8c268c

File tree

14 files changed

+111
-122
lines changed

14 files changed

+111
-122
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"yarn": ">=999.0.0",
99
"npm": ">=999.0.0"
1010
},
11-
"version": "2.20.1",
11+
"version": "2.20.2",
1212
"private": true,
1313
"license": "AGPL-3.0-or-later",
1414
"scripts": {
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,37 @@
11
import type { FC } from 'react'
2-
import type { IconButtonProps } from '@mui/material'
3-
import type { SocialIdentity } from '@masknet/shared-base'
2+
import { type IconButtonProps, Box } from '@mui/material'
3+
import { NetworkPluginID, type SocialAccount, type SocialIdentity } from '@masknet/shared-base'
44
import { useCollectionByTwitterHandler } from '../../../plugins/Trader/trending/useTrending.js'
55
import { CollectionProjectAvatarBadge } from './CollectionProjectAvatarBadge.js'
66
import { ProfileAvatarBadge } from './ProfileAvatarBadge.js'
7+
import type { Web3Helper } from '@masknet/web3-helpers'
78

89
interface Props extends IconButtonProps {
910
userId: string
1011
identity?: SocialIdentity
12+
socialAccounts?: Array<SocialAccount<Web3Helper.ChainIdAll>>
1113
}
12-
export const AvatarBadge: FC<Props> = ({ userId, identity }) => {
14+
export const AvatarBadge: FC<Props> = ({ userId, identity, socialAccounts }) => {
1315
const { value: collectionList } = useCollectionByTwitterHandler(userId)
1416
if (collectionList?.[0]) {
1517
return (
16-
<CollectionProjectAvatarBadge
17-
userId={userId}
18-
address={collectionList?.[0].address ?? ''}
19-
identity={identity}
20-
/>
18+
<Box display="flex" alignItems="top" justifyContent="center">
19+
<div style={{ display: 'flex', alignItems: 'top', justifyContent: 'center' }}>
20+
<CollectionProjectAvatarBadge
21+
userId={userId}
22+
address={collectionList?.[0].address ?? ''}
23+
identity={identity}
24+
/>
25+
</div>
26+
</Box>
2127
)
2228
}
2329

24-
return <ProfileAvatarBadge userId={userId} />
30+
return socialAccounts?.filter((x) => x.pluginID === NetworkPluginID.PLUGIN_EVM).length ? (
31+
<Box display="flex" alignItems="top" justifyContent="center">
32+
<div style={{ display: 'flex', alignItems: 'top', justifyContent: 'center' }}>
33+
<ProfileAvatarBadge userId={userId} />
34+
</div>
35+
</Box>
36+
) : null
2537
}

packages/mask/src/manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Mask Network",
3-
"version": "2.20.1",
3+
"version": "2.20.2",
44
"manifest_version": 2,
55
"permissions": ["storage", "downloads", "webNavigation", "activeTab"],
66
"optional_permissions": ["<all_urls>", "notifications", "clipboardRead"],

packages/mask/src/plugins/ProfileCard/SNSAdaptor/index.tsx

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Trans } from 'react-i18next'
22
import { Icons } from '@masknet/icons'
33
import type { Plugin } from '@masknet/plugin-infra'
4-
import { type EnhanceableSite, NetworkPluginID } from '@masknet/shared-base'
5-
import { Box } from '@mui/material'
4+
import { type EnhanceableSite } from '@masknet/shared-base'
65
import { base } from '../base.js'
76
import { PLUGIN_ID, SNS_RSS3_FIELD_KEY_MAP } from '../constants.js'
87
import { setupContext } from '../context.js'
@@ -41,23 +40,22 @@ const sns: Plugin.SNSAdaptor.Definition = {
4140
label: 'Web3 Profile Card',
4241
priority: 99999,
4342
UI: {
44-
Decorator({ identity }) {
43+
Decorator: function ProfileAvatarRealmDecorator({ identity, socialAccounts }) {
4544
if (!identity?.identifier?.userId) return null
4645
const rss3Key = SNS_RSS3_FIELD_KEY_MAP[identity.identifier.network as EnhanceableSite]
4746
if (!rss3Key) return null
4847
return (
49-
<Box display="flex" alignItems="top" justifyContent="center">
50-
<div style={{ display: 'flex', alignItems: 'top', justifyContent: 'center' }}>
51-
<AvatarBadge userId={identity.identifier.userId} identity={identity} />
52-
</div>
53-
</Box>
48+
<AvatarBadge
49+
userId={identity.identifier.userId}
50+
identity={identity}
51+
socialAccounts={socialAccounts}
52+
/>
5453
)
5554
},
5655
},
5756
Utils: {
58-
shouldDisplay(_, socialAccounts) {
59-
if (!socialAccounts?.length) return false
60-
return !!socialAccounts.filter((x) => x.pluginID === NetworkPluginID.PLUGIN_EVM).length
57+
shouldDisplay() {
58+
return true
6159
},
6260
},
6361
},

packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx

-31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import { Trans } from 'react-i18next'
2-
import { Box } from '@mui/material'
3-
import { useIsMinimalMode } from '@masknet/plugin-infra/content-script'
42
import type { Plugin } from '@masknet/plugin-infra'
53
import { base } from '../base.js'
64
import { TrendingView } from './trending/TrendingView.js'
@@ -15,8 +13,6 @@ import { CrossIsolationMessages, NetworkPluginID, PluginID } from '@masknet/shar
1513
import type { ChainId } from '@masknet/web3-shared-evm'
1614
import { SearchResultType } from '@masknet/web3-shared-base'
1715
import type { Web3Helper } from '@masknet/web3-helpers'
18-
import { CollectionProjectAvatarBadge } from '../../../components/shared/AvatarBadge/CollectionProjectAvatarBadge.js'
19-
import { useCollectionByTwitterHandler } from '../../../plugins/Trader/trending/useTrending.js'
2016

2117
function openDialog() {
2218
return CrossIsolationMessages.events.swapDialogEvent.sendToLocal({
@@ -116,33 +112,6 @@ const sns: Plugin.SNSAdaptor.Definition<ChainId> = {
116112
backgroundGradient:
117113
'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(254, 156, 0, 0.2) 100%), #FFFFFF;',
118114
},
119-
AvatarRealm: {
120-
ID: `${base.ID}_nft_project_card`,
121-
label: 'Web3 Profile Card',
122-
priority: 99999,
123-
UI: {
124-
Decorator({ userId, identity }) {
125-
const { value: collectionList } = useCollectionByTwitterHandler(userId)
126-
const isMinimalMode = useIsMinimalMode(PluginID.Web3ProfileCard)
127-
if (!userId || !collectionList?.[0] || isMinimalMode) return null
128-
129-
return (
130-
<Box display="flex" alignItems="top" justifyContent="center">
131-
<CollectionProjectAvatarBadge
132-
userId={userId}
133-
address={collectionList?.[0].address ?? ''}
134-
identity={identity}
135-
/>
136-
</Box>
137-
)
138-
},
139-
},
140-
Utils: {
141-
shouldDisplay(_, socialAccounts) {
142-
return !socialAccounts?.length
143-
},
144-
},
145-
},
146115
}
147116

148117
export default sns

packages/mask/src/plugins/Trader/SNSAdaptor/trending/TrendingViewDeck.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ export function TrendingViewDeck(props: TrendingViewDeckProps) {
358358
{isNFT ? null : (
359359
<PriceChanged
360360
amount={
361-
market?.price_change_percentage_1h_in_currency ??
361+
market?.price_change_percentage_24h_in_currency ??
362362
market?.price_change_24h ??
363363
0
364364
}

packages/plugins/EVM/src/state/IdentityService.ts

+31-32
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ import {
1212
type SocialAddress,
1313
type SocialIdentity,
1414
} from '@masknet/shared-base'
15-
import { ENS, Lens, MaskX, NextIDProof, NextIDStorageProvider, RSS3, SpaceID, Twitter } from '@masknet/web3-providers'
15+
import {
16+
ENS,
17+
Firefly,
18+
Lens,
19+
MaskX,
20+
NextIDProof,
21+
NextIDStorageProvider,
22+
RSS3,
23+
SpaceID,
24+
Twitter,
25+
} from '@masknet/web3-providers'
1626
import { captureAsyncTransaction } from '@masknet/web3-providers/helpers'
1727
import { MaskX_BaseAPI } from '@masknet/web3-providers/types'
1828
import { ChainId, isValidAddress, isZeroAddress } from '@masknet/web3-shared-evm'
@@ -82,10 +92,13 @@ const resolveMaskXAddressType = createLookupTableResolver<MaskX_BaseAPI.SourceTy
8292
{
8393
[MaskX_BaseAPI.SourceType.CyberConnect]: SocialAddressType.CyberConnect,
8494
[MaskX_BaseAPI.SourceType.Firefly]: SocialAddressType.Firefly,
95+
[MaskX_BaseAPI.SourceType.HandWriting]: SocialAddressType.Firefly,
8596
[MaskX_BaseAPI.SourceType.Leaderboard]: SocialAddressType.Leaderboard,
8697
[MaskX_BaseAPI.SourceType.OpenSea]: SocialAddressType.OpenSea,
8798
[MaskX_BaseAPI.SourceType.Sybil]: SocialAddressType.Sybil,
99+
[MaskX_BaseAPI.SourceType.Uniswap]: SocialAddressType.Sybil,
88100
[MaskX_BaseAPI.SourceType.RSS3]: SocialAddressType.RSS3,
101+
[MaskX_BaseAPI.SourceType.TwitterHexagon]: SocialAddressType.TwitterBlue,
89102
},
90103
(x) => {
91104
throw new Error(`Unknown source type: ${x}`)
@@ -242,16 +255,8 @@ export class IdentityService extends IdentityServiceState<ChainId> {
242255
if (!userId) return
243256

244257
const response = await MaskX.getIdentitiesExact(userId, MaskX_BaseAPI.PlatformType.Twitter)
245-
const sourceTypes = [
246-
MaskX_BaseAPI.SourceType.CyberConnect,
247-
MaskX_BaseAPI.SourceType.Firefly,
248-
MaskX_BaseAPI.SourceType.Leaderboard,
249-
MaskX_BaseAPI.SourceType.OpenSea,
250-
MaskX_BaseAPI.SourceType.Sybil,
251-
MaskX_BaseAPI.SourceType.RSS3,
252-
]
253258
const results = response.records.filter((x) => {
254-
if (!isValidAddress(x.web3_addr) || !sourceTypes.includes(x.source)) return false
259+
if (!isValidAddress(x.web3_addr) || !x.is_verified) return false
255260

256261
try {
257262
// detect if a valid data source
@@ -267,13 +272,9 @@ export class IdentityService extends IdentityServiceState<ChainId> {
267272
try {
268273
const name = await ENS.reverse(y.web3_addr)
269274

270-
return this.createSocialAddress(
271-
resolveMaskXAddressType(y.source),
272-
y.web3_addr,
273-
name ?? y.sns_handle,
274-
)
275+
return this.createSocialAddress(resolveMaskXAddressType(y.source), y.web3_addr, name)
275276
} catch {
276-
return this.createSocialAddress(resolveMaskXAddressType(y.source), y.web3_addr, y.sns_handle)
277+
return this.createSocialAddress(resolveMaskXAddressType(y.source), y.web3_addr)
277278
}
278279
}),
279280
)
@@ -282,6 +283,7 @@ export class IdentityService extends IdentityServiceState<ChainId> {
282283

283284
override async getFromRemote(identity: SocialIdentity, includes?: SocialAddressType[]) {
284285
const socialAddressFromMaskX = this.getSocialAddressesFromMaskX(identity)
286+
const socialAddressFromNextID = this.getSocialAddressesFromNextID(identity)
285287
const allSettled = await Promise.allSettled([
286288
captureAsyncTransaction('getSocialAddressFromBio', this.getSocialAddressFromBio(identity)),
287289
captureAsyncTransaction('getSocialAddressFromENS', this.getSocialAddressFromENS(identity)),
@@ -292,28 +294,25 @@ export class IdentityService extends IdentityServiceState<ChainId> {
292294
),
293295
captureAsyncTransaction('getSocialAddressFromCrossbell', this.getSocialAddressFromCrossbell(identity)),
294296
captureAsyncTransaction('getSocialAddressFromTwitterBlue', this.getSocialAddressFromTwitterBlue(identity)),
295-
captureAsyncTransaction('getSocialAddressesFromNextID', this.getSocialAddressesFromNextID(identity)),
297+
captureAsyncTransaction('getSocialAddressesFromNextID', socialAddressFromNextID),
296298
captureAsyncTransaction('getSocialAddressesFromMaskX', socialAddressFromMaskX),
297299
captureAsyncTransaction('getSocialAddressFromLens', this.getSocialAddressFromLens(identity)),
298300
])
299301
const identities_ = compact(allSettled.flatMap((x) => (x.status === 'fulfilled' ? x.value : [])))
300302

301303
const identities = uniqBy(identities_, (x) => [x.type, x.label, x.address.toLowerCase()].join('_'))
302-
const [identitiesFromNextID, trustedAccounts] = await Promise.all([
303-
this.getSocialAddressesFromNextID(identity),
304-
socialAddressFromMaskX,
305-
])
306-
const trustedAddresses = trustedAccounts?.map((x) => x.address.toLowerCase()) ?? []
307-
const identitiesAddressesFromNextID = identitiesFromNextID.map((y) => y.address.toLowerCase())
308-
309-
return uniqBy(
310-
identities
311-
.filter((x) => {
312-
const address = x.address.toLowerCase()
313-
return !identitiesAddressesFromNextID.includes(address) && trustedAddresses.includes(address)
314-
})
315-
.concat(identitiesFromNextID),
316-
(x) => x.address.toLowerCase(),
304+
const identitiesFromNextID = await socialAddressFromNextID
305+
306+
const handle = identity.identifier?.userId
307+
const verifiedResult = await Promise.allSettled(
308+
uniqBy(identities, (x) => x.address.toLowerCase()).map(async (x) => {
309+
const address = x.address.toLowerCase()
310+
const isReliable = await Firefly.verifyTwitterHandlerByAddress(address, handle)
311+
return isReliable ? address : null
312+
}),
317313
)
314+
const trustedAddresses = compact(verifiedResult.map((x) => (x.status === 'fulfilled' ? x.value : null)))
315+
316+
return identities.filter((x) => trustedAddresses.includes(x.address.toLowerCase())).concat(identitiesFromNextID)
318317
}
319318
}

packages/shared/src/UI/components/AccountIcon/index.tsx

+23-9
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,9 @@ export function AccountIcon({ socialAccount, classes: externalClasses }: Account
8585
}
8686
: undefined
8787

88-
const fromTwitter = [
89-
SocialAddressType.Address,
90-
SocialAddressType.ENS,
91-
SocialAddressType.SPACE_ID,
92-
SocialAddressType.RSS3,
93-
SocialAddressType.SOL,
94-
SocialAddressType.TwitterBlue,
95-
SocialAddressType.Lens,
96-
].find((x) => supportedAddressTypes.includes(x))
88+
const fromTwitter = [SocialAddressType.Address, SocialAddressType.ENS, SocialAddressType.TwitterBlue].find((x) =>
89+
supportedAddressTypes.includes(x),
90+
)
9791

9892
return (
9993
<>
@@ -200,6 +194,26 @@ export function AccountIcon({ socialAccount, classes: externalClasses }: Account
200194
/>
201195
</AccountTooltips>
202196
) : null}
197+
198+
{supportedAddressTypes.includes(SocialAddressType.SPACE_ID) ? (
199+
<AccountTooltips type={SocialAddressType.SPACE_ID}>
200+
<Icons.SpaceId
201+
className={cx(classes.actionIcon, classes.icon, classes.roundedIcon)}
202+
size={18}
203+
style={iconStyle}
204+
/>
205+
</AccountTooltips>
206+
) : null}
207+
208+
{supportedAddressTypes.includes(SocialAddressType.Lens) ? (
209+
<AccountTooltips type={SocialAddressType.Lens}>
210+
<Icons.Lens
211+
className={cx(classes.actionIcon, classes.icon, classes.roundedIcon)}
212+
size={18}
213+
style={iconStyle}
214+
/>
215+
</AccountTooltips>
216+
) : null}
203217
</>
204218
)
205219
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export const BASE_URL = 'https://mask-network.firefly.land/v1'
2+
export const TWITTER_HANDLER_VERIFY_URL = 'https://twitter-handler-proxy.r2d2.to'

packages/web3-providers/src/Firefly/index.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import urlcat from 'urlcat'
2-
import { BASE_URL } from './constants.js'
2+
import { BASE_URL, TWITTER_HANDLER_VERIFY_URL } from './constants.js'
33
import { fetchJSON } from '../entry-helpers.js'
44
import type { FireflyBaseAPI } from '../entry-types.js'
55

@@ -14,4 +14,17 @@ export class FireflyAPI implements FireflyBaseAPI.Provider {
1414
if (result.code !== 200) return []
1515
return result.data
1616
}
17+
async verifyTwitterHandlerByAddress(address: string, handler?: string): Promise<boolean> {
18+
if (!handler || !address) return false
19+
const response = await fetchJSON<FireflyBaseAPI.VerifyTwitterResult>(
20+
urlcat(TWITTER_HANDLER_VERIFY_URL, '/v1/relation/handles', {
21+
wallet: address.toLowerCase(),
22+
isVerified: true,
23+
}),
24+
)
25+
26+
if ('error' in response) return false
27+
28+
return response.data.includes(handler) || response.data.filter(Boolean).length === 0
29+
}
1730
}

packages/web3-providers/src/NextID/constants.ts

-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ export const KV_BASE_URL_PROD = 'https://kv-service.next.id'
44
export const PROOF_BASE_URL_DEV = 'https://proof-service.nextnext.id/'
55
export const PROOF_BASE_URL_PROD = 'https://proof-service.next.id/'
66
export const RELATION_SERVICE_URL = 'https://relation-service.next.id/'
7-
export const TWITTER_HANDLER_VERIFY_URL = 'https://twitter-handler-proxy.r2d2.to'

packages/web3-providers/src/NextID/proof.ts

+1-23
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,7 @@ import {
1414
type NextIDEnsRecord,
1515
createBindingProofFromProfileQuery,
1616
} from '@masknet/shared-base'
17-
import {
18-
PROOF_BASE_URL_DEV,
19-
PROOF_BASE_URL_PROD,
20-
RELATION_SERVICE_URL,
21-
TWITTER_HANDLER_VERIFY_URL,
22-
} from './constants.js'
17+
import { PROOF_BASE_URL_DEV, PROOF_BASE_URL_PROD, RELATION_SERVICE_URL } from './constants.js'
2318
import { staleNextIDCached } from './helpers.js'
2419
import PRESET_LENS from './preset-lens.json'
2520
import { fetchJSON } from '../entry-helpers.js'
@@ -424,23 +419,6 @@ export class NextIDProofAPI implements NextIDBaseAPI.Proof {
424419
}
425420
: null
426421
}
427-
428-
async verifyTwitterHandlerByAddress(address: string, handler: string): Promise<boolean> {
429-
const response = await fetchJSON<{
430-
statusCode: number
431-
data?: string[]
432-
error?: string
433-
}>(
434-
urlcat(TWITTER_HANDLER_VERIFY_URL, '/v1/relation/handles', {
435-
wallet: address.toLowerCase(),
436-
isVerified: true,
437-
}),
438-
)
439-
440-
if (response.error || !handler || !address) return false
441-
442-
return response.data?.includes(handler) || response.data?.filter((x) => x).length === 0
443-
}
444422
}
445423

446424
// Group all ens

0 commit comments

Comments
 (0)