Compare commits
27
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a1d59d789 | ||
|
|
a04cda1e5a | ||
|
|
67a363f624 | ||
|
|
1cd11a86f7 | ||
|
|
9da5cd7d49 | ||
|
|
0dd1438012 | ||
|
|
0f4e6622e0 | ||
|
|
e67a300410 | ||
|
|
00a6a56158 | ||
|
|
7855c3ea8a | ||
|
|
6597cb6525 | ||
|
|
fbd9853697 | ||
|
|
b01faacd99 | ||
|
|
ef6b4f48ef | ||
|
|
c5a2cdb3b6 | ||
|
|
5dd0c91d3e | ||
|
|
f8f90fd3ab | ||
|
|
63037f1bf1 | ||
|
|
b205f1d298 | ||
|
|
cb6a0537d8 | ||
|
|
772604eee2 | ||
|
|
6e4cd214a3 | ||
|
|
77380200bb | ||
|
|
85e7d15f22 | ||
|
|
3a141e742c | ||
|
|
5f09091a23 | ||
|
|
d08b9be3c5 |
@@ -96,4 +96,8 @@ UNTHREAD_PRO_TIER_ID=""
|
||||
NEXT_PUBLIC_DEMO_ENGINE_URL=""
|
||||
|
||||
# API server secret (required for thirdweb.com SIWE login). Copy from Vercel.
|
||||
API_SERVER_SECRET=""
|
||||
API_SERVER_SECRET=""
|
||||
|
||||
# Used for the Faucet page (/<chain_id>)
|
||||
NEXT_PUBLIC_TURNSTILE_SITE_KEY=""
|
||||
TURNSTILE_SECRET_KEY=""
|
||||
@@ -8,7 +8,7 @@ const ContentSecurityPolicy = `
|
||||
style-src 'self' 'unsafe-inline' vercel.live;
|
||||
font-src 'self' vercel.live assets.vercel.com framerusercontent.com;
|
||||
frame-src * data:;
|
||||
script-src 'self' 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval' 'inline-speculation-rules' *.thirdweb.com *.thirdweb-dev.com vercel.live js.stripe.com framerusercontent.com events.framer.com;
|
||||
script-src 'self' 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval' 'inline-speculation-rules' *.thirdweb.com *.thirdweb-dev.com vercel.live js.stripe.com framerusercontent.com events.framer.com challenges.cloudflare.com;
|
||||
connect-src * data: blob:;
|
||||
worker-src 'self' blob:;
|
||||
block-all-mixed-content;
|
||||
@@ -167,7 +167,6 @@ const moduleExports = {
|
||||
};
|
||||
|
||||
const { withSentryConfig } = require("@sentry/nextjs");
|
||||
|
||||
const { withPlausibleProxy } = require("next-plausible");
|
||||
|
||||
// we only want sentry on production environments
|
||||
@@ -183,48 +182,45 @@ module.exports = withBundleAnalyzer(
|
||||
customDomain: "https://pl.thirdweb.com",
|
||||
scriptName: "pl",
|
||||
})(
|
||||
wSentry(
|
||||
moduleExports,
|
||||
{
|
||||
// For all available options, see:
|
||||
// https://github.com/getsentry/sentry-webpack-plugin#options
|
||||
wSentry(moduleExports, {
|
||||
// For all available options, see:
|
||||
// https://github.com/getsentry/sentry-webpack-plugin#options
|
||||
|
||||
// Suppresses source map uploading logs during build
|
||||
silent: true,
|
||||
org: "thirdweb-dev",
|
||||
project: "dashboard",
|
||||
},
|
||||
{
|
||||
// For all available options, see:
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
||||
org: "thirdweb-dev",
|
||||
project: "dashboard",
|
||||
// An auth token is required for uploading source maps.
|
||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||
// Suppresses source map uploading logs during build
|
||||
silent: false,
|
||||
// For all available options, see:
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
||||
|
||||
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
||||
widenClientFileUpload: true,
|
||||
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
||||
widenClientFileUpload: true,
|
||||
|
||||
// Transpiles SDK to be compatible with IE11 (increases bundle size)
|
||||
transpileClientSDK: false,
|
||||
// Transpiles SDK to be compatible with IE11 (increases bundle size)
|
||||
transpileClientSDK: false,
|
||||
|
||||
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
|
||||
tunnelRoute: "/err",
|
||||
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
|
||||
tunnelRoute: "/err",
|
||||
|
||||
// Hides source maps from generated client bundles
|
||||
hideSourceMaps: true,
|
||||
// Hides source maps from generated client bundles
|
||||
hideSourceMaps: true,
|
||||
|
||||
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
||||
disableLogger: true,
|
||||
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
||||
disableLogger: true,
|
||||
|
||||
// Enables automatic instrumentation of Vercel Cron Monitors.
|
||||
// See the following for more information:
|
||||
// https://docs.sentry.io/product/crons/
|
||||
// https://vercel.com/docs/cron-jobs
|
||||
automaticVercelMonitors: false,
|
||||
// Enables automatic instrumentation of Vercel Cron Monitors.
|
||||
// See the following for more information:
|
||||
// https://docs.sentry.io/product/crons/
|
||||
// https://vercel.com/docs/cron-jobs
|
||||
automaticVercelMonitors: false,
|
||||
|
||||
/**
|
||||
* Disables the Sentry Webpack plugin on the server.
|
||||
* See: https://github.com/getsentry/sentry-javascript/issues/10468#issuecomment-2004710692
|
||||
*/
|
||||
disableServerWebpackPlugin: true,
|
||||
},
|
||||
),
|
||||
/**
|
||||
* Disables the Sentry Webpack plugin on the server.
|
||||
* See: https://github.com/getsentry/sentry-javascript/issues/10468#issuecomment-2004710692
|
||||
*/
|
||||
disableServerWebpackPlugin: true,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"@emotion/react": "11.13.3",
|
||||
"@emotion/styled": "11.13.0",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
"@marsidev/react-turnstile": "^1.0.2",
|
||||
"@n8tb1t/use-scroll-position": "^2.0.3",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.2",
|
||||
"@radix-ui/react-avatar": "^1.1.1",
|
||||
|
||||
@@ -23,3 +23,6 @@ export const DASHBOARD_STORAGE_URL =
|
||||
|
||||
export const API_SERVER_URL =
|
||||
process.env.NEXT_PUBLIC_THIRDWEB_API_HOST || "https://api.thirdweb.com";
|
||||
|
||||
export const TURNSTILE_SITE_KEY =
|
||||
process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY || "";
|
||||
|
||||
@@ -21,6 +21,21 @@ export const accountKeys = {
|
||||
to,
|
||||
period,
|
||||
] as const,
|
||||
userOpStats: (
|
||||
walletAddress: string,
|
||||
clientId: string,
|
||||
from: string,
|
||||
to: string,
|
||||
period: string,
|
||||
) =>
|
||||
[
|
||||
...accountKeys.wallet(walletAddress),
|
||||
"userOps",
|
||||
clientId,
|
||||
from,
|
||||
to,
|
||||
period,
|
||||
] as const,
|
||||
credits: (walletAddress: string) =>
|
||||
[...accountKeys.wallet(walletAddress), "credits"] as const,
|
||||
billingSession: (walletAddress: string) =>
|
||||
|
||||
@@ -234,6 +234,13 @@ export interface WalletStats {
|
||||
walletType: string;
|
||||
}
|
||||
|
||||
export interface UserOpStats {
|
||||
date: string;
|
||||
successful: number;
|
||||
failed: number;
|
||||
sponsoredUsd: number;
|
||||
}
|
||||
|
||||
interface BillingProduct {
|
||||
name: string;
|
||||
id: string;
|
||||
@@ -383,6 +390,100 @@ async function getWalletUsage(args: {
|
||||
return json.data;
|
||||
}
|
||||
|
||||
async function getUserOpUsage(args: {
|
||||
clientId: string;
|
||||
from?: Date;
|
||||
to?: Date;
|
||||
period?: "day" | "week" | "month" | "year" | "all";
|
||||
}) {
|
||||
const { clientId, from, to, period } = args;
|
||||
|
||||
const searchParams = new URLSearchParams();
|
||||
searchParams.append("clientId", clientId);
|
||||
if (from) {
|
||||
searchParams.append("from", from.toISOString());
|
||||
}
|
||||
if (to) {
|
||||
searchParams.append("to", to.toISOString());
|
||||
}
|
||||
if (period) {
|
||||
searchParams.append("period", period);
|
||||
}
|
||||
const res = await fetch(
|
||||
`${THIRDWEB_ANALYTICS_API_HOST}/v1/user-ops?${searchParams.toString()}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
const json = await res.json();
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error(json.message);
|
||||
}
|
||||
|
||||
return json.data;
|
||||
}
|
||||
|
||||
export function useUserOpUsageAggregate(args: {
|
||||
clientId: string;
|
||||
from?: Date;
|
||||
to?: Date;
|
||||
}) {
|
||||
const { clientId, from, to } = args;
|
||||
const { user, isLoggedIn } = useLoggedInUser();
|
||||
|
||||
return useQuery({
|
||||
queryKey: accountKeys.userOpStats(
|
||||
user?.address as string,
|
||||
clientId as string,
|
||||
from?.toISOString() || "",
|
||||
to?.toISOString() || "",
|
||||
"all",
|
||||
),
|
||||
queryFn: async () => {
|
||||
return getUserOpUsage({
|
||||
clientId,
|
||||
from,
|
||||
to,
|
||||
period: "all",
|
||||
});
|
||||
},
|
||||
enabled: !!clientId && !!user?.address && isLoggedIn,
|
||||
});
|
||||
}
|
||||
|
||||
export function useUserOpUsagePeriod(args: {
|
||||
clientId: string;
|
||||
from?: Date;
|
||||
to?: Date;
|
||||
period: "day" | "week" | "month" | "year";
|
||||
}) {
|
||||
const { clientId, from, to, period } = args;
|
||||
const { user, isLoggedIn } = useLoggedInUser();
|
||||
|
||||
return useQuery({
|
||||
queryKey: accountKeys.userOpStats(
|
||||
user?.address as string,
|
||||
clientId as string,
|
||||
from?.toISOString() || "",
|
||||
to?.toISOString() || "",
|
||||
period,
|
||||
),
|
||||
queryFn: async () => {
|
||||
return getUserOpUsage({
|
||||
clientId,
|
||||
from,
|
||||
to,
|
||||
period,
|
||||
});
|
||||
},
|
||||
enabled: !!clientId && !!user?.address && isLoggedIn,
|
||||
});
|
||||
}
|
||||
|
||||
export function useWalletUsageAggregate(args: {
|
||||
clientId: string;
|
||||
from?: Date;
|
||||
|
||||
+55
-21
@@ -2,17 +2,24 @@
|
||||
|
||||
import { Spinner } from "@/components/ui/Spinner/Spinner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { THIRDWEB_ENGINE_FAUCET_WALLET } from "@/constants/env";
|
||||
import { Form, FormControl, FormField, FormItem } from "@/components/ui/form";
|
||||
import {
|
||||
THIRDWEB_ENGINE_FAUCET_WALLET,
|
||||
TURNSTILE_SITE_KEY,
|
||||
} from "@/constants/env";
|
||||
import { useThirdwebClient } from "@/constants/thirdweb.client";
|
||||
import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet";
|
||||
import { Turnstile } from "@marsidev/react-turnstile";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import type { CanClaimResponseType } from "app/api/testnet-faucet/can-claim/CanClaimResponseType";
|
||||
import { mapV4ChainToV5Chain } from "contexts/map-chains";
|
||||
import { useTrack } from "hooks/analytics/useTrack";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { toUnits } from "thirdweb";
|
||||
import type { ChainMetadata } from "thirdweb/chains";
|
||||
import { useActiveAccount, useWalletBalance } from "thirdweb/react";
|
||||
import { z } from "zod";
|
||||
|
||||
function formatTime(seconds: number) {
|
||||
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
|
||||
@@ -29,6 +36,12 @@ function formatTime(seconds: number) {
|
||||
return rtf.format(+seconds, "second");
|
||||
}
|
||||
|
||||
const claimFaucetSchema = z.object({
|
||||
turnstileToken: z.string().min(1, {
|
||||
message: "Captcha validation is required.",
|
||||
}),
|
||||
});
|
||||
|
||||
export function FaucetButton({
|
||||
chain,
|
||||
amount,
|
||||
@@ -52,7 +65,7 @@ export function FaucetButton({
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const claimMutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
mutationFn: async (turnstileToken: string) => {
|
||||
trackEvent({
|
||||
category: "faucet",
|
||||
action: "claim",
|
||||
@@ -67,6 +80,7 @@ export function FaucetButton({
|
||||
body: JSON.stringify({
|
||||
chainId: chainId,
|
||||
toAddress: address,
|
||||
turnstileToken,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -117,6 +131,8 @@ export function FaucetButton({
|
||||
faucetWalletBalanceQuery.data !== undefined &&
|
||||
faucetWalletBalanceQuery.data.value < toUnits("1", 17);
|
||||
|
||||
const form = useForm<z.infer<typeof claimFaucetSchema>>();
|
||||
|
||||
// loading state
|
||||
if (faucetWalletBalanceQuery.isPending || canClaimFaucetQuery.isPending) {
|
||||
return (
|
||||
@@ -161,28 +177,46 @@ export function FaucetButton({
|
||||
);
|
||||
}
|
||||
|
||||
const claimFunds = (values: z.infer<typeof claimFaucetSchema>) => {
|
||||
// Instead of having a dedicated endpoint (/api/verify-token),
|
||||
// we can just attach the token in the payload and send it to the claim-faucet endpoint, to avoid a round-trip request
|
||||
const claimPromise = claimMutation.mutateAsync(values.turnstileToken);
|
||||
toast.promise(claimPromise, {
|
||||
success: `${amount} ${chain.nativeCurrency.symbol} sent successfully`,
|
||||
error: `Failed to claim ${amount} ${chain.nativeCurrency.symbol}`,
|
||||
});
|
||||
};
|
||||
|
||||
// eligible to claim and faucet has balance
|
||||
return (
|
||||
<div className="flex w-full flex-col text-center">
|
||||
<Button
|
||||
variant="primary"
|
||||
className="w-full gap-2"
|
||||
onClick={() => {
|
||||
const claimPromise = claimMutation.mutateAsync();
|
||||
toast.promise(claimPromise, {
|
||||
success: `${amount} ${chain.nativeCurrency.symbol} sent successfully`,
|
||||
error: `Failed to claim ${amount} ${chain.nativeCurrency.symbol}`,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{claimMutation.isPending ? (
|
||||
<>
|
||||
Claiming <Spinner className="size-3" />
|
||||
</>
|
||||
) : (
|
||||
`Get ${amount} ${chain.nativeCurrency.symbol}`
|
||||
)}
|
||||
</Button>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(claimFunds)}>
|
||||
<Button variant="primary" className="w-full gap-2" type="submit">
|
||||
{claimMutation.isPending ? (
|
||||
<>
|
||||
Claiming <Spinner className="size-3" />
|
||||
</>
|
||||
) : (
|
||||
`Get ${amount} ${chain.nativeCurrency.symbol}`
|
||||
)}
|
||||
</Button>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="turnstileToken"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Turnstile
|
||||
siteKey={TURNSTILE_SITE_KEY}
|
||||
onSuccess={(token) => field.onChange(token)}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
{faucetWalletBalanceQuery.data && (
|
||||
<p className="mt-3 text-muted-foreground text-xs">
|
||||
|
||||
@@ -46,6 +46,10 @@ export async function generateMetadata({
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ export default async function Image({
|
||||
right: -2,
|
||||
height: 150,
|
||||
width: 150,
|
||||
objectFit: "contain",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
+10
-11
@@ -2,11 +2,11 @@
|
||||
|
||||
import { TransactionButton } from "components/buttons/TransactionButton";
|
||||
import { useTrack } from "hooks/analytics/useTrack";
|
||||
import { useTxNotifications } from "hooks/useTxNotifications";
|
||||
import { useAllChainsData } from "hooks/chains/allChains";
|
||||
import { toast } from "sonner";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import { cancelAuction, cancelListing } from "thirdweb/extensions/marketplace";
|
||||
import { useSendAndConfirmTransaction } from "thirdweb/react";
|
||||
import { useAllChainsData } from "../../../hooks/chains/allChains";
|
||||
|
||||
interface CancelTabProps {
|
||||
id: string;
|
||||
@@ -25,14 +25,9 @@ export const CancelTab: React.FC<CancelTabProps> = ({
|
||||
const transaction = isAuction
|
||||
? cancelAuction({ contract, auctionId: BigInt(id) })
|
||||
: cancelListing({ contract, listingId: BigInt(id) });
|
||||
const { onSuccess, onError } = useTxNotifications(
|
||||
"Listing cancelled",
|
||||
"Error cancelling listing",
|
||||
);
|
||||
const cancelQuery = useSendAndConfirmTransaction();
|
||||
return (
|
||||
<div className="flex flex-col gap-3 pt-3">
|
||||
{/* maybe some text? */}
|
||||
<TransactionButton
|
||||
txChainID={contract.chain.id}
|
||||
transactionCount={1}
|
||||
@@ -43,7 +38,7 @@ export const CancelTab: React.FC<CancelTabProps> = ({
|
||||
action: "cancel-listing",
|
||||
label: "attempt",
|
||||
});
|
||||
cancelQuery.mutate(transaction, {
|
||||
const promise = cancelQuery.mutateAsync(transaction, {
|
||||
onSuccess: () => {
|
||||
trackEvent({
|
||||
category: "marketplace",
|
||||
@@ -51,7 +46,6 @@ export const CancelTab: React.FC<CancelTabProps> = ({
|
||||
label: "success",
|
||||
network,
|
||||
});
|
||||
onSuccess();
|
||||
},
|
||||
onError: (error) => {
|
||||
trackEvent({
|
||||
@@ -61,14 +55,19 @@ export const CancelTab: React.FC<CancelTabProps> = ({
|
||||
network,
|
||||
error,
|
||||
});
|
||||
onError(error);
|
||||
console.error(error);
|
||||
},
|
||||
});
|
||||
toast.promise(promise, {
|
||||
loading: `Cancelling ${isAuction ? "auction" : "listing"}`,
|
||||
success: "Item cancelled successfully",
|
||||
error: "Failed to cancel",
|
||||
});
|
||||
}}
|
||||
colorScheme="primary"
|
||||
alignSelf="flex-end"
|
||||
>
|
||||
Cancel Listing
|
||||
Cancel {isAuction ? "Auction" : "Listing"}
|
||||
</TransactionButton>
|
||||
</div>
|
||||
);
|
||||
+1
-1
@@ -8,7 +8,7 @@ import { useState } from "react";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import { useActiveAccount } from "thirdweb/react";
|
||||
import { Button, Drawer } from "tw-components";
|
||||
import { CreateListingsForm } from "../listings/components/list-form";
|
||||
import { CreateListingsForm } from "./list-form";
|
||||
|
||||
const LIST_FORM_ID = "marketplace-list-form";
|
||||
|
||||
+1
-2
@@ -15,6 +15,7 @@ import {
|
||||
import { CurrencySelector } from "components/shared/CurrencySelector";
|
||||
import { SolidityInput } from "contract-ui/components/solidity-inputs";
|
||||
import { useTrack } from "hooks/analytics/useTrack";
|
||||
import { useAllChainsData } from "hooks/chains/allChains";
|
||||
import { useTxNotifications } from "hooks/useTxNotifications";
|
||||
import { isAlchemySupported } from "lib/wallet/nfts/alchemy";
|
||||
import { isMoralisSupported } from "lib/wallet/nfts/moralis";
|
||||
@@ -57,8 +58,6 @@ import {
|
||||
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
|
||||
import { shortenIfAddress } from "utils/usedapp-external";
|
||||
|
||||
import { useAllChainsData } from "../../../../hooks/chains/allChains";
|
||||
|
||||
type ListForm =
|
||||
| (Omit<CreateListingParams, "quantity" | "currencyContractAddress"> & {
|
||||
currencyContractAddress: string;
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
import { WalletAddress } from "@/components/blocks/wallet-address";
|
||||
import { CopyAddressButton } from "@/components/ui/CopyAddressButton";
|
||||
import { CopyTextButton } from "@/components/ui/CopyTextButton";
|
||||
import { Sheet, SheetContent } from "@/components/ui/sheet";
|
||||
import { Flex, GridItem, SimpleGrid, usePrevious } from "@chakra-ui/react";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import type {
|
||||
DirectListing,
|
||||
EnglishAuction,
|
||||
} from "thirdweb/extensions/marketplace";
|
||||
import { useActiveAccount } from "thirdweb/react";
|
||||
import { Badge, Card, CodeBlock, Heading, Text } from "tw-components";
|
||||
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
|
||||
import { CancelTab } from "./cancel-tab";
|
||||
import { LISTING_STATUS } from "./types";
|
||||
|
||||
interface NFTDrawerProps {
|
||||
contract: ThirdwebContract;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
data: DirectListing | EnglishAuction | null;
|
||||
}
|
||||
|
||||
export const ListingDrawer: React.FC<NFTDrawerProps> = ({
|
||||
contract,
|
||||
isOpen,
|
||||
onClose,
|
||||
data,
|
||||
}) => {
|
||||
const address = useActiveAccount()?.address;
|
||||
const prevData = usePrevious(data);
|
||||
|
||||
const renderData = data || prevData;
|
||||
const isOwner =
|
||||
address?.toLowerCase() === renderData?.creatorAddress.toLowerCase();
|
||||
|
||||
const tokenId = renderData?.asset.id.toString() || "";
|
||||
|
||||
if (!renderData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Sheet open={isOpen} onOpenChange={onClose}>
|
||||
<SheetContent className="flex w-full flex-col gap-6 py-6 md:min-w-[600px]">
|
||||
<div className="flex flex-row gap-6">
|
||||
<NFTMediaWithEmptyState
|
||||
metadata={renderData.asset.metadata}
|
||||
requireInteraction
|
||||
width="150px"
|
||||
height="150px"
|
||||
/>
|
||||
<Flex flexDir="column" gap={2} w="70%">
|
||||
<Heading size="title.lg">{renderData.asset.metadata.name}</Heading>
|
||||
<Text size="label.md" noOfLines={6}>
|
||||
{renderData.asset.metadata.name}
|
||||
</Text>
|
||||
</Flex>
|
||||
</div>
|
||||
|
||||
<Flex flexDir="column" gap={4}>
|
||||
<Card as={Flex} flexDir="column" gap={3}>
|
||||
<SimpleGrid rowGap={3} columns={12} placeItems="center left">
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Asset contract address</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<CopyAddressButton
|
||||
address={renderData.assetContractAddress}
|
||||
copyIconPosition="right"
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Token ID</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<CopyTextButton
|
||||
textToCopy={tokenId}
|
||||
textToShow={tokenId}
|
||||
copyIconPosition="right"
|
||||
tooltip="Token ID"
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Seller</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<WalletAddress address={renderData.creatorAddress} />
|
||||
</GridItem>
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Listing ID</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<CopyTextButton
|
||||
textToCopy={renderData.id.toString()}
|
||||
textToShow={renderData.id.toString()}
|
||||
copyIconPosition="right"
|
||||
tooltip="Listing ID"
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Type</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<Text fontFamily="mono" size="body.md">
|
||||
{renderData.asset.type}
|
||||
</Text>
|
||||
</GridItem>
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Status</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<Badge
|
||||
size="label.sm"
|
||||
variant="subtle"
|
||||
textTransform="capitalize"
|
||||
>
|
||||
{LISTING_STATUS[renderData.status]}
|
||||
</Badge>
|
||||
</GridItem>
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Quantity</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<Text fontFamily="mono" size="body.md">
|
||||
{(renderData.quantity || 0n).toString()}{" "}
|
||||
{/* For listings that are completed, the `quantity` would be `0`
|
||||
So we show this text to make it clear */}
|
||||
{LISTING_STATUS[renderData.status] === "Completed"
|
||||
? "(Sold out)"
|
||||
: ""}
|
||||
</Text>
|
||||
</GridItem>
|
||||
|
||||
{renderData.type === "direct-listing" && (
|
||||
<>
|
||||
<GridItem colSpan={3}>
|
||||
<Heading size="label.md">Price</Heading>
|
||||
</GridItem>
|
||||
<GridItem colSpan={9}>
|
||||
<Text fontFamily="mono" size="body.md">
|
||||
{renderData.currencyValuePerToken.displayValue}{" "}
|
||||
{renderData.currencyValuePerToken.symbol}
|
||||
</Text>
|
||||
</GridItem>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/*
|
||||
Todo: Add a Buy button somewhere in this section once the Dashboard is fully migrated to v5 (?)
|
||||
Kien already shipped a prebuilt component for the Marketplace Buy Button in SDK v5
|
||||
*/}
|
||||
</SimpleGrid>
|
||||
</Card>
|
||||
{data?.asset.metadata.properties ? (
|
||||
<Card as={Flex} flexDir="column" gap={4}>
|
||||
<Heading size="label.md">Attributes</Heading>
|
||||
<CodeBlock
|
||||
code={
|
||||
JSON.stringify(data.asset.metadata.properties, null, 2) || ""
|
||||
}
|
||||
language="json"
|
||||
canCopy={false}
|
||||
wrap={false}
|
||||
overflow="auto"
|
||||
/>
|
||||
</Card>
|
||||
) : null}
|
||||
</Flex>
|
||||
{isOwner && (
|
||||
<CancelTab
|
||||
contract={contract}
|
||||
id={renderData.id.toString()}
|
||||
isAuction={renderData.type === "english-auction"}
|
||||
/>
|
||||
)}
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
};
|
||||
+1
-4
@@ -17,7 +17,6 @@ import {
|
||||
} from "@chakra-ui/react";
|
||||
import type { UseQueryResult } from "@tanstack/react-query";
|
||||
import { MediaCell } from "components/contract-pages/table/table-columns/cells/media-cell";
|
||||
import { ListingDrawer } from "contract-ui/tabs/shared-components/listing-drawer";
|
||||
import {
|
||||
ChevronFirstIcon,
|
||||
ChevronLastIcon,
|
||||
@@ -40,6 +39,7 @@ import type {
|
||||
} from "thirdweb/extensions/marketplace";
|
||||
import { min } from "thirdweb/utils";
|
||||
import { Button, Text } from "tw-components";
|
||||
import { ListingDrawer } from "./listing-drawer";
|
||||
import { LISTING_STATUS } from "./types";
|
||||
|
||||
const tableColumns: Column<DirectListing | EnglishAuction>[] = [
|
||||
@@ -100,7 +100,6 @@ interface MarketplaceTableProps {
|
||||
start: number;
|
||||
}>
|
||||
>;
|
||||
type: "direct-listings" | "english-auctions";
|
||||
}
|
||||
|
||||
const DEFAULT_QUERY_STATE = { count: 50, start: 0 };
|
||||
@@ -112,7 +111,6 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
|
||||
totalCountQuery,
|
||||
queryParams,
|
||||
setQueryParams,
|
||||
type,
|
||||
}) => {
|
||||
const [listingsToShow, setListingsToShow_] = useState<"all" | "valid">("all");
|
||||
|
||||
@@ -215,7 +213,6 @@ export const MarketplaceTable: React.FC<MarketplaceTableProps> = ({
|
||||
data={tokenRow}
|
||||
isOpen={!!tokenRow}
|
||||
onClose={() => setTokenRow(null)}
|
||||
type={type}
|
||||
/>
|
||||
<Table {...getTableProps()}>
|
||||
<Thead>
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import { Heading } from "tw-components";
|
||||
import { CreateListingButton } from "../shared-components/list-button";
|
||||
import { CreateListingButton } from "../components/list-button";
|
||||
import { DirectListingsTable } from "./components/table";
|
||||
|
||||
interface ContractDirectListingsPageProps {
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { MarketplaceTable } from "contract-ui/tabs/shared-components/marketplace-table";
|
||||
import { useState } from "react";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import {
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
totalListings,
|
||||
} from "thirdweb/extensions/marketplace";
|
||||
import { useReadContract } from "thirdweb/react";
|
||||
import { MarketplaceTable } from "../../components/marketplace-table";
|
||||
|
||||
interface DirectListingsTableProps {
|
||||
contract: ThirdwebContract;
|
||||
@@ -40,7 +40,6 @@ export const DirectListingsTable: React.FC<DirectListingsTableProps> = ({
|
||||
totalCountQuery={totalCountQuery}
|
||||
queryParams={queryParams}
|
||||
setQueryParams={setQueryParams}
|
||||
type="direct-listings"
|
||||
/>
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { ContractDirectListingsPage } from "../../../../../../contract-ui/tabs/direct-listings/page";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
|
||||
import { ContractDirectListingsPage } from "./ContractDirectListingsPage";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import { Heading } from "tw-components";
|
||||
import { CreateListingButton } from "../shared-components/list-button";
|
||||
import { CreateListingButton } from "../components/list-button";
|
||||
import { EnglishAuctionsTable } from "./components/table";
|
||||
|
||||
interface ContractEnglishAuctionsProps {
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { MarketplaceTable } from "contract-ui/tabs/shared-components/marketplace-table";
|
||||
import { useState } from "react";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import {
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
totalAuctions,
|
||||
} from "thirdweb/extensions/marketplace";
|
||||
import { useReadContract } from "thirdweb/react";
|
||||
import { MarketplaceTable } from "../../components/marketplace-table";
|
||||
|
||||
interface EnglishAuctionsTableProps {
|
||||
contract: ThirdwebContract;
|
||||
@@ -40,7 +40,6 @@ export const EnglishAuctionsTable: React.FC<EnglishAuctionsTableProps> = ({
|
||||
totalCountQuery={totalCountQuery}
|
||||
queryParams={queryParams}
|
||||
setQueryParams={setQueryParams}
|
||||
type="english-auctions"
|
||||
/>
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { ContractEnglishAuctionsPage } from "../../../../../../contract-ui/tabs/english-auctions/page";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
|
||||
import { ContractEnglishAuctionsPage } from "./ContractEnglishAuctionsPage";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
+1
-1
@@ -15,7 +15,7 @@ import type { z } from "zod";
|
||||
import type {
|
||||
ClaimCondition as LegacyClaimCondition,
|
||||
ClaimConditionInputSchema as LegacyClaimConditionInputSchema,
|
||||
} from "../../legacy-zod-schema";
|
||||
} from "../legacy-zod-schema";
|
||||
|
||||
type SnapshotEntry = {
|
||||
address: string;
|
||||
+2
-2
@@ -16,7 +16,6 @@ import {
|
||||
Spinner,
|
||||
} from "@chakra-ui/react";
|
||||
import { TransactionButton } from "components/buttons/TransactionButton";
|
||||
import { SnapshotUpload } from "contract-ui/tabs/claim-conditions/components/snapshot-upload";
|
||||
import { useTrack } from "hooks/analytics/useTrack";
|
||||
import { useTxNotifications } from "hooks/useTxNotifications";
|
||||
import { CircleHelpIcon, PlusIcon } from "lucide-react";
|
||||
@@ -46,8 +45,9 @@ import {
|
||||
type ClaimConditionInput,
|
||||
ClaimConditionInputSchema,
|
||||
type SnapshotEntry,
|
||||
} from "../../legacy-zod-schema";
|
||||
} from "../legacy-zod-schema";
|
||||
import { ResetClaimEligibility } from "../reset-claim-eligibility";
|
||||
import { SnapshotUpload } from "../snapshot-upload";
|
||||
import { getClaimPhasesInLegacyFormat, setClaimPhasesTx } from "./hooks";
|
||||
import { ClaimConditionsPhase } from "./phase";
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ export const ClaimConditions: React.FC<ClaimConditionsProps> = ({
|
||||
isERC20,
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex w-full flex-col gap-8">
|
||||
<Flex p={0} position="relative">
|
||||
<Flex
|
||||
pt={{ base: isColumn ? 0 : 6, md: 6 }}
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { CURRENCIES } from "constants/currencies";
|
||||
import { useAllChainsData } from "hooks/chains/allChains";
|
||||
import { Text } from "tw-components";
|
||||
import { shortenIfAddress } from "utils/usedapp-external";
|
||||
import { isAddressZero } from "utils/zeroAddress";
|
||||
import { useAllChainsData } from "../../../../hooks/chains/allChains";
|
||||
|
||||
interface PricePreviewProps {
|
||||
price: string | number | undefined;
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { ClaimConditions } from "../../../../../../contract-ui/tabs/claim-conditions/components/claim-conditions";
|
||||
import { ClaimConditions } from "../_components/claim-conditions/claim-conditions";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
|
||||
|
||||
+2
-2
@@ -3,11 +3,13 @@
|
||||
import { useApiKeys, useCreateApiKey } from "@3rdweb-sdk/react/hooks/useApi";
|
||||
import { Flex, FormControl, Input, Link, Select } from "@chakra-ui/react";
|
||||
import { useTrack } from "hooks/analytics/useTrack";
|
||||
import { useAllChainsData } from "hooks/chains/allChains";
|
||||
import { useClipboard } from "hooks/useClipboard";
|
||||
import { useTxNotifications } from "hooks/useTxNotifications";
|
||||
import { CheckIcon, CopyIcon } from "lucide-react";
|
||||
import { useMemo } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import type { StoredChain } from "stores/chainStores";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import type { ChainMetadata } from "thirdweb/chains";
|
||||
import {
|
||||
@@ -19,8 +21,6 @@ import {
|
||||
Heading,
|
||||
Text,
|
||||
} from "tw-components";
|
||||
import { useAllChainsData } from "../../../../hooks/chains/allChains";
|
||||
import type { StoredChain } from "../../../../stores/chainStores";
|
||||
|
||||
interface EmbedSetupProps {
|
||||
contract: ThirdwebContract;
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { EmbedSetup } from "../../../../../../contract-ui/tabs/embed/components/embed-setup";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
import { EmbedSetup } from "./embed-setup";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
+1
-1
@@ -24,6 +24,7 @@ import {
|
||||
Tooltip,
|
||||
} from "@chakra-ui/react";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { useChainSlug } from "hooks/chains/chainSlug";
|
||||
import { useClipboard } from "hooks/useClipboard";
|
||||
import { ChevronDownIcon, CircleHelpIcon, CopyIcon } from "lucide-react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
@@ -39,7 +40,6 @@ import {
|
||||
Heading,
|
||||
Text,
|
||||
} from "tw-components";
|
||||
import { useChainSlug } from "../../../../hooks/chains/chainSlug";
|
||||
|
||||
interface EventsFeedProps {
|
||||
contract: ThirdwebContract;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { EventsFeed } from "../../../../../../contract-ui/tabs/events/components/events-feed";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { EventsFeed } from "./events-feed";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
+1
-1
@@ -2,8 +2,8 @@ import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
import { CircleAlertIcon } from "lucide-react";
|
||||
import { notFound } from "next/navigation";
|
||||
import { resolveContractAbi } from "thirdweb/contract";
|
||||
import { ContractExplorerPage } from "../../../../../../contract-ui/tabs/explorer/page";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { ContractExplorerPage } from "./ContractExplorerPage";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
@@ -2,12 +2,12 @@ import { ChakraProviderSetup } from "@/components/ChakraProviderSetup";
|
||||
import { SidebarLayout } from "@/components/blocks/SidebarLayout";
|
||||
import { ContractMetadata } from "components/custom-contract/contract-header/contract-metadata";
|
||||
import { DeprecatedAlert } from "components/shared/DeprecatedAlert";
|
||||
import { PrimaryDashboardButton } from "contract-ui/components/primary-dashboard-button";
|
||||
import type { Metadata } from "next";
|
||||
import { getContractMetadata } from "thirdweb/extensions/common";
|
||||
import { resolveFunctionSelectors } from "../../../../../lib/selectors";
|
||||
import { shortenIfAddress } from "../../../../../utils/usedapp-external";
|
||||
import { ConfigureCustomChain } from "./ConfigureCustomChain";
|
||||
import { PrimaryDashboardButton } from "./_components/primary-dashboard-button";
|
||||
import { supportedERCs } from "./_utils/detectedFeatures/supportedERCs";
|
||||
import { getContractPageParamsInfo } from "./_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "./_utils/getContractPageMetadata";
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { FormControl } from "@chakra-ui/react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { SolidityInput } from "contract-ui/components/solidity-inputs";
|
||||
import invariant from "tiny-invariant";
|
||||
import { FormErrorMessage, FormLabel } from "tw-components";
|
||||
import { SolidityInput } from "../../../components/solidity-inputs";
|
||||
import type { InstallModuleForm } from "./ModuleForm";
|
||||
import { getModuleInstalledParams } from "./getModuleInstalledParams";
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { ContractEditModulesPage } from "../../../../../../contract-ui/tabs/manage/page";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
import { ContractEditModulesPage } from "./ContractEditModulesPage";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
+1
-4
@@ -2,10 +2,6 @@
|
||||
|
||||
import { Flex, useDisclosure } from "@chakra-ui/react";
|
||||
import { TransactionButton } from "components/buttons/TransactionButton";
|
||||
import {
|
||||
type AirdropAddressInput,
|
||||
AirdropUpload,
|
||||
} from "contract-ui/tabs/nfts/components/airdrop-upload";
|
||||
import { useTrack } from "hooks/analytics/useTrack";
|
||||
import { useTxNotifications } from "hooks/useTxNotifications";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
@@ -15,6 +11,7 @@ import { multicall } from "thirdweb/extensions/common";
|
||||
import { balanceOf, encodeSafeTransferFrom } from "thirdweb/extensions/erc1155";
|
||||
import { useActiveAccount, useSendAndConfirmTransaction } from "thirdweb/react";
|
||||
import { Button, Text } from "tw-components";
|
||||
import { type AirdropAddressInput, AirdropUpload } from "./airdrop-upload";
|
||||
|
||||
interface AirdropTabProps {
|
||||
contract: ThirdwebContract;
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { TokenIdPage } from "../../../../../../../contract-ui/tabs/nfts/components/token-id";
|
||||
import { getContractPageParamsInfo } from "../../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../../_utils/getContractPageMetadata";
|
||||
import { TokenIdPage } from "./token-id";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
+3
-3
@@ -14,7 +14,7 @@ import {
|
||||
Tooltip,
|
||||
useBreakpointValue,
|
||||
} from "@chakra-ui/react";
|
||||
import { useNFTDrawerTabs } from "core-ui/nft-drawer/useNftDrawerTabs";
|
||||
import { useChainSlug } from "hooks/chains/chainSlug";
|
||||
import { ChevronLeftIcon } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
@@ -24,8 +24,8 @@ import { useReadContract } from "thirdweb/react";
|
||||
import { Badge, Button, Card, CodeBlock, Heading, Text } from "tw-components";
|
||||
import { AddressCopyButton } from "tw-components/AddressCopyButton";
|
||||
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
|
||||
import { useChainSlug } from "../../../../hooks/chains/chainSlug";
|
||||
import { NftProperty } from "./nft-property";
|
||||
import { NftProperty } from "../components/nft-property";
|
||||
import { useNFTDrawerTabs } from "./useNftDrawerTabs";
|
||||
|
||||
function isValidUrl(possibleUrl?: string | null) {
|
||||
if (!possibleUrl) {
|
||||
+8
-18
@@ -1,11 +1,11 @@
|
||||
import { useIsMinter } from "@3rdweb-sdk/react/hooks/useContractRoles";
|
||||
import { useContractFunctionSelectors } from "contract-ui/hooks/useContractFunctionSelectors";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useMemo } from "react";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import * as ERC721Ext from "thirdweb/extensions/erc721";
|
||||
import * as ERC1155Ext from "thirdweb/extensions/erc1155";
|
||||
import { useActiveAccount, useReadContract } from "thirdweb/react";
|
||||
import { useContractFunctionSelectors } from "../../contract-ui/hooks/useContractFunctionSelectors";
|
||||
import type { NFTDrawerTab } from "./types";
|
||||
|
||||
type UseNFTDrawerTabsParams = {
|
||||
@@ -13,28 +13,18 @@ type UseNFTDrawerTabsParams = {
|
||||
tokenId: string;
|
||||
};
|
||||
|
||||
const TransferTab = dynamic(
|
||||
() => import("contract-ui/tabs/nfts/components/transfer-tab"),
|
||||
);
|
||||
const AirdropTab = dynamic(
|
||||
() => import("contract-ui/tabs/nfts/components/airdrop-tab"),
|
||||
);
|
||||
const BurnTab = dynamic(
|
||||
() => import("contract-ui/tabs/nfts/components/burn-tab"),
|
||||
);
|
||||
const MintSupplyTab = dynamic(
|
||||
() => import("contract-ui/tabs/nfts/components/mint-supply-tab"),
|
||||
);
|
||||
const TransferTab = dynamic(() => import("./components/transfer-tab"));
|
||||
const AirdropTab = dynamic(() => import("./components/airdrop-tab"));
|
||||
const BurnTab = dynamic(() => import("./components/burn-tab"));
|
||||
const MintSupplyTab = dynamic(() => import("./components/mint-supply-tab"));
|
||||
const ClaimConditionTab = dynamic(() =>
|
||||
import("contract-ui/tabs/claim-conditions/components/claim-conditions").then(
|
||||
import("../../_components/claim-conditions/claim-conditions").then(
|
||||
({ ClaimConditions }) => ClaimConditions,
|
||||
),
|
||||
);
|
||||
const ClaimTabERC1155 = dynamic(
|
||||
() => import("contract-ui/tabs/nfts/components/claim-tab"),
|
||||
);
|
||||
const ClaimTabERC1155 = dynamic(() => import("./components/claim-tab"));
|
||||
const UpdateMetadataTab = dynamic(
|
||||
() => import("contract-ui/tabs/nfts/components/update-metadata-tab"),
|
||||
() => import("./components/update-metadata-tab"),
|
||||
);
|
||||
|
||||
export function useNFTDrawerTabs({
|
||||
+1
-1
@@ -17,6 +17,7 @@ import {
|
||||
Tr,
|
||||
} from "@chakra-ui/react";
|
||||
import { MediaCell } from "components/contract-pages/table/table-columns/cells/media-cell";
|
||||
import { useChainSlug } from "hooks/chains/chainSlug";
|
||||
import {
|
||||
ArrowRightIcon,
|
||||
ChevronFirstIcon,
|
||||
@@ -36,7 +37,6 @@ import * as ERC721Ext from "thirdweb/extensions/erc721";
|
||||
import * as ERC1155Ext from "thirdweb/extensions/erc1155";
|
||||
import { useReadContract } from "thirdweb/react";
|
||||
import { Heading, Text } from "tw-components";
|
||||
import { useChainSlug } from "../../../../hooks/chains/chainSlug";
|
||||
|
||||
interface ContractOverviewNFTGetAllProps {
|
||||
contract: ThirdwebContract;
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { ContractNFTPage } from "../../../../../../contract-ui/tabs/nfts/page";
|
||||
import { resolveFunctionSelectors } from "../../../../../../lib/selectors";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
import { ContractNFTPage } from "./ContractNFTPage";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
+1
-1
@@ -2,7 +2,6 @@ import { WalletAddress } from "@/components/blocks/wallet-address";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { SkeletonContainer } from "@/components/ui/skeleton";
|
||||
import { TrackedLinkTW } from "@/components/ui/tracked-link";
|
||||
import { ListingStatsV3 } from "contract-ui/tabs/listings/components/listing-stats";
|
||||
import { useMemo } from "react";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import {
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
import { useReadContract } from "thirdweb/react";
|
||||
import { min } from "thirdweb/utils";
|
||||
import { NFTMediaWithEmptyState } from "tw-components/nft-media";
|
||||
import { ListingStatsV3 } from "./listing-stats";
|
||||
|
||||
type ListingData =
|
||||
| (Pick<
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { TokenSupply } from "contract-ui/tabs/tokens/components/supply";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import { TokenSupply } from "../../tokens/components/supply";
|
||||
|
||||
interface TokenDetailsProps {
|
||||
contract: ThirdwebContract;
|
||||
|
||||
+4
-4
@@ -3,6 +3,10 @@
|
||||
import { ButtonGroup, Flex } from "@chakra-ui/react";
|
||||
import { TransactionButton } from "components/buttons/TransactionButton";
|
||||
import { ROLE_DESCRIPTION_MAP } from "constants/mappings";
|
||||
import {
|
||||
createSetAllRoleMembersTx,
|
||||
getAllRoleMembers,
|
||||
} from "contract-ui/hooks/permissions";
|
||||
import { useTrack } from "hooks/analytics/useTrack";
|
||||
import { useTxNotifications } from "hooks/useTxNotifications";
|
||||
import { useMemo } from "react";
|
||||
@@ -14,10 +18,6 @@ import {
|
||||
useSendAndConfirmTransaction,
|
||||
} from "thirdweb/react";
|
||||
import { Button } from "tw-components";
|
||||
import {
|
||||
createSetAllRoleMembersTx,
|
||||
getAllRoleMembers,
|
||||
} from "../../../hooks/permissions";
|
||||
import { ContractPermission } from "./contract-permission";
|
||||
|
||||
type PermissionFormContext = {
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { ContractPermissionsPage } from "../../../../../../contract-ui/tabs/permissions/page";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
import { ContractPermissionsPage } from "./ContractPermissionsPage";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { ContractProposalsPage } from "../../../../../../contract-ui/tabs/proposals/page";
|
||||
import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
|
||||
import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
|
||||
import { ContractProposalsPage } from "./ContractProposalsPage";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user