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.0><1>For example: with a 1-day edit deadline, edits must be made at least 1 day before a ruleset cycle starts.1>"
+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>queued0> 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.0><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.1><2>This choice isn't permanent — you can switch between locked and unlocked rulesets in the future.2>"
+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.0><1><2>This helps build trust with your contributors.2>1>"
+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-minimal1> 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.0><2>The Juicebox protocol is governed by a community of JBX token holders who vote on proposals fortnightly.2><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.3>"
msgstr ""
-msgid "<0>With unlocked rulesets, you can edit your project's rules at any time.0><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.1><2>This choice isn't permanent — you can switch between locked and unlocked rulesets in the future.2>"
-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>controller0> at any time."
msgstr ""
-msgid "<0>With Locked Rulesets, your project's rules are locked for a period of time.0><1><2>This helps build trust with your contributors.2>1>"
-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 Cycle0> 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>queued0> 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.0><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.1><2>This choice isn't permanent — you can switch between locked and unlocked rulesets in the future.2>"
+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.0><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.1><2>This choice isn't permanent — you can switch between locked and unlocked cycles in the future.2>"
-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
+}
+