Skip to content
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
8 changes: 6 additions & 2 deletions packages/nextjs/app/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ const Multisig: FC = () => {
contractAddress: multisigAddress,
});

const { profile, loading: profileLoading } = useProfileMetadata({
const {
profile,
loading: profileLoading,
refetch: refetchProfile,
} = useProfileMetadata({
address: upAddress as `0x${string}`,
enabled: true,
});
Expand All @@ -36,7 +40,7 @@ const Multisig: FC = () => {
/>

<div className="w-full flex flex-col px-4 pt-6">
<Pool multisigAddress={multisigAddress as `0x${string}`} />
<Pool multisigAddress={multisigAddress as `0x${string}`} refetchProfile={refetchProfile} />
</div>
</div>
);
Expand Down
9 changes: 8 additions & 1 deletion packages/nextjs/app/multisig_components/Pool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { notification } from "~~/utils/scaffold-eth";
export const Pool = ({
multisigAddress,
isHistory = false,
refetchProfile,
}: {
multisigAddress: `0x${string}`;
isHistory?: boolean;
refetchProfile: () => Promise<void>;
}) => {
const queryClient = useQueryClient();
const { targetNetwork } = useTargetNetwork();
Expand Down Expand Up @@ -85,7 +87,12 @@ export const Pool = ({
<div className="w-full" />
) : (
filteredTransactions.map(tx => (
<TransactionItem key={tx.hash} tx={tx} onRefetch={() => queryClient.invalidateQueries({ queryKey })} />
<TransactionItem
key={tx.hash}
tx={tx}
onRefetch={() => queryClient.invalidateQueries({ queryKey })}
refetchProfile={refetchProfile}
/>
))
)}
</div>
Expand Down
15 changes: 11 additions & 4 deletions packages/nextjs/app/multisig_components/TransactionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import { getPoolServerUrl } from "~~/utils/getPoolServerUrl";
import { truncateString } from "~~/utils/helpers";
import { notification } from "~~/utils/scaffold-eth";

type TransactionItemProps = { tx: TransactionData; onRefetch?: () => void };
type TransactionItemProps = { tx: TransactionData; onRefetch?: () => void; refetchProfile: () => Promise<void> };

export const TransactionItem: FC<TransactionItemProps> = ({ tx, onRefetch }) => {
export const TransactionItem: FC<TransactionItemProps> = ({ tx, onRefetch, refetchProfile }) => {
const { address } = useAccount();
const { data: walletClient } = useWalletClient();
const publicClient = usePublicClient();
Expand Down Expand Up @@ -138,6 +138,7 @@ export const TransactionItem: FC<TransactionItemProps> = ({ tx, onRefetch }) =>
const executeTransaction = async () => {
try {
setIsExecuting(true);

if (!contractInfo || !metaMultiSigWallet) {
console.log("No contract info");
return;
Expand Down Expand Up @@ -191,7 +192,12 @@ export const TransactionItem: FC<TransactionItemProps> = ({ tx, onRefetch }) =>

if (onRefetch) {
onRefetch();

refetchProfile();
}
} else {
notification.error("Error executing transaction");
setIsExecuting(false);
}
} catch (e) {
//notification.error("Error executing transaction");
Expand Down Expand Up @@ -398,8 +404,9 @@ export const TransactionItem: FC<TransactionItemProps> = ({ tx, onRefetch }) =>
</div>
</div>
))}

<div>{truncateString(formatEther(BigInt(tx.amount)), 9)} LYX</div>
{tx.title.trim().toLowerCase() === "transfer funds" && (
<div>{truncateString(formatEther(BigInt(tx.amount)), 9)} LYX</div>
)}
</div>
</div>
</div>
Expand Down
8 changes: 5 additions & 3 deletions packages/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { useEffect, useState } from "react";
import Link from "next/link";
import WelcomeUI from "./_components/WelcomeUI";
import type { NextPage } from "next";
import { useIsMounted } from "usehooks-ts";
import { useAccount } from "wagmi";
import { MultisigCard } from "~~/components/cards/MultisigCard";
import { useUPProvider } from "~~/contexts/UPProviderContext";
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";
import { getController } from "~~/utils/helpers";

const Home: NextPage = () => {
const isMounted = useIsMounted();
const { address: connectedAddress } = useAccount();

const [controller, setController] = useState<string | undefined>(undefined);
Expand Down Expand Up @@ -41,14 +43,14 @@ const Home: NextPage = () => {
})();
}, [connectedAddress, contextAccounts]);

return (
return isMounted() ? (
<div className="flex items-center flex-col flex-grow pt-10 w-full h-screen overflow-y-auto">
<div className="flex flex-col justify-center items-center gap-y-8 w-full">
{multisigsLoading || registryAddressLoading ? (
<div className="flex items-center justify-center py-32">
<span className="loading w-6" />
</div>
) : !multisigs || multisigs.length === 0 ? (
) : multisigs && multisigs.length === 0 ? (
<div className="max-w-[398px]">
<WelcomeUI />
</div>
Expand Down Expand Up @@ -77,7 +79,7 @@ const Home: NextPage = () => {
)}
</div>
</div>
);
) : null;
};

export default Home;
102 changes: 48 additions & 54 deletions packages/nextjs/hooks/useProfileMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { useTargetNetwork } from "./scaffold-eth";
import { ERC725, ERC725JSONSchema } from "@erc725/erc725.js";
import lsp3ProfileSchema from "@erc725/erc725.js/schemas/LSP3ProfileMetadata.json";
import { useQuery, useQueryClient } from "@tanstack/react-query";

export interface Profile {
name: string;
Expand Down Expand Up @@ -53,6 +53,7 @@ interface UseProfileMetadataOptions {
interface UseProfileMetadataResult {
profile: Profile | null;
loading: boolean;
refetch: () => Promise<void>;
fetchProfile: (address: `0x${string}`) => Promise<Profile | null>;
}

Expand All @@ -64,61 +65,54 @@ interface UseProfileMetadataResult {
*/
export function useProfileMetadata(options: UseProfileMetadataOptions = { enabled: true }): UseProfileMetadataResult {
const { address, enabled = true } = options;
const [profile, setProfile] = useState<Profile | null>(null);
const [loading, setLoading] = useState(false);

const { targetNetwork } = useTargetNetwork();

// Fetch profile data
const fetchProfile = useCallback(
async (address: `0x${string}`): Promise<Profile | null> => {
const erc725js = new ERC725(
lsp3ProfileSchema as ERC725JSONSchema[],
address,
targetNetwork.rpcUrls.default.http[0],
{
ipfsGateway: "https://api.universalprofile.cloud/ipfs/",
},
);

try {
setLoading(true);
const profileMetaData = await erc725js.fetchData("LSP3Profile");

if (
profileMetaData.value &&
typeof profileMetaData.value === "object" &&
"LSP3Profile" in profileMetaData.value
) {
const fetchedProfile = profileMetaData.value.LSP3Profile;
setProfile(fetchedProfile);

return fetchedProfile;
}
} catch (error) {
console.log("Cannot fetch universal profile data: ", error);
} finally {
setLoading(false);
const queryClient = useQueryClient();

const fetchProfile = async (address: `0x${string}`): Promise<Profile | null> => {
const erc725js = new ERC725(
lsp3ProfileSchema as ERC725JSONSchema[],
address,
targetNetwork.rpcUrls.default.http[0],
{
ipfsGateway: "https://api.universalprofile.cloud/ipfs/",
},
);

try {
const profileMetaData = await erc725js.fetchData("LSP3Profile");

if (
profileMetaData.value &&
typeof profileMetaData.value === "object" &&
"LSP3Profile" in profileMetaData.value
) {
return profileMetaData.value.LSP3Profile;
}

return null;
},
[address],
);

// Fetch profile automatically if enabled
useEffect(() => {
if (enabled && address) {
fetchProfile(address);
} catch (error) {
console.log("Cannot fetch universal profile data: ", error);
}
}, [address, fetchProfile, enabled]);

return useMemo(
() => ({
profile,
loading,
fetchProfile,
}),
[profile, loading, fetchProfile],
);
return null;
};

const queryKey = ["profile", address];

const {
data: profile,
isLoading: loading,
refetch,
} = useQuery({
queryKey: ["profile", address],
queryFn: () => (address ? fetchProfile(address) : null),
enabled: enabled && !!address,
});

return {
profile: profile ?? null,
loading,
refetch: async () => {
queryClient.invalidateQueries({ queryKey });
},
fetchProfile,
};
}
Loading