From 78127179c5c762c02d388ca780c41861d02b3189 Mon Sep 17 00:00:00 2001 From: johnnyd-eth Date: Tue, 29 Oct 2024 17:56:52 +1100 Subject: [PATCH] feat: update cycle/ruleset verbiage for v4 --- src/components/strings.tsx | 27 ++++-- src/locales/messages.pot | 51 ++++++++---- .../v2v3/constants/ballotStrategies/index.ts | 6 +- src/packages/v4/components/Create/Create.tsx | 13 +-- .../pages/FundingCycles/FundingCyclesPage.tsx | 21 ++--- .../ReconfigurationRulesPage.tsx | 13 +-- .../useAvailableReconfigurationStrategies.ts | 2 +- .../components/ReceiveTokensItem.tsx | 24 ++---- .../hooks/useProjectPaymentTokens.ts | 9 +- .../v4/constants/ballotStrategies/index.ts | 83 +++++++++++++++++++ 10 files changed, 179 insertions(+), 70 deletions(-) create mode 100644 src/packages/v4/constants/ballotStrategies/index.ts diff --git a/src/components/strings.tsx b/src/components/strings.tsx index 2d80c61a48..300f160ff3 100644 --- a/src/components/strings.tsx +++ b/src/components/strings.tsx @@ -1,4 +1,8 @@ import { Trans } from '@lingui/macro' +import ExternalLink from 'components/ExternalLink' +import Link from 'next/link' +import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' +import { helpPagePath } from 'utils/helpPagePath' export const ISSUE_ERC20_EXPLANATION = ( @@ -29,15 +33,15 @@ export const CYCLE_EXPLANATION = ( supporters.

- This choice isn't permanent — you can switch between locked and unlocked - cycles in the future. + This choice isn't permanent — you can switch between locked and unlocked rulesets + in the future.

) export const RULESET_EXPLANATION = ( -

With unlocked rulesets, you can edit your project's rules at any time.

+

With unlocked ruleset cycles, you can edit your project's rules at any time.

With locked rulesets, you can lock your project's rules for a period of time (like 3 minutes, 2 years, or 14 days), helping you build trust with your @@ -57,10 +61,6 @@ export const LOCKED_PAYOUT_EXPLANATION = ( ) -import ExternalLink from 'components/ExternalLink' -import Link from 'next/link' -import { v2v3ProjectRoute } from 'packages/v2v3/utils/routes' -import { helpPagePath } from 'utils/helpPagePath' export const DISTRIBUTION_LIMIT_EXPLANATION = ( @@ -216,6 +216,19 @@ export const RECONFIG_RULES_EXPLANATION = ( ) +export const DEADLINE_EXPLANATION = ( + +

+ Edits to this project must be made before this deadline. This gives token + holders time to verify the edits before they take effect. +

+

+ For example: with a 1-day edit deadline, edits must be made at least 1 day + before a ruleset cycle starts. +

+
+) + export const RECONFIG_RULES_WARN = ( Adding an edit deadline is recommended. Projects with no deadline will diff --git a/src/locales/messages.pot b/src/locales/messages.pot index 77a55f2016..59a1d53d17 100644 --- a/src/locales/messages.pot +++ b/src/locales/messages.pot @@ -218,6 +218,9 @@ msgstr "" msgid "Staked balance" msgstr "" +msgid "<0>Edits to this project must be made before this deadline. This gives token holders time to verify the edits before they take effect.<1>For example: with a 1-day edit deadline, edits must be made at least 1 day before a ruleset cycle starts." +msgstr "" + msgid "While enabled, the project owner can mint any amount of project tokens." msgstr "" @@ -233,6 +236,9 @@ msgstr "" msgid "Set a future date & time to start your project's first cycle." msgstr "" +msgid "Ruleset #1 starts when you create your project. With locked ruleset cycles, if you edit your project's rules during Ruleset #1, those edits will be <0>queued for the next ruleset." +msgstr "" + msgid "No" msgstr "" @@ -245,6 +251,9 @@ msgstr "" msgid "Amount (USD)" msgstr "" +msgid "<0>With unlocked ruleset cycles, you can edit your project's rules at any time.<1>With locked rulesets, you can lock your project's rules for a period of time (like 3 minutes, 2 years, or 14 days), helping you build trust with your supporters.<2>This choice isn't permanent — you can switch between locked and unlocked rulesets in the future." +msgstr "" + msgid "Payout recipients" msgstr "" @@ -1007,6 +1016,9 @@ msgstr "" msgid "Redeem {0} {tokensTextShort} for ETH" msgstr "" +msgid "<0>With Locked Ruleset Cycles, your project's rules are locked for a period of time.<1><2>This helps build trust with your contributors." +msgstr "" + msgid "Are you sure you want to remove {0}?" msgstr "" @@ -1301,6 +1313,9 @@ msgstr "" msgid "Use NFTs for redemptions" msgstr "" +msgid "Set a cycle duration for locked rulesets." +msgstr "" + msgid "Assets" msgstr "" @@ -1349,6 +1364,9 @@ msgstr "" msgid "Need help?" msgstr "" +msgid "{receivedTokenSymbolText}" +msgstr "" + msgid "Custom strategy" msgstr "" @@ -1457,9 +1475,6 @@ msgstr "" msgid "<0>Juicebox is a <1>governance-minimal protocol. There are only a few levers that can be tuned, none of which impose changes for users without their consent. The Juicebox governance smart contract can adjust these levers.<2>The Juicebox protocol is governed by a community of JBX token holders who vote on proposals fortnightly.<3>Juicebox is on-chain and non-custodial. Project creators actually own their projects, and JuiceboxDAO has no way to access project's ETH or change their rules." msgstr "" -msgid "<0>With unlocked rulesets, you can edit your project's rules at any time.<1>With locked rulesets, you can lock your project's rules for a period of time (like 3 minutes, 2 years, or 14 days), helping you build trust with your supporters.<2>This choice isn't permanent — you can switch between locked and unlocked rulesets in the future." -msgstr "" - msgid "Pay {projectTitle}" msgstr "" @@ -1847,9 +1862,6 @@ msgstr "" msgid "Project rules" msgstr "" -msgid "Set a duration for locked rulesets." -msgstr "" - msgid "Upload" msgstr "" @@ -2471,9 +2483,6 @@ msgstr "" msgid "While enabled, the project owner can change the project's <0>controller at any time." msgstr "" -msgid "<0>With Locked Rulesets, your project's rules are locked for a period of time.<1><2>This helps build trust with your contributors." -msgstr "" - msgid "Ruleset #" msgstr "" @@ -2489,6 +2498,9 @@ msgstr "" msgid "Read case studies" msgstr "" +msgid "{days, plural, one {Edits to an upcoming ruleset cycle must be submitted at least # day before that ruleset cycle starts.} other {Edits to an upcoming ruleset cycle must be submitted at least # days before that ruleset cycle starts.}}" +msgstr "" + msgid "tokens" msgstr "" @@ -3020,6 +3032,9 @@ msgstr "" msgid "Your legacy balance" msgstr "" +msgid "ERC-20" +msgstr "" + msgid "Error loading ETH transfers to project" msgstr "" @@ -3068,6 +3083,9 @@ msgstr "" msgid "Deploy NFT collection" msgstr "" +msgid "Edits to upcoming ruleset cycles will take effect when the current cycle ends. A project with no deadline is vulnerable to last-second edits by its owner." +msgstr "" + msgid "You must <0>Edit your Cycle to change your total payout amount." msgstr "" @@ -3209,13 +3227,13 @@ msgstr "" msgid "Payout total (max.)" msgstr "" -msgid "Prevent NFT overspending" +msgid "Locked Ruleset Cycles" msgstr "" -msgid "Yes, start over" +msgid "Prevent NFT overspending" msgstr "" -msgid "Ruleset #1 starts when you create your project. With locked rulesets, if you edit your project's rules during Ruleset #1, those edits will be <0>queued for the next ruleset." +msgid "Yes, start over" msgstr "" msgid "All {tokensText} will go to the project owner:" @@ -3401,6 +3419,9 @@ msgstr "" msgid "New" msgstr "" +msgid "<0>With unlocked cycles, you can edit your project's rules at any time.<1>With locked cycles, you can lock your project's rules for a period of time (like 3 minutes, 2 years, or 14 days), helping you build trust with your supporters.<2>This choice isn't permanent — you can switch between locked and unlocked rulesets in the future." +msgstr "" + msgid "This project has no upcoming ruleset. Its rules can change at any time." msgstr "" @@ -3647,9 +3668,6 @@ msgstr "" msgid "Redeem {tokensLabel} for ETH" msgstr "" -msgid "Locked Rulesets" -msgstr "" - msgid "Made a mistake?" msgstr "" @@ -3689,9 +3707,6 @@ msgstr "" msgid "Request a feature" msgstr "" -msgid "<0>With unlocked cycles, you can edit your project's rules at any time.<1>With locked cycles, you can lock your project's rules for a period of time (like 3 minutes, 2 years, or 14 days), helping you build trust with your supporters.<2>This choice isn't permanent — you can switch between locked and unlocked cycles in the future." -msgstr "" - msgid "I confirm that the use and redemption of crypto tokens is legal in my jurisdiction, and that I am fully responsible for compliance with all relevant laws and regulations." msgstr "" diff --git a/src/packages/v2v3/constants/ballotStrategies/index.ts b/src/packages/v2v3/constants/ballotStrategies/index.ts index e431bb3f54..2384a345b4 100644 --- a/src/packages/v2v3/constants/ballotStrategies/index.ts +++ b/src/packages/v2v3/constants/ballotStrategies/index.ts @@ -1,12 +1,12 @@ import { plural, t } from '@lingui/macro' + +import { CV_V2 } from 'constants/cv' import { readNetwork } from 'constants/networks' import { SECONDS_IN_DAY } from 'constants/numbers' import { constants } from 'ethers' -import { CV2V3 } from 'packages/v2v3/models/cv' - -import { CV_V2 } from 'constants/cv' import { NetworkName } from 'models/networkName' import { ReconfigurationStrategy } from 'models/reconfigurationStrategy' +import { CV2V3 } from 'packages/v2v3/models/cv' type BallotOption = Record< 'ONE_DAY' | 'THREE_DAY' | 'SEVEN_DAY', diff --git a/src/packages/v4/components/Create/Create.tsx b/src/packages/v4/components/Create/Create.tsx index e641cd834c..e4bd960031 100644 --- a/src/packages/v4/components/Create/Create.tsx +++ b/src/packages/v4/components/Create/Create.tsx @@ -1,11 +1,12 @@ -import { t, Trans } from '@lingui/macro' +import { Trans, t } from '@lingui/macro' +import { + DEADLINE_EXPLANATION, + RULESET_EXPLANATION +} from 'components/strings' + import { Badge } from 'components/Badge' import { DeployButtonText } from 'components/buttons/DeployProjectButtonText' import Loading from 'components/Loading' -import { - RECONFIG_RULES_EXPLANATION, - RULESET_EXPLANATION, -} from 'components/strings' import { readNetwork } from 'constants/networks' import { NetworkName } from 'models/networkName' import { useRouter } from 'next/router' @@ -102,7 +103,7 @@ export function Create() { Edit Deadline} - description={RECONFIG_RULES_EXPLANATION} + description={DEADLINE_EXPLANATION} > diff --git a/src/packages/v4/components/Create/components/pages/FundingCycles/FundingCyclesPage.tsx b/src/packages/v4/components/Create/components/pages/FundingCycles/FundingCyclesPage.tsx index 0bda8587e0..d269012810 100644 --- a/src/packages/v4/components/Create/components/pages/FundingCycles/FundingCyclesPage.tsx +++ b/src/packages/v4/components/Create/components/pages/FundingCycles/FundingCyclesPage.tsx @@ -5,6 +5,12 @@ import { } from '@ant-design/icons' import { Trans, t } from '@lingui/macro' import { Form, Tooltip } from 'antd' +import { useContext, useEffect } from 'react' +import { + FundingCyclesFormProps, + useFundingCyclesForm, +} from './hooks/useFundingCyclesForm' + import { useWatch } from 'antd/lib/form/Form' import { Callout } from 'components/Callout/Callout' import { DurationInput } from 'components/inputs/DurationInput' @@ -14,7 +20,6 @@ import { trackFathomGoal } from 'lib/fathom' import moment from 'moment' import Link from 'next/link' import { useLockPageRulesWrapper } from 'packages/v2v3/components/Create/hooks/useLockPageRulesWrapper' -import { useContext, useEffect } from 'react' import { useSetCreateFurthestPageReached } from 'redux/hooks/useEditingCreateFurthestPageReached' import { durationMustExistRule } from 'utils/antdRules' import { CreateBadge } from '../../CreateBadge' @@ -22,12 +27,8 @@ import { CreateCollapse } from '../../CreateCollapse/CreateCollapse' import { Icons } from '../../Icons' import { OptionalHeader } from '../../OptionalHeader' import { Selection } from '../../Selection/Selection' -import { Wizard } from '../../Wizard/Wizard' import { PageContext } from '../../Wizard/contexts/PageContext' -import { - FundingCyclesFormProps, - useFundingCyclesForm, -} from './hooks/useFundingCyclesForm' +import { Wizard } from '../../Wizard/Wizard' const FundingCycleCallout: React.FC> = () => { const form = Form.useFormInstance() @@ -41,7 +42,7 @@ const FundingCycleCallout: React.FC> = () => {

- Ruleset #1 starts when you create your project. With locked rulesets, + Ruleset #1 starts when you create your project. With locked ruleset cycles, if you edit your project's rules during Ruleset #1, those edits will be queued for the next ruleset. @@ -117,13 +118,13 @@ export const FundingCyclesPage = () => { name="automated" title={

- Locked Rulesets{' '} + Locked Ruleset Cycles{' '}

- With Locked Rulesets, your project's rules are + With Locked Ruleset Cycles, your project's rules are locked for a period of time.

@@ -137,7 +138,7 @@ export const FundingCyclesPage = () => { />

} - description={t`Set a duration for locked rulesets.`} + description={t`Set a cycle duration for locked rulesets.`} icon={} > { diff --git a/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/components/ReceiveTokensItem.tsx b/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/components/ReceiveTokensItem.tsx index 9b5bf7e33f..3aa82bbce0 100644 --- a/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/components/ReceiveTokensItem.tsx +++ b/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/components/ReceiveTokensItem.tsx @@ -1,24 +1,16 @@ import { Trans } from '@lingui/macro' import { CartItemBadge } from 'components/CartItemBadge' import { ProjectHeaderLogo } from 'components/Project/ProjectHeader/ProjectHeaderLogo' -import { ProjectMetadataContext } from 'contexts/ProjectMetadataContext' +import { twMerge } from 'tailwind-merge' // import { useProjectHasErc20Token } from 'packages/v2v3/components/V2V3Project/ProjectDashboard/hooks/useProjectHasErc20Token' // import { BUYBACK_DELEGATE_ENABLED_PROJECT_IDS } from 'packages/v2v3/constants/buybackDelegateEnabledProjectIds' -import { useContext } from 'react' -import { twMerge } from 'tailwind-merge' +import { useProjectHasErc20Token } from 'packages/v4/hooks/useProjectHasErc20Token' import { useProjectPaymentTokens } from '../hooks/useProjectPaymentTokens' export const ReceiveTokensItem = ({ className }: { className?: string }) => { - const { projectId } = useContext(ProjectMetadataContext) const { receivedTickets, receivedTokenSymbolText } = useProjectPaymentTokens() - // const projectHasErc20Token = useProjectHasErc20Token() - const projectHasErc20Token = false + const projectHasErc20Token = useProjectHasErc20Token() - const badgeTitle = projectHasErc20Token ? ( - 'ERC-20' - ) : ( - Juicebox Native - ) if (receivedTickets === '0') { return null @@ -30,11 +22,13 @@ export const ReceiveTokensItem = ({ className }: { className?: string }) => {
- {receivedTokenSymbolText} Token + {receivedTokenSymbolText} - - {badgeTitle} Token - + { projectHasErc20Token ? + + ERC-20 + + : null}
{receivedTickets}
diff --git a/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/hooks/useProjectPaymentTokens.ts b/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/hooks/useProjectPaymentTokens.ts index ae6283fb0e..379752e218 100644 --- a/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/hooks/useProjectPaymentTokens.ts +++ b/src/packages/v4/components/ProjectDashboard/V4PayRedeemCard/PayProjectModal/hooks/useProjectPaymentTokens.ts @@ -1,10 +1,11 @@ -import { FixedInt } from 'fpnum' -import { getTokenAToBQuote, NATIVE_TOKEN_DECIMALS } from 'juice-sdk-core' +import { NATIVE_TOKEN_DECIMALS, getTokenAToBQuote } from 'juice-sdk-core' import { useJBRulesetContext, useJBTokenContext, useNativeTokenSymbol, } from 'juice-sdk-react' + +import { FixedInt } from 'fpnum' import { useProjectSelector } from 'packages/v4/components/ProjectDashboard/redux/hooks' import { V4_CURRENCY_USD } from 'packages/v4/utils/currency' import { tokenSymbolText } from 'utils/tokenSymbolText' @@ -48,7 +49,7 @@ export const useProjectPaymentTokens = () => { receivedTickets, receivedTokenSymbolText: receivedTokenSymbolText === 'tokens' - ? 'Project' - : receivedTokenSymbolText, + ? 'Project Token Credits' + : `${receivedTokenSymbolText} Token`, } } diff --git a/src/packages/v4/constants/ballotStrategies/index.ts b/src/packages/v4/constants/ballotStrategies/index.ts new file mode 100644 index 0000000000..b09263a0b2 --- /dev/null +++ b/src/packages/v4/constants/ballotStrategies/index.ts @@ -0,0 +1,83 @@ +import { plural, t } from '@lingui/macro' + +import { readNetwork } from 'constants/networks' +import { SECONDS_IN_DAY } from 'constants/numbers' +import { constants } from 'ethers' +import { NetworkName } from 'models/networkName' +import { ReconfigurationStrategy } from 'models/reconfigurationStrategy' + +type BallotOption = Record< + 'ONE_DAY' | 'THREE_DAY' | 'SEVEN_DAY', + Partial> +> + + +// v4TODO: Apply real v4 addresses +const BALLOT_ADDRESSES: BallotOption = { + ONE_DAY: { + mainnet: '0xDd9303491328F899796319C2b6bD614324b86314', + sepolia: '0x34E2992ea3C3E6CcfCf5bC668B68F285C1EDFE24', + }, + THREE_DAY: { + mainnet: '0x19D8C293D35EA4b2879A864A68D45a2025694929', + sepolia: '0xa2154aBD135be068540073cB4390139906d0FDc6', + }, + SEVEN_DAY: { + mainnet: '0x8E1AEc30063565e597705E71Ba14Dffc4C390Ef0', + sepolia: '0xb958fEa9089208d0Cc990EceCEcc42458F1B618e', + }, +} + +interface BallotStrategy { + id: ReconfigurationStrategy + name: string + description: string + address: string + durationSeconds: number +} + +const durationBallotStrategyDescription = (days: number) => + plural(days, { + one: 'Edits to an upcoming ruleset cycle must be submitted at least # day before that ruleset cycle starts.', + other: + 'Edits to an upcoming ruleset cycle must be submitted at least # days before that ruleset cycle starts.', + }) + +export function ballotStrategiesFn({ + network, +}: { + network?: NetworkName +} = {}): BallotStrategy[] { + const ballotStrategies: BallotStrategy[] = [ + { + id: 'none', + name: t`No deadline`, + description: t`Edits to upcoming ruleset cycles will take effect when the current cycle ends. A project with no deadline is vulnerable to last-second edits by its owner.`, + address: constants.AddressZero, + durationSeconds: 0, + }, + { + id: 'oneDay', + name: t`1-day deadline`, + description: durationBallotStrategyDescription(1), + address: BALLOT_ADDRESSES.ONE_DAY[network ?? readNetwork.name]!, + durationSeconds: SECONDS_IN_DAY, + }, + { + id: 'threeDay', + name: t`3-day deadline`, + description: durationBallotStrategyDescription(3), + address: BALLOT_ADDRESSES.THREE_DAY[network ?? readNetwork.name]!, + durationSeconds: SECONDS_IN_DAY * 3, + }, + { + id: 'sevenDay', + name: t`7-day deadline`, + description: durationBallotStrategyDescription(7), + address: BALLOT_ADDRESSES.SEVEN_DAY[network ?? readNetwork.name]!, + durationSeconds: SECONDS_IN_DAY * 7, + }, + ] + return ballotStrategies +} +