Skip to content

Commit

Permalink
feat: ui demo user card reflects 7702 delegation status (#1294)
Browse files Browse the repository at this point in the history
* feat: have user avatar reflect if account has been delegated

* feat: reflects delegation status in user details card

* fix: forces delegation status query to refetch until available

* chore: updates comment

* refactor: uses viem public client and refetches delegation addr when nftTransferred status changes

* refactor: uses defined url constant

* chore: removes unnecessary check
  • Loading branch information
linnall authored and adamegyed committed Jan 29, 2025
1 parent 0b55c41 commit af481b4
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,54 @@ import DialogMenu from "@/components/shared/user-connection-avatar/UserConnectio
import { UserConnectionAvatar } from "./UserConnectionAvatar";
import { UserConnectionDetails } from "./UserConnectionDetails";
import React, { useEffect, useState } from "react";
import { useAccount } from "@account-kit/react";
import { useAccount, useSigner } from "@account-kit/react";
import { useQuery } from "@tanstack/react-query";
import { useConfigStore } from "@/state";
import { WalletTypes } from "@/app/config";
import { createPublicClient, Hex, http } from "viem";
import { odysseyTestnet } from "viem/chains";

type RenderAvatarMenuProps = {
deploymentStatus: boolean;
delegationAddress?: Hex;
};
export const RenderUserConnectionAvatar = (
props: React.HTMLAttributes<HTMLDivElement>
) => {
const { account } = useAccount({
type: "LightAccount",
});
const { walletType } = useConfigStore();

const publicClient = createPublicClient({
chain: odysseyTestnet,
transport: http(),
});

const signer = useSigner();

const { nftTransferred } = useConfigStore(({ nftTransferred }) => ({
nftTransferred,
}));

const { data: deploymentStatus = false, refetch } = useQuery({
queryKey: ["deploymentStatus"],
const { data: hybridAccount, refetch: refetch7702 } = useQuery({
queryKey: ["deploymentStatus7702"],
queryFn: async () => {
const delegationAddress = signer
? await publicClient.getCode({
address: await signer?.getAddress(),
})
: "0x";
const delegationStatus = delegationAddress !== "0x";
return {
delegationAddress,
delegationStatus,
};
},
});

const { data: deploymentStatusSCA = false, refetch: refetchSCA } = useQuery({
queryKey: ["deploymentStatusSCA"],
queryFn: async () => {
const initCode = await account?.getInitCode();
return initCode && initCode === "0x";
Expand All @@ -33,10 +61,20 @@ export const RenderUserConnectionAvatar = (
useEffect(() => {
// Refetch the deployment status if the NFT transferred state changes.
// Only refetch if this is a user's first NFT Transfer...
if (nftTransferred && !deploymentStatus) {
refetch();
if (nftTransferred && !deploymentStatusSCA) {
refetchSCA();
}
}, [nftTransferred, deploymentStatus, refetch]);

if (nftTransferred && !hybridAccount?.delegationStatus) {
refetch7702();
}
}, [
nftTransferred,
deploymentStatusSCA,
refetchSCA,
hybridAccount?.delegationStatus,
refetch7702,
]);

return (
<div
Expand All @@ -45,17 +83,42 @@ export const RenderUserConnectionAvatar = (
>
{/* Popover - Visible on desktop screens */}
<div className="hidden lg:block overflow-hidden">
<RenderPopoverMenu deploymentStatus={deploymentStatus} />
<RenderPopoverMenu
deploymentStatus={
walletType === WalletTypes.hybrid7702
? hybridAccount
? hybridAccount.delegationStatus
: false
: deploymentStatusSCA
}
delegationAddress={
hybridAccount ? hybridAccount.delegationAddress : "0x"
}
/>
</div>
{/* Dialog - Visible on mobile screens */}
<div className="block lg:hidden">
<RenderDialogMenu deploymentStatus={deploymentStatus} />
<RenderDialogMenu
deploymentStatus={
walletType === WalletTypes.hybrid7702
? hybridAccount
? hybridAccount.delegationStatus
: false
: deploymentStatusSCA
}
delegationAddress={
hybridAccount ? hybridAccount.delegationAddress : "0x"
}
/>
</div>
</div>
);
};

const RenderPopoverMenu = ({ deploymentStatus }: RenderAvatarMenuProps) => {
const RenderPopoverMenu = ({
deploymentStatus,
delegationAddress,
}: RenderAvatarMenuProps) => {
const [popoverOpen, setPopoverOpen] = useState(false);

return (
Expand All @@ -67,13 +130,19 @@ const RenderPopoverMenu = ({ deploymentStatus }: RenderAvatarMenuProps) => {
/>
</PopoverMenu.Trigger>
<PopoverMenu.Content>
<UserConnectionDetails deploymentStatus={deploymentStatus} />
<UserConnectionDetails
deploymentStatus={deploymentStatus}
delegationAddress={delegationAddress}
/>
</PopoverMenu.Content>
</PopoverMenu>
);
};

const RenderDialogMenu = ({ deploymentStatus }: RenderAvatarMenuProps) => {
const RenderDialogMenu = ({
deploymentStatus,
delegationAddress,
}: RenderAvatarMenuProps) => {
const [dialogOpen, setDialogOpen] = useState(false);

return (
Expand All @@ -90,7 +159,10 @@ const RenderDialogMenu = ({ deploymentStatus }: RenderAvatarMenuProps) => {
<DialogMenu isOpen={dialogOpen} onClose={() => setDialogOpen(false)}>
<DialogMenu.Content>
<p className="text-lg font-semibold text-fg-primary mb-5">Profile</p>
<UserConnectionDetails deploymentStatus={deploymentStatus} />
<UserConnectionDetails
deploymentStatus={deploymentStatus}
delegationAddress={delegationAddress}
/>
</DialogMenu.Content>
</DialogMenu>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ import { ExternalLinkIcon } from "@/components/icons/external-link";
import { LogoutIcon } from "@/components/icons/logout";
import { DeploymentStatusIndicator } from "@/components/shared/DeploymentStatusIndicator";
import { UserAddressLink } from "@/components/shared/user-connection-avatar/UserAddressLink";
import { ODYSSEY_EXPLORER_URL } from "@/hooks/7702/constants";
import { useConfigStore } from "@/state";
import { useAccount, useLogout, useSigner, useUser } from "@account-kit/react";
import { useQuery } from "@tanstack/react-query";
import { Hex } from "viem";

type UserConnectionDetailsProps = {
deploymentStatus: boolean;
delegationAddress?: Hex;
};
export function UserConnectionDetails({
deploymentStatus,
delegationAddress,
}: UserConnectionDetailsProps) {
const user = useUser();
const signer = useSigner();
Expand Down Expand Up @@ -119,11 +123,23 @@ export function UserConnectionDetails({
</span>
<div className="flex flex-row items-center">
<DeploymentStatusIndicator
isDeployed={false}
isDeployed={deploymentStatus}
className="w-[12px] h-[12px]"
/>
<span className="text-fg-primary block ml-1 text-md md:text-sm">
None
{deploymentStatus && delegationAddress ? (
<a
href={`${ODYSSEY_EXPLORER_URL}/address/0x${delegationAddress.slice(
8
)}`}
target="_blank"
className="underline"
>
Modular Account
</a>
) : (
"None"
)}
</span>
</div>
</div>
Expand Down

0 comments on commit af481b4

Please sign in to comment.