-
-
Notifications
You must be signed in to change notification settings - Fork 127
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve
/settings/nfts
and /settings/cycle
conflicting `reconfigu…
…reFundingCyclesOf` tx (#4068) Co-authored-by: Tom Quirk <[email protected]>
- Loading branch information
1 parent
72e6d24
commit 073e53c
Showing
8 changed files
with
378 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
...ts/CyclesPayoutsPanel/hooks/useConfigurationPanel/useFormatConfigurationCyclesSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import { t } from '@lingui/macro' | ||
import { AmountInCurrency } from 'components/currency/AmountInCurrency' | ||
import { timeSecondsToDateString } from 'components/v2v3/V2V3Project/ProjectDashboard/utils/timeSecondsToDateString' | ||
import { BigNumber } from 'ethers' | ||
import { V2V3CurrencyOption } from 'models/v2v3/currencyOption' | ||
import { V2V3FundingCycle } from 'models/v2v3/fundingCycle' | ||
import { useMemo } from 'react' | ||
import { fromWad } from 'utils/format/formatNumber' | ||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' | ||
import { getBallotStrategyByAddress } from 'utils/v2v3/ballotStrategies' | ||
import { V2V3CurrencyName } from 'utils/v2v3/currency' | ||
import { MAX_DISTRIBUTION_LIMIT } from 'utils/v2v3/math' | ||
import { ConfigurationPanelDatum } from '../../components/ConfigurationPanel' | ||
import { pairToDatum } from '../../utils/pairToDatum' | ||
|
||
export const useFormatConfigurationCyclesSection = ({ | ||
fundingCycle, | ||
upcomingFundingCycle, | ||
distributionLimitAmountCurrency, | ||
upcomingDistributionLimitAmountCurrency, | ||
}: { | ||
fundingCycle: V2V3FundingCycle | undefined | ||
upcomingFundingCycle?: V2V3FundingCycle | null | ||
distributionLimitAmountCurrency: | ||
| { | ||
distributionLimit: BigNumber | undefined | ||
currency: BigNumber | undefined | ||
} | ||
| undefined | ||
upcomingDistributionLimitAmountCurrency?: { | ||
distributionLimit: BigNumber | undefined | ||
currency: BigNumber | undefined | ||
} | null | ||
}) => { | ||
const durationDatum: ConfigurationPanelDatum = useMemo(() => { | ||
const formatDuration = (duration: BigNumber | undefined) => { | ||
if (duration === undefined) return undefined | ||
if (duration.eq(0)) return t`Not set` | ||
return timeSecondsToDateString(duration.toNumber(), 'short', 'lower') | ||
} | ||
const currentDuration = formatDuration(fundingCycle?.duration) | ||
if (upcomingFundingCycle === null) { | ||
return pairToDatum(t`Duration`, currentDuration, null) | ||
} | ||
const upcomingDuration = formatDuration(upcomingFundingCycle?.duration) | ||
|
||
return pairToDatum(t`Duration`, currentDuration, upcomingDuration) | ||
}, [fundingCycle?.duration, upcomingFundingCycle]) | ||
|
||
const payoutsDatum: ConfigurationPanelDatum = useMemo(() => { | ||
const formatCurrency = (currency: BigNumber | undefined) => { | ||
if (currency === undefined) return undefined | ||
return currency.toNumber() as V2V3CurrencyOption | ||
} | ||
const formatAmountWad = ( | ||
amountWad: BigNumber | undefined, | ||
currency: V2V3CurrencyOption | undefined, | ||
) => { | ||
if (amountWad === undefined) return undefined | ||
if (amountWad.eq(MAX_DISTRIBUTION_LIMIT)) return t`Unlimited` | ||
if (amountWad.eq(0)) return t`Zero (no payouts)` | ||
return formatCurrencyAmount({ | ||
amount: Number(fromWad(amountWad)), | ||
currency, | ||
}) | ||
} | ||
const { distributionLimit, currency } = | ||
distributionLimitAmountCurrency ?? {} | ||
// const currentPayout = formatAmountWad( | ||
// distributionLimit, | ||
// formatCurrency(currency), | ||
// ) | ||
const currentPayout = ( | ||
<AmountInCurrency | ||
amount={distributionLimit} | ||
currency={V2V3CurrencyName(formatCurrency(currency))} | ||
/> | ||
) | ||
|
||
if (upcomingDistributionLimitAmountCurrency === null) { | ||
return pairToDatum(t`Payouts`, currentPayout, null) | ||
} | ||
|
||
const upcomingDistributionLimit = | ||
upcomingDistributionLimitAmountCurrency?.distributionLimit !== undefined | ||
? upcomingDistributionLimitAmountCurrency.distributionLimit | ||
: undefined | ||
const upcomingDistributionLimitCurrency = | ||
upcomingDistributionLimitAmountCurrency?.currency !== undefined | ||
? upcomingDistributionLimitAmountCurrency.currency | ||
: undefined | ||
const upcomingPayout = formatAmountWad( | ||
upcomingDistributionLimit, | ||
formatCurrency(upcomingDistributionLimitCurrency), | ||
) | ||
|
||
return pairToDatum(t`Payouts`, currentPayout, upcomingPayout) | ||
}, [distributionLimitAmountCurrency, upcomingDistributionLimitAmountCurrency]) | ||
|
||
const editDeadlineDatum: ConfigurationPanelDatum = useMemo(() => { | ||
const currentBallotStrategy = fundingCycle?.ballot | ||
? getBallotStrategyByAddress(fundingCycle.ballot) | ||
: undefined | ||
const current = currentBallotStrategy?.name | ||
if (upcomingFundingCycle === null) { | ||
return pairToDatum(t`Edit deadline`, current, null) | ||
} | ||
|
||
const upcomingBallotStrategy = upcomingFundingCycle?.ballot | ||
? getBallotStrategyByAddress(upcomingFundingCycle.ballot) | ||
: undefined | ||
const upcoming = upcomingBallotStrategy?.name | ||
return pairToDatum(t`Edit deadline`, current, upcoming) | ||
}, [fundingCycle?.ballot, upcomingFundingCycle]) | ||
|
||
return useMemo(() => { | ||
return { | ||
duration: durationDatum, | ||
payouts: payoutsDatum, | ||
editDeadline: editDeadlineDatum, | ||
} | ||
}, [durationDatum, editDeadlineDatum, payoutsDatum]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
src/components/v2v3/V2V3Project/V2V3ProjectSettings/hooks/useResolveEditCycleConflicts.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { ProjectMetadataContext } from 'contexts/shared/ProjectMetadataContext' | ||
import { V2V3ProjectContext } from 'contexts/v2v3/Project/V2V3ProjectContext' | ||
import useProjectQueuedFundingCycle from 'hooks/v2v3/contractReader/useProjectQueuedFundingCycle' | ||
import { ReconfigureFundingCycleTxParams } from 'hooks/v2v3/transactor/useReconfigureV2V3FundingCycleTx' | ||
import { | ||
V2V3FundingCycleData, | ||
V2V3FundingCycleMetadata, | ||
} from 'models/v2v3/fundingCycle' | ||
import { useContext } from 'react' | ||
|
||
/** | ||
* Determines if a "Launch NFTs" (NftDeployer.reconfigureFundingCycleOf) has been called | ||
* in the same cycle as an "Edit cycle" (reconfigureFundingCycleOf) tx. | ||
* | ||
* If so, we need to pass the new delegate and other NFT-related data into the subsequent | ||
* "Edit cycle" tx so they are not overriden and lost. | ||
* | ||
* @param {V2V3FundingCycleMetadata} currentFcMetadata - The current funding cycle metadata. | ||
* @param {V2V3FundingCycleMetadata} queuedFcMetadata - The queued funding cycle metadata. | ||
* @returns {boolean} - Whether a conflict exists or not. | ||
*/ | ||
function hasNftConflict( | ||
currentFcMetadata: V2V3FundingCycleMetadata, | ||
queuedFcMetadata: V2V3FundingCycleMetadata, | ||
): boolean { | ||
// if the queued cycle's NFT data has any changes to the current cycle, return true. | ||
const useDataSourceForPayHasDiff = | ||
queuedFcMetadata.useDataSourceForPay !== | ||
currentFcMetadata.useDataSourceForPay | ||
const useDataSourceForRedeemHasDiff = | ||
queuedFcMetadata.useDataSourceForRedeem !== | ||
currentFcMetadata.useDataSourceForRedeem | ||
const useDataSourceHasDiff = | ||
queuedFcMetadata.dataSource !== currentFcMetadata.dataSource | ||
|
||
return ( | ||
useDataSourceForPayHasDiff || | ||
useDataSourceForRedeemHasDiff || | ||
useDataSourceHasDiff | ||
) | ||
} | ||
|
||
/** | ||
* | ||
* @returns | ||
*/ | ||
export const useResolveEditCycleConflicts = () => { | ||
const { projectId } = useContext(ProjectMetadataContext) | ||
const { fundingCycleMetadata } = useContext(V2V3ProjectContext) | ||
|
||
const { data: queuedCycle } = useProjectQueuedFundingCycle({ projectId }) | ||
|
||
// If no queued cycle, no resolving needs to be done. Return current data | ||
if (!queuedCycle || !fundingCycleMetadata) { | ||
return (data: ReconfigureFundingCycleTxParams) => data | ||
} | ||
|
||
const queuedFcData: V2V3FundingCycleData = queuedCycle[0] | ||
const queuedFcMetadata: V2V3FundingCycleMetadata = queuedCycle[1] | ||
|
||
return ( | ||
data: ReconfigureFundingCycleTxParams & { launchedNewNfts?: boolean }, | ||
) => { | ||
// Calling from "Edit cycle" and an NFT tx has be called same cycle: pass that previously queued NFT data into this "Edit cycle" tx | ||
if (hasNftConflict(fundingCycleMetadata, queuedFcMetadata)) { | ||
return { | ||
...data, | ||
fundingCycleMetadata: { | ||
...data.fundingCycleMetadata, | ||
useDataSourceForPay: queuedFcMetadata.useDataSourceForPay, | ||
useDataSourceForRedeem: queuedFcMetadata.useDataSourceForRedeem, | ||
dataSource: queuedFcMetadata.dataSource, | ||
}, | ||
} | ||
} | ||
// Calling from "Launch NFTs" and an "Edit cycle" tx has be called same cycle: pass that previously queued data into this "Launch NFTs" tx | ||
if (data.launchedNewNfts) { | ||
return { | ||
...data, | ||
fundingCycleMetadata: { | ||
...data.fundingCycleMetadata, | ||
...queuedFcMetadata, | ||
}, | ||
fundingCycleData: { | ||
...data.fundingCycleData, | ||
...queuedFcData, | ||
}, | ||
} | ||
// Calling "Edit cycle" when a previously "Edit cycle" tx exists: ignore the old tx data, return the new one | ||
} else return data | ||
} | ||
} |
Oops, something went wrong.
073e53c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
juice-interface-goerli – ./
juice-interface-goerli-peel.vercel.app
goerli.juicebox.money
juice-interface-goerli.vercel.app
juice-interface-goerli-git-main-peel.vercel.app