[Update] Fix ERC721 delayed reveal detection and refactor related components (#4503)

FIX: DASH-218

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on fixing ERC721 delayed reveal detection and improving lazy minting functionality.

### Detailed summary
- Fixed ERC721 delayed reveal detection
- Updated functions related to lazy minting
- Improved detection of supported methods in ERC721 extensions

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
This commit is contained in:
jnsdls
2024-09-10 19:40:18 +00:00
parent 50212762f3
commit 8636c28d0f
11 changed files with 81 additions and 34 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---
fix erc721 delayed reveal detection
@@ -11,14 +11,14 @@ import { useReadContract, useSendAndConfirmTransaction } from "thirdweb/react";
import { Button, Drawer } from "tw-components";
interface BatchLazyMintButtonProps {
isRevealable: boolean;
canCreateDelayedRevealBatch: boolean;
contract: ThirdwebContract;
isErc721: boolean;
}
export const BatchLazyMintButton: React.FC<BatchLazyMintButtonProps> = ({
contract,
isRevealable,
canCreateDelayedRevealBatch,
isErc721,
}) => {
const trackEvent = useTrack();
@@ -112,7 +112,7 @@ export const BatchLazyMintButton: React.FC<BatchLazyMintButtonProps> = ({
}
}}
nextTokenIdToMint={nextTokenIdToMintQuery.data || 0n}
isRevealable={isRevealable}
canCreateDelayedRevealBatch={canCreateDelayedRevealBatch}
/>
</Drawer>
<Button
@@ -18,6 +18,7 @@ export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
const batchesQuery = useReadContract(getBatchesToReveal, {
contract,
});
console.log("*** batches", batchesQuery);
return batchesQuery.data?.length ? (
<MinterOnly contract={contract}>
<Drawer
@@ -68,9 +68,9 @@ export const ContractNFTPage: React.FC<NftOverviewPageProps> = ({
return ERC1155Ext.isGetNFTsSupported(functionSelectorQuery.data);
})();
const isRevealable = ERC721Ext.isGetBaseURICountSupported(
functionSelectorQuery.data,
);
const isRevealable = ERC721Ext.isRevealSupported(functionSelectorQuery.data);
const canCreateDelayedRevealBatch =
ERC721Ext.isCreateDelayedRevealBatchSupported(functionSelectorQuery.data);
return (
<div className="flex flex-col gap-6">
@@ -96,7 +96,7 @@ export const ContractNFTPage: React.FC<NftOverviewPageProps> = ({
)}
{isLazyMintable && (
<BatchLazyMintButton
isRevealable={isRevealable}
canCreateDelayedRevealBatch={canCreateDelayedRevealBatch}
isErc721={isErc721}
contract={contract}
/>
@@ -160,8 +160,7 @@ function Inner({
return false;
})();
const isRevealable =
ERC721Ext.isGetBaseURICountSupported(functionSelectors);
const isRevealable = ERC721Ext.isRevealSupported(functionSelectors);
const needsReveal = batchesToReveal.data?.length;
const steps: Step[] = [
@@ -56,7 +56,7 @@ type SubmitType = DelayedSubmit | InstantSubmit;
interface BatchLazyMintEVMProps {
nextTokenIdToMint: bigint;
isRevealable: boolean;
canCreateDelayedRevealBatch: boolean;
onSubmit: (formData: SubmitType) => Promise<unknown>;
}
@@ -281,7 +281,10 @@ export const BatchLazyMint: ComponentWithChildren<BatchLazyMintProps> = (
</Heading>
</HStack>
</Flex>
<SelectReveal form={form} isRevealable={props.isRevealable} />
<SelectReveal
form={form}
canCreateDelayedRevealBatch={props.canCreateDelayedRevealBatch}
/>
{form.watch("revealType") && (
<>
<Checkbox {...form.register("shuffle")} mt={3}>
@@ -331,10 +334,13 @@ export const BatchLazyMint: ComponentWithChildren<BatchLazyMintProps> = (
interface SelectRevealProps {
form: ReturnType<typeof useBatchLazyMintForm>;
isRevealable: boolean;
canCreateDelayedRevealBatch: boolean;
}
const SelectReveal: React.FC<SelectRevealProps> = ({ form, isRevealable }) => {
const SelectReveal: React.FC<SelectRevealProps> = ({
form,
canCreateDelayedRevealBatch,
}) => {
const [show, setShow] = useState(false);
const imageUrl = useImageFileOrUrl(form.watch("placeHolder.image"));
@@ -356,7 +362,7 @@ const SelectReveal: React.FC<SelectRevealProps> = ({ form, isRevealable }) => {
description="Collectors will mint your placeholder image, then you reveal at a later time"
isActive={form.watch("revealType") === "delayed"}
onClick={() => form.setValue("revealType", "delayed")}
disabled={!isRevealable}
disabled={!canCreateDelayedRevealBatch}
disabledText="This contract doesn't implement Delayed Reveal"
/>
</Flex>
@@ -191,15 +191,17 @@ export {
export {
type CreateDelayedRevealBatchParams,
createDelayedRevealBatch,
isCreateDelayedRevealBatchSupported,
} from "../../extensions/erc721/lazyMinting/write/createDelayedRevealBatch.js";
export {
type RevealParams,
reveal,
isRevealSupported,
} from "../../extensions/erc721/lazyMinting/write/reveal.js";
export {
type BatchToReveal,
getBatchesToReveal,
isGetBaseURICountSupported,
isGetBatchesToRevealSupported,
} from "../../extensions/erc721/lazyMinting/read/getBatchesToReveal.js";
export {
updateMetadata,
@@ -49,23 +49,23 @@ export async function getBatchesToReveal(
const countRangeArray = Array.from(Array(Number(count)).keys());
const uriIndices = await Promise.all(
countRangeArray.map(async (batchId) => {
try {
return await GetBatchIdAtIndex.getBatchIdAtIndex({
const promiseAll = await Promise.allSettled([
GetBatchIdAtIndex.getBatchIdAtIndex({
contract: options.contract,
index: BigInt(batchId),
});
} catch {
try {
return await BaseURIIndicies.baseURIIndices({
contract: options.contract,
index: BigInt(batchId),
});
} catch {
throw new Error(
"Contract does not have `getBatchIdAtIndex` or `baseURIIndices`, which are required for `getBatchesToReveal`",
);
}
}),
BaseURIIndicies.baseURIIndices({
contract: options.contract,
index: BigInt(batchId),
}),
]);
const result = promiseAll.find((result) => result.status === "fulfilled");
if (!result) {
throw new Error(
"Contract does not have `getBatchIdAtIndex` or `baseURIIndices`, which are required for `getBatchesToReveal`",
);
}
return result.value;
}),
);
@@ -131,7 +131,7 @@ export async function getBatchesToReveal(
* const supported = isGetBatchesToRevealSupported(["0x..."]);
* ```
*/
export function isGetBaseURICountSupported(availableSelectors: string[]) {
export function isGetBatchesToRevealSupported(availableSelectors: string[]) {
return [
GetBaseURICount.isGetBaseURICountSupported(availableSelectors),
GetBatchIdAtIndex.isGetBatchIdAtIndexSupported(availableSelectors),
@@ -6,9 +6,18 @@ import { toHex } from "../../../../utils/encoding/hex.js";
import { keccak256 } from "../../../../utils/hashing/keccak256.js";
import { getBaseUriFromBatch } from "../../../../utils/ipfs.js";
import type { NFTInput } from "../../../../utils/nft/parseNft.js";
import { getBaseURICount } from "../../__generated__/IBatchMintMetadata/read/getBaseURICount.js";
import { encryptDecrypt } from "../../__generated__/IDelayedReveal/read/encryptDecrypt.js";
import { lazyMint as generatedLazyMint } from "../../__generated__/ILazyMint/write/lazyMint.js";
import {
getBaseURICount,
isGetBaseURICountSupported,
} from "../../__generated__/IBatchMintMetadata/read/getBaseURICount.js";
import {
encryptDecrypt,
isEncryptDecryptSupported,
} from "../../__generated__/IDelayedReveal/read/encryptDecrypt.js";
import {
lazyMint as generatedLazyMint,
isLazyMintSupported,
} from "../../__generated__/ILazyMint/write/lazyMint.js";
import { hashDelayedRevealPassword } from "../helpers/hashDelayedRevealBatch.js";
/**
@@ -123,3 +132,24 @@ export function createDelayedRevealBatch(
},
});
}
/**
* Checks if the `createDelayedRevealBatch` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `createDelayedRevealBatch` method is supported.
* @extension ERC721
* @example
* ```ts
* import { isCreateDelayedRevealBatchSupported } from "thirdweb/extensions/erc721";
* const supported = isCreateDelayedRevealBatchSupported(["0x..."]);
* ```
*/
export function isCreateDelayedRevealBatchSupported(
availableSelectors: string[],
) {
return [
isGetBaseURICountSupported(availableSelectors),
isEncryptDecryptSupported(availableSelectors),
isLazyMintSupported(availableSelectors),
].every(Boolean);
}
@@ -2,6 +2,8 @@ import type { BaseTransactionOptions } from "../../../../transaction/types.js";
import { reveal as generatedReveal } from "../../__generated__/IDelayedReveal/write/reveal.js";
import { hashDelayedRevealPassword } from "../helpers/hashDelayedRevealBatch.js";
export { isRevealSupported } from "../../__generated__/IDelayedReveal/write/reveal.js";
/**
* @extension ERC721
*/
+3 -1
View File
@@ -107,7 +107,9 @@ export async function uploadOrExtractURIs<
* @throws If the batch contains URIs with different base URIs or if no base URI is found.
* @internal
*/
export function getBaseUriFromBatch(uris: string[]): string {
export function getBaseUriFromBatch(uris: string | string[]): string {
// biome-ignore lint/style/noParameterAssign: lemme do my stuff
uris = Array.isArray(uris) ? uris : [uris];
const [base, ...rest] = uris.map((uri) => {
// remove query parameters
// biome-ignore lint/style/noParameterAssign: lemme do my stuff