Skip to content

Dashboard: Migrate contract/account from chakra to tailwind #7741

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

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
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import { Flex, SimpleGrid, useBreakpointValue } from "@chakra-ui/react";
import { Card } from "chakra/card";
import { Heading } from "chakra/heading";
import { Text } from "chakra/text";
import { formatDistance } from "date-fns";
import type { ThirdwebClient } from "thirdweb";
import { useActiveAccount } from "thirdweb/react";
Expand All @@ -22,15 +18,14 @@ interface AccountSignerProps {
client: ThirdwebClient;
}

export const AccountSigner: React.FC<AccountSignerProps> = ({
export function AccountSigner({
item,
contractChainId,
client,
}) => {
}: AccountSignerProps) {
const address = useActiveAccount()?.address;
const { idToChain } = useAllChainsData();
const chain = contractChainId ? idToChain.get(contractChainId) : undefined;
const isMobile = useBreakpointValue({ base: true, md: false });
const {
isAdmin,
signer,
Expand All @@ -39,58 +34,49 @@ export const AccountSigner: React.FC<AccountSignerProps> = ({
endTimestamp,
} = item;
return (
<Card p={8} position="relative">
<Flex direction="column" gap={8}>
<Flex flexDir="column" gap={2} mt={{ base: 4, md: 0 }}>
<Flex
alignItems="center"
flexDir={{ base: "column", lg: "row" }}
gap={3}
>
<Heading size="label.lg">
<WalletAddress
address={signer}
client={client}
shortenAddress={isMobile}
/>
</Heading>
<div className="flex flex-row gap-2">
{isAdmin ? <Badge>Admin Key</Badge> : <Badge>Scoped key</Badge>}
{signer === address && (
<Badge variant="success">Currently connected</Badge>
)}
</div>
</Flex>
</Flex>
<div className="p-4 rounded-lg bg-card border lg:p-6">
<div className="flex lg:items-center lg:justify-between items-start flex-col lg:flex-row gap-4">
<WalletAddress
address={signer}
client={client}
className="h-auto py-1"
iconClassName="size-5"
/>
<div className="flex flex-row gap-2">
{isAdmin ? <Badge>Admin Key</Badge> : <Badge>Scoped key</Badge>}
{signer === address && (
<Badge variant="secondary">Currently connected</Badge>
)}
</div>
</div>

{isAdmin ? null : (
<SimpleGrid columns={{ base: 2, md: 4 }} gap={2}>
<div className="flex flex-col">
<Text fontWeight="bold">Maximum value per transaction</Text>
<Text textTransform="capitalize">
{nativeTokenLimitPerTransaction.toString()}{" "}
{chain?.nativeCurrency.symbol}
</Text>
</div>
<div className="flex flex-col">
<Text fontWeight="bold">Approved targets</Text>
<Text textTransform="capitalize">{approvedTargets.length}</Text>
</div>
<div className="flex flex-col">
<Text fontWeight="bold">Expiration</Text>
<Text>
{formatDistance(
new Date(new Date(Number(endTimestamp * 1000n))),
new Date(),
{
addSuffix: true,
},
)}
</Text>
</div>
</SimpleGrid>
)}
</Flex>
</Card>
<div className="flex flex-col lg:flex-row gap-4 lg:gap-16 border-t pt-4 mt-6 lg:mt-4 border-dashed">
<div className="space-y-0.5 text-sm">
<div className="font-medium">Maximum value per transaction</div>
<div className="capitalize">
{nativeTokenLimitPerTransaction.toString()}{" "}
{chain?.nativeCurrency.symbol}
</div>
</div>

<div className="space-y-0.5 text-sm">
<div className="font-medium">Approved targets</div>
<div className="capitalize">{approvedTargets.length}</div>
</div>

<div className="space-y-0.5 text-sm">
<div className="font-medium">Expiration</div>
<div>
{formatDistance(
new Date(new Date(Number(endTimestamp * 1000n))),
new Date(),
{
addSuffix: true,
},
)}
</div>
</div>
</div>
</div>
);
};
}
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
"use client";

import { Heading } from "chakra/heading";
import type { ThirdwebContract } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import type { ProjectMeta } from "../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types";
import { AccountBalance } from "./components/account-balance";
import { DepositNative } from "./components/deposit-native";
import { NftsOwned } from "./components/nfts-owned";

interface AccountPageProps {
export function AccountPage(props: {
contract: ThirdwebContract;
chainMetadata: ChainMetadata;
isLoggedIn: boolean;
isInsightSupported: boolean;
projectMeta: ProjectMeta | undefined;
}

export const AccountPage: React.FC<AccountPageProps> = ({
contract,
chainMetadata,
isLoggedIn,
isInsightSupported,
projectMeta,
}) => {
const symbol = chainMetadata.nativeCurrency.symbol || "Native Token";
}) {
const {
contract,
chainMetadata,
isLoggedIn,
isInsightSupported,
projectMeta,
} = props;
const symbol = chainMetadata.nativeCurrency.symbol;

return (
<div className="flex flex-col gap-6">
<div className="flex flex-row items-center justify-between">
<Heading size="title.sm">Balances</Heading>
</div>
<AccountBalance contract={contract} />
<div className="flex flex-row items-center justify-between">
<Heading size="title.sm">Deposit {symbol}</Heading>
<div className="space-y-6">
<div>
<h2 className="text-lg font-semibold tracking-tight mb-2">Balances</h2>
<AccountBalance contract={contract} />
</div>

{chainMetadata && (
<div>
<h3 className="text-lg font-semibold tracking-tight mb-2">
Deposit {symbol}
</h3>
<DepositNative
address={contract.address}
chain={chainMetadata}
client={contract.client}
isLoggedIn={isLoggedIn}
symbol={symbol}
/>
)}
</div>

<div className="flex flex-row items-center justify-between">
<Heading size="title.sm">NFTs owned</Heading>
<div>
<h3 className="text-lg font-semibold tracking-tight mb-1">
NFTs owned
</h3>
<NftsOwned
contract={contract}
isInsightSupported={isInsightSupported}
projectMeta={projectMeta}
/>
</div>
<NftsOwned
contract={contract}
isInsightSupported={isInsightSupported}
projectMeta={projectMeta}
/>
</div>
);
};
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
"use client";

import { SimpleGrid, Stat, StatLabel, StatNumber } from "@chakra-ui/react";
import { Card } from "chakra/card";
import type { ThirdwebContract } from "thirdweb";
import { useActiveWalletChain, useWalletBalance } from "thirdweb/react";
import { useSplitBalances } from "@/hooks/useSplit";
import { StatCard } from "../../overview/components/stat-card";

interface AccountBalanceProps {
contract: ThirdwebContract;
}

export const AccountBalance: React.FC<AccountBalanceProps> = ({ contract }) => {
export function AccountBalance(props: { contract: ThirdwebContract }) {
const activeChain = useActiveWalletChain();
const { data: balance } = useWalletBalance({
address: contract.address,
address: props.contract.address,
chain: activeChain,
client: contract.client,
client: props.contract.client,
});
const balanceQuery = useSplitBalances(contract);

const balanceQuery = useSplitBalances(props.contract);

return (
<SimpleGrid columns={{ base: 2, md: 4 }} spacing={{ base: 3, md: 6 }}>
<Card as={Stat}>
<StatLabel mb={{ base: 1, md: 0 }}>{balance?.symbol}</StatLabel>
<StatNumber>{balance?.displayValue}</StatNumber>
</Card>
<div className="grid grid-cols-2 gap-3 md:grid-cols-3">
<StatCard
label={balance?.symbol || ""}
value={balance?.displayValue || ""}
isPending={balanceQuery.isPending}
/>
{balanceQuery?.data
?.filter((bl) => bl.name !== "Native Token")
.map((bl) => (
<Card as={Stat} key={bl.symbol}>
<StatLabel mb={{ base: 1, md: 0 }}>{bl.symbol}</StatLabel>
<StatNumber>{bl.display_balance}</StatNumber>
</Card>
<StatCard
key={bl.symbol}
label={bl.symbol}
value={bl.display_balance}
isPending={false}
/>
))}
</SimpleGrid>
</div>
);
};
}
Original file line number Diff line number Diff line change
@@ -1,82 +1,68 @@
"use client";

import { Card } from "chakra/card";
import { type ChangeEvent, useState } from "react";
import { ArrowUpRightIcon } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { prepareTransaction, type ThirdwebClient, toWei } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { useSendAndConfirmTransaction } from "thirdweb/react";
import { TransactionButton } from "@/components/tx-button";
import { Input } from "@/components/ui/input";
import { useV5DashboardChain } from "@/hooks/chains/v5-adapter";
import type { StoredChain } from "@/stores/chainStores";
import { mapV4ChainToV5Chain } from "@/utils/map-chains";

interface DepositNativeProps {
export function DepositNative(props: {
address: string;
symbol: string;
chain: StoredChain;
chain: ChainMetadata;
isLoggedIn: boolean;
client: ThirdwebClient;
}

export const DepositNative: React.FC<DepositNativeProps> = ({
address,
symbol,
chain,
isLoggedIn,
client,
}) => {
const { mutate: transfer, isPending } = useSendAndConfirmTransaction();
}) {
const sendTransaction = useSendAndConfirmTransaction();
const [amount, setAmount] = useState("");
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setAmount(e.currentTarget.value);
};
const v5Chain = useV5DashboardChain(chain.chainId);

return (
<Card
maxW={{ base: "100%", md: "49%" }}
style={{
alignItems: "center",
display: "flex",
flexDirection: "row",
gap: 16,
}}
>
<div className="flex flex-row items-center max-w-lg">
<Input
onChange={handleChange}
placeholder={`Amount in ${symbol}. ex: 0.001`}
onChange={(e) => setAmount(e.currentTarget.value)}
placeholder="0.001"
type="number"
className="border-r-0 rounded-r-none bg-card"
value={amount}
/>

<TransactionButton
client={client}
disabled={
amount.length === 0 || Number.parseFloat(amount) <= 0 || !address
}
isLoggedIn={isLoggedIn}
isPending={isPending}
client={props.client}
variant="default"
disabled={amount.length === 0 || Number.parseFloat(amount) <= 0}
isLoggedIn={props.isLoggedIn}
className="border-l-0 rounded-l-none px-6"
isPending={sendTransaction.isPending}
onClick={() => {
if (!address) {
throw new Error("Invalid address");
}

const transaction = prepareTransaction({
chain: v5Chain,
client,
to: address,
// eslint-disable-next-line no-restricted-syntax
chain: mapV4ChainToV5Chain(props.chain),
client: props.client,
to: props.address,
value: toWei(amount),
});
transfer(transaction, {
sendTransaction.mutate(transaction, {
onSuccess: () => {
toast.success("Deposit successful");
setAmount("");
},
onError: (error) => {
toast.error("Deposit failed", {
description: error.message,
});
},
});
}}
style={{ minWidth: 160 }}
transactionCount={1}
txChainID={v5Chain.id}
transactionCount={undefined}
txChainID={props.chain.chainId}
>
Deposit
<ArrowUpRightIcon className="w-4 h-4" />
</TransactionButton>
</Card>
</div>
);
};
}
Loading
Loading