From 78919aa7d5f08f22fe91a2d222af00d511750e2b Mon Sep 17 00:00:00 2001 From: Atatakai Date: Tue, 27 Aug 2024 14:51:16 +0400 Subject: [PATCH 1/3] (govern) feat: migrate donate to govern --- apps/govern/common-util/functions/requests.ts | 103 ++++++++- apps/govern/common-util/functions/web3.ts | 21 +- apps/govern/components/Donate/DonateForm.tsx | 134 ++++++++++++ apps/govern/components/Donate/hooks.ts | 104 +++++++++ apps/govern/components/Donate/index.tsx | 206 ++++++++++++++++++ apps/govern/components/Donate/styles.tsx | 50 +++++ apps/govern/components/Layout/Menu.tsx | 1 + .../{Proposals.spec.tsx => index.spec.tsx} | 2 +- .../Proposals/{Proposals.tsx => index.tsx} | 0 apps/govern/pages/donate.tsx | 3 + apps/govern/pages/proposals.tsx | 2 +- .../{treasury.js => treasury.ts} | 4 +- libs/util-functions/src/lib/requests.ts | 6 +- 13 files changed, 627 insertions(+), 9 deletions(-) create mode 100644 apps/govern/components/Donate/DonateForm.tsx create mode 100644 apps/govern/components/Donate/hooks.ts create mode 100644 apps/govern/components/Donate/index.tsx create mode 100644 apps/govern/components/Donate/styles.tsx rename apps/govern/components/Proposals/{Proposals.spec.tsx => index.spec.tsx} (95%) rename apps/govern/components/Proposals/{Proposals.tsx => index.tsx} (100%) create mode 100644 apps/govern/pages/donate.tsx rename libs/util-contracts/src/lib/abiAndAddresses/{treasury.js => treasury.ts} (99%) diff --git a/apps/govern/common-util/functions/requests.ts b/apps/govern/common-util/functions/requests.ts index f4d3de8b..0904e1ff 100644 --- a/apps/govern/common-util/functions/requests.ts +++ b/apps/govern/common-util/functions/requests.ts @@ -1,20 +1,29 @@ import { readContract, readContracts } from '@wagmi/core'; import { ethers } from 'ethers'; -import { AbiFunction, TransactionReceipt, parseUnits } from 'viem'; +import { Abi, AbiFunction, TransactionReceipt, parseUnits } from 'viem'; import { Address } from 'viem'; import { mainnet } from 'viem/chains'; + + import { sendTransaction } from '@autonolas/frontend-library'; -import { STAKING_FACTORY, VE_OLAS } from 'libs/util-contracts/src/lib/abiAndAddresses'; + + +import { SERVICE_REGISTRY, STAKING_FACTORY, VE_OLAS } from 'libs/util-contracts/src/lib/abiAndAddresses'; import { getEstimatedGasLimit } from 'libs/util-functions/src'; + + import { SUPPORTED_CHAINS, wagmiConfig } from 'common-util/config/wagmi'; import { RPC_URLS } from 'common-util/constants/rpcs'; + + import { getAddressFromBytes32 } from './addresses'; import { getUnixNextWeekStartTimestamp } from './time'; -import { getOlasContract, getVeOlasContract, getVoteWeightingContract } from './web3'; +import { getOlasContract, getTokenomicsContract, getTreasuryContract, getVeOlasContract, getVoteWeightingContract } from './web3'; + type VoteForNomineeWeightsParams = { account: Address | undefined; @@ -288,3 +297,91 @@ export const withdrawVeolasRequest = async ({ account }: { account: Address }) = throw error; } }; + +/** + * Start new epoch + */ +export const checkpointRequest = async ({ account }: { account: Address }) => { + const contract = getTokenomicsContract(); + try { + const checkpointFn = contract.methods.checkpoint(); + const estimatedGas = await getEstimatedGasLimit(checkpointFn, account); + const fn = checkpointFn.send({ from: account, gasLimit: estimatedGas }); + + const response = await sendTransaction(fn, account, { + supportedChains: SUPPORTED_CHAINS, + rpcUrls: RPC_URLS, + }); + + return (response as TransactionReceipt)?.transactionHash; + } catch (error) { + window.console.log('Error occurred on starting new epoch'); + throw error; + } +}; + +/** + * Check services are eligible for donating + */ + +export const checkServicesTerminatedOrNotDeployed = async (ids: string[]) => { + const invalidServiceIds: string[] = []; + + try { + const response = await readContracts(wagmiConfig, { + contracts: ids.map((id) => ({ + abi: SERVICE_REGISTRY.abi as Abi, + address: (SERVICE_REGISTRY.addresses as Record)[mainnet.id], + chainId: mainnet.id, + functionName: 'getService', + args: [id], + })), + }); + + response.forEach((service, index) => { + const serviceData = service.result as { state: number } | null; + if (serviceData && serviceData.state !== 4 && serviceData.state !== 5) { + invalidServiceIds.push(ids[index]); + } + }); + } catch (error) { + window.console.log('Error on checking service status'); + throw error; + } + + return invalidServiceIds; +}; + +/** + * Donate to services + */ + +export const depositServiceDonationRequest = async ({ + account, + serviceIds, + amounts, + totalAmount, +}: { + account: Address; + serviceIds: string[]; + amounts: string[]; + totalAmount: string; +}) => { + const contract = getTreasuryContract(); + + try { + const depositFn = contract.methods.depositServiceDonationsETH(serviceIds, amounts); + const estimatedGas = await getEstimatedGasLimit(depositFn, account, totalAmount); + const fn = depositFn.send({ from: account, value: totalAmount, gasLimit: estimatedGas }); + + const response = await sendTransaction(fn, account, { + supportedChains: SUPPORTED_CHAINS, + rpcUrls: RPC_URLS, + }); + + return (response as TransactionReceipt)?.transactionHash; + } catch (error) { + window.console.log('Error occurred on depositing service donation'); + throw error; + } +}; \ No newline at end of file diff --git a/apps/govern/common-util/functions/web3.ts b/apps/govern/common-util/functions/web3.ts index 3362c14a..390a43e8 100644 --- a/apps/govern/common-util/functions/web3.ts +++ b/apps/govern/common-util/functions/web3.ts @@ -2,10 +2,15 @@ import { mainnet } from 'viem/chains'; import Web3 from 'web3'; import { AbiItem } from 'web3-utils'; -import { OLAS, VE_OLAS, VOTE_WEIGHTING } from 'libs/util-contracts/src/lib/abiAndAddresses'; + + +import { OLAS, TOKENOMICS, TREASURY, VE_OLAS, VOTE_WEIGHTING } from 'libs/util-contracts/src/lib/abiAndAddresses'; + + import { getChainId, getProvider } from 'common-util/functions/frontend-library'; + /** * returns the web3 details */ @@ -46,3 +51,17 @@ export const getVeOlasContract = () => { const contract = getContract(abi, address); return contract; }; + +export const getTokenomicsContract = () => { + const abi = TOKENOMICS.abi as unknown as AbiItem[]; + const address = TOKENOMICS.addresses[mainnet.id]; + const contract = getContract(abi, address); + return contract; +}; + +export const getTreasuryContract = () => { + const abi = TREASURY.abi as AbiItem[]; + const address = TREASURY.addresses[mainnet.id]; + const contract = getContract(abi, address); + return contract; +}; \ No newline at end of file diff --git a/apps/govern/components/Donate/DonateForm.tsx b/apps/govern/components/Donate/DonateForm.tsx new file mode 100644 index 00000000..2131405d --- /dev/null +++ b/apps/govern/components/Donate/DonateForm.tsx @@ -0,0 +1,134 @@ +import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; +import { Button, Form, Grid, InputNumber, Space, Typography } from 'antd'; +import styled from 'styled-components'; +import { useAccount } from 'wagmi'; + +const { Text } = Typography; +const { useBreakpoint } = Grid; + +export const DynamicFormContainer = styled.div` + max-width: 720px; + .ant-input-number { + width: 200px; + } +`; + +type DonateFormProps = { + isLoading: boolean; + onSubmit: ({ unitIds, amounts }: { unitIds: number[]; amounts: number[] }) => Promise; +}; + +export const DonateForm = ({ isLoading, onSubmit }: DonateFormProps) => { + const { address: account } = useAccount(); + const [form] = Form.useForm(); + + const screens = useBreakpoint(); + const inputStyle = screens.xs ? { width: '140px' } : { width: 'auto' }; + + const onFinish = async (values: { units: { unitId: number; amount: number }[] }) => { + if (onSubmit) { + try { + await onSubmit({ + unitIds: values.units.map((unit) => unit.unitId), + amounts: values.units.map((unit) => unit.amount), + }); + + form.resetFields(); + } catch (error) { + window.console.error(error); + } + } + }; + + return ( + +
+ { + if (!units || units?.length === 0) { + return Promise.reject(new Error('At least 1 unit is required')); + } + return Promise.resolve(); + }, + }, + ]} + > + {(fields, { add, remove }, { errors }) => ( + <> + {fields.map((field) => ( + + prevValues.units !== curValues.units} + > + {() => ( + + + + )} + + + + + + + {fields.length > 1 && remove(field.name)} />} + + ))} + + + + + + + + )} + + + + + + {!account && ( + + To donate, connect a wallet + + )} + +
+
+ ); +}; diff --git a/apps/govern/components/Donate/hooks.ts b/apps/govern/components/Donate/hooks.ts new file mode 100644 index 00000000..c13ed9db --- /dev/null +++ b/apps/govern/components/Donate/hooks.ts @@ -0,0 +1,104 @@ +import { ethers } from 'ethers'; +import { useCallback, useMemo } from 'react'; +import { mainnet } from 'viem/chains'; +import { useReadContract } from 'wagmi'; + + + +import { TOKENOMICS, TREASURY } from 'libs/util-contracts/src/lib/abiAndAddresses'; + + +const useVeOLASThreshold = () => + useReadContract({ + address: TOKENOMICS.addresses[mainnet.id], + abi: TOKENOMICS.abi, + chainId: mainnet.id, + functionName: 'veOLASThreshold', + query: { + select: (data) => ethers.formatEther(`${data}`), + }, + }); + +const useMinAcceptedETH = () => + useReadContract({ + address: TREASURY.addresses[mainnet.id], + abi: TREASURY.abi, + chainId: mainnet.id, + functionName: 'minAcceptedETH', + }); + +const useEpochCounter = () => + useReadContract({ + address: TOKENOMICS.addresses[mainnet.id], + abi: TOKENOMICS.abi, + chainId: mainnet.id, + functionName: 'epochCounter', + }); + +const useEpochTokenomics = (epochCounter: number | undefined) => + useReadContract({ + address: TOKENOMICS.addresses[mainnet.id], + abi: TOKENOMICS.abi, + chainId: mainnet.id, + functionName: 'mapEpochTokenomics', + args: [BigInt(epochCounter || 0)], + query: { + enabled: epochCounter !== undefined, + }, + }); + +const useEpochLength = () => + useReadContract({ + address: TOKENOMICS.addresses[mainnet.id], + abi: TOKENOMICS.abi, + chainId: mainnet.id, + functionName: 'epochLen', + }); + +export const useThresholdData = () => { + const { data: veOLASThreshold, isFetching: isVeOLASThresholdFetching, refetch: refetchVeOLASThreshold } = useVeOLASThreshold(); + const { data: minAcceptedETH, isFetching: isMinAcceptedETHFetching, refetch: refetchMinAcceptedETH } = useMinAcceptedETH(); + const { data: epochCounter, isFetching: isEpochCounterFetching, refetch: refetchEpochCounter } = useEpochCounter(); + const { data: prevEpochPoint, isFetching: isPrevEpochPointFetching, refetch: refetchPrevEpochPoint } = useEpochTokenomics( + epochCounter !== undefined ? Number(epochCounter) - 1 : undefined, + ); + const { + data: epochLength, + isFetching: isEpochLengthFetching, + refetch: refetchEpochLength, + } = useEpochLength(); + + const nextEpochEndTime = useMemo(() => { + if (prevEpochPoint === undefined) return null; + if (epochLength === undefined) return null; + return prevEpochPoint.endTime + epochLength; + }, [prevEpochPoint, epochLength]); + + const refetchData = useCallback(async () => { + const promises = [ + refetchVeOLASThreshold(), + refetchMinAcceptedETH(), + refetchEpochCounter(), + refetchPrevEpochPoint(), + refetchEpochLength(), + ]; + + return Promise.all(promises); + }, []); + + return { + veOLASThreshold, + minAcceptedETH: minAcceptedETH as bigint | undefined, + epochCounter, + prevEpochEndTime: prevEpochPoint?.endTime, + epochLength, + nextEpochEndTime, + isDataLoading: + isVeOLASThresholdFetching || + isMinAcceptedETHFetching || + isEpochCounterFetching || + isPrevEpochPointFetching || + isEpochLengthFetching, + refetchData + }; +}; \ No newline at end of file diff --git a/apps/govern/components/Donate/index.tsx b/apps/govern/components/Donate/index.tsx new file mode 100644 index 00000000..ac93b3b1 --- /dev/null +++ b/apps/govern/components/Donate/index.tsx @@ -0,0 +1,206 @@ +import { Alert, Button, Skeleton, Typography } from 'antd'; +import { ethers } from 'ethers'; +import isNumber from 'lodash/isNumber'; +import Link from 'next/link'; +import { useState } from 'react'; +import { useAccount } from 'wagmi'; + +import { NA, getFullFormattedDate, notifySuccess } from '@autonolas/frontend-library'; + +import { notifyError } from 'libs/util-functions/src'; + +import { + checkServicesTerminatedOrNotDeployed, + checkpointRequest, + depositServiceDonationRequest, +} from 'common-util/functions'; + +import { DonateForm } from './DonateForm'; +import { useThresholdData } from './hooks'; +import { DonateContainer, EpochCheckpointRow, EpochStatus } from './styles'; + +const { Title, Paragraph, Text } = Typography; + +const sortUnitIdsAndAmounts = (unitIds: number[], amounts: number[]) => { + const sortedUnitIds = [...unitIds].sort((a, b) => a - b); + const sortedAmounts = sortedUnitIds.map((e) => amounts[unitIds.indexOf(e)]); + return [sortedUnitIds, sortedAmounts]; +}; + +export const DonatePage = () => { + const { address: account } = useAccount(); + + const [isDonationLoading, setIsDonationLoading] = useState(false); + const [isCheckpointLoading, setIsCheckpointLoading] = useState(false); + + const { + isDataLoading, + refetchData, + veOLASThreshold, + minAcceptedETH, + epochCounter, + prevEpochEndTime, + epochLength, + nextEpochEndTime, + } = useThresholdData(); + + const onDepositServiceDonationSubmit = async (values: { + unitIds: number[]; + amounts: number[]; + }) => { + if (!account) return; + + try { + setIsDonationLoading(true); + + const [sortedUnitIds, sortedAmounts] = sortUnitIdsAndAmounts(values.unitIds, values.amounts); + + const serviceIds = sortedUnitIds.map((e) => `${e}`); + + const invalidServices = await checkServicesTerminatedOrNotDeployed(serviceIds); + + // deposit only if all services are deployed or not terminated + if (invalidServices.length > 0) { + throw new Error( + `Provided service IDs are not deployed or terminated ${invalidServices.join(', ')}`, + ); + } else { + const amounts = sortedAmounts.map((e) => ethers.parseUnits(`${e}`, 18).toString()); + const totalAmount = amounts.reduce( + (a, b) => ethers.toBigInt(a) + ethers.toBigInt(b), + BigInt(0), + ); + + if (minAcceptedETH !== undefined && minAcceptedETH > totalAmount) { + throw new Error( + `At least ${ethers.formatEther( + `${minAcceptedETH}`, + )} ETH of donations is required to trigger boosts.`, + ); + } else { + const params = { + account, + serviceIds, + amounts, + totalAmount: totalAmount.toString(), + }; + + await depositServiceDonationRequest(params); + notifySuccess('Deposited service donation successfully'); + } + } + } catch (error) { + console.error(error); + const errorMessage = + (error as Error).message || 'Error occurred on depositing service donation'; + notifyError(errorMessage); + throw error; + } finally { + setIsDonationLoading(false); + } + }; + + const onCheckpoint = async () => { + if (!account) return; + + try { + setIsCheckpointLoading(true); + await checkpointRequest({ account }); + await refetchData(); // update epoch details after checkpoint + notifySuccess('Started new epoch'); + } catch (error) { + console.error(error); + const errorMessage = (error as Error).message || 'Error occurred on starting new epoch'; + notifyError(errorMessage); + } finally { + setIsCheckpointLoading(false); + } + }; + + const epochStatusList = [ + { + text: 'Earliest possible expected end time', + value: nextEpochEndTime ? getFullFormattedDate(nextEpochEndTime * 1000) : NA, + }, + { + text: 'Epoch length', + value: isNumber(epochLength) ? `${epochLength / 3600 / 24} days` : NA, + }, + { + text: 'Previous epoch end time', + value: prevEpochEndTime ? getFullFormattedDate(prevEpochEndTime * 1000) : NA, + }, + { + text: 'Epoch counter', + value: epochCounter || NA, + }, + ]; + + // disable checkpoint button if expected end time is in the future + const isExpectedEndTimeInFuture = (nextEpochEndTime || 0) * 1000 > Date.now(); + + return ( + +
+ + Donate + + + Show appreciation for the value of an autonomous service by making a donation. The + protocol will reward devs who have contributed code for that service. + + + + To boost rewards of devs with freshly minted OLAS, you must hold at least  + {veOLASThreshold || NA} +  veOLAS. Grab your veOLAS by locking OLAS  + here. At least  + + {minAcceptedETH ? ethers.formatEther(`${minAcceptedETH}`) : NA} +  ETH + +  of donations is required to trigger boosts. + + } + className="mb-16" + /> + + +
+ +
+ + Epoch Status + + + {epochStatusList.map(({ text, value }, index) => ( + + {`${text}:`} + {isDataLoading ? ( + + ) : ( + {value} + )} + + ))} + + + + New epochs must be manually triggered by community members + +
+
+ ); +}; diff --git a/apps/govern/components/Donate/styles.tsx b/apps/govern/components/Donate/styles.tsx new file mode 100644 index 00000000..59ba1325 --- /dev/null +++ b/apps/govern/components/Donate/styles.tsx @@ -0,0 +1,50 @@ +import styled from 'styled-components'; + +import { COLOR, MEDIA_QUERY } from 'libs/ui-theme/src'; + +export const DonateContainer = styled.div` + display: flex; + padding: 0 16px; + + .donate-section { + width: 720px; + } + .last-epoch-section { + padding-left: 1rem; + margin-left: 1rem; + border-left: 1px solid ${COLOR.BORDER_GREY_2}; + } + + ${MEDIA_QUERY.mobileL} { + flex-direction: column; + .donate-section { + width: 100%; + } + .last-epoch-section { + padding-left: 0; + margin-left: 0; + border-left: none; + } + } +`; + +export const EpochStatus = styled.div` + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.75rem; + h5, + div { + margin: 0; + } +`; + +export const EpochCheckpointRow = styled.div` + display: flex; + flex-direction: column; + gap: 4px; + margin-top: 1rem; + .ant-btn { + width: 200px; + } +`; diff --git a/apps/govern/components/Layout/Menu.tsx b/apps/govern/components/Layout/Menu.tsx index 6f4cb926..d981bd4a 100644 --- a/apps/govern/components/Layout/Menu.tsx +++ b/apps/govern/components/Layout/Menu.tsx @@ -12,6 +12,7 @@ const items: MenuItem[] = [ { label: 'Staking contracts', key: 'contracts', path: '/contracts' }, { label: 'Proposals', key: 'proposals', path: '/proposals' }, { label: 'veOLAS', key: 'veolas', path: '/veolas' }, + { label: 'Donate', key: 'donate', path: '/donate' }, { label: 'Docs', key: 'docs', path: '/docs' }, ]; diff --git a/apps/govern/components/Proposals/Proposals.spec.tsx b/apps/govern/components/Proposals/index.spec.tsx similarity index 95% rename from apps/govern/components/Proposals/Proposals.spec.tsx rename to apps/govern/components/Proposals/index.spec.tsx index 63d42e29..591ab2e9 100644 --- a/apps/govern/components/Proposals/Proposals.spec.tsx +++ b/apps/govern/components/Proposals/index.spec.tsx @@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react'; import { UNICODE_SYMBOLS } from 'libs/util-constants/src'; -import { ProposalsPage, proposals } from './Proposals'; +import { ProposalsPage, proposals } from './index'; describe('', () => { it('should display the page title and description', () => { diff --git a/apps/govern/components/Proposals/Proposals.tsx b/apps/govern/components/Proposals/index.tsx similarity index 100% rename from apps/govern/components/Proposals/Proposals.tsx rename to apps/govern/components/Proposals/index.tsx diff --git a/apps/govern/pages/donate.tsx b/apps/govern/pages/donate.tsx new file mode 100644 index 00000000..a655e295 --- /dev/null +++ b/apps/govern/pages/donate.tsx @@ -0,0 +1,3 @@ +import { DonatePage } from 'components/Donate'; + +export default DonatePage; diff --git a/apps/govern/pages/proposals.tsx b/apps/govern/pages/proposals.tsx index 1d63f204..c983755b 100644 --- a/apps/govern/pages/proposals.tsx +++ b/apps/govern/pages/proposals.tsx @@ -1,3 +1,3 @@ -import { ProposalsPage } from 'components/Proposals/Proposals'; +import { ProposalsPage } from 'components/Proposals'; export default ProposalsPage; diff --git a/libs/util-contracts/src/lib/abiAndAddresses/treasury.js b/libs/util-contracts/src/lib/abiAndAddresses/treasury.ts similarity index 99% rename from libs/util-contracts/src/lib/abiAndAddresses/treasury.js rename to libs/util-contracts/src/lib/abiAndAddresses/treasury.ts index aeb306c3..f8766fb7 100644 --- a/libs/util-contracts/src/lib/abiAndAddresses/treasury.js +++ b/libs/util-contracts/src/lib/abiAndAddresses/treasury.ts @@ -1,4 +1,6 @@ -export const TREASURY = { +import { Contract } from "./types"; + +export const TREASURY: Contract = { contractName: 'Treasury', addresses: { 1: '0xa0DA53447C0f6C4987964d8463da7e6628B30f82', diff --git a/libs/util-functions/src/lib/requests.ts b/libs/util-functions/src/lib/requests.ts index 36533382..3ac16366 100644 --- a/libs/util-functions/src/lib/requests.ts +++ b/libs/util-functions/src/lib/requests.ts @@ -1,5 +1,6 @@ import { Contract } from 'ethers'; + const ESTIMATED_GAS_LIMIT = 500_000; /** @@ -8,17 +9,18 @@ const ESTIMATED_GAS_LIMIT = 500_000; export const getEstimatedGasLimit = async ( fn: Contract['methods'], account: `0x${string}` | string | undefined, + value?: string, ) => { if (!account) { throw new Error('Invalid account passed to estimate gas limit'); } try { - const estimatedGas = await fn.estimateGas({ from: account }); + const estimatedGas = await fn.estimateGas({ from: account, value }); return Math.ceil(Number(estimatedGas) * 1.2); } catch (error) { window.console.warn(`Error occurred on estimating gas, defaulting to ${ESTIMATED_GAS_LIMIT}`); } return ESTIMATED_GAS_LIMIT; -}; +}; \ No newline at end of file From 0bf812e9c29c78a04414043c0e1b486d3d87a616 Mon Sep 17 00:00:00 2001 From: Atatakai Date: Tue, 27 Aug 2024 14:51:33 +0400 Subject: [PATCH 2/3] (tokenomics) feat: migrate donate to govern --- apps/tokenomics/components/Layout/index.jsx | 8 +++++--- apps/tokenomics/next.config.js | 7 ++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/tokenomics/components/Layout/index.jsx b/apps/tokenomics/components/Layout/index.jsx index b8bf8ead..e19f7143 100644 --- a/apps/tokenomics/components/Layout/index.jsx +++ b/apps/tokenomics/components/Layout/index.jsx @@ -45,12 +45,14 @@ const Layout = ({ children }) => { useEffect(() => { if (router.pathname) { const name = router.pathname.split('/')[1]; - setSelectedMenu(name || 'veolas'); + setSelectedMenu(name || 'dev-incentives'); } }, [router.pathname]); const handleMenuItemClick = ({ key }) => { - if (key === 'docs') { + if (key === 'donate') { + window.open('https://govern.olas.network/donate', '_blank'); + } else if (key === 'docs') { window.open('https://docs.autonolas.network/protocol/tokenomics/', '_blank'); } else if (key === 'bonding-products') { window.open('https://bond.olas.network/bonding-products', '_blank'); @@ -80,8 +82,8 @@ const Layout = ({ children }) => { selectedKeys={[selectedMenu]} onClick={handleMenuItemClick} items={[ - { key: 'donate', label: 'Donate' }, { key: 'dev-incentives', label: 'Dev Rewards' }, + { key: 'donate', label: }, { key: 'bonding-products', label: }, { key: 'my-bonds', label: }, { diff --git a/apps/tokenomics/next.config.js b/apps/tokenomics/next.config.js index 56e8cd93..ff80f99a 100644 --- a/apps/tokenomics/next.config.js +++ b/apps/tokenomics/next.config.js @@ -30,8 +30,13 @@ const nextConfig = { return [ { source: '/', - destination: '/donate', + destination: '/dev-incentives', permanent: false, + }, + { + source: '/donate', + destination: 'https://govern.olas.network/donate', + permanent: true, }, { source: '/bonding-products', From fde79aff7987e756bb42ab27d4c550adf1fa5f85 Mon Sep 17 00:00:00 2001 From: Atatakai Date: Tue, 27 Aug 2024 16:42:10 +0400 Subject: [PATCH 3/3] (govern) chore: review fixes --- apps/govern/common-util/functions/requests.ts | 27 ++++++------ apps/govern/common-util/functions/web3.ts | 15 ++++--- apps/govern/components/Donate/DonateForm.tsx | 22 +++++----- apps/govern/components/Donate/hooks.ts | 43 +++++++++++++------ apps/govern/components/Donate/index.tsx | 15 +++---- apps/govern/components/Donate/styles.tsx | 10 ++--- 6 files changed, 71 insertions(+), 61 deletions(-) diff --git a/apps/govern/common-util/functions/requests.ts b/apps/govern/common-util/functions/requests.ts index 0904e1ff..28c506aa 100644 --- a/apps/govern/common-util/functions/requests.ts +++ b/apps/govern/common-util/functions/requests.ts @@ -4,26 +4,27 @@ import { Abi, AbiFunction, TransactionReceipt, parseUnits } from 'viem'; import { Address } from 'viem'; import { mainnet } from 'viem/chains'; - - import { sendTransaction } from '@autonolas/frontend-library'; - - -import { SERVICE_REGISTRY, STAKING_FACTORY, VE_OLAS } from 'libs/util-contracts/src/lib/abiAndAddresses'; +import { + SERVICE_REGISTRY, + STAKING_FACTORY, + VE_OLAS, +} from 'libs/util-contracts/src/lib/abiAndAddresses'; import { getEstimatedGasLimit } from 'libs/util-functions/src'; - - import { SUPPORTED_CHAINS, wagmiConfig } from 'common-util/config/wagmi'; import { RPC_URLS } from 'common-util/constants/rpcs'; - - import { getAddressFromBytes32 } from './addresses'; import { getUnixNextWeekStartTimestamp } from './time'; -import { getOlasContract, getTokenomicsContract, getTreasuryContract, getVeOlasContract, getVoteWeightingContract } from './web3'; - +import { + getOlasContract, + getTokenomicsContract, + getTreasuryContract, + getVeOlasContract, + getVoteWeightingContract, +} from './web3'; type VoteForNomineeWeightsParams = { account: Address | undefined; @@ -323,7 +324,6 @@ export const checkpointRequest = async ({ account }: { account: Address }) => { /** * Check services are eligible for donating */ - export const checkServicesTerminatedOrNotDeployed = async (ids: string[]) => { const invalidServiceIds: string[] = []; @@ -355,7 +355,6 @@ export const checkServicesTerminatedOrNotDeployed = async (ids: string[]) => { /** * Donate to services */ - export const depositServiceDonationRequest = async ({ account, serviceIds, @@ -384,4 +383,4 @@ export const depositServiceDonationRequest = async ({ window.console.log('Error occurred on depositing service donation'); throw error; } -}; \ No newline at end of file +}; diff --git a/apps/govern/common-util/functions/web3.ts b/apps/govern/common-util/functions/web3.ts index 390a43e8..0640eb5b 100644 --- a/apps/govern/common-util/functions/web3.ts +++ b/apps/govern/common-util/functions/web3.ts @@ -2,15 +2,16 @@ import { mainnet } from 'viem/chains'; import Web3 from 'web3'; import { AbiItem } from 'web3-utils'; - - -import { OLAS, TOKENOMICS, TREASURY, VE_OLAS, VOTE_WEIGHTING } from 'libs/util-contracts/src/lib/abiAndAddresses'; - - +import { + OLAS, + TOKENOMICS, + TREASURY, + VE_OLAS, + VOTE_WEIGHTING, +} from 'libs/util-contracts/src/lib/abiAndAddresses'; import { getChainId, getProvider } from 'common-util/functions/frontend-library'; - /** * returns the web3 details */ @@ -64,4 +65,4 @@ export const getTreasuryContract = () => { const address = TREASURY.addresses[mainnet.id]; const contract = getContract(abi, address); return contract; -}; \ No newline at end of file +}; diff --git a/apps/govern/components/Donate/DonateForm.tsx b/apps/govern/components/Donate/DonateForm.tsx index 2131405d..6c1c535f 100644 --- a/apps/govern/components/Donate/DonateForm.tsx +++ b/apps/govern/components/Donate/DonateForm.tsx @@ -26,17 +26,15 @@ export const DonateForm = ({ isLoading, onSubmit }: DonateFormProps) => { const inputStyle = screens.xs ? { width: '140px' } : { width: 'auto' }; const onFinish = async (values: { units: { unitId: number; amount: number }[] }) => { - if (onSubmit) { - try { - await onSubmit({ - unitIds: values.units.map((unit) => unit.unitId), - amounts: values.units.map((unit) => unit.amount), - }); + try { + await onSubmit({ + unitIds: values.units.map((unit) => unit.unitId), + amounts: values.units.map((unit) => unit.amount), + }); - form.resetFields(); - } catch (error) { - window.console.error(error); - } + form.resetFields(); + } catch (error) { + window.console.error(error); } }; @@ -103,7 +101,7 @@ export const DonateForm = ({ isLoading, onSubmit }: DonateFormProps) => { - @@ -111,7 +109,7 @@ export const DonateForm = ({ isLoading, onSubmit }: DonateFormProps) => { )} - + New epochs must be manually triggered by community members - + ); }; diff --git a/apps/govern/components/Donate/styles.tsx b/apps/govern/components/Donate/styles.tsx index 59ba1325..484d0ba3 100644 --- a/apps/govern/components/Donate/styles.tsx +++ b/apps/govern/components/Donate/styles.tsx @@ -1,21 +1,19 @@ import styled from 'styled-components'; -import { COLOR, MEDIA_QUERY } from 'libs/ui-theme/src'; +import { MEDIA_QUERY } from 'libs/ui-theme/src'; export const DonateContainer = styled.div` display: flex; - padding: 0 16px; + gap: 16px; .donate-section { width: 720px; } .last-epoch-section { - padding-left: 1rem; - margin-left: 1rem; - border-left: 1px solid ${COLOR.BORDER_GREY_2}; + flex: auto; } - ${MEDIA_QUERY.mobileL} { + ${MEDIA_QUERY.tabletL} { flex-direction: column; .donate-section { width: 100%;