diff --git a/apps/web/core/hooks/use-propose-add-editor.ts b/apps/web/core/hooks/use-propose-add-editor.ts index f66b1a3be2..0987d3d7c1 100644 --- a/apps/web/core/hooks/use-propose-add-editor.ts +++ b/apps/web/core/hooks/use-propose-add-editor.ts @@ -1,15 +1,17 @@ 'use client'; -import { daoSpace } from '@geoprotocol/geo-sdk'; import { useMutation } from '@tanstack/react-query'; import { useCallback } from 'react'; import { Effect, Either } from 'effect'; +import { type Hex } from 'viem'; import { usePersonalSpaceId } from '~/core/hooks/use-personal-space-id'; import { useSmartAccount } from '~/core/hooks/use-smart-account'; import { useSmartAccountTransaction } from '~/core/hooks/use-smart-account-transaction'; +import { useSpace } from '~/core/hooks/use-space'; +import { geo } from '~/core/sdk/geo-client'; import { useStatusBar } from '~/core/state/status-bar-store'; import { runEffectEither } from '~/core/telemetry/effect-runtime'; import { SPACE_REGISTRY_ADDRESS } from '~/core/utils/contracts/space-registry'; @@ -36,6 +38,7 @@ export function useProposeAddEditor({ spaceId }: UseProposeAddEditorArgs) { const { smartAccount } = useSmartAccount(); const { personalSpaceId, isRegistered } = usePersonalSpaceId(); + const { space } = useSpace(spaceId ?? undefined); const tx = useSmartAccountTransaction({ address: SPACE_REGISTRY_ADDRESS, @@ -71,15 +74,24 @@ export function useProposeAddEditor({ spaceId }: UseProposeAddEditorArgs) { throw new Error(message); } + // The proposal's addEditor action must call the DAO space contract directly. + if (!space?.address) { + const message = 'No space address found. Please try again.'; + console.error('No space address found for space:', spaceId); + dispatch({ type: 'ERROR', payload: message }); + throw new Error(message); + } + console.log('Proposing to add editor', { authorSpaceId: personalSpaceId, spaceId, targetEditorSpaceId, }); - const { calldata: callData } = daoSpace.proposeAddEditor({ + const { calldata: callData } = geo.daoSpaces.proposeAddEditor({ authorSpaceId: personalSpaceId, spaceId, + daoSpaceAddress: space.address as Hex, newEditorSpaceId: targetEditorSpaceId, votingMode: 'SLOW', }); @@ -111,7 +123,7 @@ export function useProposeAddEditor({ spaceId }: UseProposeAddEditorArgs) { onRight: hash => console.log('Successfully proposed to add editor. Transaction hash:', hash), }); }, - [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, tx] + [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, space, tx] ); const { mutate, status } = useMutation({ diff --git a/apps/web/core/hooks/use-propose-add-member.ts b/apps/web/core/hooks/use-propose-add-member.ts index a6428154d6..937b07dee6 100644 --- a/apps/web/core/hooks/use-propose-add-member.ts +++ b/apps/web/core/hooks/use-propose-add-member.ts @@ -1,15 +1,17 @@ 'use client'; -import { daoSpace } from '@geoprotocol/geo-sdk'; import { useMutation } from '@tanstack/react-query'; import { useCallback } from 'react'; import { Effect, Either } from 'effect'; +import { type Hex } from 'viem'; import { usePersonalSpaceId } from '~/core/hooks/use-personal-space-id'; import { useSmartAccount } from '~/core/hooks/use-smart-account'; import { useSmartAccountTransaction } from '~/core/hooks/use-smart-account-transaction'; +import { useSpace } from '~/core/hooks/use-space'; +import { geo } from '~/core/sdk/geo-client'; import { useStatusBar } from '~/core/state/status-bar-store'; import { runEffectEither } from '~/core/telemetry/effect-runtime'; import { SPACE_REGISTRY_ADDRESS } from '~/core/utils/contracts/space-registry'; @@ -32,6 +34,7 @@ export function useProposeAddMember({ spaceId }: UseProposeAddMemberArgs) { const { smartAccount } = useSmartAccount(); const { personalSpaceId, isRegistered } = usePersonalSpaceId(); + const { space } = useSpace(spaceId ?? undefined); const tx = useSmartAccountTransaction({ address: SPACE_REGISTRY_ADDRESS, @@ -67,6 +70,14 @@ export function useProposeAddMember({ spaceId }: UseProposeAddMemberArgs) { throw new Error(message); } + // The proposal's addMember action must call the DAO space contract directly. + if (!space?.address) { + const message = 'No space address found. Please try again.'; + console.error('No space address found for space:', spaceId); + dispatch({ type: 'ERROR', payload: message }); + throw new Error(message); + } + const normalizedVotingMode = votingMode === 'slow' ? 'SLOW' : 'FAST'; console.log('Proposing to add member', { @@ -76,9 +87,10 @@ export function useProposeAddMember({ spaceId }: UseProposeAddMemberArgs) { votingMode: normalizedVotingMode, }); - const { calldata: callData } = daoSpace.proposeAddMember({ + const { calldata: callData } = geo.daoSpaces.proposeAddMember({ authorSpaceId: personalSpaceId, spaceId, + daoSpaceAddress: space.address as Hex, newMemberSpaceId: targetMemberSpaceId, votingMode: normalizedVotingMode, }); @@ -114,7 +126,7 @@ export function useProposeAddMember({ spaceId }: UseProposeAddMemberArgs) { onRight: hash => console.log('Successfully proposed to add member. Transaction hash:', hash), }); }, - [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, tx] + [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, space, tx] ); const { mutate, status } = useMutation({ diff --git a/apps/web/core/hooks/use-propose-remove-editor.ts b/apps/web/core/hooks/use-propose-remove-editor.ts index 6a19d75cbc..804f90fb1e 100644 --- a/apps/web/core/hooks/use-propose-remove-editor.ts +++ b/apps/web/core/hooks/use-propose-remove-editor.ts @@ -1,15 +1,17 @@ 'use client'; -import { daoSpace } from '@geoprotocol/geo-sdk'; import { useMutation } from '@tanstack/react-query'; import { useCallback } from 'react'; import { Effect, Either } from 'effect'; +import { type Hex } from 'viem'; import { usePersonalSpaceId } from '~/core/hooks/use-personal-space-id'; import { useSmartAccount } from '~/core/hooks/use-smart-account'; import { useSmartAccountTransaction } from '~/core/hooks/use-smart-account-transaction'; +import { useSpace } from '~/core/hooks/use-space'; +import { geo } from '~/core/sdk/geo-client'; import { useStatusBar } from '~/core/state/status-bar-store'; import { runEffectEither } from '~/core/telemetry/effect-runtime'; import { SPACE_REGISTRY_ADDRESS } from '~/core/utils/contracts/space-registry'; @@ -36,6 +38,7 @@ export function useProposeRemoveEditor({ spaceId }: UseProposeRemoveEditorArgs) const { smartAccount } = useSmartAccount(); const { personalSpaceId, isRegistered } = usePersonalSpaceId(); + const { space } = useSpace(spaceId ?? undefined); const tx = useSmartAccountTransaction({ address: SPACE_REGISTRY_ADDRESS, @@ -71,15 +74,24 @@ export function useProposeRemoveEditor({ spaceId }: UseProposeRemoveEditorArgs) throw new Error(message); } + // The proposal's removeEditor action must call the DAO space contract directly. + if (!space?.address) { + const message = 'No space address found. Please try again.'; + console.error('No space address found for space:', spaceId); + dispatch({ type: 'ERROR', payload: message }); + throw new Error(message); + } + console.log('Proposing to remove editor', { authorSpaceId: personalSpaceId, spaceId, targetEditorSpaceId, }); - const { calldata: callData } = daoSpace.proposeRemoveEditor({ + const { calldata: callData } = geo.daoSpaces.proposeRemoveEditor({ authorSpaceId: personalSpaceId, spaceId, + daoSpaceAddress: space.address as Hex, editorToRemoveSpaceId: targetEditorSpaceId, votingMode: 'SLOW', }); @@ -111,7 +123,7 @@ export function useProposeRemoveEditor({ spaceId }: UseProposeRemoveEditorArgs) onRight: hash => console.log('Successfully proposed to remove editor. Transaction hash:', hash), }); }, - [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, tx] + [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, space, tx] ); const { mutate, status } = useMutation({ diff --git a/apps/web/core/hooks/use-propose-remove-member.ts b/apps/web/core/hooks/use-propose-remove-member.ts index 7626e88da7..7bef72a2de 100644 --- a/apps/web/core/hooks/use-propose-remove-member.ts +++ b/apps/web/core/hooks/use-propose-remove-member.ts @@ -1,15 +1,17 @@ 'use client'; -import { daoSpace } from '@geoprotocol/geo-sdk'; import { useMutation } from '@tanstack/react-query'; import { useCallback } from 'react'; import { Effect, Either } from 'effect'; +import { type Hex } from 'viem'; import { usePersonalSpaceId } from '~/core/hooks/use-personal-space-id'; import { useSmartAccount } from '~/core/hooks/use-smart-account'; import { useSmartAccountTransaction } from '~/core/hooks/use-smart-account-transaction'; +import { useSpace } from '~/core/hooks/use-space'; +import { geo } from '~/core/sdk/geo-client'; import { useStatusBar } from '~/core/state/status-bar-store'; import { runEffectEither } from '~/core/telemetry/effect-runtime'; import { SPACE_REGISTRY_ADDRESS } from '~/core/utils/contracts/space-registry'; @@ -32,6 +34,7 @@ export function useProposeRemoveMember({ spaceId }: UseProposeRemoveMemberArgs) const { smartAccount } = useSmartAccount(); const { personalSpaceId, isRegistered } = usePersonalSpaceId(); + const { space } = useSpace(spaceId ?? undefined); const tx = useSmartAccountTransaction({ address: SPACE_REGISTRY_ADDRESS, @@ -67,6 +70,14 @@ export function useProposeRemoveMember({ spaceId }: UseProposeRemoveMemberArgs) throw new Error(message); } + // The proposal's removeMember action must call the DAO space contract directly. + if (!space?.address) { + const message = 'No space address found. Please try again.'; + console.error('No space address found for space:', spaceId); + dispatch({ type: 'ERROR', payload: message }); + throw new Error(message); + } + const normalizedVotingMode = votingMode === 'slow' ? 'SLOW' : 'FAST'; console.log('Proposing to remove member', { @@ -76,9 +87,10 @@ export function useProposeRemoveMember({ spaceId }: UseProposeRemoveMemberArgs) votingMode: normalizedVotingMode, }); - const { calldata: callData } = daoSpace.proposeRemoveMember({ + const { calldata: callData } = geo.daoSpaces.proposeRemoveMember({ authorSpaceId: personalSpaceId, spaceId, + daoSpaceAddress: space.address as Hex, memberToRemoveSpaceId: targetMemberSpaceId, votingMode: normalizedVotingMode, }); @@ -114,7 +126,7 @@ export function useProposeRemoveMember({ spaceId }: UseProposeRemoveMemberArgs) onRight: hash => console.log('Successfully proposed to remove member. Transaction hash:', hash), }); }, - [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, tx] + [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, space, tx] ); const { mutate, status } = useMutation({ diff --git a/apps/web/core/hooks/use-request-to-be-editor.ts b/apps/web/core/hooks/use-request-to-be-editor.ts index 834e712b28..0546c3e5b0 100644 --- a/apps/web/core/hooks/use-request-to-be-editor.ts +++ b/apps/web/core/hooks/use-request-to-be-editor.ts @@ -1,17 +1,19 @@ 'use client'; -import { daoSpace } from '@geoprotocol/geo-sdk'; import { useMutation } from '@tanstack/react-query'; import { useCallback } from 'react'; import { Effect, Either } from 'effect'; +import { type Hex } from 'viem'; import { normalizeSpaceId } from '~/core/access/space-access'; import { usePersonalSpaceId } from '~/core/hooks/use-personal-space-id'; import { useSmartAccount } from '~/core/hooks/use-smart-account'; import { useSmartAccountTransaction } from '~/core/hooks/use-smart-account-transaction'; +import { useSpace } from '~/core/hooks/use-space'; import { getIsEditorOfSpace } from '~/core/io/queries'; +import { geo } from '~/core/sdk/geo-client'; import { useStatusBar } from '~/core/state/status-bar-store'; import { runEffectEither } from '~/core/telemetry/effect-runtime'; import { SPACE_REGISTRY_ADDRESS } from '~/core/utils/contracts/space-registry'; @@ -27,6 +29,7 @@ export function useRequestToBeEditor({ spaceId }: UseRequestToBeEditorArgs) { const { smartAccount } = useSmartAccount(); const { personalSpaceId, isRegistered } = usePersonalSpaceId(); + const { space } = useSpace(spaceId ?? undefined); const tx = useSmartAccountTransaction({ address: SPACE_REGISTRY_ADDRESS, @@ -49,6 +52,14 @@ export function useRequestToBeEditor({ spaceId }: UseRequestToBeEditorArgs) { throw new Error('Invalid target space ID'); } + // The proposal's addEditor action must call the DAO space contract directly. + if (!space?.address) { + const message = 'No space address found. Please try again.'; + console.error('No space address found for space:', spaceId); + dispatch({ type: 'ERROR', payload: message }); + throw new Error(message); + } + // Existing editors already belong to the space; a duplicate editor request errors on vote. // Check at submit time rather than via reactive access-control state, which reads false // while still hydrating and would let a fast click through. Fail open if the check errors. @@ -66,9 +77,10 @@ export function useRequestToBeEditor({ spaceId }: UseRequestToBeEditorArgs) { }); // Caller proposes themselves as a new editor. Editor proposals are slow-path only. - const { calldata: callData } = daoSpace.proposeAddEditor({ + const { calldata: callData } = geo.daoSpaces.proposeAddEditor({ authorSpaceId: personalSpaceId, spaceId, + daoSpaceAddress: space.address as Hex, newEditorSpaceId: personalSpaceId, votingMode: 'SLOW', }); @@ -95,7 +107,7 @@ export function useRequestToBeEditor({ spaceId }: UseRequestToBeEditorArgs) { }, onRight: hash => console.log('Successfully requested to be editor. Transaction hash:', hash), }); - }, [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, tx]); + }, [dispatch, smartAccount, personalSpaceId, isRegistered, spaceId, space, tx]); const { mutate, status } = useMutation({ mutationFn: handleRequestToBeEditor,