Skip to content

Commit

Permalink
feat: transform v2v3 create flow data to v4
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnyd-eth committed Aug 29, 2024
1 parent 239552a commit 8039440
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 152 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const getProjectIdFromLaunchReceipt = (
* Attempt to find the transaction receipt from a transaction hash.
* Will retry up to 5 times with a 2 second delay between each attempt. If no
* receipt is found after 5 attempts, undefined is returned.
* receipt is not found after 5 attempts, undefined is returned.
*
* @param txHash transaction hash
* @returns transaction receipt or undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { useJBPrices } from 'packages/v2v3/hooks/JBPrices'
import { DEFAULT_JB_721_DELEGATE_VERSION } from 'packages/v2v3/hooks/defaultContracts/useDefaultJB721Delegate'
import { useDefaultJBController } from 'packages/v2v3/hooks/defaultContracts/useDefaultJBController'
import { useDefaultJBETHPaymentTerminal } from 'packages/v2v3/hooks/defaultContracts/useDefaultJBETHPaymentTerminal'
import { LaunchProjectData } from 'packages/v2v3/hooks/transactor/useLaunchProjectTx'
import { LaunchV2V3ProjectData } from 'packages/v2v3/hooks/transactor/useLaunchProjectTx'
import { useV2ProjectTitle } from 'packages/v2v3/hooks/useProjectTitle'
import { V2V3CurrencyOption } from 'packages/v2v3/models/currencyOption'
import {
Expand Down Expand Up @@ -61,7 +61,7 @@ interface JB721DelegateLaunchFundingCycleData {

interface LaunchProjectWithNftsTxArgs {
tiered721DelegateData: DeployTiered721DelegateData
projectData: LaunchProjectData
projectData: LaunchV2V3ProjectData
}

type JB721DelegateLaunchProjectData = JB721DelegateLaunchFundingCycleData & {
Expand Down
4 changes: 2 additions & 2 deletions src/packages/v2v3/hooks/transactor/useLaunchProjectTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useContext } from 'react'
import { DEFAULT_MUST_START_AT_OR_AFTER } from 'redux/slices/editingV2Project'
import { useV2ProjectTitle } from '../useProjectTitle'

export interface LaunchProjectData {
export interface LaunchV2V3ProjectData {
projectMetadataCID: string
fundingCycleData: V2V3FundingCycleData
fundingCycleMetadata: V2V3FundingCycleMetadata
Expand All @@ -31,7 +31,7 @@ export interface LaunchProjectData {
owner?: string // If not provided, the current user's address will be used.
}

export function useLaunchProjectTx(): TransactorInstance<LaunchProjectData> {
export function useLaunchProjectTx(): TransactorInstance<LaunchV2V3ProjectData> {
const { transactor } = useContext(TransactionContext)
const { contracts } = useContext(V2V3ContractsContext)
const defaultJBController = useDefaultJBController()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { isValidMustStartAtOrAfter } from 'packages/v2v3/utils/fundingCycle'
import { useContext } from 'react'
import { DEFAULT_MUST_START_AT_OR_AFTER } from 'redux/slices/editingV2Project'
import { useV2ProjectTitle } from '../useProjectTitle'
import { LaunchProjectData } from './useLaunchProjectTx'
import { LaunchV2V3ProjectData } from './useLaunchProjectTx'

export type ReconfigureFundingCycleTxParams = Omit<
LaunchProjectData,
LaunchV2V3ProjectData,
'projectMetadataCID'
> & {
memo?: string
Expand Down
3 changes: 2 additions & 1 deletion src/packages/v4/components/Create/Create.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { t, Trans } from '@lingui/macro'
import { DeployButtonText } from 'components/buttons/DeployProjectButtonText'
import Loading from 'components/Loading'
import {
CYCLE_EXPLANATION,
RECONFIG_RULES_EXPLANATION,
Expand All @@ -24,7 +25,7 @@ export function Create() {
const deployedProjectId = router.query.deployedProjectId as string
const initialStateLoading = useLoadingInitialStateFromQuery()

if (initialStateLoading) return <>XX</>//<Loading />
if (initialStateLoading) return <Loading />

if (deployedProjectId) {
const projectId = parseInt(deployedProjectId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { emitConfirmationDeletionModal } from 'hooks/emitConfirmationDeletionMod
import useMobile from 'hooks/useMobile'
import { useModal } from 'hooks/useModal'
import { useRouter } from 'next/router'
import { useDeployProject } from 'packages/v2v3/components/Create/hooks/DeployProject/useDeployProject'
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { useDispatch } from 'react-redux'
import { useAppSelector } from 'redux/hooks/useAppSelector'
import { useSetCreateFurthestPageReached } from 'redux/hooks/useEditingCreateFurthestPageReached'
import { editingV2ProjectActions } from 'redux/slices/editingV2Project'
import { helpPagePath } from 'utils/helpPagePath'
import { useDeployProject } from '../../../hooks/DeployProject/useDeployProject'
import { CreateBadge } from '../../CreateBadge'
import { CreateCollapse } from '../../CreateCollapse/CreateCollapse'
import { Wizard } from '../../Wizard/Wizard'
Expand Down Expand Up @@ -93,7 +93,7 @@ export const ReviewDeployPage = () => {

transactionModal.open()
await deployProject({
onProjectDeployed: deployedProjectId => {
onProjectDeployed: (deployedProjectId: number) => {
router.push({ query: { deployedProjectId } }, '/create', {
shallow: true,
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { TransactionCallbacks } from 'models/transaction'
import { useLaunchProjectTx } from 'packages/v2v3/hooks/transactor/useLaunchProjectTx'
import { LaunchTxOpts, useLaunchProjectTx } from 'packages/v4/hooks/useLaunchProjectTx'
import { useCallback } from 'react'
import {
useAppSelector,
Expand All @@ -9,14 +8,13 @@ import {
} from 'redux/hooks/useAppSelector'

/**
* Hook that returns a function that deploys a project.
* Hook that returns a function that deploys a v4 project.
*
* The distinction is made between standard and NFT projects because the NFT
* project contract uses more gas.
* Takes data from the redux store built for v2v3 projects, data is converted to v4 format in useLaunchProjectTx.
* @returns A function that deploys a project.
*/
export const useDeployStandardProject = () => {
const launchProject = useLaunchProjectTx()
const launchProjectTx = useLaunchProjectTx()
const {
payoutGroupedSplits,
reservedTokensGroupedSplits,
Expand All @@ -30,18 +28,14 @@ export const useDeployStandardProject = () => {
const deployStandardProjectCallback = useCallback(
async ({
metadataCid,

onDone,
onConfirmed,
onCancelled,
onTransactionPending,
onTransactionConfirmed,
onTransactionError
}: {
metadataCid: string
} & Pick<
TransactionCallbacks,
'onCancelled' | 'onConfirmed' | 'onDone'
>) => {
} & LaunchTxOpts) => {
const groupedSplits = [payoutGroupedSplits, reservedTokensGroupedSplits]
return await launchProject(
return await launchProjectTx(
{
owner: inputProjectOwner?.length ? inputProjectOwner : undefined,
projectMetadataCID: metadataCid,
Expand All @@ -52,16 +46,16 @@ export const useDeployStandardProject = () => {
groupedSplits,
},
{
onDone,
onConfirmed,
onCancelled,
onTransactionPending,
onTransactionConfirmed,
onTransactionError
},
)
},
[
payoutGroupedSplits,
reservedTokensGroupedSplits,
launchProject,
launchProjectTx,
inputProjectOwner,
fundingCycleData,
fundingCycleMetadata,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { readProvider } from 'constants/readProvider'
import { BigNumber, providers } from 'ethers'
import { uploadProjectMetadata } from 'lib/api/ipfs'
import { TransactionCallbacks } from 'models/transaction'
import { LaunchTxOpts } from 'packages/v4/hooks/useLaunchProjectTx'
import { useCallback, useState } from 'react'
import { useAppDispatch } from 'redux/hooks/useAppDispatch'
import {
Expand All @@ -13,69 +11,10 @@ import {
import { editingV2ProjectActions } from 'redux/slices/editingV2Project'
import { emitErrorNotification } from 'utils/notifications'
import { useDeployNftProject } from './hooks/NFT/useDeployNftProject'
import { useIsNftProject } from './hooks/NFT/useIsNftProject'
import { useUploadNftRewards } from './hooks/NFT/useUploadNftRewards'
import { useDeployStandardProject } from './hooks/useDeployStandardProject'

const CREATE_EVENT_IDX = 2
const NFT_CREATE_EVENT_IDX = 3
const PROJECT_ID_TOPIC_IDX = 1

const JUICEBOX_DOMAIN = 'juicebox'
const JUICECROWD_DOMAIN = 'juicecrowd'

/**
* Return the project ID created from a `launchProjectFor` transaction.
* @param txReceipt receipt of `launchProjectFor` transaction
*/
const getProjectIdFromNftLaunchReceipt = (
txReceipt: providers.TransactionReceipt,
): number => {
const projectIdHex: unknown | undefined =
txReceipt?.logs[NFT_CREATE_EVENT_IDX]?.topics?.[PROJECT_ID_TOPIC_IDX]
const projectId = BigNumber.from(projectIdHex).toNumber()

return projectId
}

/**
* Return the project ID created from a `launchProjectFor` transaction.
* @param txReceipt receipt of `launchProjectFor` transaction
*/
const getProjectIdFromLaunchReceipt = (
txReceipt: providers.TransactionReceipt,
): number => {
const projectIdHex: unknown | undefined =
txReceipt?.logs[CREATE_EVENT_IDX]?.topics?.[PROJECT_ID_TOPIC_IDX]
const projectId = BigNumber.from(projectIdHex).toNumber()

return projectId
}

/**
* Attempt to find the transaction receipt from a transaction hash.
* Will retry up to 5 times with a 2 second delay between each attempt. If no
* receipt is found after 5 attempts, undefined is returned.
*
* @param txHash transaction hash
* @returns transaction receipt or undefined
*/
const findTransactionReceipt = async (txHash: string) => {
let retries = 5
let receipt
while (retries > 0 && !receipt) {
receipt = await readProvider.getTransactionReceipt(txHash)
if (receipt) break

retries -= 1
// wait 2s
await new Promise(r => setTimeout(r, 2000))
console.info('Retrying tx receipt lookup...')
}

return receipt
}

/**
* Hook that returns a function that deploys a project.
Expand All @@ -85,7 +24,7 @@ export const useDeployProject = () => {
const [isDeploying, setIsDeploying] = useState<boolean>(false)
const [transactionPending, setTransactionPending] = useState<boolean>()

const isNftProject = useIsNftProject()
// const isNftProject = useIsNftProject()
const uploadNftRewards = useUploadNftRewards()
const deployNftProject = useDeployNftProject()

Expand All @@ -111,46 +50,22 @@ export const useDeployProject = () => {
const operationCallbacks = useCallback(
(
onProjectDeployed?: (projectId: number) => void,
): Pick<
TransactionCallbacks,
'onCancelled' | 'onConfirmed' | 'onDone' | 'onError'
> => ({
onDone: () => {
): LaunchTxOpts => ({
onTransactionPending: () => {
console.info('Project transaction executed. Await confirmation...')
setTransactionPending(true)
},
onConfirmed: async result => {
const hash = result?.hash
if (!hash) {
return // TODO error notification
}
const txReceipt = await findTransactionReceipt(hash)
if (!txReceipt) {
return // TODO error notification
}

const projectId = isNftProject
? getProjectIdFromNftLaunchReceipt(txReceipt)
: getProjectIdFromLaunchReceipt(txReceipt)

if (projectId === undefined) {
return // TODO error notification
}

onTransactionConfirmed: async (hash, projectId) => {
// Reset the project state
dispatch(editingV2ProjectActions.resetState())
onProjectDeployed?.(projectId)
},
onError: error => {
onTransactionError: error => {
console.error(error)
emitErrorNotification(`Error deploying project: ${error}`)
},
onCancelled: () => {
setIsDeploying(false)
setTransactionPending(false)
},
}),
[dispatch, isNftProject],
[dispatch],
)

/**
Expand All @@ -176,15 +91,15 @@ export const useDeployProject = () => {
setIsDeploying(false)
throw new Error('Error deploying project.')
}
let nftCids: Awaited<ReturnType<typeof uploadNftRewards>> | undefined
try {
if (isNftProject) {
nftCids = await uploadNftRewards()
}
} catch (error) {
handleDeployFailure(error)
return
}
// let nftCids: Awaited<ReturnType<typeof uploadNftRewards>> | undefined
// try {
// if (isNftProject) {
// nftCids = await uploadNftRewards()
// }
// } catch (error) {
// handleDeployFailure(error)
// return
// }

let softTargetAmount: string | undefined
let softTargetCurrency: string | undefined
Expand All @@ -207,42 +122,42 @@ export const useDeployProject = () => {
}

try {
let tx
if (isNftProject) {
tx = await deployNftProject({
metadataCid: projectMetadataCid,
rewardTierCids: nftCids!.rewardTiers,
nftCollectionMetadataUri: nftCids!.nfCollectionMetadata,
...operationCallbacks(onProjectDeployed),
})
} else {
tx = await deployStandardProject({
metadataCid: projectMetadataCid,
...operationCallbacks(onProjectDeployed),
})
}
if (!tx) {
setIsDeploying(false)
setTransactionPending(false)
return
}
// let tx
// if (isNftProject) {
// tx = await deployNftProject({
// metadataCid: projectMetadataCid,
// rewardTierCids: nftCids!.rewardTiers,
// nftCollectionMetadataUri: nftCids!.nfCollectionMetadata,
// ...operationCallbacks(onProjectDeployed),
// })
// } else {
const tx = await deployStandardProject({
metadataCid: projectMetadataCid,
...operationCallbacks(onProjectDeployed),
})
// }
// if (!tx) {
setIsDeploying(false)
setTransactionPending(false)
return
// }
} catch (error) {
handleDeployFailure(error)
return
}
},
[
deployNftProject,
// deployNftProject,
deployStandardProject,
fundAccessConstraints,
fundingCycleData,
fundingCycleMetadata,
handleDeployFailure,
isNftProject,
// isNftProject,
operationCallbacks,
postPayModal,
projectMetadata,
uploadNftRewards,
// uploadNftRewards,
],
)
return {
Expand Down
Loading

0 comments on commit 8039440

Please sign in to comment.