Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: remove ipfs dependencies #167

Merged
merged 8 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions components/groups/components/myGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,16 @@ export function YourGroups({
const router = useRouter();
const { address } = useChain('manifest');

const filteredGroups = groups.groups.filter(group =>
(group.ipfsMetadata?.title || 'Untitled Group').toLowerCase().includes(searchTerm.toLowerCase())
);
const filteredGroups = groups.groups.filter(group => {
try {
const metadata = group.metadata ? JSON.parse(group.metadata) : null;
const groupTitle = metadata?.title || 'Untitled Group';
return groupTitle.toLowerCase().includes(searchTerm.toLowerCase());
} catch (e) {
console.warn('Failed to parse group metadata:', e);
return 'Untitled Group'.toLowerCase().includes(searchTerm.toLowerCase());
}
});

const totalPages = Math.ceil(filteredGroups.length / pageSize);
const paginatedGroups = filteredGroups.slice(
Expand All @@ -72,9 +79,18 @@ export function YourGroups({
g => g.policies && g.policies.length > 0 && g.policies[0]?.address === policyAddress
);
if (group) {
let groupName = 'Untitled Group';
try {
const metadata = group.metadata ? JSON.parse(group.metadata) : null;
groupName = metadata?.title ?? 'Untitled Group';
} catch (e) {
// If JSON parsing fails, fall back to default name
console.warn('Failed to parse group metadata:', e);
}

setSelectedGroup({
policyAddress,
name: group.ipfsMetadata?.title ?? 'Untitled Group',
name: groupName,
threshold:
(group.policies[0]?.decision_policy as ThresholdDecisionPolicySDKType)?.threshold ??
'0',
Expand Down Expand Up @@ -451,8 +467,13 @@ function GroupRow({
setActiveInfoModalId: (id: string | null) => void;
}) {
const policyAddress = (group.policies && group.policies[0]?.address) || '';
const groupName = group.ipfsMetadata?.title || 'Untitled Group';

let groupName = 'Untitled Group';
try {
const metadata = group.metadata ? JSON.parse(group.metadata) : null;
groupName = metadata?.title || 'Untitled Group';
} catch (e) {
console.warn('Failed to parse group metadata:', e);
}
const filterActiveProposals = (proposals: ProposalSDKType[]) => {
return proposals?.filter(
proposal =>
Expand Down
10 changes: 1 addition & 9 deletions components/groups/forms/groups/ConfirmationForm.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useEffect, useState } from 'react';
import { TruncatedAddressWithCopy } from '@/components/react/addressCopy';
import { FormData } from '@/helpers/formReducer';
import { useFeeEstimation } from '@/hooks/useFeeEstimation';
import { uploadJsonToIPFS } from '@/hooks/useIpfs';
import { useTx } from '@/hooks/useTx';
import { cosmos } from '@liftedinit/manifestjs';
import { ThresholdDecisionPolicy } from '@liftedinit/manifestjs/dist/codegen/cosmos/group/v1/types';
Expand Down Expand Up @@ -35,11 +33,6 @@ export default function ConfirmationForm({
const { tx, isSigning, setIsSigning } = useTx('manifest');
const { estimateFee } = useFeeEstimation('manifest');

const uploadMetaDataToIPFS = async () => {
const CID = await uploadJsonToIPFS(jsonString);
return CID;
};

const minExecutionPeriod: Duration = {
seconds: BigInt(0),
nanos: 0,
Expand All @@ -62,7 +55,6 @@ export default function ConfirmationForm({
const handleConfirm = async () => {
setIsSigning(true);
try {
const CID = await uploadMetaDataToIPFS();
const msg = createGroupWithPolicy({
admin: address ?? '',
members: formData.members.map(member => ({
Expand All @@ -71,7 +63,7 @@ export default function ConfirmationForm({
metadata: member.name,
added_at: new Date(),
})),
groupMetadata: CID,
groupMetadata: jsonString,
groupPolicyMetadata: '',
groupPolicyAsAdmin: true,
decisionPolicy: {
Expand Down
96 changes: 54 additions & 42 deletions components/groups/forms/groups/GroupDetailsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,63 @@ import { isValidManifestAddress } from '@/utils/string';
import { MdContacts } from 'react-icons/md';
import { TailwindModal } from '@/components/react/modal';

const GroupSchema = Yup.object().shape({
title: Yup.string()
.required('Title is required')
.max(50, 'Title must not exceed 50 characters')
.noProfanity(),
authors: Yup.lazy(val =>
Array.isArray(val)
? Yup.array()
.of(
Yup.string().test(
'author-validation',
'Invalid author name or address',
function (value) {
if (value?.startsWith('manifest')) {
return isValidManifestAddress(value);
const GroupSchema = Yup.object()
.shape({
title: Yup.string()
.required('Title is required')
.max(50, 'Title must not exceed 50 characters')
.noProfanity(),
authors: Yup.lazy(val =>
Array.isArray(val)
? Yup.array()
.of(
Yup.string().test(
'author-validation',
'Invalid author name or address',
function (value) {
if (value?.startsWith('manifest')) {
return isValidManifestAddress(value);
}
return Yup.string()
.max(50, 'Author name must not exceed 50 characters')
.noProfanity('Profanity is not allowed')
.isValidSync(value);
}
return Yup.string()
.max(50, 'Author name must not exceed 50 characters')
.noProfanity('Profanity is not allowed')
.isValidSync(value);
}
)
)
)
.min(1, 'At least one author is required')
: Yup.string().test(
'single-author-validation',
'Invalid author name or address',
function (value) {
if (value?.startsWith('manifest')) {
return isValidManifestAddress(value);
.min(1, 'At least one author is required')
: Yup.string().test(
'single-author-validation',
'Invalid author name or address',
function (value) {
if (value?.startsWith('manifest')) {
return isValidManifestAddress(value);
}
return Yup.string()
.max(50, 'Author name must not exceed 50 characters')
.noProfanity('Profanity is not allowed')
.isValidSync(value);
}
return Yup.string()
.max(50, 'Author name must not exceed 50 characters')
.noProfanity('Profanity is not allowed')
.isValidSync(value);
}
)
),

description: Yup.string()
.required('Description is required')
.min(20, 'Description must be at least 20 characters')
.max(1000, 'Description must not exceed 1000 characters')
.noProfanity('Profanity is not allowed'),
});
)
),
description: Yup.string()
.required('Description is required')
.min(20, 'Description must be at least 20 characters')
.max(100, 'Description must not exceed 100 characters')
.noProfanity('Profanity is not allowed'),
})
.test(
'metadata-total-length',
'Total metadata length must not exceed 10000 characters',
function (values) {
const metadata = JSON.stringify({
title: values.title || '',
authors: Array.isArray(values.authors) ? values.authors.join(', ') : values.authors || '',
details: values.description || '',
});
return metadata.length <= 10000;
}
);

export default function GroupDetails({
nextStep,
Expand Down
1 change: 1 addition & 0 deletions components/groups/forms/groups/MemberInfoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ export default function MemberInfoForm({
isOpen={isContactsOpen}
setOpen={setIsContactsOpen}
showContacts={true}
currentAddress={address}
onSelect={(selectedAddress: string) => {
if (activeMemberIndex !== null) {
setFieldValue(`members.${activeMemberIndex}.address`, selectedAddress);
Expand Down
64 changes: 37 additions & 27 deletions components/groups/modals/groupDetailsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { TruncatedAddressWithCopy } from '@/components/react/addressCopy';
import { IPFSMetadata } from '@/hooks/useQueries';
import ProfileAvatar from '@/utils/identicon';
import {
GroupMemberSDKType,
GroupPolicyInfoSDKType,
ThresholdDecisionPolicySDKType,
} from '@liftedinit/manifestjs/dist/codegen/cosmos/group/v1/types';
import { PiXCircleLight } from 'react-icons/pi';

interface Group {
group: {
admin: string;
metadata: string;
ipfsMetadata: IPFSMetadata | null;
members: any[];
policies: any[];
members: GroupMemberSDKType[];
policies: GroupPolicyInfoSDKType[];
};
}

Expand All @@ -24,6 +26,19 @@ export function GroupDetailsModal({ group, modalId }: Group & { modalId: string
return adminAddresses.includes(address);
};

const metadata = (() => {
try {
return group.metadata ? JSON.parse(group.metadata) : null;
} catch (error) {
console.error('Failed to parse group metadata:', error);
return null;
}
})();

const authors = metadata?.authors || 'No authors available';
const summary = metadata?.summary || 'No summary available';
const details = metadata?.details || 'No details available';

return (
<dialog id={modalId} className="modal">
<div className="modal-box absolute max-w-4xl mx-auto rounded-lg md:ml-20 shadow-lg">
Expand All @@ -37,29 +52,19 @@ export function GroupDetailsModal({ group, modalId }: Group & { modalId: string
<div>
<p className="text-sm font-light mt-4 ">AUTHORS</p>
<div className="bg-base-200 shadow rounded-lg p-4 mt-2 mb-2">
<p className="text-md ">{group?.ipfsMetadata?.authors ?? 'No authors available'}</p>
<p className="text-md ">{authors}</p>
</div>
</div>
<div>
<p className="text-sm font-light mt-4 ">SUMMARY</p>
<div className="bg-base-200 shadow rounded-lg p-4 mt-2 mb-2">
<p className="text-md ">{group?.ipfsMetadata?.summary ?? 'No summary available'}</p>
<p className="text-md ">{summary}</p>
</div>
</div>
<div>
<p className="text-sm font-light mt-4 ">DETAILS</p>
<div className="bg-base-200 shadow rounded-lg p-4 mt-2 mb-2 max-h-[9.53rem] overflow-y-auto">
<p className="text-md text-wrap ">
{group?.ipfsMetadata?.details ?? 'No details available'}
</p>
</div>
</div>
<div>
<p className="text-sm font-light mt-4 ">FORUM</p>
<div className="bg-base-200 shadow rounded-lg p-4 mt-2 mb-2">
<p className="text-md ">
{group?.ipfsMetadata?.proposalForumURL ?? 'No forum URL available'}
</p>
<p className="text-md text-wrap ">{details}</p>
</div>
</div>
</div>
Expand All @@ -82,10 +87,14 @@ export function GroupDetailsModal({ group, modalId }: Group & { modalId: string
<p className="text-sm font-light mt-4 ">VOTING WINDOW</p>
<div className="bg-base-200 shadow rounded-lg p-4 mt-2 mb-2">
<p className="text-md ">
{policy?.decision_policy?.windows?.voting_period
{(policy?.decision_policy as ThresholdDecisionPolicySDKType)?.windows
?.voting_period
? Math.floor(
parseInt(policy.decision_policy.windows.voting_period.slice(0, -1)) /
86400
parseInt(
(
policy?.decision_policy as ThresholdDecisionPolicySDKType
)?.windows?.voting_period.seconds.toString() ?? '0'
) / 86400
)
: 'No voting period available'}{' '}
days
Expand All @@ -96,8 +105,9 @@ export function GroupDetailsModal({ group, modalId }: Group & { modalId: string
<p className="text-sm font-light mt-4 ">THRESHOLD</p>
<div className="bg-base-200 shadow rounded-lg p-4 mt-2 mb-2">
<p className="text-md ">
{policy?.decision_policy?.threshold ?? 'No threshold available'} /
{group?.members.length ?? 'No members available'}
{(policy?.decision_policy as ThresholdDecisionPolicySDKType)?.threshold ??
'No threshold available'}{' '}
/ {group?.members.length ?? 'No members available'}
</p>
</div>
</div>
Expand Down Expand Up @@ -152,12 +162,12 @@ export function GroupDetailsModal({ group, modalId }: Group & { modalId: string
/>
</td>
<td>
{isPolicyAdmin(member?.member?.address) &&
isAdmin(member?.member?.address) ? (
{isPolicyAdmin(member?.member?.address ?? '') &&
isAdmin(member?.member?.address ?? '') ? (
'Super Admin'
) : isPolicyAdmin(member?.member?.address) ? (
) : isPolicyAdmin(member?.member?.address ?? '') ? (
'Policy'
) : isAdmin(member?.member?.address) ? (
) : isAdmin(member?.member?.address ?? '') ? (
'Group'
) : (
<PiXCircleLight className="text-red-500 h-5 w-5" />
Expand Down
Loading
Loading