Skip to content

Commit

Permalink
Change logic for delegation voting power and add validation for user …
Browse files Browse the repository at this point in the history
…balance

Signed-off-by: Manank Patni <[email protected]>
  • Loading branch information
Man-Jain committed Sep 15, 2023
1 parent e2fe956 commit 152011a
Show file tree
Hide file tree
Showing 17 changed files with 118 additions and 126 deletions.
1 change: 1 addition & 0 deletions src/models/Community.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ export interface CommunityToken {
symbol: string
tokenAddress: string
decimals: string
message?: string
}
16 changes: 3 additions & 13 deletions src/modules/explorer/pages/User/components/DelegationBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,12 @@ export const matchTextToStatus = (value: DelegationsType | undefined) => {

export const Delegation: React.FC<{ daoId: string }> = ({ daoId }) => {
const { data: dao } = useDAO(daoId)
const { network, account, connect } = useTezos()
const { account } = useTezos()

const { data: delegatedTo, isLoading, refetch } = useDelegationStatus(dao?.data.token.contract)
const [delegationStatus, setDelegationStatus] = useState<DelegationsType>(DelegationsType.NOT_DELEGATING)
const [openModal, setOpenModal] = useState(false)
const { data: delegateVoteBalances } = useDelegationVoteWeight(dao?.data.token.contract, dao?.data.address)
const [voteWeight, setVoteWeight] = useState(new BigNumber(0))
const { data: voteWeight } = useDelegationVoteWeight(dao?.data.token.contract)
const [loadingRes, setLoadingRes] = useState(true)
const [shouldRefetch, setShouldRefetch] = useState(true)

Expand Down Expand Up @@ -97,15 +96,6 @@ export const Delegation: React.FC<{ daoId: string }> = ({ daoId }) => {
setShouldRefetch(false)
}, [delegatedTo])

useEffect(() => {
let totalVoteWeight = new BigNumber(0)
delegateVoteBalances?.forEach(delegatedVote => {
const balance = new BigNumber(delegatedVote.balance)
totalVoteWeight = totalVoteWeight.plus(balance)
})
setVoteWeight(totalVoteWeight)
}, [delegateVoteBalances])

return (
<DelegationBox container direction="column">
<Grid container style={{ gap: 12 }} direction="column">
Expand All @@ -114,7 +104,7 @@ export const Delegation: React.FC<{ daoId: string }> = ({ daoId }) => {
</Typography>
<Subtitle variant="body1">These settings only affect your participation in off-chain polls</Subtitle>
</Grid>
{dao && (
{dao && voteWeight && (
<Grid container style={{ gap: 12 }} direction="column">
<Typography color="textPrimary">Voting Weight</Typography>
<Balance color="secondary">
Expand Down
24 changes: 21 additions & 3 deletions src/modules/lite/explorer/components/Choices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import { theme } from "theme"
import { AddCircleOutline, RemoveCircleOutline } from "@material-ui/icons"
import { FieldArray, Field } from "formik"
import { TextField as FormikTextField } from "formik-material-ui"
import { useDAOID } from "modules/explorer/pages/DAO/router"
import { useDAO } from "services/services/dao/hooks/useDAO"
import { useToken } from "../hooks/useToken"
import { useUserTokenBalance } from "services/contracts/token/hooks/useUserTokenBalance"
import BigNumber from "bignumber.js"

const ChoicesContainer = styled(Grid)(({ theme }) => ({
paddingBottom: 19,
Expand Down Expand Up @@ -76,9 +81,22 @@ const CustomFormikTextField = withStyles({
disabled: {}
})(FormikTextField)

export const Choices: React.FC<any> = ({ choices, submitForm, isLoading, votingStrategy, setFieldValue }) => {
const MainButton = styled(Button)(({ theme }) => ({
"&$disabled": {
boxShadow: "none"
}
}))

export const Choices: React.FC<any> = ({ choices, submitForm, isLoading, votingStrategy, setFieldValue, id }) => {
const isMobileExtraSmall = useMediaQuery(theme.breakpoints.down("sm"))

const daoId = useDAOID()
const { data } = useDAO(daoId)
const liteDAOId = data?.liteDAOData?._id ? data?.liteDAOData?._id : id
const tokenAddress = useToken(liteDAOId)
const { data: userBalance } = useUserTokenBalance(tokenAddress)
const canCreateProposal = userBalance && new BigNumber(userBalance).gt(0) ? true : false

return (
<Grid container direction="column" style={{ gap: 30 }}>
<ChoicesContainer container direction="column">
Expand Down Expand Up @@ -175,9 +193,9 @@ export const Choices: React.FC<any> = ({ choices, submitForm, isLoading, votingS
</ChoicesContainer>
<Grid container style={{ gap: 10, marginTop: 31 }}>
{!isLoading ? (
<Button variant="contained" color="secondary" onClick={submitForm}>
<MainButton disabled={canCreateProposal} variant="contained" color="secondary" onClick={submitForm}>
Create Proposal
</Button>
</MainButton>
) : (
<CircularProgress color="secondary" />
)}
Expand Down
3 changes: 2 additions & 1 deletion src/modules/lite/explorer/components/ProposalList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ export const ProposalList: React.FC<{ polls: Poll[]; id: string | undefined; dao
polls.forEach(async poll => {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/token/${communityId}`).then(async response => {
if (!response.ok) {
const data = await response.json()
openNotification({
message: "An error has occurred",
message: data.message,
autoHideDuration: 2000,
variant: "error"
})
Expand Down
3 changes: 2 additions & 1 deletion src/modules/lite/explorer/hooks/useCommunity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ export const useCommunity = (daoId: string, isUpdated?: number) => {
try {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/daos/${daoId.toString()}`).then(async response => {
if (!response.ok) {
const data = await response.json()
openNotification({
message: "An error has occurred",
message: data.message,
autoHideDuration: 2000,
variant: "error"
})
Expand Down
5 changes: 3 additions & 2 deletions src/modules/lite/explorer/hooks/useCommunityToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ export const useCommunityToken = (communityId: any) => {
if (communityId !== undefined) {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/token/${String(communityId)}`).then(async response => {
if (!response.ok) {
const message = `An error has occurred: ${response.statusText}`
return
const data = await response.json()
const message = data.message
return message
}

const record: CommunityToken = await response.json()
Expand Down
3 changes: 2 additions & 1 deletion src/modules/lite/explorer/hooks/useHasVoted.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ export const useHasVoted = (refresh?: number) => {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/choices/${String(account)}/user`).then(
async response => {
if (!response.ok) {
const data = await response.json()
openNotification({
message: "An error has occurred",
message: data.message,
autoHideDuration: 2000,
variant: "error"
})
Expand Down
3 changes: 2 additions & 1 deletion src/modules/lite/explorer/hooks/usePoll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ export const useSinglePoll = (pollId: string | undefined, id?: any, community?:
try {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/polls/${pollId}/polls`).then(async response => {
if (!response.ok) {
const data = await response.json()
openNotification({
message: "An error has occurred",
message: data.message,
autoHideDuration: 2000,
variant: "error"
})
Expand Down
3 changes: 2 additions & 1 deletion src/modules/lite/explorer/hooks/usePollChoices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ export const usePollChoices = (poll: Poll | undefined, refresh?: number) => {
if (poll) {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/choices/${poll._id}/find`).then(async response => {
if (!response.ok) {
const data = await response.json()
openNotification({
message: "An error has occurred",
message: data.message,
autoHideDuration: 2000,
variant: "error"
})
Expand Down
4 changes: 2 additions & 2 deletions src/modules/lite/explorer/hooks/usePolls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ export const usePolls = (id: any) => {
async function fetchPoll() {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/polls/${id}/list`).then(async response => {
if (!response.ok) {
const data = await response.json()
openNotification({
message: "An error has occurred",
message: data.message,
autoHideDuration: 2000,
variant: "error"
})
Expand All @@ -36,7 +37,6 @@ export const usePolls = (id: any) => {
if (poll) {
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/choices/${poll._id}/votes`).then(async response => {
if (!response.ok) {
console.log("error in query")
return
}
const records: number = await response.json()
Expand Down
3 changes: 2 additions & 1 deletion src/modules/lite/explorer/hooks/useToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ export const useToken = (daoId: string | undefined) => {
const communityId = daoId
await fetch(`${getEnv(EnvKey.REACT_APP_LITE_API_URL)}/token/${communityId}`).then(async response => {
if (!response.ok) {
const data = await response.json()
openNotification({
message: "An error has occurred",
message: data.message,
autoHideDuration: 2000,
variant: "error"
})
Expand Down
5 changes: 4 additions & 1 deletion src/modules/lite/explorer/pages/CreateProposal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { useToken } from "../../hooks/useToken"
import { isWebUri } from "valid-url"
import { useDAO } from "services/services/dao/hooks/useDAO"
import { useDAOID } from "modules/explorer/pages/DAO/router"
import { useUserTokenBalance } from "services/contracts/token/hooks/useUserTokenBalance"
dayjs.extend(duration)

const ProposalContainer = styled(Grid)(({ theme }) => ({
Expand Down Expand Up @@ -430,6 +431,7 @@ export const ProposalForm = ({
) : null}
<ProposalChoices>
<Choices
id={id}
choices={getIn(values, "choices")}
isLoading={isSubmitting}
submitForm={submitForm}
Expand Down Expand Up @@ -596,6 +598,7 @@ export const ProposalCreator: React.FC<{ id?: string; onClose?: any }> = props =
}

const res = await saveLiteProposal(signature, publicKey, payloadBytes)
const respData = await res.json()
if (res.ok) {
openNotification({
message: "Proposal created!",
Expand All @@ -609,7 +612,7 @@ export const ProposalCreator: React.FC<{ id?: string; onClose?: any }> = props =
: navigate.push(`/explorer/lite/dao/${id}/community`)
} else {
openNotification({
message: "Proposal could not be created",
message: respData.message,
autoHideDuration: 3000,
variant: "error"
})
Expand Down
4 changes: 3 additions & 1 deletion src/modules/lite/explorer/pages/ProposalDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const ProposalDetails: React.FC<{ id: string }> = ({ id }) => {
return
}
const resp = await voteOnLiteProposal(signature, publicKey, payloadBytes)
const response = await resp.json()
if (resp.ok) {
openNotification({
message: "Your vote has been submitted",
Expand All @@ -107,13 +108,14 @@ export const ProposalDetails: React.FC<{ id: string }> = ({ id }) => {
setSelectedVotes([])
} else {
openNotification({
message: `Something went wrong!!`,
message: response.message,
autoHideDuration: 3000,
variant: "error"
})
return
}
} catch (error) {
console.log("error: ", error)
openNotification({
message: `Something went wrong!!`,
autoHideDuration: 3000,
Expand Down
104 changes: 14 additions & 90 deletions src/services/bakingBad/delegations/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Network } from "services/beacon"
import { networkNameMap } from ".."
import { DelegationDTO, TokenDelegationDTO, UserDelegateBalance } from "./types"
import { getUserTokenBalance } from "../tokenBalances"
import { DelegationDTO, TokenDelegationDTO } from "./types"
import BigNumber from "bignumber.js"
import { getCurrentBlock } from "services/utils/utils"
import { EnvKey, getEnv } from "services/config"

export const getLatestDelegation = async (daoAddress: string, network: Network) => {
const url = `https://api.${networkNameMap[network]}.tzkt.io/v1/operations/delegations?sender=${daoAddress}&status=applied`
Expand Down Expand Up @@ -40,99 +41,22 @@ export const getTokenDelegation = async (tokenAddress: string, account: string,
return delegatedTo
}

export const getUserDAODepositBalance = async (account: string, network: Network, daoAddress: string) => {
const url = `https://api.${network}.tzkt.io/v1/contracts/${daoAddress}/bigmaps/freeze_history/keys?key.eq=${account}`
export const getTokenDelegationVoteWeight = async (tokenAddress: string, account: string, network: Network) => {
const level = await getCurrentBlock(network)

const url = `${getEnv(
EnvKey.REACT_APP_LITE_API_URL
)}/network/${network}/token/${tokenAddress}/token-id/0/voting-power?userAddress=${account}&level=${level}`
const response = await fetch(url)

if (!response.ok) {
throw new Error("Failed to fetch token delegations from TZKT API")
const data = await response.json()
throw new Error(data.message)
}

const userStakedBalances = await response.json()

let userDAODepositBalance = new BigNumber(0)

if (userStakedBalances && userStakedBalances[0]) {
const userStakedBalance = new BigNumber(userStakedBalances[0].value.staked)
const userCurrentUnstakedBalance = new BigNumber(userStakedBalances[0].value.current_unstaked)
const userPastUnstakedBalance = new BigNumber(userStakedBalances[0].value.past_unstaked)

userDAODepositBalance = userStakedBalance.plus(userCurrentUnstakedBalance).plus(userPastUnstakedBalance)
const result: { votingWeight: string } = await response.json()
if (result) {
return new BigNumber(result.votingWeight)
}

return userDAODepositBalance.toString()
}

export const getTokenDelegationVoteWeight = async (
tokenAddress: string,
account: string,
network: Network,
daoContract?: string
) => {
const tokenDelegationStatus = await getTokenDelegation(tokenAddress, account, network)
console.log("tokenDelegationStatus: ", tokenDelegationStatus)
if (tokenDelegationStatus && tokenDelegationStatus !== account) {
return []
} else {
const selfBalance = await getUserTokenBalance(account, network, tokenAddress)
if (!selfBalance) {
throw new Error("Could not fetch delegate token balance from the TZKT API")
}
console.log("selfBalance: ", selfBalance)

let selfDAOBalance

console.log("daoContract: ", daoContract)
if (daoContract) {
selfDAOBalance = await getUserDAODepositBalance(account, network, daoContract)
console.log("selfDAOBalance: ", selfDAOBalance)
if (!selfDAOBalance) {
throw new Error("Could not fetch delegate dao balance from the TZKT API")
}

const url = `https://api.${networkNameMap[network]}.tzkt.io/v1/contracts/${tokenAddress}/bigmaps/delegates/keys?value.eq=${account}&active=true`
console.log("ursssssl: ", url)
const response = await fetch(url)

if (!response.ok) {
throw new Error("Failed to fetch token delegations from TZKT API")
}

const resultingDelegations: TokenDelegationDTO[] = await response.json()

const delegateBalance: UserDelegateBalance = {
address: account,
balance: selfDAOBalance
? new BigNumber(selfBalance).plus(new BigNumber(selfDAOBalance)).toString()
: selfBalance
}

if (resultingDelegations.length === 0) {
return [delegateBalance]
}

const delegatedAddressBalances: UserDelegateBalance[] = [delegateBalance]

await Promise.all(
resultingDelegations.map(async del => {
if (del.key === del.value) {
return
}
const balance = await getUserTokenBalance(del.key, network, tokenAddress)
const userDAOBalance = await getUserDAODepositBalance(del.key, network, daoContract)
if (balance) {
delegatedAddressBalances.push({
address: del.key,
balance: userDAOBalance ? new BigNumber(userDAOBalance).plus(new BigNumber(balance)).toString() : balance
})
}
})
)

console.log("delegatedAddressBalances: ", delegatedAddressBalances)

return delegatedAddressBalances
}
}
return new BigNumber(0)
}
Loading

0 comments on commit 152011a

Please sign in to comment.