Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
always-auth=true
@uxdprotocol:registry=https://npm.pkg.github.com/uxdprotocol/
//npm.pkg.github.com/:_authToken=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
//npm.pkg.github.com/uxdprotocol/:_authToken=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
registry=https://registry.npmjs.org
97 changes: 58 additions & 39 deletions components/ProposalCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import styled from '@emotion/styled'
import { ChevronRightIcon } from '@heroicons/react/solid'
import ProposalStateBadge from './ProposalStateBadge'
import Link from 'next/link'
import { GovernanceAccountType, Proposal, ProposalState, VoteType } from '@solana/spl-governance'
import {
GovernanceAccountType,
Proposal,
ProposalState,
VoteType,
} from '@solana/spl-governance'
import { ApprovalProgress, VetoProgress } from './QuorumProgress'
import useRealm from '../hooks/useRealm'
import useProposalVotes from '../hooks/useProposalVotes'
Expand All @@ -17,6 +22,7 @@ import MultiChoiceVotes from './MultiChoiceVotes'
type ProposalCardProps = {
proposalPk: PublicKey
proposal: Proposal
unrelinquishedVote?: boolean
}

const StyledSvg = styled(ChevronRightIcon)``
Expand All @@ -29,12 +35,17 @@ const StyledCardWrapper = styled.div`
}
`

const ProposalCard = ({ proposalPk, proposal }: ProposalCardProps) => {
const ProposalCard = ({
proposalPk,
proposal,
unrelinquishedVote,
}: ProposalCardProps) => {
const { symbol } = useRealm()
const { fmtUrlWithCluster } = useQueryContext()
const votesData = useProposalVotes(proposal)
const isMulti = proposal.voteType !== VoteType.SINGLE_CHOICE
&& proposal.accountType === GovernanceAccountType.ProposalV2
const isMulti =
proposal.voteType !== VoteType.SINGLE_CHOICE &&
proposal.accountType === GovernanceAccountType.ProposalV2

return (
<div>
Expand All @@ -59,44 +70,52 @@ const ProposalCard = ({ proposalPk, proposal }: ProposalCardProps) => {
<StyledSvg className="default-transition h-6 ml-3 text-fgd-2 w-6" />
</div>
</div>
<ProposalTimeStatus proposal={proposal} />
</div>
{proposal.state === ProposalState.Voting ?
isMulti ?
<div className="pb-4 px-6">
<MultiChoiceVotes proposal={proposal} limit={3}/>
<div>
<ProposalTimeStatus proposal={proposal} />
</div>
:
(<div className="border-t border-fgd-4 flex flex-col lg:flex-row mt-2 p-4 gap-x-4 gap-y-3">
<div className="w-full lg:w-auto flex-1">
<VoteResults isListView proposal={proposal} />
</div>
<div className="border-r border-fgd-4 hidden lg:block" />
<div className="w-full lg:w-auto flex-1">
<ApprovalProgress
progress={votesData.yesVoteProgress}
votesRequired={votesData.yesVotesRequired}
/>
<div className="text-fgd-3 text-sm mt-4">
{unrelinquishedVote ? '** Vote not relinquished **' : null}
</div>
</div>
{proposal.state === ProposalState.Voting ? (
isMulti ? (
<div className="pb-4 px-6">
<MultiChoiceVotes proposal={proposal} limit={3} />
</div>
{votesData._programVersion !== undefined &&
// @asktree: here is some typescript gore because typescript doesn't know that a number being > 3 means it isn't 1 or 2
votesData._programVersion !== 1 &&
votesData._programVersion !== 2 &&
votesData.veto !== undefined &&
(votesData.veto.voteProgress ?? 0) > 0 ? (
<>
<div className="border-r border-fgd-4 hidden lg:block" />
) : (
<div className="border-t border-fgd-4 flex flex-col lg:flex-row mt-2 p-4 gap-x-4 gap-y-3">
<div className="w-full lg:w-auto flex-1">
<VoteResults isListView proposal={proposal} />
</div>
<div className="border-r border-fgd-4 hidden lg:block" />
<div className="w-full lg:w-auto flex-1">
<ApprovalProgress
progress={votesData.yesVoteProgress}
votesRequired={votesData.yesVotesRequired}
/>
</div>
{votesData._programVersion !== undefined &&
// @asktree: here is some typescript gore because typescript doesn't know that a number being > 3 means it isn't 1 or 2
votesData._programVersion !== 1 &&
votesData._programVersion !== 2 &&
votesData.veto !== undefined &&
(votesData.veto.voteProgress ?? 0) > 0 ? (
<>
<div className="border-r border-fgd-4 hidden lg:block" />

<div className="w-full lg:w-auto flex-1">
<VetoProgress
progress={votesData.veto.voteProgress}
votesRequired={votesData.veto.votesRequired}
/>
</div>
</>
) : undefined}
</div>)
: ""}
<div className="w-full lg:w-auto flex-1">
<VetoProgress
progress={votesData.veto.voteProgress}
votesRequired={votesData.veto.votesRequired}
/>
</div>
</>
) : undefined}
</div>
)
) : (
''
)}
</StyledCardWrapper>
</a>
</Link>
Expand Down
101 changes: 86 additions & 15 deletions components/TokenBalance/DelegateTokenBalanceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore'
import { PublicKey } from '@solana/web3.js'
import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext'
import { useRealmQuery } from '@hooks/queries/realm'
import { useMemo } from 'react'
import { useEffect, useMemo, useState } from 'react'
import { UXD_STAKING_PROGRAM } from '@tools/constants'

const DelegateBalanceCard = () => {
const wallet = useWalletOnePointOh()
Expand All @@ -19,6 +20,12 @@ const DelegateBalanceCard = () => {
const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result
const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result
const realm = useRealmQuery().data?.result
const [
communityTorsDelegatedAccOwnerAliases,
setCommunityTorsDelegatedAccOwnerAliases,
] = useState<{
[key: string]: string
}>({})

const delegatesArray = useTokenOwnerRecordsDelegatedToUser()

Expand Down Expand Up @@ -67,6 +74,48 @@ const DelegateBalanceCard = () => {
(communityTorsDelegatedToUser?.length ?? 0) > 0 ||
(councilTorsDelegatedToUser?.length ?? 0) > 0

// Load up aliases for delegates accounts
useEffect(() => {
if (!communityTorsDelegatedToUser) {
setCommunityTorsDelegatedAccOwnerAliases({})
return
}

;(async () => {
const owners = communityTorsDelegatedToUser.map(
(acc) => acc.account.governingTokenOwner
)

const accountsInfo = await connection.current.getMultipleAccountsInfo(
owners
)

setCommunityTorsDelegatedAccOwnerAliases(
accountsInfo.reduce((acc, accountInfo, index) => {
if (!accountInfo) {
return acc
}

if (!accountInfo.owner.equals(UXD_STAKING_PROGRAM)) {
return acc
}

const govTokenOwner = communityTorsDelegatedToUser[
index
].account.governingTokenOwner.toBase58()

return {
...acc,
[govTokenOwner]: `UXP Staking account ${govTokenOwner.slice(
0,
3
)}...${govTokenOwner.slice(-2)}`,
}
}, {})
)
})()
}, [communityTorsDelegatedToUser])

if (!walletId || !hasDelegators) {
return null
}
Expand Down Expand Up @@ -166,13 +215,21 @@ const DelegateBalanceCard = () => {
componentLabel={
ownTokenRecord ? (
<div className="relative">
<DisplayAddress
connection={connection.current}
address={ownTokenRecord.account.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
{communityTorsDelegatedAccOwnerAliases[
ownTokenRecord.account.governingTokenOwner.toBase58()
] ? (
communityTorsDelegatedAccOwnerAliases[
ownTokenRecord.account.governingTokenOwner.toBase58()
]
) : (
<DisplayAddress
connection={connection.current}
address={ownTokenRecord.account.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
)}
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
) : (
Expand All @@ -189,13 +246,27 @@ const DelegateBalanceCard = () => {
value={communityDelegate.account.governingTokenOwner.toBase58()}
>
<div className="relative">
<DisplayAddress
connection={connection.current}
address={communityDelegate.account.governingTokenOwner}
height="12px"
width="100px"
dark={true}
/>
{communityTorsDelegatedAccOwnerAliases[
communityDelegate.account.governingTokenOwner.toBase58()
] ? (
<>
{
communityTorsDelegatedAccOwnerAliases[
communityDelegate.account.governingTokenOwner.toBase58()
]
}
</>
) : (
<DisplayAddress
connection={connection.current}
address={
communityDelegate.account.governingTokenOwner
}
height="12px"
width="100px"
dark={true}
/>
)}
<div className="absolute bg-bkg-1 bottom-0 left-0 w-full h-full opacity-0 " />
</div>
</Select.Option>
Expand Down
36 changes: 36 additions & 0 deletions components/TokenBalance/RelinquishVoteCount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord'

const RelinquishVoteCount = () => {
const wallet = useWalletOnePointOh()
const walletId = wallet?.publicKey?.toBase58()
const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result

if (!walletId || !ownTokenRecord) {
return null
}

return (
<>
<h3 className="mb-0 mt-6">Vote Relinquish</h3>
<div className="mt-2 italic text-xs mb-2">
Required to withdraw governance tokens
</div>

<div className="flex space-x-4 items-center mt-4">
<div className="bg-bkg-1 px-4 py-2 justify-between rounded-md w-full">
<div className="flex flex-row justify-between w-full mb-2">
<div>
<p className="text-fgd-3 text-xs">Unrelinquished Votes Count</p>
<p className="font-bold mb-0 text-fgd-1 text-xl">
{ownTokenRecord.account.unrelinquishedVotesCount}
</p>
</div>
</div>
</div>
</div>
</>
)
}

export default RelinquishVoteCount
2 changes: 2 additions & 0 deletions components/TokenBalance/TokenBalanceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { useEffect, useState } from 'react'
import useVotePluginsClientStore from 'stores/useVotePluginsClientStore'
import { VSR_PLUGIN_PKS } from '@constants/plugins'
import DelegateTokenBalanceCard from '@components/TokenBalance/DelegateTokenBalanceCard'
import RelinquishVoteCount from '@components/TokenBalance/RelinquishVoteCount'
import SerumGovernanceTokenWrapper from './SerumGovernanceTokenWrapper'
import getNumTokens from '@components/ProposalVotingPower/getNumTokens'
import VotingPowerPct from '@components/ProposalVotingPower/VotingPowerPct'
Expand Down Expand Up @@ -129,6 +130,7 @@ const TokenBalanceCard = ({
/>
)}
<DelegateTokenBalanceCard />
<RelinquishVoteCount />
</div>
) : (
<>
Expand Down
20 changes: 17 additions & 3 deletions components/VotePanel/VotePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { GovernanceAccountType, ProposalState, VoteType } from '@solana/spl-governance'
import {
GovernanceAccountType,
ProposalState,
VoteType,
} from '@solana/spl-governance'
import { BanIcon } from '@heroicons/react/solid'

import Tooltip from '@components/Tooltip'
Expand All @@ -10,6 +14,7 @@ import { useIsVoting } from './hooks'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import { useRouteProposalQuery } from '@hooks/queries/proposal'
import { useProposalVoteRecordQuery } from '@hooks/queries/voteRecord'
import DelegateBalanceCard from '@components/TokenBalance/DelegateTokenBalanceCard'

const VotePanel = () => {
const proposal = useRouteProposalQuery().data?.result
Expand All @@ -29,8 +34,9 @@ const VotePanel = () => {
proposal.account.state !== ProposalState.Draft &&
!isVoteCast

const isMulti = proposal?.account.voteType !== VoteType.SINGLE_CHOICE
&& proposal?.account.accountType === GovernanceAccountType.ProposalV2
const isMulti =
proposal?.account.voteType !== VoteType.SINGLE_CHOICE &&
proposal?.account.accountType === GovernanceAccountType.ProposalV2

return (
<>
Expand All @@ -55,6 +61,14 @@ const VotePanel = () => {
)}
<YouVoted quorum="veto" />
{!isMulti && <VetoButtons />}

{connected ? (
<div className="bg-bkg-2 p-4 md:p-6 rounded-lg space-y-4">
<div className="flex flex-col p-4">
<DelegateBalanceCard />
</div>
</div>
) : null}
{/* END */}
</>
)
Expand Down
Loading