diff --git a/app/api/moment/comments/route.ts b/app/api/moment/comments/route.ts
index 0cec5f55..675faade 100644
--- a/app/api/moment/comments/route.ts
+++ b/app/api/moment/comments/route.ts
@@ -20,10 +20,10 @@ export async function GET(req: NextRequest) {
const { searchParams } = new URL(req.url);
const queryParams = {
moment: {
- contractAddress: searchParams.get("contractAddress") as Address,
+ collectionAddress: searchParams.get("collectionAddress") as Address,
tokenId: searchParams.get("tokenId") || "1",
+ chainId: Number(searchParams.get("chainId")) || CHAIN_ID,
},
- chainId: Number(searchParams.get("chainId")) || CHAIN_ID,
offset: Number(searchParams.get("offset")) || 0,
};
diff --git a/app/api/moment/route.ts b/app/api/moment/route.ts
index 7f243a84..9cf0f81d 100644
--- a/app/api/moment/route.ts
+++ b/app/api/moment/route.ts
@@ -1,16 +1,16 @@
import { NextRequest, NextResponse } from "next/server";
-import { getAddress } from "viem";
-import getTokenInfo from "@/lib/viem/getTokenInfo";
import { fetchTokenMetadata } from "@/lib/protocolSdk/ipfs/token-metadata";
+import selectAdmins from "@/lib/supabase/in_process_admins/selectAdmins";
+import { getMomentAdvancedInfo } from "@/lib/moment/getMomentAdvancedInfo";
+import { getAddress } from "viem";
import { getMomentSchema } from "@/lib/schema/getMomentSchema";
-import { selectInProcessToken } from "@/lib/supabase/in_process_tokens/selectInProcessToken";
-import { CHAIN_ID } from "@/lib/consts";
+import { Moment } from "@/types/moment";
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url);
const queryParams = {
- tokenContract: searchParams.get("tokenContract"),
+ collectionAddress: searchParams.get("collectionAddress"),
tokenId: searchParams.get("tokenId"),
chainId: searchParams.get("chainId"),
};
@@ -27,51 +27,22 @@ export async function GET(req: NextRequest) {
);
}
- const { tokenContract, tokenId, chainId } = parseResult.data;
- const chainIdNum = chainId ? parseInt(chainId, 10) : CHAIN_ID;
-
- // Get token info from chain
- const tokenInfo = await getTokenInfo(getAddress(tokenContract), tokenId, chainIdNum);
-
- if (!tokenInfo.tokenUri) {
- return NextResponse.json({ error: "Token URI not found" }, { status: 404 });
- }
-
- // Fetch metadata from URI
- const metadata = await fetchTokenMetadata(tokenInfo.tokenUri);
-
- const token = await selectInProcessToken({
- address: getAddress(tokenContract),
- chainId: chainIdNum,
- });
-
- if (!token) {
- return NextResponse.json({ error: "Token not found" }, { status: 404 });
- }
-
- // Validate saleConfig exists and has all required fields
- if (!tokenInfo.saleConfig) {
- return NextResponse.json(
- { error: "Sale configuration not found for this token" },
- { status: 400 }
- );
- }
-
- const { pricePerToken, saleStart, saleEnd, maxTokensPerAddress } = tokenInfo.saleConfig;
-
- const saleConfig: any = {
- ...tokenInfo.saleConfig,
- pricePerToken: pricePerToken.toString(),
- saleStart: Number(saleStart),
- saleEnd: Number(saleEnd),
- maxTokensPerAddress: Number(maxTokensPerAddress),
+ const { collectionAddress, tokenId, chainId } = parseResult.data;
+ const moment: Moment = {
+ collectionAddress: getAddress(collectionAddress),
+ tokenId,
+ chainId: parseInt(chainId, 10),
};
+ const { uri, owner, saleConfig } = await getMomentAdvancedInfo(moment);
+ const metadata = await fetchTokenMetadata(uri || "");
+ const admins = await selectAdmins(moment);
+
return NextResponse.json({
- uri: tokenInfo.tokenUri,
- owner: getAddress(tokenInfo.owner),
+ uri,
+ owner,
saleConfig,
- momentAdmins: token.token_admins.map((admin) => admin.artist_address),
+ momentAdmins: admins.map((admin) => admin.artist_address),
metadata: {
name: metadata.name || "",
image: metadata.image || "",
diff --git a/app/api/moment/update-uri/route.ts b/app/api/moment/update-uri/route.ts
index b95b6a79..0a300641 100644
--- a/app/api/moment/update-uri/route.ts
+++ b/app/api/moment/update-uri/route.ts
@@ -4,6 +4,7 @@ import { updateMomentURI } from "@/lib/moment/updateMomentURI";
import { authMiddleware } from "@/middleware/authMiddleware";
import { updateMomentURISchema } from "@/lib/schema/updateMomentURISchema";
import { Address } from "viem";
+import { Moment } from "@/types/moment";
// CORS headers for allowing cross-origin requests
const corsHeaders = getCorsHeader();
@@ -37,8 +38,7 @@ export async function POST(req: NextRequest) {
}
const data = parseResult.data;
const result = await updateMomentURI({
- tokenContractAddress: data.moment.contractAddress as Address,
- tokenId: data.moment.tokenId,
+ moment: data.moment as Moment,
newUri: data.newUri,
artistAddress: artistAddress as Address,
});
diff --git a/app/api/og/artist/route.tsx b/app/api/og/artist/route.tsx
index e98240c1..3871a3c6 100644
--- a/app/api/og/artist/route.tsx
+++ b/app/api/og/artist/route.tsx
@@ -38,7 +38,7 @@ export async function GET(req: NextRequest) {
let imageMetadata = null;
if (metadata) {
- if (metadata.content.mime === "text/plain") {
+ if (metadata.content?.mime === "text/plain") {
const response = await fetch(getFetchableUrl(metadata.content.uri) || "");
const data = await response.text();
writingText = data;
@@ -85,7 +85,7 @@ export async function GET(req: NextRequest) {
>
{metadata ? (
<>
- {metadata.content.mime === "text/plain" ? (
+ {metadata.content?.mime === "text/plain" ? (
) : (
diff --git a/app/api/og/token/route.tsx b/app/api/og/token/route.tsx
index 3f80e531..c324ec55 100644
--- a/app/api/og/token/route.tsx
+++ b/app/api/og/token/route.tsx
@@ -33,7 +33,7 @@ export async function GET(req: NextRequest) {
if (!metadata) throw Error("failed to get token metadata");
const previewBackgroundUrl = getFetchableUrl(metadata.image);
- const isWriting = metadata.content.mime === "text/plain";
+ const isWriting = metadata.content?.mime === "text/plain";
let orientation = 1;
let originalWidth = 1;
@@ -43,7 +43,7 @@ export async function GET(req: NextRequest) {
let writingText = "";
if (isWriting) {
- const response = await fetch(getFetchableUrl(metadata.content.uri) || "");
+ const response = await fetch(getFetchableUrl(metadata.content?.uri) || "");
const data = await response.text();
writingText = data;
const paragraphs = writingText.split("\n");
diff --git a/components/ArtSlider/CarouselItem.tsx b/components/ArtSlider/CarouselItem.tsx
index 8f324e82..2d4d2296 100644
--- a/components/ArtSlider/CarouselItem.tsx
+++ b/components/ArtSlider/CarouselItem.tsx
@@ -1,12 +1,12 @@
import { getFetchableUrl } from "@/lib/protocolSdk/ipfs/gateway";
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import PdfViewer from "../Renderers/PdfViewer";
import VideoPlayer from "../Renderers/VideoPlayer";
import AudioPlayer from "../Renderers/AudioPlayer";
import Writing from "../Renderers/Writing";
interface CarouselItemProps {
- metadata: Metadata;
+ metadata: MomentMetadata;
}
const CarouselItem = ({ metadata }: CarouselItemProps) => {
@@ -38,7 +38,7 @@ const CarouselItem = ({ metadata }: CarouselItemProps) => {
return (
diff --git a/components/CollectionManagePage/CollectionOverview.tsx b/components/CollectionManagePage/CollectionOverview.tsx
index 8b87c6ab..b52d1b9a 100644
--- a/components/CollectionManagePage/CollectionOverview.tsx
+++ b/components/CollectionManagePage/CollectionOverview.tsx
@@ -2,7 +2,7 @@ import ContentRenderer from "../Renderers";
import { useCollectionProvider } from "@/providers/CollectionProvider";
import { useRouter } from "next/navigation";
import { Skeleton } from "../ui/skeleton";
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import { networkConfigByChain } from "@/lib/protocolSdk/apis/chain-constants";
import CopyButton from "../CopyButton";
@@ -39,7 +39,7 @@ const CollectionOverview = () => {
{isLoading ? (
) : (
-
+
)}
diff --git a/components/CollectionManagePage/TokenOverview.tsx b/components/CollectionManagePage/TokenOverview.tsx
index 19b5287b..2a4b7776 100644
--- a/components/CollectionManagePage/TokenOverview.tsx
+++ b/components/CollectionManagePage/TokenOverview.tsx
@@ -3,11 +3,11 @@ import { useRouter } from "next/navigation";
import { Skeleton } from "../ui/skeleton";
import { networkConfigByChain } from "@/lib/protocolSdk/apis/chain-constants";
import CopyButton from "../CopyButton";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useCollectionProvider } from "@/providers/CollectionProvider";
const TokenOverview = () => {
- const { metadata, isLoading } = useTokenProvider();
+ const { metadata, isLoading } = useMomentProvider();
const { push } = useRouter();
const { collection } = useCollectionProvider();
diff --git a/components/CreatedMoment/CreatedMomentAirdrop.tsx b/components/CreatedMoment/CreatedMomentAirdrop.tsx
index 8c073263..125febbd 100644
--- a/components/CreatedMoment/CreatedMomentAirdrop.tsx
+++ b/components/CreatedMoment/CreatedMomentAirdrop.tsx
@@ -3,9 +3,9 @@
import { useMomentCreateProvider } from "@/providers/MomentCreateProvider/MomentCreateProvider";
import { Fragment } from "react";
import MomentAirdrop from "../MomentAirdrop";
-import { Address } from "viem";
-import { TokenProvider } from "@/providers/TokenProvider";
+import { MomentProvider } from "@/providers/MomentProvider";
import { CHAIN_ID } from "@/lib/consts";
+import { Address } from "viem";
const CreatedMomentAirdrop = () => {
const { createdContract, createdTokenId } = useMomentCreateProvider();
@@ -13,12 +13,15 @@ const CreatedMomentAirdrop = () => {
if (!createdContract || !createdTokenId) return ;
return (
-
-
+
);
};
diff --git a/components/HorizontalFeed/FeedHover.tsx b/components/HorizontalFeed/FeedHover.tsx
index e40a3576..fda8a735 100644
--- a/components/HorizontalFeed/FeedHover.tsx
+++ b/components/HorizontalFeed/FeedHover.tsx
@@ -1,11 +1,11 @@
import { FC } from "react";
import { Skeleton } from "../ui/skeleton";
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import ContentRenderer from "../Renderers/ContentRenderer";
interface FeedHoverProps {
isLoading: boolean;
- data: Metadata;
+ data: MomentMetadata;
}
const FeedHover: FC = ({ isLoading, data }) => {
diff --git a/components/Renderers/ContentRenderer.tsx b/components/Renderers/ContentRenderer.tsx
index 6368d082..dd4fcf80 100644
--- a/components/Renderers/ContentRenderer.tsx
+++ b/components/Renderers/ContentRenderer.tsx
@@ -1,6 +1,6 @@
import { getFetchableUrl } from "@/lib/protocolSdk/ipfs/gateway";
import { usePathname } from "next/navigation";
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import PdfViewer from "./PdfViewer";
import VideoPlayer from "./VideoPlayer";
import AudioPlayer from "./AudioPlayer";
@@ -8,7 +8,7 @@ import useIsMobile from "@/hooks/useIsMobile";
import Writing from "./Writing";
interface ContentRendererProps {
- metadata: Metadata;
+ metadata: MomentMetadata;
}
const ContentRenderer = ({ metadata }: ContentRendererProps) => {
diff --git a/components/TokenManagePage/AirdropButton.tsx b/components/TokenManagePage/AirdropButton.tsx
index 6f1b867a..0d076a30 100644
--- a/components/TokenManagePage/AirdropButton.tsx
+++ b/components/TokenManagePage/AirdropButton.tsx
@@ -1,11 +1,11 @@
import { AirdropItem } from "@/hooks/useAirdrop";
import { useAirdropProvider } from "@/providers/AirdropProvider";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useUserProvider } from "@/providers/UserProvider";
const AirdropButton = () => {
const { airdopToItems, onAirdrop, loading } = useAirdropProvider();
- const { owner, tokenAdmins } = useTokenProvider();
+ const { owner, tokenAdmins } = useMomentProvider();
const { connectedAddress, artistWallet } = useUserProvider();
const canAirdrop =
Boolean(owner?.toLowerCase() === connectedAddress?.toLowerCase()) ||
diff --git a/components/TokenManagePage/AnimationUpload.tsx b/components/TokenManagePage/AnimationUpload.tsx
index 7be1a37d..929d26a2 100644
--- a/components/TokenManagePage/AnimationUpload.tsx
+++ b/components/TokenManagePage/AnimationUpload.tsx
@@ -2,13 +2,13 @@ import NoFileSelected from "@/components/MetadataCreation/NoFileSelected";
import MediaUploaded from "@/components/MetadataCreation/MediaUploaded";
import ResetButton from "@/components/MetadataCreation/ResetButton";
import useUpdateMomentURI from "@/hooks/useUpdateMomentURI";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useRef } from "react";
import { useMomentMetadataProvider } from "@/providers/MomentMetadataProvider";
import { useMomentFormProvider } from "@/providers/MomentFormProvider";
const AnimationUpload = () => {
- const { isOwner } = useTokenProvider();
+ const { isOwner } = useMomentProvider();
const { imageUri, animationUri, setImageUri, setAnimationUri } = useMomentFormProvider();
const { fileUpload, fileUploading } = useMomentMetadataProvider();
const { isLoading: isSaving } = useUpdateMomentURI();
diff --git a/components/TokenManagePage/Media.tsx b/components/TokenManagePage/Media.tsx
index 267ad931..321e739e 100644
--- a/components/TokenManagePage/Media.tsx
+++ b/components/TokenManagePage/Media.tsx
@@ -1,7 +1,7 @@
"use client";
import { Fragment } from "react";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import MediaSkeleton from "./MediaSkeleton";
@@ -13,7 +13,7 @@ import AnimationUpload from "./AnimationUpload";
import { useMomentFormProvider } from "@/providers/MomentFormProvider";
const Media = () => {
- const { metadata, isOwner, isLoading } = useTokenProvider();
+ const { metadata, isOwner, isLoading } = useMomentProvider();
const { form } = useMomentFormProvider();
const { isLoading: isSaving } = useUpdateMomentURI();
diff --git a/components/TokenManagePage/OwnerWarning.tsx b/components/TokenManagePage/OwnerWarning.tsx
index f4a779b9..b6282afe 100644
--- a/components/TokenManagePage/OwnerWarning.tsx
+++ b/components/TokenManagePage/OwnerWarning.tsx
@@ -1,8 +1,8 @@
"use client";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
const OwnerWarning = () => {
- const { isOwner } = useTokenProvider();
+ const { isOwner } = useMomentProvider();
if (isOwner) return null;
diff --git a/components/TokenManagePage/Sale.tsx b/components/TokenManagePage/Sale.tsx
index 17626c01..7a76e87c 100644
--- a/components/TokenManagePage/Sale.tsx
+++ b/components/TokenManagePage/Sale.tsx
@@ -1,11 +1,11 @@
import useSaleConfig from "@/hooks/useSaleConfig";
import { Fragment } from "react";
import { DateTimePicker } from "../ui/date-time-picker";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
const Sale = () => {
const { saleStart, setSaleStart, setSale, isLoading } = useSaleConfig();
- const { saleConfig } = useTokenProvider();
+ const { saleConfig } = useMomentProvider();
if (!saleConfig) return ;
return (
diff --git a/components/TokenManagePage/SaveMediaButton.tsx b/components/TokenManagePage/SaveMediaButton.tsx
index 2f7bf0dc..cf0c6623 100644
--- a/components/TokenManagePage/SaveMediaButton.tsx
+++ b/components/TokenManagePage/SaveMediaButton.tsx
@@ -1,12 +1,12 @@
"use client";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import useUpdateMomentURI from "@/hooks/useUpdateMomentURI";
import { toast } from "sonner";
import { useFormState } from "react-hook-form";
import { useMomentFormProvider } from "@/providers/MomentFormProvider";
const SaveMediaButton = () => {
- const { isOwner } = useTokenProvider();
+ const { isOwner } = useMomentProvider();
const { updateTokenURI, isLoading: isSaving } = useUpdateMomentURI();
const { form } = useMomentFormProvider();
const { errors } = useFormState({ control: form.control });
diff --git a/components/TokenManagePage/TokenManagePage.tsx b/components/TokenManagePage/TokenManagePage.tsx
index 43920f88..f2170dc5 100644
--- a/components/TokenManagePage/TokenManagePage.tsx
+++ b/components/TokenManagePage/TokenManagePage.tsx
@@ -5,7 +5,7 @@ import ManageTabs, { MANAGE_TABS } from "./ManageTabs";
import Sale from "./Sale";
import Media from "./Media";
import { useParams } from "next/navigation";
-import { TokenProvider } from "@/providers/TokenProvider";
+import { MomentProvider } from "@/providers/MomentProvider";
import { useCollectionProvider } from "@/providers/CollectionProvider";
import TokenOverview from "../CollectionManagePage/TokenOverview";
import MomentAirdrop from "../MomentAirdrop";
@@ -17,12 +17,12 @@ const TokenManagePage = () => {
const tokenId = params.tokenId as string;
return (
-
{
{selectedTab === MANAGE_TABS.SALE && }
{selectedTab === MANAGE_TABS.MEDIA && }
-
+
);
};
diff --git a/components/TokenPage/BackToTimeline.tsx b/components/TokenPage/BackToTimeline.tsx
index 37bfe0bb..9f58a175 100644
--- a/components/TokenPage/BackToTimeline.tsx
+++ b/components/TokenPage/BackToTimeline.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useArtistProfile } from "@/hooks/useArtistProfile";
import truncateAddress from "@/lib/truncateAddress";
import Link from "next/link";
@@ -8,7 +8,7 @@ import { ChevronLeft } from "lucide-react";
import { Skeleton } from "@/components/ui/skeleton";
const BackToTimeline = () => {
- const { owner } = useTokenProvider();
+ const { owner } = useMomentProvider();
const { data: artistProfile, isLoading } = useArtistProfile(owner || undefined);
if (!owner) return null;
diff --git a/components/TokenPage/CollectModal.tsx b/components/TokenPage/CollectModal.tsx
index 0bf043c5..a8d5f325 100644
--- a/components/TokenPage/CollectModal.tsx
+++ b/components/TokenPage/CollectModal.tsx
@@ -1,6 +1,6 @@
import { Dialog, DialogContent, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Label } from "../ui/label";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useMomentCommentsProvider } from "@/providers/MomentCommentsProvider";
import CommentButton from "../CommentButton/CommentButton";
import { Fragment, MouseEvent } from "react";
@@ -16,7 +16,7 @@ import Advanced from "./Advanced";
const CollectModal = () => {
const { comment, isOpenCommentModal, setIsOpenCommentModal, setComment } =
useMomentCommentsProvider();
- const { saleConfig, isLoading, isSetSale, metadata } = useTokenProvider();
+ const { saleConfig, isLoading, isSetSale, metadata } = useMomentProvider();
const { amountToCollect } = useMomentCollectProvider();
const { isPrepared } = useUserProvider();
diff --git a/components/TokenPage/CommentSection.tsx b/components/TokenPage/CommentSection.tsx
index 5e5fe90d..051fccec 100644
--- a/components/TokenPage/CommentSection.tsx
+++ b/components/TokenPage/CommentSection.tsx
@@ -1,4 +1,4 @@
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import CommentsContainer from "./CommentsContainer";
import { Skeleton } from "../ui/skeleton";
import { Comment } from "./Comment";
@@ -7,7 +7,7 @@ import { useMomentCommentsProvider } from "@/providers/MomentCommentsProvider";
const CommentSection = () => {
const { comments, hasMore, isLoading, fetchMore } = useMomentCommentsProvider();
- const { isSetSale } = useTokenProvider();
+ const { isSetSale } = useMomentProvider();
if (isLoading)
return (
diff --git a/components/TokenPage/MetaAndComments.tsx b/components/TokenPage/MetaAndComments.tsx
index 2e5b082f..4826f034 100644
--- a/components/TokenPage/MetaAndComments.tsx
+++ b/components/TokenPage/MetaAndComments.tsx
@@ -1,4 +1,4 @@
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { Fragment } from "react";
import { Skeleton } from "../ui/skeleton";
import CommentSection from "./CommentSection";
@@ -16,7 +16,7 @@ interface MetaAndCommentsProps {
}
const MetaAndComments = ({ priceHidden = false, commentsHidden = false }: MetaAndCommentsProps) => {
- const { saleConfig, metadata, isLoading, isSetSale } = useTokenProvider();
+ const { saleConfig, metadata, isLoading, isSetSale } = useMomentProvider();
const { balanceOf } = useBalanceOf();
const { download } = useDownload();
diff --git a/components/TokenPage/Token.tsx b/components/TokenPage/Token.tsx
index 29310b8a..3b093aa0 100644
--- a/components/TokenPage/Token.tsx
+++ b/components/TokenPage/Token.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import CollectModal from "./CollectModal";
import MetaAndComments from "./MetaAndComments";
import MomentCollected from "./MomentCollected";
@@ -12,7 +12,7 @@ import MomentAirdrop from "../MomentAirdrop/MomentAirdrop";
import { useMomentCollectProvider } from "@/providers/MomentCollectProvider";
const Token = () => {
- const { metadata, isOwner } = useTokenProvider();
+ const { metadata, isOwner } = useMomentProvider();
const { collected } = useMomentCollectProvider();
const isMobile = useIsMobile();
diff --git a/components/TokenPage/TokenPage.tsx b/components/TokenPage/TokenPage.tsx
index bd54e019..12ce04ed 100644
--- a/components/TokenPage/TokenPage.tsx
+++ b/components/TokenPage/TokenPage.tsx
@@ -2,7 +2,7 @@
import Token from "./Token";
import { ZORA_TO_VIEM, ZoraChains } from "@/lib/zora/zoraToViem";
-import { TokenProvider } from "@/providers/TokenProvider";
+import { MomentProvider } from "@/providers/MomentProvider";
import { MomentCommentsProvider } from "@/providers/MomentCommentsProvider";
import { MomentCollectProvider } from "@/providers/MomentCollectProvider";
import { useParams } from "next/navigation";
@@ -18,8 +18,8 @@ const TokenPage = () => {
const viemChainName = ZORA_TO_VIEM[chain as ZoraChains];
const viemChain = chains[viemChainName];
- const token = {
- tokenContractAddress: address as Address,
+ const moment = {
+ collectionAddress: address as Address,
tokenId,
chainId: viemChain.id,
};
@@ -27,13 +27,13 @@ const TokenPage = () => {
return (
-
+
-
+
);
diff --git a/hooks/useAirdrop.ts b/hooks/useAirdrop.ts
index 77f9934b..c7b46a7b 100644
--- a/hooks/useAirdrop.ts
+++ b/hooks/useAirdrop.ts
@@ -8,7 +8,7 @@ import { toast } from "sonner";
import { useSmartWalletProvider } from "@/providers/SmartWalletProvider";
import { usePrivy } from "@privy-io/react-auth";
import { executeAirdrop } from "@/lib/moment/executeAirdrop";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
export interface AirdropItem {
address: string;
@@ -16,8 +16,8 @@ export interface AirdropItem {
ensName: string;
}
const useAirdrop = () => {
- const { token } = useTokenProvider();
- const { tokenContractAddress: momentContract, tokenId } = token;
+ const { moment } = useMomentProvider();
+ const { collectionAddress: momentContract, tokenId } = moment;
const [airdopToItems, setAirdropToItems] = useState([]);
const { artistWallet, isPrepared } = useUserProvider();
const { smartWallet } = useSmartWalletProvider();
diff --git a/hooks/useBalanceOf.ts b/hooks/useBalanceOf.ts
index fde36c45..be403c9f 100644
--- a/hooks/useBalanceOf.ts
+++ b/hooks/useBalanceOf.ts
@@ -1,5 +1,5 @@
import { getPublicClient } from "@/lib/viem/publicClient";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useUserProvider } from "@/providers/UserProvider";
import { zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
import { useEffect, useState } from "react";
@@ -7,23 +7,23 @@ import { Address } from "viem";
const useBalanceOf = () => {
const [balanceOf, setBalanceOf] = useState(0);
- const { token } = useTokenProvider();
+ const { moment } = useMomentProvider();
const { connectedAddress } = useUserProvider();
useEffect(() => {
const getBalanceOf = async () => {
const publicClient = getPublicClient();
const response = await publicClient.readContract({
- address: token.tokenContractAddress as Address,
+ address: moment.collectionAddress as Address,
abi: zoraCreator1155ImplABI,
functionName: "balanceOf",
- args: [connectedAddress as Address, BigInt(token.tokenId)],
+ args: [connectedAddress as Address, BigInt(moment.tokenId)],
});
setBalanceOf(parseInt(response.toString(), 10));
};
- if (token && connectedAddress) getBalanceOf();
- }, [token, connectedAddress]);
+ if (moment && connectedAddress) getBalanceOf();
+ }, [moment, connectedAddress]);
return {
balanceOf,
diff --git a/hooks/useCollectBalanceValidation.ts b/hooks/useCollectBalanceValidation.ts
index 69277c55..1b850420 100644
--- a/hooks/useCollectBalanceValidation.ts
+++ b/hooks/useCollectBalanceValidation.ts
@@ -1,5 +1,5 @@
import { formatEther, formatUnits } from "viem";
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
import { SaleConfig } from "@/types/moment";
import { useSmartWalletProvider } from "@/providers/SmartWalletProvider";
import { showInsufficientBalanceError } from "@/lib/balance/showInsufficientBalanceError";
@@ -11,7 +11,7 @@ const useCollectBalanceValidation = () => {
const ethPrice = formatEther(saleConfig.pricePerToken * BigInt(mintCount));
const usdcPrice = formatUnits(saleConfig.pricePerToken * BigInt(mintCount), 6);
- if (saleConfig.type === MintType.Erc20Mint) {
+ if (saleConfig.type === MomentType.Erc20Mint) {
if (Number(balance) < Number(usdcPrice)) {
showInsufficientBalanceError("usdc");
}
diff --git a/hooks/useCollection.ts b/hooks/useCollection.ts
index 20c84e51..d6117c67 100644
--- a/hooks/useCollection.ts
+++ b/hooks/useCollection.ts
@@ -1,10 +1,10 @@
import { getPublicClient } from "@/lib/viem/publicClient";
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import { useQuery } from "@tanstack/react-query";
import { zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
import { Address } from "viem";
-async function fetchCollectionURI(address: Address, chainId: number): Promise {
+async function fetchCollectionURI(address: Address, chainId: number): Promise {
const publicClient = getPublicClient(chainId);
const uri = await publicClient.readContract({
address,
diff --git a/hooks/useComments.ts b/hooks/useComments.ts
index 2dd194d5..41c57894 100644
--- a/hooks/useComments.ts
+++ b/hooks/useComments.ts
@@ -3,24 +3,20 @@ import { useCallback, useMemo } from "react";
import { useInfiniteQuery, useQueryClient, InfiniteData } from "@tanstack/react-query";
import { MintComment } from "@/types/moment";
import fetchComments from "@/lib/moment/fetchComments";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
const COMMENTS_PER_PAGE = 20;
export function useComments() {
- const { token } = useTokenProvider();
+ const { moment } = useMomentProvider();
const queryClient = useQueryClient();
- const { tokenContractAddress: contractAddress, tokenId, chainId } = token;
+ const { collectionAddress: contractAddress, tokenId, chainId } = moment;
const query = useInfiniteQuery({
queryKey: ["comments", contractAddress, tokenId, chainId],
queryFn: ({ pageParam = 0 }) =>
fetchComments({
- moment: {
- contractAddress: contractAddress!,
- tokenId: tokenId!,
- },
- chainId: chainId!,
+ moment,
offset: pageParam as number,
}),
enabled: Boolean(contractAddress && tokenId && chainId),
diff --git a/hooks/useDownload.ts b/hooks/useDownload.ts
index 10e2d0b3..c7213292 100644
--- a/hooks/useDownload.ts
+++ b/hooks/useDownload.ts
@@ -1,9 +1,9 @@
import { getFetchableUrl } from "@/lib/protocolSdk/ipfs/gateway";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useState } from "react";
const useDownload = () => {
- const { metadata } = useTokenProvider();
+ const { metadata } = useMomentProvider();
const [isDownloading, setIsDownloading] = useState(false);
const download = async () => {
diff --git a/hooks/useMediaInitialization.ts b/hooks/useMediaInitialization.ts
index 85e7f5df..9466e940 100644
--- a/hooks/useMediaInitialization.ts
+++ b/hooks/useMediaInitialization.ts
@@ -1,8 +1,8 @@
import { useEffect, useRef } from "react";
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import { useMomentFormProvider } from "@/providers/MomentFormProvider";
-const useMediaInitialization = (meta: Metadata | undefined) => {
+const useMediaInitialization = (meta: MomentMetadata | undefined) => {
const {
name,
description,
diff --git a/hooks/useMetadata.ts b/hooks/useMetadata.ts
index db446e2b..d6433096 100644
--- a/hooks/useMetadata.ts
+++ b/hooks/useMetadata.ts
@@ -1,8 +1,8 @@
import { getFetchableUrl } from "@/lib/protocolSdk/ipfs/gateway";
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import { useQuery } from "@tanstack/react-query";
-async function fetchMetadata(uri: string): Promise {
+async function fetchMetadata(uri: string): Promise {
const response = await fetch(`${getFetchableUrl(uri)}`);
if (!response.ok) {
return {
diff --git a/hooks/useTokenInfo.ts b/hooks/useMoment.ts
similarity index 79%
rename from hooks/useTokenInfo.ts
rename to hooks/useMoment.ts
index 5025e0cf..abe8e6c1 100644
--- a/hooks/useTokenInfo.ts
+++ b/hooks/useMoment.ts
@@ -1,16 +1,18 @@
-import { Address, getAddress } from "viem";
+import { getAddress } from "viem";
import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import { useUserProvider } from "@/providers/UserProvider";
import { getMomentApi } from "@/lib/moment/getMomentApi";
+import { Moment } from "@/types/moment";
-const useTokenInfo = (tokenContract: Address, tokenId: string, chainId: number) => {
+const useMoment = (moment: Moment) => {
+ const { collectionAddress, tokenId, chainId } = moment;
const { artistWallet } = useUserProvider();
const query = useQuery({
- queryKey: ["tokenInfo", tokenContract, tokenId, chainId],
- queryFn: () => getMomentApi(tokenContract, tokenId, chainId),
- enabled: Boolean(tokenContract && tokenId && chainId),
+ queryKey: ["moment", collectionAddress, tokenId, chainId],
+ queryFn: () => getMomentApi(moment),
+ enabled: Boolean(collectionAddress && tokenId && chainId),
staleTime: 1000 * 60 * 5, // 5 minutes
retry: (failureCount) => failureCount < 3,
});
@@ -50,4 +52,4 @@ const useTokenInfo = (tokenContract: Address, tokenId: string, chainId: number)
};
};
-export default useTokenInfo;
+export default useMoment;
diff --git a/hooks/useMomentCollect.ts b/hooks/useMomentCollect.ts
index 6b39b9e1..5fa4a39a 100644
--- a/hooks/useMomentCollect.ts
+++ b/hooks/useMomentCollect.ts
@@ -3,7 +3,7 @@ import { zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
import { zoraCreatorFixedPriceSaleStrategyAddress } from "@/lib/protocolSdk/constants";
import { CHAIN } from "@/lib/consts";
import { Address, encodeAbiParameters, parseAbiParameters } from "viem";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { useUserProvider } from "@/providers/UserProvider";
import { toast } from "sonner";
import useCollectBalanceValidation from "./useCollectBalanceValidation";
@@ -33,7 +33,7 @@ const useMomentCollect = () => {
const [collected, setCollected] = useState(false);
const { artistWallet } = useUserProvider();
const [isLoading, setIsLoading] = useState(false);
- const { token, saleConfig } = useTokenProvider();
+ const { saleConfig, moment } = useMomentProvider();
const { comment, addComment, setComment, setIsOpenCommentModal } = useMomentCommentsProvider();
const { validateBalance } = useCollectBalanceValidation();
const { getAccessToken } = usePrivy();
@@ -50,12 +50,12 @@ const useMomentCollect = () => {
if (saleConfig.pricePerToken === BigInt(0)) {
await mintOnSmartWallet({
- address: token.tokenContractAddress,
+ address: moment.collectionAddress,
abi: zoraCreator1155ImplABI,
functionName: "mint",
args: [
zoraCreatorFixedPriceSaleStrategyAddress[CHAIN.id],
- token.tokenId,
+ moment.tokenId,
amountToCollect,
[],
minterArguments,
@@ -67,15 +67,7 @@ const useMomentCollect = () => {
if (!accessToken) {
throw new Error("Failed to get access token");
}
- await collectMomentApi(
- {
- contractAddress: token.tokenContractAddress,
- tokenId: token.tokenId,
- },
- amountToCollect,
- comment,
- accessToken
- );
+ await collectMomentApi(moment, amountToCollect, comment, accessToken);
}
addComment({
sender: artistWallet as Address,
diff --git a/hooks/useSaleConfig.ts b/hooks/useSaleConfig.ts
index 737103f2..fe34c5d7 100644
--- a/hooks/useSaleConfig.ts
+++ b/hooks/useSaleConfig.ts
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { Address, encodeFunctionData } from "viem";
import useSignTransaction from "./useSignTransaction";
import { getPublicClient } from "@/lib/viem/publicClient";
@@ -12,9 +12,9 @@ import { zoraCreatorFixedPriceSaleStrategyAddress } from "@/lib/protocolSdk/cons
import { useUserProvider } from "@/providers/UserProvider";
const useSaleConfig = () => {
- const { saleConfig: sale } = useTokenProvider();
+ const { saleConfig: sale } = useMomentProvider();
const [saleStart, setSaleStart] = useState(new Date());
- const { token, fetchTokenInfo } = useTokenProvider();
+ const { moment, fetchTokenInfo } = useMomentProvider();
const { signTransaction } = useSignTransaction();
const { connectedAddress } = useUserProvider();
const [isLoading, setIsLoading] = useState(false);
@@ -29,14 +29,14 @@ const useSaleConfig = () => {
const calldata = encodeFunctionData({
abi: zoraCreatorFixedPriceSaleStrategyABI,
functionName: "setSale",
- args: [BigInt(token.tokenId), newSale],
+ args: [BigInt(moment.tokenId), newSale],
});
const publicClient = getPublicClient(CHAIN_ID);
const hash = await signTransaction({
- address: token.tokenContractAddress,
+ address: moment.collectionAddress,
abi: zoraCreator1155ImplABI,
functionName: "callSale",
- args: [token.tokenId, zoraCreatorFixedPriceSaleStrategyAddress[CHAIN_ID], calldata],
+ args: [moment.tokenId, zoraCreatorFixedPriceSaleStrategyAddress[CHAIN_ID], calldata],
account: connectedAddress as Address,
chain: CHAIN,
});
diff --git a/hooks/useShareMoment.ts b/hooks/useShareMoment.ts
index 424fc1ee..ab8f47b9 100644
--- a/hooks/useShareMoment.ts
+++ b/hooks/useShareMoment.ts
@@ -1,15 +1,15 @@
import { CHAIN, SITE_ORIGINAL_URL } from "@/lib/consts";
import { getShortNetworkName } from "@/lib/zora/zoraToViem";
-import { useTokenProvider } from "@/providers/TokenProvider";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { toast } from "sonner";
const useShareMoment = () => {
- const { token } = useTokenProvider();
+ const { moment } = useMomentProvider();
const share = async () => {
const shortNetworkName = getShortNetworkName(CHAIN.name.toLowerCase());
await navigator.clipboard.writeText(
- `${SITE_ORIGINAL_URL}/collect/${shortNetworkName}:${token.tokenContractAddress}/${token.tokenId}`
+ `${SITE_ORIGINAL_URL}/collect/${shortNetworkName}:${moment.collectionAddress}/${moment.tokenId}`
);
toast.success("copied!");
};
diff --git a/hooks/useToken.ts b/hooks/useToken.ts
deleted file mode 100644
index cbdb3ea4..00000000
--- a/hooks/useToken.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { getPublicClient } from "@/lib/viem/publicClient";
-import { zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
-import { Address } from "abitype";
-import { useEffect, useState } from "react";
-
-const useToken = (collectionAddress: Address, tokenId: string, chainId: number) => {
- const [tokenUri, setTokenUri] = useState("");
- useEffect(() => {
- const init = async () => {
- const publicClient = getPublicClient(chainId);
- const uri = await publicClient.readContract({
- address: collectionAddress,
- abi: zoraCreator1155ImplABI,
- functionName: "uri",
- args: [BigInt(tokenId)],
- });
-
- setTokenUri(uri as string);
- };
- if (collectionAddress && chainId && tokenId) init();
- }, [collectionAddress, chainId, tokenId]);
-
- return {
- tokenUri,
- };
-};
-
-export default useToken;
diff --git a/hooks/useUpdateMomentURI.ts b/hooks/useUpdateMomentURI.ts
index 538047a1..1b38d28e 100644
--- a/hooks/useUpdateMomentURI.ts
+++ b/hooks/useUpdateMomentURI.ts
@@ -1,17 +1,16 @@
import { useState } from "react";
-import { useTokenProvider } from "@/providers/TokenProvider";
-import { CHAIN_ID } from "@/lib/consts";
+import { useMomentProvider } from "@/providers/MomentProvider";
import { usePrivy } from "@privy-io/react-auth";
import { uploadJson } from "@/lib/arweave/uploadJson";
import { fetchTokenMetadata } from "@/lib/protocolSdk/ipfs/token-metadata";
-import getTokenInfo from "@/lib/viem/getTokenInfo";
+import getMomentOnChainInfo from "@/lib/viem/getTokenInfo";
import { toast } from "sonner";
import { callUpdateMomentURI } from "@/lib/moment/callUpdateMomentURI";
import { useMomentFormProvider } from "@/providers/MomentFormProvider";
import { migrateMuxToArweaveApi } from "@/lib/mux/migrateMuxToArweaveApi";
const useUpdateMomentURI = () => {
- const { token, fetchTokenInfo } = useTokenProvider();
+ const { moment, fetchTokenInfo } = useMomentProvider();
const {
name: providerName,
description: providerDescription,
@@ -27,7 +26,7 @@ const useUpdateMomentURI = () => {
const updateTokenURI = async () => {
setIsLoading(true);
try {
- const tokenInfo = await getTokenInfo(token.tokenContractAddress, token.tokenId, CHAIN_ID);
+ const tokenInfo = await getMomentOnChainInfo(moment);
const current = await fetchTokenMetadata(tokenInfo.tokenUri);
const updatedAnimationUrl = animationUri || current?.animation_url;
@@ -37,17 +36,19 @@ const useUpdateMomentURI = () => {
const name = providerName || current?.name;
const description = providerDescription || current?.description;
+ const isImage = mimeType?.includes("image");
+
const updated = {
...(current || {}),
name,
description,
image: imageUri || current?.image,
- animation_url: updatedAnimationUrl,
+ animation_url: isImage ? imageUri : updatedAnimationUrl,
content:
- (updatedContentUri || updatedMimeType) && !updatedMimeType?.includes("image")
+ updatedContentUri || updatedMimeType
? {
mime: updatedMimeType || current?.content?.mime || "",
- uri: updatedContentUri || current?.content?.uri || "",
+ uri: isImage ? imageUri : updatedContentUri || current?.content?.uri || "",
}
: current?.content,
};
@@ -56,7 +57,7 @@ const useUpdateMomentURI = () => {
const newUri = await uploadJson(updated);
- if (!token?.tokenContractAddress || !token?.tokenId) {
+ if (!moment?.collectionAddress || !moment?.tokenId) {
throw new Error("Missing token context");
}
@@ -66,16 +67,15 @@ const useUpdateMomentURI = () => {
}
await callUpdateMomentURI({
- tokenContractAddress: token.tokenContractAddress,
- tokenId: token.tokenId,
+ moment,
newUri,
accessToken,
});
if (updatedMimeType?.includes("video")) {
await migrateMuxToArweaveApi({
- tokenContractAddress: token.tokenContractAddress,
- tokenId: token.tokenId,
+ tokenContractAddress: moment.collectionAddress,
+ tokenId: moment.tokenId,
accessToken,
});
resetForm();
diff --git a/lib/fetchArtistLatestMint.ts b/lib/fetchArtistLatestMint.ts
index d0c4b74b..55758a45 100644
--- a/lib/fetchArtistLatestMint.ts
+++ b/lib/fetchArtistLatestMint.ts
@@ -1,11 +1,11 @@
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import { VERCEL_OG } from "./og/consts";
import fetchTokenMetadata from "./fetchTokenMetadata";
const getArtistLatestMint = async (
artistAddress: string,
chainId: number
-): Promise => {
+): Promise => {
try {
const response = await fetch(
`${VERCEL_OG}/api/artist/latest_mint?artistAddress=${artistAddress}&chainId=${chainId}`
diff --git a/lib/fetchTokenMetadata.ts b/lib/fetchTokenMetadata.ts
index e3fb6270..61d61b5d 100644
--- a/lib/fetchTokenMetadata.ts
+++ b/lib/fetchTokenMetadata.ts
@@ -1,10 +1,10 @@
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import { VERCEL_OG } from "./og/consts";
const fetchTokenMetadata = async (
tokenContract: string,
tokenId: string
-): Promise => {
+): Promise => {
try {
const response = await fetch(
`${VERCEL_OG}/api/token/metadata?tokenId=${BigInt(tokenId).toString()}&collection=${tokenContract}`
diff --git a/lib/getArtistLatestMoment.ts b/lib/getArtistLatestMoment.ts
index aadbf3b1..7274e886 100644
--- a/lib/getArtistLatestMoment.ts
+++ b/lib/getArtistLatestMoment.ts
@@ -1,11 +1,11 @@
-import { Metadata } from "@/types/token";
+import { MomentMetadata } from "@/types/moment";
import { VERCEL_OG } from "./og/consts";
import fetchTokenMetadata from "./fetchTokenMetadata";
const getArtistLatestMoment = async (
artistAddress: string,
chainId: number
-): Promise => {
+): Promise => {
try {
const response = await fetch(
`${VERCEL_OG}/api/collections?artistAddress=${artistAddress}&chainId=${chainId}`,
diff --git a/lib/getPrice.ts b/lib/getPrice.ts
index 077407bd..f09dc385 100644
--- a/lib/getPrice.ts
+++ b/lib/getPrice.ts
@@ -1,9 +1,9 @@
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
import { formatUnits } from "viem";
const getPrice = (pricePerToken: bigint | number | string, type: string | undefined) => {
if (!type) return "";
- return formatUnits(BigInt(pricePerToken), type === MintType.Erc20Mint ? 6 : 18);
+ return formatUnits(BigInt(pricePerToken), type === MomentType.Erc20Mint ? 6 : 18);
};
export default getPrice;
diff --git a/lib/getPriceUnit.ts b/lib/getPriceUnit.ts
index 58334222..726efd3f 100644
--- a/lib/getPriceUnit.ts
+++ b/lib/getPriceUnit.ts
@@ -1,8 +1,8 @@
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
const getPriceUnit = (type: string | undefined) => {
if (!type) return "";
- return type === MintType.Erc20Mint ? "usdc" : "eth";
+ return type === MomentType.Erc20Mint ? "usdc" : "eth";
};
export default getPriceUnit;
diff --git a/lib/getSaleConfigType.ts b/lib/getSaleConfigType.ts
index fb71dc3b..bf817839 100644
--- a/lib/getSaleConfigType.ts
+++ b/lib/getSaleConfigType.ts
@@ -1,9 +1,9 @@
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
const getSaleConfigType = (value: "erc20Mint" | "timed" | "fixedPrice") => {
- if (value === "erc20Mint") return MintType.Erc20Mint;
- if (value === "timed") return MintType.TimedMint;
- return MintType.FixedPriceMint;
+ if (value === "erc20Mint") return MomentType.Erc20Mint;
+ if (value === "timed") return MomentType.TimedMint;
+ return MomentType.FixedPriceMint;
};
export default getSaleConfigType;
diff --git a/lib/moment/callUpdateMomentURI.ts b/lib/moment/callUpdateMomentURI.ts
index 7eb236eb..56ac5399 100644
--- a/lib/moment/callUpdateMomentURI.ts
+++ b/lib/moment/callUpdateMomentURI.ts
@@ -1,6 +1,7 @@
+import { Moment } from "@/types/moment";
+
export interface CallUpdateMomentURIInput {
- tokenContractAddress: string;
- tokenId: string;
+ moment: Moment;
newUri: string;
accessToken: string;
}
@@ -10,8 +11,7 @@ export interface CallUpdateMomentURIInput {
* Handles authentication and error responses.
*/
export async function callUpdateMomentURI({
- tokenContractAddress,
- tokenId,
+ moment,
newUri,
accessToken,
}: CallUpdateMomentURIInput): Promise {
@@ -23,10 +23,7 @@ export async function callUpdateMomentURI({
authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
- moment: {
- contractAddress: tokenContractAddress,
- tokenId: tokenId,
- },
+ moment,
newUri,
}),
});
diff --git a/lib/moment/collectMoment.ts b/lib/moment/collectMoment.ts
index 1240a7a9..2fae895e 100644
--- a/lib/moment/collectMoment.ts
+++ b/lib/moment/collectMoment.ts
@@ -4,10 +4,10 @@ import { CHAIN_ID, IS_TESTNET, USDC_ADDRESS } from "@/lib/consts";
import { sendUserOperation } from "@/lib/coinbase/sendUserOperation";
import { getOrCreateSmartWallet } from "../coinbase/getOrCreateSmartWallet";
import { collectSchema } from "../schema/collectSchema";
-import getTokenInfo from "../viem/getTokenInfo";
+import getMomentOnChainInfo from "../viem/getTokenInfo";
import { distributeSplitFunds } from "../splits/distributeSplitFunds";
import isSplitContract from "../splits/isSplitContract";
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
import getCollectCall from "../viem/getCollectCall";
import { validateBalanceAndAllowance } from "./validateBalanceAndAllowance";
import { Call } from "@coinbase/coinbase-sdk/dist/types/calls";
@@ -35,17 +35,16 @@ export async function collectMoment({
});
// Get token info and sale config
- const { saleConfig } = await getTokenInfo(
- moment.contractAddress as Address,
- moment.tokenId,
- CHAIN_ID
- );
+ const { saleConfig } = await getMomentOnChainInfo({
+ ...moment,
+ collectionAddress: moment.collectionAddress as Address,
+ });
const approveCall = await validateBalanceAndAllowance(smartAccount.address, saleConfig, amount);
// Get the collect call using the shared function
const collectCall = getCollectCall(
- moment.contractAddress as Address,
+ moment.collectionAddress as Address,
Number(moment.tokenId),
saleConfig,
artistAddress,
@@ -69,7 +68,7 @@ export async function collectMoment({
if (isSplit) {
await distributeSplitFunds({
splitAddress: saleConfig.fundsRecipient,
- tokenAddress: saleConfig.type === MintType.Erc20Mint ? USDC_ADDRESS : zeroAddress, // zeroAddress for native ETH
+ tokenAddress: saleConfig.type === MomentType.Erc20Mint ? USDC_ADDRESS : zeroAddress, // zeroAddress for native ETH
smartAccount,
});
}
diff --git a/lib/moment/collectMomentApi.ts b/lib/moment/collectMomentApi.ts
index 8008357d..d7bc2a7c 100644
--- a/lib/moment/collectMomentApi.ts
+++ b/lib/moment/collectMomentApi.ts
@@ -14,10 +14,7 @@ export const collectMomentApi = async (
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
- moment: {
- contractAddress: moment.contractAddress,
- tokenId: moment.tokenId,
- },
+ moment,
amount,
comment,
}),
diff --git a/lib/moment/fetchComments.ts b/lib/moment/fetchComments.ts
index 1cb1bfe1..a50e10e7 100644
--- a/lib/moment/fetchComments.ts
+++ b/lib/moment/fetchComments.ts
@@ -1,28 +1,12 @@
-import {
- CommentsQueryParams,
- MintComment,
- MomentCommentsInput,
- MomentCommentsResult,
-} from "@/types/moment";
+import { MintComment, MomentCommentsInput, MomentCommentsResult } from "@/types/moment";
-async function fetchComments({
- moment,
- chainId,
- offset,
-}: MomentCommentsInput): Promise {
+async function fetchComments({ moment, offset }: MomentCommentsInput): Promise {
try {
- const params: CommentsQueryParams = {
- contractAddress: moment.contractAddress,
- tokenId: moment.tokenId,
- chainId,
- offset,
- };
-
const queryString = new URLSearchParams({
- contractAddress: params.contractAddress,
- tokenId: params.tokenId,
- chainId: params.chainId.toString(),
- offset: params.offset?.toString() || "0",
+ collectionAddress: moment.collectionAddress.toString(),
+ tokenId: moment.tokenId,
+ chainId: moment.chainId.toString(),
+ offset: offset.toString(),
});
const response = await fetch(`/api/moment/comments?${queryString}`);
diff --git a/lib/moment/getMomentAdvancedInfo.ts b/lib/moment/getMomentAdvancedInfo.ts
new file mode 100644
index 00000000..7bc0b50d
--- /dev/null
+++ b/lib/moment/getMomentAdvancedInfo.ts
@@ -0,0 +1,42 @@
+import { Moment, MomentAdvancedInfo } from "@/types/moment";
+import selectMoment from "@/lib/supabase/in_process_moments/selectMoment";
+import selectSale from "@/lib/supabase/in_process_sales/selectSale";
+import getMomentOnChainInfo from "@/lib/viem/getTokenInfo";
+import { convertDatabaseSaleToApi } from "@/lib/sales/convertDatabaseSaleToApi";
+import { convertOnChainSaleToApi } from "@/lib/sales/convertOnChainSaleToApi";
+
+export const getMomentAdvancedInfo = async (moment: Moment): Promise => {
+ const momentdata = await selectMoment(moment);
+
+ if (momentdata) {
+ const uri = momentdata.uri;
+ const owner = momentdata.collection.default_admin;
+ const sale = await selectSale(momentdata.id);
+
+ if (sale) {
+ return {
+ uri,
+ owner,
+ saleConfig: convertDatabaseSaleToApi(sale),
+ };
+ }
+
+ const { saleConfig: onChainSale } = await getMomentOnChainInfo(moment);
+ return {
+ uri,
+ owner,
+ saleConfig: convertOnChainSaleToApi(onChainSale),
+ };
+ }
+
+ const {
+ saleConfig: onChainSale,
+ owner: tokenOwner,
+ tokenUri,
+ } = await getMomentOnChainInfo(moment);
+ return {
+ uri: tokenUri,
+ owner: tokenOwner as string,
+ saleConfig: convertOnChainSaleToApi(onChainSale),
+ };
+};
diff --git a/lib/moment/getMomentApi.ts b/lib/moment/getMomentApi.ts
index 66ccc1ac..0b62e69e 100644
--- a/lib/moment/getMomentApi.ts
+++ b/lib/moment/getMomentApi.ts
@@ -1,10 +1,10 @@
-import { Address } from "viem";
+import { Moment } from "@/types/moment";
-export const getMomentApi = async (tokenContract: Address, tokenId: string, chainId: number) => {
+export const getMomentApi = async (moment: Moment) => {
const params = new URLSearchParams({
- tokenContract,
- tokenId,
- chainId: String(chainId),
+ collectionAddress: moment.collectionAddress.toString(),
+ tokenId: moment.tokenId,
+ chainId: moment.chainId.toString(),
});
const res = await fetch(`/api/moment?${params.toString()}`);
if (!res.ok) {
diff --git a/lib/moment/indexMoment.ts b/lib/moment/indexMoment.ts
index d06e3ae7..071bea4d 100644
--- a/lib/moment/indexMoment.ts
+++ b/lib/moment/indexMoment.ts
@@ -2,11 +2,15 @@ import { Address } from "viem";
import { getInProcessTokens } from "@/lib/supabase/in_process_tokens/getInProcessTokens";
import { updateInProcessTokens } from "@/lib/supabase/in_process_tokens/updateInProcessTokens";
import { insertInProcessTokens } from "@/lib/supabase/in_process_tokens/insertInProcessTokens";
-import getTokenInfo from "../viem/getTokenInfo";
+import getMomentOnChainInfo from "../viem/getTokenInfo";
const indexMoment = async (address: Address, tokenId: number, chainId: number) => {
// Fetch onchain details
- const { tokenUri: uri, owner: admin } = await getTokenInfo(address, tokenId.toString(), chainId);
+ const { tokenUri: uri, owner: admin } = await getMomentOnChainInfo({
+ collectionAddress: address,
+ tokenId: tokenId.toString(),
+ chainId,
+ });
// Look for existing moment
const { data: existingRows, error: fetchError } = await getInProcessTokens({
diff --git a/lib/moment/momentComments.ts b/lib/moment/momentComments.ts
index d7cc4092..c778186f 100644
--- a/lib/moment/momentComments.ts
+++ b/lib/moment/momentComments.ts
@@ -1,6 +1,6 @@
import { z } from "zod";
import { commentsSchema } from "../schema/commentsSchema";
-import selectMoments from "../supabase/in_process_moments/selectMoments";
+import selectMoment from "../supabase/in_process_moments/selectMoment";
import { Address } from "viem";
import selectComments from "../supabase/in_process_moment_comments/selectComments";
import { MomentCommentsResult } from "@/types/moment";
@@ -9,23 +9,20 @@ export type GetCommentsInput = z.infer;
export async function momentComments({
moment,
- chainId,
offset,
}: GetCommentsInput): Promise {
- const data = await selectMoments({
- collectionAddress: moment.contractAddress as Address,
+ const momentdata = await selectMoment({
+ collectionAddress: moment.collectionAddress as Address,
tokenId: moment.tokenId,
- chainId,
+ chainId: moment.chainId,
});
- const momentData = data[0];
-
- if (!momentData) {
+ if (!momentdata) {
throw new Error("Moment not found");
}
const comments = await selectComments({
- momentId: momentData.id,
+ momentId: momentdata.id,
offset,
});
diff --git a/lib/moment/updateMomentURI.ts b/lib/moment/updateMomentURI.ts
index 1a974198..ccb53b38 100644
--- a/lib/moment/updateMomentURI.ts
+++ b/lib/moment/updateMomentURI.ts
@@ -3,10 +3,10 @@ import { CHAIN_ID, IS_TESTNET } from "@/lib/consts";
import { sendUserOperation } from "@/lib/coinbase/sendUserOperation";
import getUpdateTokenURICall from "@/lib/viem/getUpdateTokenURICall";
import { getOrCreateSmartWallet } from "@/lib/coinbase/getOrCreateSmartWallet";
+import { Moment } from "@/types/moment";
export interface UpdateMomentURIInput {
- tokenContractAddress: Address;
- tokenId: string;
+ moment: Moment;
newUri: string;
artistAddress: Address;
}
@@ -21,8 +21,7 @@ export interface UpdateMomentURIResult {
* Handles the transaction on the backend side.
*/
export async function updateMomentURI({
- tokenContractAddress,
- tokenId,
+ moment,
newUri,
artistAddress,
}: UpdateMomentURIInput): Promise {
@@ -30,7 +29,11 @@ export async function updateMomentURI({
address: artistAddress,
});
- const updateTokenURICall = getUpdateTokenURICall(tokenContractAddress, tokenId, newUri);
+ const updateTokenURICall = getUpdateTokenURICall(
+ moment.collectionAddress,
+ moment.tokenId,
+ newUri
+ );
// Send the transaction and wait for receipt using the helper
const transaction = await sendUserOperation({
diff --git a/lib/moment/validateBalanceAndAllowance.ts b/lib/moment/validateBalanceAndAllowance.ts
index 1ae9de7f..b518435f 100644
--- a/lib/moment/validateBalanceAndAllowance.ts
+++ b/lib/moment/validateBalanceAndAllowance.ts
@@ -6,7 +6,7 @@ import getUsdcBalance from "@/lib/balance/getUsdcBalance";
import getEthBalance from "@/lib/balance/getEthBalance";
import getAllowance from "@/lib/viem/getAllowance";
import getApproveCall from "@/lib/viem/getApproveCall";
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
/**
* Validates balance and checks allowance for moment collection.
@@ -18,7 +18,7 @@ export async function validateBalanceAndAllowance(
amount: number
) {
const approveCall = [];
- const isErc20Mint = saleConfig.type === MintType.Erc20Mint;
+ const isErc20Mint = saleConfig.type === MomentType.Erc20Mint;
if (isErc20Mint) {
const pricePerToken = formatUnits(saleConfig.pricePerToken, 6);
diff --git a/lib/mux/migrateMuxToArweave.ts b/lib/mux/migrateMuxToArweave.ts
index 3fd50e55..6baad776 100644
--- a/lib/mux/migrateMuxToArweave.ts
+++ b/lib/mux/migrateMuxToArweave.ts
@@ -3,7 +3,7 @@ import { downloadVideoFromMux } from "@/lib/mux/downloadVideoFromMux";
import { deleteMuxAsset } from "@/lib/mux/deleteMuxAsset";
import { findMuxAssetIdFromPlaybackUrl } from "@/lib/mux/findMuxAssetIdFromPlaybackUrl";
import { fetchTokenMetadata } from "@/lib/protocolSdk/ipfs/token-metadata";
-import getTokenInfo from "@/lib/viem/getTokenInfo";
+import getMomentOnChainInfo from "@/lib/viem/getTokenInfo";
import getUpdateTokenURICall from "@/lib/viem/getUpdateTokenURICall";
import getUpdateContractMetadataCall from "@/lib/viem/getUpdateContractMetadataCall";
import { CHAIN_ID, IS_TESTNET } from "@/lib/consts";
@@ -44,7 +44,11 @@ export async function migrateMuxToArweave({
}: MigrateMuxToArweaveInput): Promise {
try {
// Step 1: Get token info using viem and fetch metadata from IPFS
- const tokenInfo = await getTokenInfo(tokenContractAddress, tokenId, CHAIN_ID);
+ const tokenInfo = await getMomentOnChainInfo({
+ collectionAddress: tokenContractAddress,
+ tokenId,
+ chainId: CHAIN_ID,
+ });
const currentMetadata = await fetchTokenMetadata(tokenInfo.tokenUri);
if (!currentMetadata) {
diff --git a/lib/sales/convertDatabaseSaleToApi.ts b/lib/sales/convertDatabaseSaleToApi.ts
new file mode 100644
index 00000000..f7c26657
--- /dev/null
+++ b/lib/sales/convertDatabaseSaleToApi.ts
@@ -0,0 +1,15 @@
+import { Address, zeroAddress } from "viem";
+import { MomentType, MomentApiSaleConfig } from "@/types/moment";
+import { DatabaseSale } from "@/types/sale";
+
+export const convertDatabaseSaleToApi = (sale: DatabaseSale): MomentApiSaleConfig => ({
+ pricePerToken: sale.price_per_token.toString(),
+ saleStart: Number(sale.sale_start),
+ saleEnd: Number(sale.sale_end),
+ maxTokensPerAddress: Number(sale.max_tokens_per_address),
+ fundsRecipient: sale.funds_recipient as Address,
+ type:
+ sale.currency.toLowerCase() === zeroAddress.toLowerCase()
+ ? MomentType.FixedPriceMint
+ : MomentType.Erc20Mint,
+});
diff --git a/lib/sales/convertOnChainSaleToApi.ts b/lib/sales/convertOnChainSaleToApi.ts
new file mode 100644
index 00000000..776c7998
--- /dev/null
+++ b/lib/sales/convertOnChainSaleToApi.ts
@@ -0,0 +1,11 @@
+import { MomentApiSaleConfig } from "@/types/moment";
+import { OnChainSaleConfig } from "@/types/sale";
+
+export const convertOnChainSaleToApi = (sale: OnChainSaleConfig): MomentApiSaleConfig => ({
+ pricePerToken: sale.pricePerToken.toString(),
+ saleStart: Number(sale.saleStart),
+ saleEnd: Number(sale.saleEnd),
+ maxTokensPerAddress: Number(sale.maxTokensPerAddress),
+ fundsRecipient: sale.fundsRecipient,
+ type: sale.type,
+});
diff --git a/lib/schema/collectSchema.ts b/lib/schema/collectSchema.ts
index d2c8e1d0..b189b801 100644
--- a/lib/schema/collectSchema.ts
+++ b/lib/schema/collectSchema.ts
@@ -1,9 +1,11 @@
import { z } from "zod";
import addressSchema from "./addressSchema";
+import { CHAIN_ID } from "../consts";
export const momentSchema = z.object({
tokenId: z.string(),
- contractAddress: addressSchema,
+ collectionAddress: addressSchema,
+ chainId: z.number().optional().default(CHAIN_ID),
});
export const collectSchema = z.object({
diff --git a/lib/schema/commentsSchema.ts b/lib/schema/commentsSchema.ts
index 89abf761..453b8071 100644
--- a/lib/schema/commentsSchema.ts
+++ b/lib/schema/commentsSchema.ts
@@ -1,13 +1,14 @@
import { z } from "zod";
import addressSchema from "./addressSchema";
+import { CHAIN_ID } from "../consts";
export const momentSchema = z.object({
tokenId: z.string(),
- contractAddress: addressSchema,
+ collectionAddress: addressSchema,
+ chainId: z.number().optional().default(CHAIN_ID),
});
export const commentsSchema = z.object({
moment: momentSchema,
- chainId: z.number(),
offset: z.number(),
});
diff --git a/lib/schema/getMomentSchema.ts b/lib/schema/getMomentSchema.ts
index f7195d1f..32a6aa56 100644
--- a/lib/schema/getMomentSchema.ts
+++ b/lib/schema/getMomentSchema.ts
@@ -1,13 +1,15 @@
import { z } from "zod";
import addressSchema from "./addressSchema";
+import { CHAIN_ID } from "../consts";
export const getMomentSchema = z.object({
- tokenContract: addressSchema,
+ collectionAddress: addressSchema,
tokenId: z.string().min(1, "Token ID is required"),
chainId: z
.string()
.optional()
.refine((val) => !val || !isNaN(parseInt(val, 10)), {
message: "Chain ID must be a valid number",
- }),
+ })
+ .default(CHAIN_ID.toString()),
});
diff --git a/lib/supabase/in_process_admins/selectAdmins.ts b/lib/supabase/in_process_admins/selectAdmins.ts
new file mode 100644
index 00000000..dae80ddd
--- /dev/null
+++ b/lib/supabase/in_process_admins/selectAdmins.ts
@@ -0,0 +1,14 @@
+import { Moment } from "@/types/moment";
+import { supabase } from "../client";
+
+const selectAdmins = async (moment: Moment) => {
+ const { data, error } = await supabase
+ .from("in_process_admins")
+ .select("*")
+ .eq("collection", moment.collectionAddress)
+ .or(`token_id.in.(0,${moment.tokenId})`);
+ if (error) return [];
+ return data || [];
+};
+
+export default selectAdmins;
diff --git a/lib/supabase/in_process_moments/selectMoments.ts b/lib/supabase/in_process_moments/selectMoment.ts
similarity index 60%
rename from lib/supabase/in_process_moments/selectMoments.ts
rename to lib/supabase/in_process_moments/selectMoment.ts
index 288be188..82150e4e 100644
--- a/lib/supabase/in_process_moments/selectMoments.ts
+++ b/lib/supabase/in_process_moments/selectMoment.ts
@@ -1,15 +1,8 @@
-import { Address } from "viem";
import { supabase } from "../client";
+import { Moment } from "@/types/moment";
-const selectMoments = async ({
- collectionAddress,
- tokenId,
- chainId,
-}: {
- collectionAddress: Address;
- tokenId: string;
- chainId: number;
-}) => {
+const selectMoment = async (moment: Moment) => {
+ const { collectionAddress, tokenId, chainId } = moment;
let query = supabase
.from("in_process_moments")
.select("*, collection:in_process_collections!inner(*)");
@@ -24,9 +17,9 @@ const selectMoments = async ({
query = query.eq("token_id", Number(tokenId));
}
- const { data, error } = await query;
- if (error) throw error;
+ const { data, error } = await query.single();
+ if (error) return null;
return data;
};
-export default selectMoments;
+export default selectMoment;
diff --git a/lib/supabase/in_process_sales/selectSale.ts b/lib/supabase/in_process_sales/selectSale.ts
new file mode 100644
index 00000000..e4405d7d
--- /dev/null
+++ b/lib/supabase/in_process_sales/selectSale.ts
@@ -0,0 +1,13 @@
+import { supabase } from "../client";
+
+const selectSale = async (momentId: string) => {
+ const { data, error } = await supabase
+ .from("in_process_sales")
+ .select("*")
+ .eq("moment", momentId)
+ .single();
+ if (error) return null;
+ return data;
+};
+
+export default selectSale;
diff --git a/lib/supabase/in_process_tokens/selectInProcessToken.ts b/lib/supabase/in_process_tokens/selectInProcessToken.ts
deleted file mode 100644
index 2aa59957..00000000
--- a/lib/supabase/in_process_tokens/selectInProcessToken.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { supabase } from "@/lib/supabase/client";
-
-/**
- * Fetches tokens from the "in_process_tokens" table.
- * @param filters Optional filters to apply (e.g. by artist address, chainId, etc).
- * @returns Array of token rows, or throws on error.
- */
-export async function selectInProcessToken({
- address,
- chainId,
-}: {
- chainId?: number;
- address?: string;
-}) {
- let query = supabase
- .from("in_process_tokens")
- .select("*, token_admins:in_process_token_admins(*)");
-
- if (address) {
- query = query.eq("address", address.toLowerCase());
- }
-
- if (chainId !== undefined) {
- query = query.eq("chainId", chainId);
- }
-
- const { data, error } = await query.single();
- if (error) {
- throw error;
- }
- return data;
-}
diff --git a/lib/viem/getCollectCall.ts b/lib/viem/getCollectCall.ts
index 9b5320e0..9364d0c2 100644
--- a/lib/viem/getCollectCall.ts
+++ b/lib/viem/getCollectCall.ts
@@ -2,7 +2,7 @@ import { SaleConfig } from "@/types/moment";
import { erc20MinterABI, zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
import { Address, encodeAbiParameters, encodeFunctionData, parseAbiParameters } from "viem";
import { CHAIN_ID, USDC_ADDRESS } from "../consts";
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
import {
erc20MinterAddresses,
zoraCreatorFixedPriceSaleStrategyAddress,
@@ -22,7 +22,7 @@ const getCollectCall = (
]);
const totalPrice = sale.pricePerToken * BigInt(amount);
- if (sale.type === MintType.Erc20Mint) {
+ if (sale.type === MomentType.Erc20Mint) {
return {
to: erc20MinterAddresses[CHAIN_ID],
data: encodeFunctionData({
diff --git a/lib/viem/getNextTokenIds.ts b/lib/viem/getNextTokenIds.ts
deleted file mode 100644
index 61f4816b..00000000
--- a/lib/viem/getNextTokenIds.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { getPublicClient } from "./publicClient";
-import { zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
-import { Collection } from "@/types/token";
-
-export type CollectionAndNextTokenId = Collection & {
- nextTokenId: number;
-};
-
-const getNextTokenIds = async (collections: Collection[]) => {
- const groupedFeedByNetwork = collections.reduce(
- (acc: { [network: string]: Collection[] }, item: Collection) => {
- const network = item.chainId;
- if (!acc[network]) {
- acc[network] = [];
- }
- acc[network].push(item);
- return acc;
- },
- {}
- );
-
- const promise = Object.entries(groupedFeedByNetwork).map(async ([chainId, collections]) => {
- const publicClient = getPublicClient(parseInt(chainId, 10));
- const calls = collections.map((c: Collection) => ({
- address: c.newContract,
- abi: zoraCreator1155ImplABI,
- functionName: "nextTokenId",
- }));
- const returnValues = await publicClient.multicall({
- contracts: calls as any,
- });
- return collections.map((c: Collection, i) => ({
- ...c,
- nextTokenId: Number(returnValues[i].result as bigint),
- }));
- });
- const result = await Promise.all(promise);
- return result.flat() as CollectionAndNextTokenId[];
-};
-
-export default getNextTokenIds;
diff --git a/lib/viem/getTokenInfo.ts b/lib/viem/getTokenInfo.ts
index b6565cae..119015c9 100644
--- a/lib/viem/getTokenInfo.ts
+++ b/lib/viem/getTokenInfo.ts
@@ -1,5 +1,4 @@
import { getPublicClient } from "@/lib/viem/publicClient";
-import { CHAIN_ID } from "@/lib/consts";
import {
erc20MinterAddresses,
zoraCreatorFixedPriceSaleStrategyAddress,
@@ -9,20 +8,17 @@ import {
zoraCreator1155ImplABI,
zoraCreatorFixedPriceSaleStrategyABI,
} from "@zoralabs/protocol-deployments";
-import { Address } from "viem";
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
+import { Moment } from "@/types/moment";
-const getTokenInfo = async (
- tokenContract: Address,
- tokenId: string,
- chainId: number = CHAIN_ID
-) => {
+const getMomentOnChainInfo = async (moment: Moment) => {
+ const { collectionAddress, tokenId, chainId } = moment;
const publicClient: any = getPublicClient(chainId);
const erc20SaleConfigCall = {
address: erc20MinterAddresses[chainId as keyof typeof erc20MinterAddresses],
abi: erc20MinterABI,
functionName: "sale",
- args: [tokenContract, tokenId],
+ args: [collectionAddress, tokenId],
};
const fixedSaleConfigCall = {
address:
@@ -31,16 +27,16 @@ const getTokenInfo = async (
],
abi: zoraCreatorFixedPriceSaleStrategyABI,
functionName: "sale",
- args: [tokenContract, tokenId],
+ args: [collectionAddress, tokenId],
};
const uriCall = {
- address: tokenContract,
+ address: collectionAddress,
abi: zoraCreator1155ImplABI,
functionName: "uri",
args: [tokenId],
};
const ownerCall = {
- address: tokenContract,
+ address: collectionAddress,
abi: zoraCreator1155ImplABI,
functionName: "owner",
args: [],
@@ -54,11 +50,11 @@ const getTokenInfo = async (
infoCalls[0]?.result?.saleEnd > BigInt(0)
? {
...infoCalls[0]?.result,
- type: MintType.Erc20Mint,
+ type: MomentType.Erc20Mint,
}
: {
...infoCalls[1]?.result,
- type: MintType.FixedPriceMint,
+ type: MomentType.FixedPriceMint,
};
return {
@@ -68,4 +64,4 @@ const getTokenInfo = async (
};
};
-export default getTokenInfo;
+export default getMomentOnChainInfo;
diff --git a/lib/zora/getSalesConfig.tsx b/lib/zora/getSalesConfig.tsx
index a138b75f..f157c10d 100644
--- a/lib/zora/getSalesConfig.tsx
+++ b/lib/zora/getSalesConfig.tsx
@@ -1,7 +1,7 @@
import { TimedSaleParamsType } from "@/lib/protocolSdk";
import { maxUint64, parseEther, parseUnits } from "viem";
import { USDC_ADDRESS } from "../consts";
-import { MintType } from "@/types/zora";
+import { MomentType } from "@/types/moment";
const getSalesConfig = (saleStrategy: string, price: string, saleStart: Date | undefined) => {
const timedSaleConfig = {
@@ -30,11 +30,11 @@ const getSalesConfig = (saleStrategy: string, price: string, saleStart: Date | u
if (price === "0") return fixedPriceSaleConfig;
switch (saleStrategy) {
- case MintType.FixedPriceMint:
+ case MomentType.FixedPriceMint:
return fixedPriceSaleConfig;
- case MintType.TimedMint:
+ case MomentType.TimedMint:
return timedSaleConfig;
- case MintType.Erc20Mint:
+ case MomentType.Erc20Mint:
return erc20MintSaleConfig;
default:
return erc20MintSaleConfig;
diff --git a/providers/MomentProvider.tsx b/providers/MomentProvider.tsx
new file mode 100644
index 00000000..3c507ad7
--- /dev/null
+++ b/providers/MomentProvider.tsx
@@ -0,0 +1,34 @@
+import { createContext, useContext, ReactNode } from "react";
+import { Moment } from "@/types/moment";
+import useMoment from "@/hooks/useMoment";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const MomentContext = createContext<
+ | (ReturnType & {
+ moment: Moment;
+ })
+ | undefined
+>(undefined);
+
+export function MomentProvider({ children, moment }: { children: ReactNode; moment: Moment }) {
+ const momentData = useMoment(moment);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useMomentProvider() {
+ const context = useContext(MomentContext);
+ if (context === undefined) {
+ throw new Error("useMomentProvider must be used within a MomentProvider");
+ }
+ return context;
+}
diff --git a/providers/TokenProvider.tsx b/providers/TokenProvider.tsx
deleted file mode 100644
index dca4c8f1..00000000
--- a/providers/TokenProvider.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import useTokenInfo from "@/hooks/useTokenInfo";
-import { TokenInfo } from "@/types/token";
-import { createContext, useContext, ReactNode } from "react";
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const TokenContext = createContext<
- | (ReturnType & {
- token: TokenInfo;
- })
- | undefined
->(undefined);
-
-export function TokenProvider({
- children,
- token,
- chainId,
-}: {
- children: ReactNode;
- token: TokenInfo;
- chainId: number;
-}) {
- const tokenInfo = useTokenInfo(token.tokenContractAddress, token.tokenId, chainId);
-
- return (
-
- {children}
-
- );
-}
-
-export function useTokenProvider() {
- const context = useContext(TokenContext);
- if (context === undefined) {
- throw new Error("useTokenProvider must be used within a TokenProvider");
- }
- return context;
-}
diff --git a/types/dune.ts b/types/dune.ts
deleted file mode 100644
index d05a7e14..00000000
--- a/types/dune.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Address } from "viem";
-
-export type DuneDecoded = {
- name: string;
- inputs: Array<{
- name: string;
- type: string;
- value: string | Array;
- }>;
-};
-
-export type DuneDecodedEvent = {
- chain: string;
- chain_id: number;
- address: Address;
- block_time: string;
- block_number: number;
- index: number;
- hash: string;
- block_hash: string;
- value: string;
- transaction_type: "Sender" | "Receiver";
- from: Address;
- to: Address;
- nonce: string;
- gas_price: string;
- gas_used: string;
- effective_gas_price: string;
- success: boolean;
- data: string;
- decoded: DuneDecoded;
- logs: Array<{
- address: Address;
- data: string;
- topics: Array;
- decoded?: DuneDecoded;
- }>;
-};
diff --git a/types/fetch-collections.ts b/types/fetch-collections.ts
deleted file mode 100644
index 9fc54bf3..00000000
--- a/types/fetch-collections.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Collection } from "./token";
-
-export interface CollectionsOffset {
- factory?: string;
- smartWallet?: string;
-}
-export interface CollectionsResponse {
- collections: Collection[];
- nextOffsets: CollectionsOffset;
- artistAddress?: string;
-}
-
-export interface PageParam {
- offsets: CollectionsOffset | undefined;
- artistAddress: string | undefined;
-}
diff --git a/types/jam.ts b/types/jam.ts
deleted file mode 100644
index 448c09e9..00000000
--- a/types/jam.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface CustomData {
- label: string;
- isEditing: boolean;
- color: string;
-}
diff --git a/types/moment.ts b/types/moment.ts
index bbe0d745..1f4afadc 100644
--- a/types/moment.ts
+++ b/types/moment.ts
@@ -2,13 +2,13 @@ import { Address } from "viem";
import type { Database } from "@/lib/supabase/types";
export interface Moment {
- contractAddress: Address;
+ collectionAddress: Address;
tokenId: string;
+ chainId: number;
}
export interface MomentCommentsInput {
moment: Moment;
- chainId: number;
offset: number;
}
@@ -58,3 +58,44 @@ export type SaleConfig = {
fundsRecipient: Address;
type: string;
};
+
+export interface MomentMetadata {
+ image: string;
+ name: string;
+ description: string;
+ external_url?: string;
+ content?: {
+ mime: string;
+ uri: string;
+ } | null;
+ animation_url?: string;
+}
+
+export enum MomentType {
+ Erc20Mint = "erc20Mint",
+ TimedMint = "timed",
+ FixedPriceMint = "fixedPrice",
+}
+
+export type MomentApiSaleConfig = {
+ pricePerToken: string;
+ saleStart: number;
+ saleEnd: number;
+ maxTokensPerAddress: number;
+ fundsRecipient: Address;
+ type: MomentType;
+};
+
+export type MomentResponse = {
+ uri: string | null;
+ owner: string | null;
+ saleConfig: MomentApiSaleConfig | null;
+ momentAdmins: string[];
+ metadata: MomentMetadata;
+};
+
+export type MomentAdvancedInfo = {
+ uri: string | null;
+ owner: string | null;
+ saleConfig: MomentApiSaleConfig | null;
+};
diff --git a/types/sale.ts b/types/sale.ts
new file mode 100644
index 00000000..952245df
--- /dev/null
+++ b/types/sale.ts
@@ -0,0 +1,20 @@
+import { Address } from "viem";
+import { MomentType } from "@/types/moment";
+
+export type OnChainSaleConfig = {
+ pricePerToken: bigint;
+ saleStart: bigint;
+ saleEnd: bigint;
+ maxTokensPerAddress: bigint;
+ fundsRecipient: Address;
+ type: MomentType;
+};
+
+export type DatabaseSale = {
+ price_per_token: number;
+ sale_start: number;
+ sale_end: number;
+ max_tokens_per_address: number;
+ funds_recipient: string;
+ currency: string;
+};
diff --git a/types/token.ts b/types/token.ts
deleted file mode 100644
index e4bd75cb..00000000
--- a/types/token.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { Address } from "viem";
-
-export interface TokenMetadata {
- name?: string;
- description?: string;
- image?: string;
- content?: {
- mime: string;
- uri: string;
- };
- canvas_url?: string;
-}
-
-export interface TokenInfo {
- tokenId: string;
- tokenContractAddress: Address;
- chainId?: number;
-}
-
-export interface Metadata {
- image: string;
- name: string;
- description: string;
- external_url?: string;
- content: {
- mime: string;
- uri: string;
- };
- animation_url?: string;
-}
-
-export interface Collection {
- contractURI: string;
- creator: Address;
- defaultAdmin: Address;
- defaultRoyaltyConfiguration: [string, string, string];
- name: string;
- newContract: Address;
- released_at: number;
- chain: string;
- chainId: number;
-}
diff --git a/types/zora.ts b/types/zora.ts
deleted file mode 100644
index d1f7d381..00000000
--- a/types/zora.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-export interface CollectionStyle {
- theme: {
- color: {
- background: string;
- text: string;
- accent: string;
- accentText: string;
- border: string;
- };
- font: {
- heading: {
- fontFamily: string;
- fontSize: string;
- lineHeight: string;
- };
- body: {
- fontFamily: string;
- fontSize: string;
- lineHeight: string;
- };
- caption: {
- fontFamily: string;
- fontSize: string;
- lineHeight: string;
- };
- };
- button: {
- shape: string;
- };
- };
- unit: {
- radius: string;
- base: string;
- };
-}
-
-export enum MintType {
- Erc20Mint = "erc20Mint",
- TimedMint = "timed",
- FixedPriceMint = "fixedPrice",
-}