From 014ad9fba6d2a188cb454524c357e477f41e7b6b Mon Sep 17 00:00:00 2001 From: vidvidvid Date: Wed, 6 Nov 2024 13:11:29 +0100 Subject: [PATCH] set up vote table & data --- .../veion/EmissionsManagementTable.tsx | 262 ++++--- packages/ui/app/contexts/VotingContext.tsx | 4 +- .../ui/app/veion/governance/vote/page.tsx | 14 + packages/ui/constants/mock.ts | 102 --- packages/ui/utils/voteMarkets.ts | 651 ++++++++++++++++++ 5 files changed, 787 insertions(+), 246 deletions(-) create mode 100644 packages/ui/utils/voteMarkets.ts diff --git a/packages/ui/app/_components/veion/EmissionsManagementTable.tsx b/packages/ui/app/_components/veion/EmissionsManagementTable.tsx index 8c39220ba..91beafc08 100644 --- a/packages/ui/app/_components/veion/EmissionsManagementTable.tsx +++ b/packages/ui/app/_components/veion/EmissionsManagementTable.tsx @@ -2,26 +2,28 @@ import React, { useState, useMemo } from 'react'; +import Image from 'next/image'; + import { VotingContext } from '@ui/app/contexts/VotingContext'; -import type { VotingData } from '@ui/constants/mock'; -import { votingData } from '@ui/constants/mock'; +import { Checkbox } from '@ui/components/ui/checkbox'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@ui/components/ui/select'; import { useVeIONContext } from '@ui/context/VeIonContext'; import { useToast } from '@ui/hooks/use-toast'; import { MarketSide, useVeIONVote } from '@ui/hooks/veion/useVeIONVote'; +import type { VoteMarket } from '@ui/utils/voteMarkets'; +import { voteMarkets } from '@ui/utils/voteMarkets'; import EmissionsManagementFooter from './EmissionsManagementFooter'; -import VoteInput from './VoteInput'; import CommonTable from '../CommonTable'; import type { ColumnDef } from '@tanstack/react-table'; -const MARKET_ADDRESSES: Record = { - '0012': '0x1234567890123456789012345678901234567890', - '0014': '0x2345678901234567890123456789012345678901', - '0015': '0x3456789012345678901234567890123456789012', - '0016': '0x4567890123456789012345678901234567890123' -}; - interface EmissionsManagementTableProps { tokenId: number; } @@ -31,86 +33,54 @@ function EmissionsManagementTable({ tokenId }: EmissionsManagementTableProps) { const { toast } = useToast(); const [selectedRows, setSelectedRows] = useState>({}); const [autoRepeat, setAutoRepeat] = useState(false); - const [votingSide, setVotingSide] = useState>({}); + const [poolType, setPoolType] = useState<'0' | '1'>('0'); const { addVote, removeVote, submitVote, isVoting } = useVeIONVote(currentChain); const filteredVotingData = useMemo(() => { - return votingData.filter((data) => data.networkId === +currentChain); - }, [currentChain]); + return voteMarkets[+currentChain]?.[poolType] ?? []; + }, [currentChain, poolType]); - const rowColors = useMemo(() => { - const colors = [ - '#FF6B6B', - '#4ECDC4', - '#45B7D1', - '#96CEB4', - '#FFEEAD', - '#D4A5A5', - '#9B59B6' - ]; - - return filteredVotingData.reduce( - (acc, row) => { - acc[row.id] = colors[Math.floor(Math.random() * colors.length)]; - return acc; - }, - {} as Record - ); - }, [filteredVotingData]); - - const handleVoteChange = (id: string, value: string) => { + const handleVoteChange = (id: string, side: MarketSide, value: string) => { setSelectedRows((prev) => { - const newRows = { ...prev, [id]: value }; - // Update the votes in the hook - const numericValue = parseFloat(value); - if (!isNaN(numericValue)) { - const marketAddress = MARKET_ADDRESSES[id]; - if (marketAddress) { - addVote( - marketAddress, - votingSide[id] || MarketSide.Supply, - numericValue - ); - } - } else { - removeVote(id); - } - return newRows; - }); - }; + const newRows = { ...prev }; + const market = filteredVotingData.find((m) => m.marketAddress === id); - const handleSideChange = (id: string, side: MarketSide) => { - setVotingSide((prev) => { - const newSides = { ...prev, [id]: side }; - const value = selectedRows[id]; - const numericValue = parseFloat(value); - if (!isNaN(numericValue)) { - const market = filteredVotingData.find((row) => row.id === id); - if (market) { - addVote(market.marketAddress, side, numericValue); + if (market) { + const numericValue = parseFloat(value); + if (!isNaN(numericValue)) { + addVote(id, side, numericValue); + newRows[`${id}-${side === MarketSide.Supply ? 'supply' : 'borrow'}`] = + value; + } else { + removeVote(id); + delete newRows[ + `${id}-${side === MarketSide.Supply ? 'supply' : 'borrow'}` + ]; } } - return newSides; + return newRows; }); }; - const handleReset = () => { - setSelectedRows({}); - setVotingSide({}); - setAutoRepeat(false); - }; - const handleSubmitVotes = async () => { try { - const totalWeight = Object.values(selectedRows).reduce( - (sum, value) => sum + (parseFloat(value) || 0), - 0 - ); + const totalSupplyWeight = Object.entries(selectedRows) + .filter(([key]) => key.endsWith('-supply')) + .reduce((sum, [, value]) => sum + (parseFloat(value) || 0), 0); - if (Math.abs(totalWeight - 100) > 0.01) { - throw new Error('Total vote weight must equal 100'); + const totalBorrowWeight = Object.entries(selectedRows) + .filter(([key]) => key.endsWith('-borrow')) + .reduce((sum, [, value]) => sum + (parseFloat(value) || 0), 0); + + if ( + Math.abs(totalSupplyWeight - 100) > 0.01 || + Math.abs(totalBorrowWeight - 100) > 0.01 + ) { + throw new Error( + 'Total vote weight for both supply and borrow must equal 100' + ); } const success = await submitVote(tokenId); @@ -134,42 +104,27 @@ function EmissionsManagementTable({ tokenId }: EmissionsManagementTableProps) { } }; - const columns = useMemo[]>( + const handleReset = () => { + setSelectedRows({}); + setAutoRepeat(false); + }; + + const columns = useMemo[]>( () => [ { - accessorKey: 'id', - header: 'ID', - cell: ({ row }) => { - const id = row.getValue('id'); - return ( -
-
-
{id}
-
- ); - } - }, - { - accessorKey: 'supplyAsset', - header: 'SUPPLY ASSET', - cell: ({ row }) => ( -
- - {row.getValue('supplyAsset')} - -
- ) - }, - { - accessorKey: 'type', - header: 'TYPE', + accessorKey: 'asset', + header: 'ASSET', cell: ({ row }) => (
+ {row.original.asset} - {row.getValue('type')} + {row.original.asset}
) @@ -209,49 +164,55 @@ function EmissionsManagementTable({ tokenId }: EmissionsManagementTableProps) { } }, { - id: 'actions', - header: '', + accessorKey: 'supply', + header: 'SUPPLY %', cell: ({ row }) => ( -
-
- - -
- -
+ + handleVoteChange(row.original.marketAddress, 0, e.target.value) + } + disabled={isVoting} + min="0" + max="100" + step="0.1" + /> + ) + }, + { + accessorKey: 'borrow', + header: 'BORROW %', + cell: ({ row }) => ( + + handleVoteChange(row.original.marketAddress, 1, e.target.value) + } + disabled={isVoting} + min="0" + max="100" + step="0.1" + /> + ) + }, + { + accessorKey: 'autoVote', + header: 'AUTO VOTE', + cell: ({ row }) => ( + ) } ], // eslint-disable-next-line react-hooks/exhaustive-deps - [rowColors, votingSide, isVoting] + [selectedRows, isVoting] ); const votingContextValue = useMemo( @@ -266,6 +227,21 @@ function EmissionsManagementTable({ tokenId }: EmissionsManagementTableProps) { return (
+
+ +
+ ; - onVoteChange: (id: string, value: string) => void; + onVoteChange: (id: string, side: MarketSide, value: string) => void; } export const VotingContext = createContext(null); diff --git a/packages/ui/app/veion/governance/vote/page.tsx b/packages/ui/app/veion/governance/vote/page.tsx index 34e45ba28..e1a031937 100644 --- a/packages/ui/app/veion/governance/vote/page.tsx +++ b/packages/ui/app/veion/governance/vote/page.tsx @@ -31,6 +31,7 @@ const PLACEHOLDER_OPTIONS = [ const Vote: React.FC = () => { const [showPendingOnly, setShowPendingOnly] = useState(false); + const [showAutoOnly, setShowAutoOnly] = useState(false); const [selectedProposal, setSelectedProposal] = useState( PLACEHOLDER_OPTIONS[0].value ); @@ -103,6 +104,19 @@ const Vote: React.FC = () => { + + diff --git a/packages/ui/constants/mock.ts b/packages/ui/constants/mock.ts index c5a13dd8a..50b2353ab 100644 --- a/packages/ui/constants/mock.ts +++ b/packages/ui/constants/mock.ts @@ -1,5 +1,3 @@ -import type { Hex } from 'viem'; - export type LockedData = { id: string; tokensLocked: string; @@ -179,106 +177,6 @@ export const lockedDataWithDelegate: LockedDataWithDelegate[] = [ } ]; -export type VotingData = { - id: string; - network: string; - networkId: number; - supplyAsset: string; - totalVotes: { - percentage: string; - limit: string; - }; - myVotes: { - percentage: string; - value: string; - }; - marketAddress: Hex; - type: 'borrow' | 'supply'; -}; - -export const votingData: VotingData[] = [ - { - id: '0012', - network: 'Mode', - networkId: 34443, - supplyAsset: 'ETH', - totalVotes: { - percentage: '12.34%', - limit: '25% limit' - }, - myVotes: { - percentage: '0', - value: '$0' - }, - marketAddress: '0x1234567890123456789012345678901234567890', - type: 'supply' - }, - { - id: '0014', - network: 'Optimism', - networkId: 10, - supplyAsset: 'USDC', - totalVotes: { - percentage: '18.5%', - limit: '25% limit' - }, - myVotes: { - percentage: '10', - value: '$2.45' - }, - marketAddress: '0x2345678901234567890123456789012345678901', - type: 'supply' - }, - { - id: '0014', - network: 'Optimism', - networkId: 10, - supplyAsset: 'OP', - totalVotes: { - percentage: '8.5%', - limit: '23% limit' - }, - myVotes: { - percentage: '0', - value: '$0' - }, - marketAddress: '0x2345678901234567890123456789012345678901', - type: 'borrow' - }, - { - id: '0015', - network: 'Base', - networkId: 8453, - supplyAsset: 'BNB', - totalVotes: { - percentage: '5.7%', - limit: '25% limit' - }, - myVotes: { - percentage: '0', - value: '$0' - }, - marketAddress: '0x3456789012345678901234567890123456789012', - type: 'supply' - }, - { - id: '0016', - network: 'Eth', - networkId: 1, - supplyAsset: 'USDT', - totalVotes: { - percentage: '22.1%', - limit: '25% limit' - }, - myVotes: { - percentage: '0', - value: '$0' - }, - marketAddress: '0x4567890123456789012345678901234567890123', - type: 'borrow' - } -]; - export interface InfoBlock { label: string; value: string; diff --git a/packages/ui/utils/voteMarkets.ts b/packages/ui/utils/voteMarkets.ts new file mode 100644 index 000000000..9128d3a78 --- /dev/null +++ b/packages/ui/utils/voteMarkets.ts @@ -0,0 +1,651 @@ +import { base, optimism, mode } from 'viem/chains'; + +export type VoteMarket = { + asset: string; + marketAddress: `0x${string}`; + totalVotes: { + percentage: string; + limit: string; + }; + myVotes: { + percentage: string; + value: string; + }; + autoVote: boolean; + poolType: 0 | 1; +}; + +export type VoteMarketsConfig = Record>; + +export const voteMarkets: VoteMarketsConfig = { + [mode.id]: { + '0': [ + { + asset: 'M-BTC', + marketAddress: '0x1234567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'dMBTC', + marketAddress: '0x2345678901234567890123456789012345678901', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '5%', + value: '4,000' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'STONE', + marketAddress: '0x3456789012345678901234567890123456789012', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '7%', + value: '4,200' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'USDC', + marketAddress: '0x4567890123456789012345678901234567890123', + totalVotes: { + percentage: '30%', + limit: '120,000' + }, + myVotes: { + percentage: '15%', + value: '18,000' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'USDT', + marketAddress: '0x5678901234567890123456789012345678901234', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '12%', + value: '12,000' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'WBTC', + marketAddress: '0x6789012345678901234567890123456789012345', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '8%', + value: '6,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'WETH', + marketAddress: '0x7890123456789012345678901234567890123456', + totalVotes: { + percentage: '35%', + limit: '140,000' + }, + myVotes: { + percentage: '18%', + value: '25,200' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'ezETH', + marketAddress: '0x8901234567890123456789012345678901234567', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '5%', + value: '3,000' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'sUSDe', + marketAddress: '0x9012345678901234567890123456789012345678', + totalVotes: { + percentage: '10%', + limit: '40,000' + }, + myVotes: { + percentage: '2%', + value: '800' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'USDe', + marketAddress: '0xa123456789012345678901234567890123456789', + totalVotes: { + percentage: '12%', + limit: '48,000' + }, + myVotes: { + percentage: '3%', + value: '1,440' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'msDAI', + marketAddress: '0xb123456789012345678901234567890123456789', + totalVotes: { + percentage: '18%', + limit: '72,000' + }, + myVotes: { + percentage: '6%', + value: '4,320' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'weETH', + marketAddress: '0xc123456789012345678901234567890123456789', + totalVotes: { + percentage: '22%', + limit: '88,000' + }, + myVotes: { + percentage: '8%', + value: '7,040' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'wrsETH', + marketAddress: '0xd123456789012345678901234567890123456789', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: true, + poolType: 0 + } + ], + '1': [ + { + asset: 'MODE', + marketAddress: '0xe123456789012345678901234567890123456789', + totalVotes: { + percentage: '40%', + limit: '160,000' + }, + myVotes: { + percentage: '20%', + value: '32,000' + }, + autoVote: true, + poolType: 1 + }, + { + asset: 'USDC', + marketAddress: '0xf123456789012345678901234567890123456789', + totalVotes: { + percentage: '30%', + limit: '120,000' + }, + myVotes: { + percentage: '15%', + value: '18,000' + }, + autoVote: false, + poolType: 1 + }, + { + asset: 'USDT', + marketAddress: '0x0123456789012345678901234567890123456789', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: false, + poolType: 1 + }, + { + asset: 'WETH', + marketAddress: '0x1234567890123456789012345678901234567890', + totalVotes: { + percentage: '35%', + limit: '140,000' + }, + myVotes: { + percentage: '15%', + value: '21,000' + }, + autoVote: true, + poolType: 1 + } + ] + }, + [base.id]: { + '0': [ + { + asset: 'eUSD', + marketAddress: '0x2234567890123456789012345678901234567890', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '8%', + value: '6,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'bsdETH', + marketAddress: '0x3234567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'hyUSD', + marketAddress: '0x4234567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '5%', + value: '3,000' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'AERO', + marketAddress: '0x5234567890123456789012345678901234567890', + totalVotes: { + percentage: '10%', + limit: '40,000' + }, + myVotes: { + percentage: '3%', + value: '1,200' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'USDC', + marketAddress: '0x6234567890123456789012345678901234567890', + totalVotes: { + percentage: '30%', + limit: '120,000' + }, + myVotes: { + percentage: '12%', + value: '14,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'WETH', + marketAddress: '0x7234567890123456789012345678901234567890', + totalVotes: { + percentage: '30%', + limit: '120,000' + }, + myVotes: { + percentage: '12%', + value: '14,400' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'cbETH', + marketAddress: '0x8234567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'ezETH', + marketAddress: '0x9234567890123456789012345678901234567890', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '8%', + value: '6,400' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'weETH', + marketAddress: '0xa234567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'RSR', + marketAddress: '0xb234567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'wstETH', + marketAddress: '0xc234567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'wsuperOETHb', + marketAddress: '0xd234567890123456789012345678901234567890', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '8%', + value: '6,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'wUSDM', + marketAddress: '0xe234567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'USD+', + marketAddress: '0xf234567890123456789012345678901234567890', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '8%', + value: '6,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'wUSD+', + marketAddress: '0x1334567890123456789012345678901234567890', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '8%', + value: '6,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'USDz', + marketAddress: '0x2334567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'EURC', + marketAddress: '0x3334567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'cbBTC', + marketAddress: '0x4334567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'uSOL', + marketAddress: '0x5334567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'uSUI', + marketAddress: '0x6334567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'sUSDz', + marketAddress: '0x7334567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + } + ] + }, + [optimism.id]: { + '0': [ + { + asset: 'WETH', + marketAddress: '0x5234567890123456789012345678901234567890', + totalVotes: { + percentage: '35%', + limit: '140,000' + }, + myVotes: { + percentage: '15%', + value: '21,000' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'USDC', + marketAddress: '0x6234567890123456789012345678901234567890', + totalVotes: { + percentage: '30%', + limit: '120,000' + }, + myVotes: { + percentage: '12%', + value: '14,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'wstETH', + marketAddress: '0x7234567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: true, + poolType: 0 + }, + { + asset: 'wUSDM', + marketAddress: '0x8234567890123456789012345678901234567890', + totalVotes: { + percentage: '20%', + limit: '80,000' + }, + myVotes: { + percentage: '8%', + value: '6,400' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'SNX', + marketAddress: '0x9234567890123456789012345678901234567890', + totalVotes: { + percentage: '15%', + limit: '60,000' + }, + myVotes: { + percentage: '6%', + value: '3,600' + }, + autoVote: false, + poolType: 0 + }, + { + asset: 'weETH', + marketAddress: '0xa234567890123456789012345678901234567890', + totalVotes: { + percentage: '25%', + limit: '100,000' + }, + myVotes: { + percentage: '10%', + value: '10,000' + }, + autoVote: true, + poolType: 0 + } + ] + } +};