Skip to content

Commit

Permalink
fix: mf-6638 fetch proposal via box api
Browse files Browse the repository at this point in the history
  • Loading branch information
swkatmask committed Feb 26, 2025
1 parent 6de7442 commit beeb023
Show file tree
Hide file tree
Showing 18 changed files with 554 additions and 185 deletions.
28 changes: 15 additions & 13 deletions packages/plugins/Snapshot/src/SiteAdaptor/InformationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { formatWithCommas } from '@masknet/shared-base'
import { makeStyles } from '@masknet/theme'
import { EVMExplorerResolver } from '@masknet/web3-providers'
import { resolveIPFS_URL, resolveResourceURL } from '@masknet/web3-shared-base'
import { formatEthereumAddress } from '@masknet/web3-shared-evm'
import { Avatar, Box, Link, Typography } from '@mui/material'
import { format as formatDateTime } from 'date-fns'
import { useContext, type PropsWithChildren, type ReactNode } from 'react'
Expand All @@ -14,6 +13,7 @@ import { SNAPSHOT_IPFS } from '../constants.js'
import { SnapshotContext } from '../context.js'
import { useProposal } from './hooks/useProposal.js'
import { SnapshotCard } from './SnapshotCard.js'
import { formatLongHex, formatSpaceId } from './helpers.js'

interface InfoFieldProps extends withClasses<'field'>, PropsWithChildren {
title: ReactNode
Expand Down Expand Up @@ -78,7 +78,7 @@ export function InformationCard() {
const proposal = useProposal(identifier.id)
const { start, end, snapshot, strategies, chainId } = proposal
const authorProfile = `https://snapshot.box/#/${identifier.space}/profile/${proposal.address}`
const link = `https://snapshot.box/#/${identifier.space}/proposal/${identifier.id}`
const link = `https://snapshot.box/#/${identifier.space}/proposal/${identifier.id.split('/').pop()}`
return (
<SnapshotCard title={<Trans>Information</Trans>}>
<div className={classes.infos}>
Expand Down Expand Up @@ -108,20 +108,22 @@ export function InformationCard() {
: <EthereumBlockie address={proposal.address} />}
</div>
<Typography fontSize={14}>
{proposal.space.id ?? formatEthereumAddress(proposal.address, 4)}
{proposal.space.id ? formatSpaceId(proposal.space.id) : formatLongHex(proposal.address)}
</Typography>
</Link>
</InfoField>
<InfoField title={<Trans>IPFS</Trans>} classes={{ field: classes.infoColor }}>
<Link
className={classes.link}
target="_blank"
rel="noopener"
href={resolveResourceURL(urlcat(SNAPSHOT_IPFS, proposal.ipfs))}>
<Typography fontSize={14}>#{identifier.id.slice(0, 7)}</Typography>
<Icons.LinkOut size={16} sx={{ paddingLeft: 1 }} />
</Link>
</InfoField>
{proposal.ipfs ?
<InfoField title={<Trans>IPFS</Trans>} classes={{ field: classes.infoColor }}>
<Link
className={classes.link}
target="_blank"
rel="noopener"
href={resolveResourceURL(urlcat(SNAPSHOT_IPFS, proposal.ipfs))}>
<Typography fontSize={14}>#{identifier.id.slice(0, 7)}</Typography>
<Icons.LinkOut size={16} sx={{ paddingLeft: 1 }} />
</Link>
</InfoField>
: null}
<InfoField title={<Trans>Start date</Trans>} classes={{ field: classes.infoColor }}>
<Typography fontSize={14} fontWeight={400}>
{formatDateTime(start * 1000, 'MMM dd, yyyy, hh:mm a')}
Expand Down
3 changes: 2 additions & 1 deletion packages/plugins/Snapshot/src/SiteAdaptor/Snapshot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ProposalTab } from './ProposalTab.js'
import { VotingDialog } from './VotingDialog.js'
import { usePower } from './hooks/usePower.js'
import { useProposal } from './hooks/useProposal.js'
import { formatSpaceId } from './helpers.js'

const useStyles = makeStyles()((theme) => {
return {
Expand Down Expand Up @@ -149,7 +150,7 @@ export function Snapshot() {
by
</Typography>
<Typography fontSize={14} fontWeight="700">
{proposal.space.id}
{formatSpaceId(proposal.space.id)}
</Typography>
</Box>
</Box>
Expand Down
129 changes: 68 additions & 61 deletions packages/plugins/Snapshot/src/SiteAdaptor/VotesCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/// <reference types="react/canary" />
import { Trans } from '@lingui/react/macro'
import { EthereumBlockie } from '@masknet/shared'
import { EmptyStatus, EthereumBlockie } from '@masknet/shared'
import type { NetworkPluginID } from '@masknet/shared-base'
import { makeStyles, ShadowRootTooltip, TextOverflowTooltip } from '@masknet/theme'
import { useChainContext } from '@masknet/web3-hooks-base'
import { formatCount, formatPercentage, isSameAddress } from '@masknet/web3-shared-base'
import { formatEthereumAddress } from '@masknet/web3-shared-evm'
import { Badge, Box, Link, List, ListItem, Typography } from '@mui/material'
import { unstable_useCacheRefresh, useContext } from 'react'
import { SnapshotContext } from '../context.js'
Expand All @@ -14,6 +13,7 @@ import { useVotes } from './hooks/useVotes.js'
import { LoadingCard } from './LoadingCard.js'
import { LoadingFailCard } from './LoadingFailCard.js'
import { SnapshotCard } from './SnapshotCard.js'
import { formatLongHex } from './helpers.js'

const useStyles = makeStyles()((theme) => {
return {
Expand Down Expand Up @@ -101,73 +101,80 @@ function Content() {
<Trans>Votes</Trans>
</Badge>
}>
<List className={classes.list}>
{votes.map(function voteItemIter(v) {
const isAverageWeight = v.choices?.every((c) => c.weight === 1)
const fullChoiceText =
v.totalWeight && v.choices ?
v.choices
.flatMap((choice, index) => [
index === 0 ? '' : ', ',
!isAverageWeight ? formatPercentage(choice.weight / v.totalWeight!) + ' ' : '',
choice.name,
])
.join('')
: null
const link = `https://snapshot.box/#/${identifier.space}/profile/${v.address}`
return (
<ListItem className={classes.listItem} key={v.address}>
<Link
className={cx(classes.link, classes.ellipsisText)}
target="_blank"
rel="noopener"
href={link}>
<Box className={classes.avatarWrapper}>
<EthereumBlockie address={v.address} />
</Box>
<Typography color={theme.palette.maskColor.dark}>
{isSameAddress(v.address, account) ?
<Trans>You</Trans>
: formatEthereumAddress(v.address, 4)}
</Typography>
</Link>
{v.choice ?
<Typography className={classes.choice}>{v.choice}</Typography>
: v.choices ?
<ShadowRootTooltip
{votes.length ?
<List className={classes.list}>
{votes.map(function voteItemIter(v) {
const isAverageWeight = v.choices?.every((c) => c.weight === 1)
const fullChoiceText =
v.totalWeight && v.choices ?
v.choices
.flatMap((choice, index) => [
index === 0 ? '' : ', ',
!isAverageWeight ? formatPercentage(choice.weight / v.totalWeight!) + ' ' : '',
choice.name,
])
.join('')
: null
const link = `https://snapshot.box/#/${identifier.space}/profile/${v.address}`
return (
<ListItem className={classes.listItem} key={v.address}>
<Link
className={cx(classes.link, classes.ellipsisText)}
target="_blank"
rel="noopener"
href={link}>
<Box className={classes.avatarWrapper}>
<EthereumBlockie address={v.address} />
</Box>
<Typography color={theme.palette.maskColor.dark}>
{isSameAddress(v.address, account) ?
<Trans>You</Trans>
: formatLongHex(v.address)}
</Typography>
</Link>
{v.choice ?
<Typography className={classes.choice}>{v.choice}</Typography>
: v.choices ?
<ShadowRootTooltip
PopperProps={{
disablePortal: false,
}}
title={
<Typography className={classes.shadowRootTooltip}>
{fullChoiceText}
</Typography>
}
placement="top"
classes={{ tooltip: classes.tooltip, arrow: classes.arrow }}
arrow>
<Typography className={classes.choice}>{fullChoiceText}</Typography>
</ShadowRootTooltip>
: null}
<TextOverflowTooltip
as={ShadowRootTooltip}
PopperProps={{
disablePortal: false,
disablePortal: true,
}}
classes={{ tooltip: classes.tooltip, arrow: classes.arrow }}
title={
<Typography className={classes.shadowRootTooltip}>{fullChoiceText}</Typography>
<Typography className={classes.shadowRootTooltip}>
{formatCount(v.balance, 2, true) + ' ' + v.strategySymbol.toUpperCase()}
</Typography>
}
placement="top"
classes={{ tooltip: classes.tooltip, arrow: classes.arrow }}
arrow>
<Typography className={classes.choice}>{fullChoiceText}</Typography>
</ShadowRootTooltip>
: null}
<TextOverflowTooltip
as={ShadowRootTooltip}
PopperProps={{
disablePortal: true,
}}
classes={{ tooltip: classes.tooltip, arrow: classes.arrow }}
title={
<Typography className={classes.shadowRootTooltip}>
<Typography className={classes.power}>
{formatCount(v.balance, 2, true) + ' ' + v.strategySymbol.toUpperCase()}
</Typography>
}
placement="top"
arrow>
<Typography className={classes.power}>
{formatCount(v.balance, 2, true) + ' ' + v.strategySymbol.toUpperCase()}
</Typography>
</TextOverflowTooltip>
</ListItem>
)
})}
</List>
</TextOverflowTooltip>
</ListItem>
)
})}
</List>
: <EmptyStatus>
<Trans>No votes</Trans>
</EmptyStatus>
}
</SnapshotCard>
)
}
Expand Down
15 changes: 15 additions & 0 deletions packages/plugins/Snapshot/src/SiteAdaptor/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import type { ProposalIdentifier } from '../types.js'
export function getProposalIdentifier(url: string): ProposalIdentifier {
const parsedURL = new URL(url)
const [, space, , id] = parsedURL.hash.split('/')
if (id.match(/^\d+$/)) {
return {
id: `${space.split(':').pop()}/${id}`,
space,
}
}
return {
id,
space,
Expand All @@ -16,3 +22,12 @@ export function resolveSnapshotSpacePageUrl(spaceId: string) {
export function resolveSnapshotProposalUrl(spaceId: string, proposalId: string) {
return `https://snapshot.box/#/${spaceId}/proposal/${proposalId}`
}

export function formatLongHex(hex: string) {
return hex.slice(0, 6) + '...' + hex.slice(-4)
}

export function formatSpaceId(spaceId: string) {
if (spaceId.startsWith('0x') && spaceId.length === 66) return `${spaceId.slice(0, 6)}...${spaceId.slice(-4)}`
return `0x${spaceId}`
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function useVotes(identifier: ProposalIdentifier, account?: string) {
: undefined,
address: v.voter,
authorIpfsHash: v.ipfs ?? v.id,
balance: sumBy(scores, (score) => score[v.voter.toLowerCase()] ?? 0),
balance: v.vp || sumBy(scores, (score) => score[v.voter.toLowerCase()] ?? 0),
scores: scores.map((score) => score[v.voter.toLowerCase()] || 0),
strategySymbol: proposal.space.symbol ?? strategies[0].params.symbol,
timestamp: v.created,
Expand Down
Loading

0 comments on commit beeb023

Please sign in to comment.