diff --git a/packages/nextjs/app/challenge/[id]/page.tsx b/packages/nextjs/app/challenge/[id]/page.tsx index 60c39359..d196b98c 100644 --- a/packages/nextjs/app/challenge/[id]/page.tsx +++ b/packages/nextjs/app/challenge/[id]/page.tsx @@ -22,7 +22,7 @@ const PageView: React.FC = () => { }, [id]); return (
-
+
{markdown}
diff --git a/packages/nextjs/app/ipfsDownload/page.tsx b/packages/nextjs/app/ipfsDownload/page.tsx index 7d19cd35..60bc973e 100644 --- a/packages/nextjs/app/ipfsDownload/page.tsx +++ b/packages/nextjs/app/ipfsDownload/page.tsx @@ -4,7 +4,7 @@ import { lazy, useEffect, useState } from "react"; import type { NextPage } from "next"; import { notification } from "~~/utils/scaffold-stark/notification"; import ButtonStyle from "~~/components/ButtonStyle/ButtonStyle"; -// import { getMetadataFromIPFS } from "~~/utils/simpleNFT/ipfs-fetch"; +import { getMetadataFromIPFS } from "~~/utils/scaffold-stark/simpleNFT/ipfs-fetch"; const LazyReactJson = lazy(() => import("react-json-view")); @@ -17,23 +17,23 @@ const IpfsDownload: NextPage = () => { setMounted(true); }, []); - // const handleIpfsDownload = async () => { - // setLoading(true); - // const notificationId = notification.loading("Getting data from IPFS"); - // try { - // const metaData = await getMetadataFromIPFS(ipfsPath); - // notification.remove(notificationId); - // notification.success("Downloaded from IPFS"); + const handleIpfsDownload = async () => { + setLoading(true); + const notificationId = notification.loading("Getting data from IPFS"); + try { + const metaData = await getMetadataFromIPFS(ipfsPath); + notification.remove(notificationId); + notification.success("Downloaded from IPFS"); - // setYourJSON(metaData); - // } catch (error) { - // notification.remove(notificationId); - // notification.error("Error downloading from IPFS"); - // console.log(error); - // } finally { - // setLoading(false); - // } - // }; + setYourJSON(metaData); + } catch (error) { + notification.remove(notificationId); + notification.error("Error downloading from IPFS"); + console.log(error); + } finally { + setLoading(false); + } + }; return ( <> @@ -52,13 +52,13 @@ const IpfsDownload: NextPage = () => { autoComplete="off" />
- Download from IPFS - + {mounted && ( { setMounted(true); }, []); - // const handleIpfsUpload = async () => { - // setLoading(true); - // const notificationId = notification.loading("Uploading to IPFS..."); - // try { - // const uploadedItem = await addToIPFS(yourJSON); - // notification.remove(notificationId); - // notification.success("Uploaded to IPFS"); + const handleIpfsUpload = async () => { + setLoading(true); + const notificationId = notification.loading("Uploading to IPFS..."); + try { + const uploadedItem = await addToIPFS(yourJSON); + notification.remove(notificationId); + notification.success("Uploaded to IPFS"); - // setUploadedIpfsPath(uploadedItem.path); - // } catch (error) { - // notification.remove(notificationId); - // notification.error("Error uploading to IPFS"); - // console.log(error); - // } finally { - // setLoading(false); - // } - // }; + setUploadedIpfsPath(uploadedItem.path); + } catch (error) { + notification.remove(notificationId); + notification.error("Error uploading to IPFS"); + console.log(error); + } finally { + setLoading(false); + } + }; return ( <> @@ -60,18 +60,24 @@ const IpfsUpload: NextPage = () => { }} /> )} - Upload to IPFS - - {/* {uploadedIpfsPath && ( + + {uploadedIpfsPath && (
- + {`https://ipfs.io/ipfs/${uploadedIpfsPath}`}
- )} */} + )} ); diff --git a/packages/nextjs/app/myNFTs/page.tsx b/packages/nextjs/app/myNFTs/page.tsx index 1e5d5e25..2d8282cb 100644 --- a/packages/nextjs/app/myNFTs/page.tsx +++ b/packages/nextjs/app/myNFTs/page.tsx @@ -1,16 +1,88 @@ -import ButtonStyle from "~~/components/ButtonStyle/ButtonStyle"; +"use client"; + +import type { NextPage } from "next"; +import { useAccount } from "@starknet-react/core"; +import { CustomConnectButton } from "~~/components/scaffold-stark/CustomConnectButton"; import { MyHoldings } from "~~/components/SimpleNFT/MyHoldings"; +import { useScaffoldContractRead } from "~~/hooks/scaffold-stark/useScaffoldContractRead"; +import { useScaffoldContractWrite } from "~~/hooks/scaffold-stark/useScaffoldContractWrite"; +import { notification } from "~~/utils/scaffold-stark"; +import { addToIPFS } from "~~/utils/scaffold-stark/simpleNFT/ipfs-fetch"; +import { useScaffoldContract } from "~~/hooks/scaffold-stark/useScaffoldContract"; +import nftsMetadata from "~~/utils/scaffold-stark/simpleNFT/nftsMetadata"; + +const MyNFTs: NextPage = () => { + const { address: connectedAddress, isConnected, isConnecting } = useAccount(); + console.log(connectedAddress); + + const { data: yourCollectibleContract } = useScaffoldContract({ + contractName: "Challenge0", + }); + + const { writeAsync: mintItem, error: error } = useScaffoldContractWrite({ + contractName: "Challenge0", + functionName: "mint_item", + args: [ + connectedAddress ?? "", + `[${new TextEncoder().encode("Your string here").toString()}]`, + ], + }); + + // console.log(mintItem) + // console.log(error) + + const { data: tokenIdCounter } = useScaffoldContractRead({ + contractName: "Challenge0", + functionName: "token_id_counter", + watch: true, + cacheOnBlock: true, + }); + + const handleMintItem = async () => { + // circle back to the zero item if we've reached the end of the array + if (tokenIdCounter === undefined) return; + + const tokenIdCounterNumber = Number(tokenIdCounter); + const currentTokenMetaData = + nftsMetadata[tokenIdCounterNumber % nftsMetadata.length]; + const notificationId = notification.loading("Uploading to IPFS"); + try { + const uploadedItem = await addToIPFS(currentTokenMetaData); + + // First remove previous loading notification and then show success notification + notification.remove(notificationId); + notification.success("Metadata uploaded to IPFS"); + + await mintItem({ + args: [connectedAddress, uploadedItem.path], + }); + } catch (error) { + notification.remove(notificationId); + console.error(error); + } + }; -function Page() { return ( -
-
-

My NFTs

- Mint NFT - + <> +
+
+

+ My NFTs +

+
+
+
+ {!isConnected || isConnecting ? ( + + ) : ( + + )}
-
+ + ); -} +}; -export default Page; +export default MyNFTs; diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx index 4ae49158..886ddea2 100644 --- a/packages/nextjs/app/page.tsx +++ b/packages/nextjs/app/page.tsx @@ -6,7 +6,6 @@ import Image from "next/image"; // import { Address } from "~~/components/scaffold-eth"; const Home: NextPage = () => { - return ( <>
diff --git a/packages/nextjs/components/Footer.tsx b/packages/nextjs/components/Footer.tsx index c37e68ab..b1701041 100644 --- a/packages/nextjs/components/Footer.tsx +++ b/packages/nextjs/components/Footer.tsx @@ -10,6 +10,7 @@ import { CurrencyDollarIcon, MagnifyingGlassIcon, } from "@heroicons/react/24/outline"; +import { Faucet } from "./scaffold-stark"; /** * Site footer @@ -25,7 +26,7 @@ export const Footer = () => {
-
+
{nativeCurrencyPrice > 0 && (
@@ -36,7 +37,7 @@ export const Footer = () => { )} {isLocalNetwork && ( <> - {/**/} + { ); }; -/** - * Site header - */ export const Header = () => { const [isDrawerOpen, setIsDrawerOpen] = useState(false); const burgerMenuRef = useRef(null); + const pathname = usePathname(); + useOutsideClick( burgerMenuRef, useCallback(() => setIsDrawerOpen(false), []), ); + const toggleDrawer = () => { + setIsDrawerOpen((prevIsOpenState) => !prevIsOpenState); + }; + return (
@@ -99,9 +96,7 @@ export const Header = () => { className={`ml-1 btn btn-ghost ${ isDrawerOpen ? "hover:bg-secondary" : "hover:bg-transparent" }`} - onClick={() => { - setIsDrawerOpen((prevIsOpenState) => !prevIsOpenState); - }} + onClick={toggleDrawer} > @@ -144,4 +139,4 @@ export const Header = () => {
); -}; \ No newline at end of file +}; diff --git a/packages/nextjs/components/ScaffoldStarkAppWithProviders.tsx b/packages/nextjs/components/ScaffoldStarkAppWithProviders.tsx index 29cc7420..f0d04200 100644 --- a/packages/nextjs/components/ScaffoldStarkAppWithProviders.tsx +++ b/packages/nextjs/components/ScaffoldStarkAppWithProviders.tsx @@ -32,11 +32,7 @@ const ScaffoldStarkApp = ({ children }: { children: React.ReactNode }) => { <>
-
- {children} -
+
{children}
diff --git a/packages/nextjs/components/SimpleNFT/MyHoldings.tsx b/packages/nextjs/components/SimpleNFT/MyHoldings.tsx index 12ac1b31..09b825ce 100644 --- a/packages/nextjs/components/SimpleNFT/MyHoldings.tsx +++ b/packages/nextjs/components/SimpleNFT/MyHoldings.tsx @@ -2,10 +2,12 @@ import { useEffect, useState } from "react"; import { NFTCard } from "./NFTcard"; +import { useAccount } from "@starknet-react/core"; +import { useScaffoldContract } from "~~/hooks/scaffold-stark/useScaffoldContract"; +import { useScaffoldContractRead } from "~~/hooks/scaffold-stark/useScaffoldContractRead"; import { notification } from "~~/utils/scaffold-stark"; -import nftsMetadata, { - NFTMetaData, -} from "~~/utils/scaffold-stark/simpleNFT/nftsMetadata"; +import { getMetadataFromIPFS } from "~~/utils/scaffold-stark/simpleNFT/ipfs-fetch"; +import { NFTMetaData } from "~~/utils/scaffold-stark/simpleNFT/nftsMetadata"; export interface Collectible extends Partial { id: number; @@ -14,13 +16,92 @@ export interface Collectible extends Partial { } export const MyHoldings = () => { + const { address: connectedAddress } = useAccount(); + const [myAllCollectibles, setMyAllCollectibles] = useState([]); + const [allCollectiblesLoading, setAllCollectiblesLoading] = useState(false); + + const { data: yourCollectibleContract } = useScaffoldContract({ + contractName: "Challenge0", + }); + + // console.log(connectedAddress) + const { data: myTotalBalance } = useScaffoldContractRead({ + contractName: "Challenge0", + functionName: "balance_of", + args: [connectedAddress], + }); + + console.log(myTotalBalance); + + useEffect(() => { + const updateMyCollectibles = async (): Promise => { + if ( + myTotalBalance === undefined || + yourCollectibleContract === undefined || + connectedAddress === undefined + ) + return; + + setAllCollectiblesLoading(true); + const collectibleUpdate: Collectible[] = []; + const totalBalance = parseInt(myTotalBalance.toString()); + for (let tokenIndex = 0; tokenIndex < totalBalance; tokenIndex++) { + try { + const tokenId = + await yourCollectibleContract.read.tokenOfOwnerByIndex([ + connectedAddress, + BigInt(tokenIndex), + ]); + + const tokenURI = await yourCollectibleContract.read.tokenURI([ + tokenId, + ]); + + const ipfsHash = tokenURI.replace("https://ipfs.io/ipfs/", ""); + + const nftMetadata: NFTMetaData = await getMetadataFromIPFS(ipfsHash); + + collectibleUpdate.push({ + id: parseInt(tokenId.toString()), + uri: tokenURI, + owner: connectedAddress, + ...nftMetadata, + }); + } catch (e) { + notification.error("Error fetching all collectibles"); + setAllCollectiblesLoading(false); + console.log(e); + } + } + collectibleUpdate.sort((a, b) => a.id - b.id); + setMyAllCollectibles(collectibleUpdate); + setAllCollectiblesLoading(false); + }; + + updateMyCollectibles(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [connectedAddress, myTotalBalance]); + + if (allCollectiblesLoading) + return ( +
+ +
+ ); + return ( <> -
- {nftsMetadata.map((item, index) => ( - - ))} -
+ {myAllCollectibles.length === 0 ? ( +
+
No NFTs found
+
+ ) : ( +
+ {myAllCollectibles.map((item) => ( + + ))} +
+ )} ); }; diff --git a/packages/nextjs/components/SimpleNFT/NFTcard.tsx b/packages/nextjs/components/SimpleNFT/NFTcard.tsx index f6b887a3..15698ea8 100644 --- a/packages/nextjs/components/SimpleNFT/NFTcard.tsx +++ b/packages/nextjs/components/SimpleNFT/NFTcard.tsx @@ -1,8 +1,20 @@ import { useState } from "react"; import { NFTMetaData } from "~~/utils/scaffold-stark/simpleNFT/nftsMetadata"; import ButtonStyle from "../ButtonStyle/ButtonStyle"; +import { useScaffoldContractWrite } from "~~/hooks/scaffold-stark/useScaffoldContractWrite"; +import { Collectible } from "./MyHoldings"; +import { Address } from "../scaffold-stark"; +import { AddressInput } from "../scaffold-stark"; +export const NFTCard = ({ nft }: { nft: Collectible }) => { + const [transferToAddress, setTransferToAddress] = useState(""); -export const NFTCard = ({ nft }: any) => { + // const { writeAsync: transferNFT } = useScaffoldContractWrite({ + // contractName: "Challenge0", + // functionName: "transfer_from", + // args: [nft.owner, transferToAddress, BigInt(nft.id.toString())], + // }); + + // console.log(transferNFT) return (
@@ -28,15 +40,16 @@ export const NFTCard = ({ nft }: any) => {
Owner : - {/*
*/} + {nft.owner} + {/*
*/}
Transfer To: - {/* setTransferToAddress(newValue)} - /> */} + onChange={(newValue) => setTransferToAddress(newValue)} + />
Send diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index 25751cee..78430734 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -3,6 +3,1250 @@ * You should not edit it manually or your changes might be overwritten. */ -const deployedContracts = {} as const; +const deployedContracts = { + devnet: { + Challenge0: { + address: + "0x020ce7d9d6a2182c5bccad7ef9032eae02f8d3d36764308cbceeb8cb15b60753", + abi: [ + { + type: "impl", + name: "WrappedIERC721MetadataImpl", + interface_name: + "openzeppelin::token::erc721::interface::IERC721Metadata", + }, + { + type: "struct", + name: "core::byte_array::ByteArray", + members: [ + { + name: "data", + type: "core::array::Array::", + }, + { + name: "pending_word", + type: "core::felt252", + }, + { + name: "pending_word_len", + type: "core::integer::u32", + }, + ], + }, + { + type: "struct", + name: "core::integer::u256", + members: [ + { + name: "low", + type: "core::integer::u128", + }, + { + name: "high", + type: "core::integer::u128", + }, + ], + }, + { + type: "interface", + name: "openzeppelin::token::erc721::interface::IERC721Metadata", + items: [ + { + type: "function", + name: "name", + inputs: [], + outputs: [ + { + type: "core::byte_array::ByteArray", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "symbol", + inputs: [], + outputs: [ + { + type: "core::byte_array::ByteArray", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "token_uri", + inputs: [ + { + name: "token_id", + type: "core::integer::u256", + }, + ], + outputs: [ + { + type: "core::byte_array::ByteArray", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "impl", + name: "Challenge0Impl", + interface_name: "contracts::challenge0::IChallenge0", + }, + { + type: "interface", + name: "contracts::challenge0::IChallenge0", + items: [ + { + type: "function", + name: "mint_item", + inputs: [ + { + name: "recipient", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "uri", + type: "core::byte_array::ByteArray", + }, + ], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "external", + }, + { + type: "function", + name: "token_id_counter", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "impl", + name: "ERC721Impl", + interface_name: "openzeppelin::token::erc721::interface::IERC721", + }, + { + type: "struct", + name: "core::array::Span::", + members: [ + { + name: "snapshot", + type: "@core::array::Array::", + }, + ], + }, + { + type: "enum", + name: "core::bool", + variants: [ + { + name: "False", + type: "()", + }, + { + name: "True", + type: "()", + }, + ], + }, + { + type: "interface", + name: "openzeppelin::token::erc721::interface::IERC721", + items: [ + { + type: "function", + name: "balance_of", + inputs: [ + { + name: "account", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "owner_of", + inputs: [ + { + name: "token_id", + type: "core::integer::u256", + }, + ], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "safe_transfer_from", + inputs: [ + { + name: "from", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "token_id", + type: "core::integer::u256", + }, + { + name: "data", + type: "core::array::Span::", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "transfer_from", + inputs: [ + { + name: "from", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "token_id", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "approve", + inputs: [ + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "token_id", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "set_approval_for_all", + inputs: [ + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "approved", + type: "core::bool", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "get_approved", + inputs: [ + { + name: "token_id", + type: "core::integer::u256", + }, + ], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "is_approved_for_all", + inputs: [ + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + outputs: [ + { + type: "core::bool", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "impl", + name: "OwnableImpl", + interface_name: "openzeppelin::access::ownable::interface::IOwnable", + }, + { + type: "interface", + name: "openzeppelin::access::ownable::interface::IOwnable", + items: [ + { + type: "function", + name: "owner", + inputs: [], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "transfer_ownership", + inputs: [ + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "renounce_ownership", + inputs: [], + outputs: [], + state_mutability: "external", + }, + ], + }, + { + type: "constructor", + name: "constructor", + inputs: [ + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc721::erc721::ERC721Component::Transfer", + kind: "struct", + members: [ + { + name: "from", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "token_id", + type: "core::integer::u256", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc721::erc721::ERC721Component::Approval", + kind: "struct", + members: [ + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "approved", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "token_id", + type: "core::integer::u256", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc721::erc721::ERC721Component::ApprovalForAll", + kind: "struct", + members: [ + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "approved", + type: "core::bool", + kind: "data", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc721::erc721::ERC721Component::Event", + kind: "enum", + variants: [ + { + name: "Transfer", + type: "openzeppelin::token::erc721::erc721::ERC721Component::Transfer", + kind: "nested", + }, + { + name: "Approval", + type: "openzeppelin::token::erc721::erc721::ERC721Component::Approval", + kind: "nested", + }, + { + name: "ApprovalForAll", + type: "openzeppelin::token::erc721::erc721::ERC721Component::ApprovalForAll", + kind: "nested", + }, + ], + }, + { + type: "event", + name: "openzeppelin::introspection::src5::SRC5Component::Event", + kind: "enum", + variants: [], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferred", + kind: "struct", + members: [ + { + name: "previous_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferStarted", + kind: "struct", + members: [ + { + name: "previous_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "new_owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::access::ownable::ownable::OwnableComponent::Event", + kind: "enum", + variants: [ + { + name: "OwnershipTransferred", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferred", + kind: "nested", + }, + { + name: "OwnershipTransferStarted", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::OwnershipTransferStarted", + kind: "nested", + }, + ], + }, + { + type: "event", + name: "contracts::challenge0::Challenge0::Event", + kind: "enum", + variants: [ + { + name: "ERC721Event", + type: "openzeppelin::token::erc721::erc721::ERC721Component::Event", + kind: "flat", + }, + { + name: "SRC5Event", + type: "openzeppelin::introspection::src5::SRC5Component::Event", + kind: "flat", + }, + { + name: "OwnableEvent", + type: "openzeppelin::access::ownable::ownable::OwnableComponent::Event", + kind: "flat", + }, + ], + }, + ], + }, + ExampleExternalContract: { + address: + "0x023f931b2839acf2cfb1665ba795f7a1ef9244d9052b8462029a3e97de0d5c50", + abi: [ + { + type: "impl", + name: "ExampleExternalContractImpl", + interface_name: + "contracts::exampleExternalContract::IExampleExternalContract", + }, + { + type: "struct", + name: "core::integer::u256", + members: [ + { + name: "low", + type: "core::integer::u128", + }, + { + name: "high", + type: "core::integer::u128", + }, + ], + }, + { + type: "enum", + name: "core::bool", + variants: [ + { + name: "False", + type: "()", + }, + { + name: "True", + type: "()", + }, + ], + }, + { + type: "interface", + name: "contracts::exampleExternalContract::IExampleExternalContract", + items: [ + { + type: "function", + name: "complete", + inputs: [ + { + name: "amount", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "completed", + inputs: [], + outputs: [ + { + type: "core::bool", + }, + ], + state_mutability: "external", + }, + ], + }, + { + type: "event", + name: "contracts::exampleExternalContract::ExampleExternalContract::Event", + kind: "enum", + variants: [], + }, + ], + }, + Challenge1: { + address: + "0x0592f23b0088ec581863d2627567f3166830ae3d23e32e27fe8204a758611dac", + abi: [ + { + type: "impl", + name: "Challenge1Impl", + interface_name: "contracts::challenge1::IChallenge1", + }, + { + type: "struct", + name: "core::integer::u256", + members: [ + { + name: "low", + type: "core::integer::u128", + }, + { + name: "high", + type: "core::integer::u128", + }, + ], + }, + { + type: "enum", + name: "core::bool", + variants: [ + { + name: "False", + type: "()", + }, + { + name: "True", + type: "()", + }, + ], + }, + { + type: "interface", + name: "contracts::challenge1::IChallenge1", + items: [ + { + type: "function", + name: "execute", + inputs: [], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "stake", + inputs: [ + { + name: "amount", + type: "core::integer::u256", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "withdraw", + inputs: [], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "balances", + inputs: [ + { + name: "account", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "completed", + inputs: [], + outputs: [ + { + type: "core::bool", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "deadline", + inputs: [], + outputs: [ + { + type: "core::integer::u64", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "example_external_contract", + inputs: [], + outputs: [ + { + type: "core::starknet::contract_address::ContractAddress", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "open_for_withdraw", + inputs: [], + outputs: [ + { + type: "core::bool", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "threshold", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "total_balance", + inputs: [], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "time_left", + inputs: [], + outputs: [ + { + type: "core::integer::u64", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "constructor", + name: "constructor", + inputs: [ + { + name: "external_contract_address", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "eth_contract_address", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + }, + { + type: "event", + name: "contracts::challenge1::Challenge1::Event", + kind: "enum", + variants: [], + }, + ], + }, + PresetERC1155: { + address: + "0x010ec2536555c655f715c0ea462176cd24bbcee41653a1da5c36f08b5c2ec6eb", + abi: [ + { + type: "impl", + name: "ERC1155Impl", + interface_name: "openzeppelin::token::erc1155::interface::IERC1155", + }, + { + type: "struct", + name: "core::integer::u256", + members: [ + { + name: "low", + type: "core::integer::u128", + }, + { + name: "high", + type: "core::integer::u128", + }, + ], + }, + { + type: "struct", + name: "core::array::Span::", + members: [ + { + name: "snapshot", + type: "@core::array::Array::", + }, + ], + }, + { + type: "struct", + name: "core::array::Span::", + members: [ + { + name: "snapshot", + type: "@core::array::Array::", + }, + ], + }, + { + type: "struct", + name: "core::array::Span::", + members: [ + { + name: "snapshot", + type: "@core::array::Array::", + }, + ], + }, + { + type: "enum", + name: "core::bool", + variants: [ + { + name: "False", + type: "()", + }, + { + name: "True", + type: "()", + }, + ], + }, + { + type: "interface", + name: "openzeppelin::token::erc1155::interface::IERC1155", + items: [ + { + type: "function", + name: "balance_of", + inputs: [ + { + name: "account", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "token_id", + type: "core::integer::u256", + }, + ], + outputs: [ + { + type: "core::integer::u256", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "balance_of_batch", + inputs: [ + { + name: "accounts", + type: "core::array::Span::", + }, + { + name: "token_ids", + type: "core::array::Span::", + }, + ], + outputs: [ + { + type: "core::array::Span::", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "safe_transfer_from", + inputs: [ + { + name: "from", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "token_id", + type: "core::integer::u256", + }, + { + name: "value", + type: "core::integer::u256", + }, + { + name: "data", + type: "core::array::Span::", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "safe_batch_transfer_from", + inputs: [ + { + name: "from", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "token_ids", + type: "core::array::Span::", + }, + { + name: "values", + type: "core::array::Span::", + }, + { + name: "data", + type: "core::array::Span::", + }, + ], + outputs: [], + state_mutability: "external", + }, + { + type: "function", + name: "is_approved_for_all", + inputs: [ + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + }, + ], + outputs: [ + { + type: "core::bool", + }, + ], + state_mutability: "view", + }, + { + type: "function", + name: "set_approval_for_all", + inputs: [ + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "approved", + type: "core::bool", + }, + ], + outputs: [], + state_mutability: "external", + }, + ], + }, + { + type: "impl", + name: "ERC1155MetadataURIImpl", + interface_name: + "openzeppelin::token::erc1155::interface::IERC1155MetadataURI", + }, + { + type: "struct", + name: "core::byte_array::ByteArray", + members: [ + { + name: "data", + type: "core::array::Array::", + }, + { + name: "pending_word", + type: "core::felt252", + }, + { + name: "pending_word_len", + type: "core::integer::u32", + }, + ], + }, + { + type: "interface", + name: "openzeppelin::token::erc1155::interface::IERC1155MetadataURI", + items: [ + { + type: "function", + name: "uri", + inputs: [ + { + name: "token_id", + type: "core::integer::u256", + }, + ], + outputs: [ + { + type: "core::byte_array::ByteArray", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "impl", + name: "SRC5Impl", + interface_name: "openzeppelin::introspection::interface::ISRC5", + }, + { + type: "interface", + name: "openzeppelin::introspection::interface::ISRC5", + items: [ + { + type: "function", + name: "supports_interface", + inputs: [ + { + name: "interface_id", + type: "core::felt252", + }, + ], + outputs: [ + { + type: "core::bool", + }, + ], + state_mutability: "view", + }, + ], + }, + { + type: "constructor", + name: "constructor", + inputs: [ + { + name: "base_uri", + type: "core::byte_array::ByteArray", + }, + { + name: "recipient", + type: "core::starknet::contract_address::ContractAddress", + }, + { + name: "token_ids", + type: "core::array::Span::", + }, + { + name: "values", + type: "core::array::Span::", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc1155::erc1155::ERC1155Component::TransferSingle", + kind: "struct", + members: [ + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "from", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "id", + type: "core::integer::u256", + kind: "data", + }, + { + name: "value", + type: "core::integer::u256", + kind: "data", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc1155::erc1155::ERC1155Component::TransferBatch", + kind: "struct", + members: [ + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "from", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "to", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "ids", + type: "core::array::Span::", + kind: "data", + }, + { + name: "values", + type: "core::array::Span::", + kind: "data", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc1155::erc1155::ERC1155Component::ApprovalForAll", + kind: "struct", + members: [ + { + name: "owner", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "operator", + type: "core::starknet::contract_address::ContractAddress", + kind: "key", + }, + { + name: "approved", + type: "core::bool", + kind: "data", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc1155::erc1155::ERC1155Component::URI", + kind: "struct", + members: [ + { + name: "value", + type: "core::byte_array::ByteArray", + kind: "data", + }, + { + name: "id", + type: "core::integer::u256", + kind: "key", + }, + ], + }, + { + type: "event", + name: "openzeppelin::token::erc1155::erc1155::ERC1155Component::Event", + kind: "enum", + variants: [ + { + name: "TransferSingle", + type: "openzeppelin::token::erc1155::erc1155::ERC1155Component::TransferSingle", + kind: "nested", + }, + { + name: "TransferBatch", + type: "openzeppelin::token::erc1155::erc1155::ERC1155Component::TransferBatch", + kind: "nested", + }, + { + name: "ApprovalForAll", + type: "openzeppelin::token::erc1155::erc1155::ERC1155Component::ApprovalForAll", + kind: "nested", + }, + { + name: "URI", + type: "openzeppelin::token::erc1155::erc1155::ERC1155Component::URI", + kind: "nested", + }, + ], + }, + { + type: "event", + name: "openzeppelin::introspection::src5::SRC5Component::Event", + kind: "enum", + variants: [], + }, + { + type: "event", + name: "contracts::presetERC1155::PresetERC1155::Event", + kind: "enum", + variants: [ + { + name: "ERC1155Event", + type: "openzeppelin::token::erc1155::erc1155::ERC1155Component::Event", + kind: "flat", + }, + { + name: "SRC5Event", + type: "openzeppelin::introspection::src5::SRC5Component::Event", + kind: "flat", + }, + ], + }, + ], + }, + }, +} as const; export default deployedContracts; diff --git a/packages/nextjs/scaffold.config.ts b/packages/nextjs/scaffold.config.ts index f7506546..4ce7354a 100644 --- a/packages/nextjs/scaffold.config.ts +++ b/packages/nextjs/scaffold.config.ts @@ -9,7 +9,7 @@ export type ScaffoldConfig = { }; const scaffoldConfig = { - targetNetworks: [chains.sepolia], + targetNetworks: [chains.devnet], // Only show the Burner Wallet when running on sefolia onlyLocalBurnerWallet: false, rpcProviderUrl: process.env.NEXT_PUBLIC_PROVIDER_URL || "", diff --git a/packages/nextjs/styles/globals.css b/packages/nextjs/styles/globals.css index 42e6f553..3fb55aec 100644 --- a/packages/nextjs/styles/globals.css +++ b/packages/nextjs/styles/globals.css @@ -30,94 +30,3 @@ p { .btn.btn-ghost { @apply shadow-none; } - -.bg-gradient-linear { - background: linear-gradient( - 180deg, - rgba(159, 87, 131, 1) 0%, - rgba(69, 57, 114, 1) 100% - ); -} -.bg-landing { - background-image: url("/home_header_clouds.png"); - background-position: center top; - background-repeat: repeat-x; - background-size: auto 300px; -} -.footer-header-landing { - background-image: url("/footer-main-landing.png"); - background-size: contain; - background-repeat: repeat-x; - width: 100%; - height: 130px; -} -.bg-banner-join { - background-image: url("/bgBanner_join.png"); - background-position: center; - background-size: contain; - background-repeat: no-repeat; - width: 100%; -} - -.bg-ft-join { - background-image: url("/ft-join.png"); - background-position: bottom; - background-size: contain; - background-repeat: repeat-x; - width: 100%; -} - -.traslate-circule { - transform: translateX(calc(-50% - 2px)); -} - -@media (max-width: 639px) { - .footer-header-landing { - background-size: auto 70px; - width: 100%; - height: 70px; - } - .bg-landing { - background-size: contain; - } - .bg-ft-join { - background-size: auto 102px; - display: flex; - font-size: 16px; - text-align: center; - padding: 0; - } -} -@media (min-width: 640px) and (max-width: 768px) { - .footer-header-landing { - background-size: auto 70px; - width: 100%; - height: 70px; - } - .bg-landing { - background-size: contain; - } - .bg-ft-join { - background-size: auto 102px; - display: flex; - font-size: 16px; - text-align: center; - padding: 0; - } -} - -@media (min-width: 769px) and (max-width: 1023px) { - .footer-header-landing { - background-size: auto 84px; - width: 100%; - height: 90px; - } - .bg-landing { - background-size: contain; - } - .bg-ft-join { - display: flex; - font-size: 14px; - text-align: center; - } -} diff --git a/packages/nextjs/tailwind.config.ts b/packages/nextjs/tailwind.config.ts index 310609a7..ce4020af 100644 --- a/packages/nextjs/tailwind.config.ts +++ b/packages/nextjs/tailwind.config.ts @@ -130,11 +130,6 @@ module.exports = { animation: { "pulse-fast": "pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite", }, - screens: { - sm: { max: "639px" }, - md: { min: "640px", max: "767px" }, - lg: { min: "768px", max: "1023px" }, - }, fontFamily: { sans: ["Space Grotesk", "sans-serif"], }, diff --git a/packages/nextjs/utils/scaffold-stark/simpleNFT/ipfs-fetch.ts b/packages/nextjs/utils/scaffold-stark/simpleNFT/ipfs-fetch.ts new file mode 100644 index 00000000..78b745f9 --- /dev/null +++ b/packages/nextjs/utils/scaffold-stark/simpleNFT/ipfs-fetch.ts @@ -0,0 +1,28 @@ +const fetchFromApi = ({ + path, + method, + body, +}: { + path: string; + method: string; + body?: object; +}) => + fetch(path, { + method, + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }) + .then((response) => response.json()) + .catch((error) => console.error("Error:", error)); + +export const addToIPFS = (yourJSON: object) => + fetchFromApi({ path: "utils/api/ipfs/add", method: "Post", body: yourJSON }); + +export const getMetadataFromIPFS = (ipfsHash: string) => + fetchFromApi({ + path: "utils/api/ipfs/get-metadata", + method: "Post", + body: { ipfsHash }, + }); diff --git a/packages/nextjs/utils/scaffold-stark/simpleNFT/ipfs.ts b/packages/nextjs/utils/scaffold-stark/simpleNFT/ipfs.ts new file mode 100644 index 00000000..3e9b2be9 --- /dev/null +++ b/packages/nextjs/utils/scaffold-stark/simpleNFT/ipfs.ts @@ -0,0 +1,35 @@ +import { create } from "kubo-rpc-client"; + +const PROJECT_ID = "2GajDLTC6y04qsYsoDRq9nGmWwK"; +const PROJECT_SECRET = "48c62c6b3f82d2ecfa2cbe4c90f97037"; +const PROJECT_ID_SECRECT = `${PROJECT_ID}:${PROJECT_SECRET}`; + +export const ipfsClient = create({ + host: "ipfs.infura.io", + port: 5001, + protocol: "https", + headers: { + Authorization: `Basic ${Buffer.from(PROJECT_ID_SECRECT).toString("base64")}`, + }, +}); + +export async function getNFTMetadataFromIPFS(ipfsHash: string) { + for await (const file of ipfsClient.get(ipfsHash)) { + // The file is of type unit8array so we need to convert it to string + const content = new TextDecoder().decode(file); + // Remove any leading/trailing whitespace + const trimmedContent = content.trim(); + // Find the start and end index of the JSON object + const startIndex = trimmedContent.indexOf("{"); + const endIndex = trimmedContent.lastIndexOf("}") + 1; + // Extract the JSON object string + const jsonObjectString = trimmedContent.slice(startIndex, endIndex); + try { + const jsonObject = JSON.parse(jsonObjectString); + return jsonObject; + } catch (error) { + console.log("Error parsing JSON:", error); + return undefined; + } + } +} diff --git a/yarn.lock b/yarn.lock index 5bf1045a..317fa2cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1618,8 +1618,8 @@ __metadata: react-copy-to-clipboard: ^5.1.0 react-dom: ^18 react-hot-toast: ^2.4.1 - react-markdown: ^9.0.1 react-json-view: ^1.21.3 + react-markdown: ^9.0.1 starknet: 5.25.0 starknet-dev: "npm:starknet@6.7.0" tailwindcss: ^3.3.0 @@ -1655,8 +1655,6 @@ __metadata: linkType: hard "@starknet-react/core@npm:^2.3.0": - version: 2.6.1 - resolution: "@starknet-react/core@npm:2.6.1" version: 2.6.1 resolution: "@starknet-react/core@npm:2.6.1" dependencies: @@ -1670,7 +1668,6 @@ __metadata: react: ^18.0 starknet: ^5.25.0 checksum: a6b02ad8827a5a769bc46c010157df51fd6a3ff43356513a4ef6d35a08b10f9e738444b3964618bc9cd630cb55403feb9169a470beba027ff2522e998e21d4ab - checksum: a6b02ad8827a5a769bc46c010157df51fd6a3ff43356513a4ef6d35a08b10f9e738444b3964618bc9cd630cb55403feb9169a470beba027ff2522e998e21d4ab languageName: node linkType: hard @@ -1859,20 +1856,15 @@ __metadata: linkType: hard "@types/react-dom@npm:^18": - version: 18.2.25 - resolution: "@types/react-dom@npm:18.2.25" version: 18.2.25 resolution: "@types/react-dom@npm:18.2.25" dependencies: "@types/react": "*" checksum: 85f9278d6456c6cdc76da6806a33b472588cdd029b08dde32e8b5636b25a3eae529b4ac2e08c848a3d7ca44e4e97ee9a3df406c96fa0768de935c8eed6e07590 - checksum: 85f9278d6456c6cdc76da6806a33b472588cdd029b08dde32e8b5636b25a3eae529b4ac2e08c848a3d7ca44e4e97ee9a3df406c96fa0768de935c8eed6e07590 languageName: node linkType: hard "@types/react@npm:*, @types/react@npm:^18": - version: 18.2.79 - resolution: "@types/react@npm:18.2.79" version: 18.2.79 resolution: "@types/react@npm:18.2.79" dependencies: @@ -1893,7 +1885,6 @@ __metadata: version: 2.0.10 resolution: "@types/unist@npm:2.0.10" checksum: e2924e18dedf45f68a5c6ccd6015cd62f1643b1b43baac1854efa21ae9e70505db94290434a23da1137d9e31eb58e54ca175982005698ac37300a1c889f6c4aa - checksum: 85aa96e0e88725c84d8fc5f04f10a4da6a1f507dde33557ac9cc211414756867721264bfefd9e02bae1288ce2905351d949b652b931e734ea24519ee5c625138 languageName: node linkType: hard @@ -2779,9 +2770,6 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001579, caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001599": - version: 1.0.30001610 - resolution: "caniuse-lite@npm:1.0.30001610" - checksum: 580c7367aafd7e524f4e3f0e8b22ac08d081a4d44ceece211f1758e214df9a87961750fb1e1ee28a2cd2830f0daf3edafe5e1d87bf1eefbbe7c6cf3d00e2979d version: 1.0.30001611 resolution: "caniuse-lite@npm:1.0.30001611" checksum: c5beb4a0aaabe24b01a577122c61e20ca0614d2e3adfd2e4de8dbdb8529eb9dba9922be8fd8be9eba48b6cadaada0b338aa3e0d0a17f42f6b3e9a614492c029a @@ -3080,8 +3068,6 @@ __metadata: linkType: hard "daisyui@npm:^4.7.3": - version: 4.10.2 - resolution: "daisyui@npm:4.10.2" version: 4.10.2 resolution: "daisyui@npm:4.10.2" dependencies: @@ -3090,7 +3076,6 @@ __metadata: picocolors: ^1 postcss-js: ^4 checksum: 520571f366eb74ed631b17be54254d6affb345a3eaab21ad0791cdc98d87372b7327738bbc4f4a100b56702610b77687eaec6952994bd3315cb8b8dd8e1fa5c9 - checksum: 520571f366eb74ed631b17be54254d6affb345a3eaab21ad0791cdc98d87372b7327738bbc4f4a100b56702610b77687eaec6952994bd3315cb8b8dd8e1fa5c9 languageName: node linkType: hard @@ -3328,12 +3313,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.668": - version: 1.4.738 - resolution: "electron-to-chromium@npm:1.4.738" - checksum: 9adef299a9115f507389d2918162e12ab9dc8bff5e0b372bf05d795539c3b5ffa3ff029ab3db4e2d4d3dbebd38ec8bb931adc3e8f987170f93926d684b94a16c - version: 1.4.744 - resolution: "electron-to-chromium@npm:1.4.744" - checksum: 917a178500bd8a78ae73c2ad9e71981922ec47e443ca1dfdfbc7a343334e6dfbbaa28e612313710c35b6538b1332dc4d14dd533eb274a587ffad79b3f9908989 + version: 1.4.745 + resolution: "electron-to-chromium@npm:1.4.745" + checksum: f73b576108863cad160deb22b8e8c6754a8b16b22cda90cfce038a755f886be9c03fb8360bbd7c9d28ddd184800d0d6bd430a11f9289316145f0b28321dfe71d languageName: node linkType: hard @@ -3893,11 +3875,11 @@ __metadata: linkType: hard "eslint-plugin-react-hooks@npm:^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": - version: 4.6.0 - resolution: "eslint-plugin-react-hooks@npm:4.6.0" + version: 5.0.0-canary-7118f5dd7-20230705 + resolution: "eslint-plugin-react-hooks@npm:5.0.0-canary-7118f5dd7-20230705" peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 23001801f14c1d16bf0a837ca7970d9dd94e7b560384b41db378b49b6e32dc43d6e2790de1bd737a652a86f81a08d6a91f402525061b47719328f586a57e86c3 + checksum: 20e334e60bf5e56cf9f760598411847525c3ff826e6ae7757c8efdc60b33d47a97ddbe1b94ce95956ea9f7bbef37995b19c716be50bd44e6a1e789cba08b6224 languageName: node linkType: hard @@ -7061,27 +7043,6 @@ __metadata: languageName: node linkType: hard -"react-markdown@npm:^9.0.1": - version: 9.0.1 - resolution: "react-markdown@npm:9.0.1" - dependencies: - "@types/hast": ^3.0.0 - devlop: ^1.0.0 - hast-util-to-jsx-runtime: ^2.0.0 - html-url-attributes: ^3.0.0 - mdast-util-to-hast: ^13.0.0 - remark-parse: ^11.0.0 - remark-rehype: ^11.0.0 - unified: ^11.0.0 - unist-util-visit: ^5.0.0 - vfile: ^6.0.0 - peerDependencies: - "@types/react": ">=18" - react: ">=18" - checksum: ca1daa650d48b84a5a9771683cdb3f3d2d418247ce0faf73ede3207c65f2a21cdebb9df37afda67f6fc8f0f0a7b9ce00eb239781954a4d6c7ad88ea4df068add - languageName: node - linkType: hard - "react-json-view@npm:^1.21.3": version: 1.21.3 resolution: "react-json-view@npm:1.21.3" @@ -7104,6 +7065,27 @@ __metadata: languageName: node linkType: hard +"react-markdown@npm:^9.0.1": + version: 9.0.1 + resolution: "react-markdown@npm:9.0.1" + dependencies: + "@types/hast": ^3.0.0 + devlop: ^1.0.0 + hast-util-to-jsx-runtime: ^2.0.0 + html-url-attributes: ^3.0.0 + mdast-util-to-hast: ^13.0.0 + remark-parse: ^11.0.0 + remark-rehype: ^11.0.0 + unified: ^11.0.0 + unist-util-visit: ^5.0.0 + vfile: ^6.0.0 + peerDependencies: + "@types/react": ">=18" + react: ">=18" + checksum: ca1daa650d48b84a5a9771683cdb3f3d2d418247ce0faf73ede3207c65f2a21cdebb9df37afda67f6fc8f0f0a7b9ce00eb239781954a4d6c7ad88ea4df068add + languageName: node + linkType: hard + "react-remove-scroll-bar@npm:^2.3.3": version: 2.3.6 resolution: "react-remove-scroll-bar@npm:2.3.6"