diff --git a/docs/sdk.delayedreveal.featurename.md b/docs/sdk.delayedreveal.featurename.md
new file mode 100644
index 000000000..7cf1413d7
--- /dev/null
+++ b/docs/sdk.delayedreveal.featurename.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [@thirdweb-dev/sdk](./sdk.md) > [DelayedReveal](./sdk.delayedreveal.md) > [featureName](./sdk.delayedreveal.featurename.md)
+
+## DelayedReveal.featureName property
+
+Signature:
+
+```typescript
+featureName: "ERC721Revealable";
+```
diff --git a/docs/sdk.delayedreveal.md b/docs/sdk.delayedreveal.md
index 2001bcdbb..a499e7422 100644
--- a/docs/sdk.delayedreveal.md
+++ b/docs/sdk.delayedreveal.md
@@ -9,7 +9,7 @@ Handles delayed reveal logic
Signature:
```typescript
-export declare class DelayedReveal
+export declare class DelayedReveal
```
## Constructors
@@ -18,6 +18,12 @@ export declare class DelayedReveal
| --- | --- | --- |
| [(constructor)(contractWrapper, storage)](./sdk.delayedreveal._constructor_.md) | | Constructs a new instance of the DelayedReveal class |
+## Properties
+
+| Property | Modifiers | Type | Description |
+| --- | --- | --- | --- |
+| [featureName](./sdk.delayedreveal.featurename.md) | | "ERC721Revealable" | |
+
## Methods
| Method | Modifiers | Description |
diff --git a/docs/sdk.erc721.md b/docs/sdk.erc721.md
index 7547069af..7af46465c 100644
--- a/docs/sdk.erc721.md
+++ b/docs/sdk.erc721.md
@@ -41,6 +41,7 @@ await contract.nft.transfer(walletAddress, tokenId);
| [mint](./sdk.erc721.mint.md) | | [Erc721Mintable](./sdk.erc721mintable.md) \| undefined | |
| [options](./sdk.erc721.options.md) | | [SDKOptions](./sdk.sdkoptions.md) | |
| [query](./sdk.erc721.query.md) | | [Erc721Supply](./sdk.erc721supply.md) \| undefined | |
+| [revealer](./sdk.erc721.revealer.md) | | [DelayedReveal](./sdk.delayedreveal.md)<BaseDelayedRevealERC721 \| DropERC721> \| undefined | |
| [storage](./sdk.erc721.storage.md) | | [IStorage](./sdk.istorage.md) | |
## Methods
diff --git a/docs/sdk.erc721.revealer.md b/docs/sdk.erc721.revealer.md
new file mode 100644
index 000000000..479b07c8d
--- /dev/null
+++ b/docs/sdk.erc721.revealer.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [@thirdweb-dev/sdk](./sdk.md) > [Erc721](./sdk.erc721.md) > [revealer](./sdk.erc721.revealer.md)
+
+## Erc721.revealer property
+
+Signature:
+
+```typescript
+revealer: DelayedReveal | undefined;
+```
diff --git a/etc/sdk.api.md b/etc/sdk.api.md
index 1a89c54fc..2e194b498 100644
--- a/etc/sdk.api.md
+++ b/etc/sdk.api.md
@@ -855,15 +855,17 @@ export const DEFAULT_IPFS_GATEWAY = "https://gateway.ipfscdn.io/ipfs/";
// @internal (undocumented)
export const DEFAULT_QUERY_ALL_COUNT = 100;
-// Warning: (ae-forgotten-export) The symbol "SignatureDrop" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "DropERC721" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "BaseDelayedRevealERC721" needs to be exported by the entry point index.d.ts
//
// @public
-export class DelayedReveal {
+export class DelayedReveal {
constructor(contractWrapper: ContractWrapper, storage: IStorage);
createDelayedRevealBatch(placeholder: NFTMetadataInput, metadatas: NFTMetadataInput[], password: string, options?: {
onProgress: (event: UploadProgressEvent) => void;
}): Promise;
+ // (undocumented)
+ featureName: "ERC721Revealable";
getBatchesToReveal(): Promise;
reveal(batchId: BigNumberish, password: string): Promise;
}
@@ -1682,6 +1684,7 @@ export type ERC20Wrappable = {
};
// Warning: (ae-forgotten-export) The symbol "Multiwrap" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "SignatureDrop" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "TokenERC721" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "BaseERC721" needs to be exported by the entry point index.d.ts
//
@@ -1713,6 +1716,8 @@ export class Erc721;
// (undocumented)
query: Erc721Supply | undefined;
+ // (undocumented)
+ revealer: DelayedReveal | undefined;
// @internal
setApprovalForAll(operator: string, approved: boolean): Promise;
// @internal
@@ -4216,7 +4221,6 @@ export class SignatureDrop extends Erc721 {
metadata: ContractMetadata;
// (undocumented)
platformFees: ContractPlatformFee;
- revealer: DelayedReveal;
// (undocumented)
roles: ContractRoles;
royalties: ContractRoyalty;
@@ -4338,8 +4342,6 @@ export class SignatureDrop extends Erc721 {
}>;
};
// Warning: (ae-forgotten-export) The symbol "Erc721WithQuantitySignatureMinting" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
signature: Erc721WithQuantitySignatureMinting;
totalClaimedSupply(): Promise;
totalSupply(): Promise;
diff --git a/src/constants/contract-features.ts b/src/constants/contract-features.ts
index 0c5909480..197ff0753 100644
--- a/src/constants/contract-features.ts
+++ b/src/constants/contract-features.ts
@@ -5,6 +5,7 @@ import {
FEATURE_NFT_LAZY_MINTABLE,
FEATURE_NFT_MINTABLE,
FEATURE_NFT_SUPPLY,
+ FEATURE_NFT_REVEALABLE,
} from "./erc721-features";
import {
FEATURE_TOKEN,
@@ -46,7 +47,8 @@ export type Feature =
| typeof FEATURE_PLATFORM_FEE
| typeof FEATURE_PRIMARY_SALE
| typeof FEATURE_PERMISSIONS
- | typeof FEATURE_METADATA;
+ | typeof FEATURE_METADATA
+ | typeof FEATURE_NFT_REVEALABLE;
/**
* @internal
diff --git a/src/constants/erc721-features.ts b/src/constants/erc721-features.ts
index c4a92537b..36898ec01 100644
--- a/src/constants/erc721-features.ts
+++ b/src/constants/erc721-features.ts
@@ -4,6 +4,7 @@ import Erc721SupplyAbi from "../../abis/IERC721Supply.json";
import IMintableERC721Abi from "../../abis/IMintableERC721.json";
import MulticallAbi from "../../abis/IMulticall.json";
import LazyMintERC721Abi from "../../abis/LazyMintERC721.json";
+import DelayedRevealAbi from "../../abis/DelayedReveal.json";
export const FEATURE_NFT_LAZY_MINTABLE = {
name: "ERC721LazyMintable",
@@ -64,6 +65,17 @@ export const FEATURE_NFT_SUPPLY = {
},
} as const;
+export const FEATURE_NFT_REVEALABLE = {
+ name: "ERC721Revealable",
+ namespace: "nft.revealer",
+ docLinks: {
+ sdk: "sdk.delayedreveal",
+ contracts: "IDelayedReveal",
+ },
+ abis: [Erc721Abi, DelayedRevealAbi, LazyMintERC721Abi],
+ features: {},
+} as const;
+
export const FEATURE_NFT = {
name: "ERC721",
namespace: "nft",
@@ -76,5 +88,6 @@ export const FEATURE_NFT = {
[FEATURE_NFT_SUPPLY.name]: FEATURE_NFT_SUPPLY,
[FEATURE_NFT_MINTABLE.name]: FEATURE_NFT_MINTABLE,
[FEATURE_NFT_LAZY_MINTABLE.name]: FEATURE_NFT_LAZY_MINTABLE,
+ [FEATURE_NFT_REVEALABLE.name]: FEATURE_NFT_REVEALABLE,
},
} as const;
diff --git a/src/contracts/nft-drop.ts b/src/contracts/nft-drop.ts
index 5496df633..d59c486fd 100644
--- a/src/contracts/nft-drop.ts
+++ b/src/contracts/nft-drop.ts
@@ -4,9 +4,9 @@ import {
BigNumber,
BigNumberish,
BytesLike,
+ constants,
ethers,
utils,
- constants,
} from "ethers";
import { ContractMetadata } from "../core/classes/contract-metadata";
import { ContractRoyalty } from "../core/classes/contract-royalty";
@@ -159,7 +159,7 @@ export class NFTDrop extends Erc721 {
* await contract.revealer.reveal(batchId, "my secret password");
* ```
*/
- public revealer: DelayedReveal;
+ public override revealer: DelayedReveal;
private _query = this.query as Erc721Supply;
private _owned = this._query.owned as Erc721Enumerable;
diff --git a/src/contracts/signature-drop.ts b/src/contracts/signature-drop.ts
index 82a32da6d..21161960b 100644
--- a/src/contracts/signature-drop.ts
+++ b/src/contracts/signature-drop.ts
@@ -31,7 +31,6 @@ import { Erc721 } from "../core/classes/erc-721";
import { ContractPrimarySale } from "../core/classes/contract-sales";
import { prepareClaim } from "../common/claim-conditions";
import { ContractEncoder } from "../core/classes/contract-encoder";
-import { DelayedReveal } from "../core/classes/delayed-reveal";
import {
Erc721Enumerable,
Erc721Supply,
@@ -160,8 +159,6 @@ export class SignatureDrop extends Erc721 {
* await contract.revealer.reveal(batchId, "my secret password");
* ```
*/
- public revealer: DelayedReveal;
-
public signature: Erc721WithQuantitySignatureMinting;
private _query = this.query as Erc721Supply;
@@ -196,10 +193,6 @@ export class SignatureDrop extends Erc721 {
this.estimator = new GasCostEstimator(this.contractWrapper);
this.events = new ContractEvents(this.contractWrapper);
this.platformFees = new ContractPlatformFee(this.contractWrapper);
- this.revealer = new DelayedReveal(
- this.contractWrapper,
- this.storage,
- );
this.interceptor = new ContractInterceptor(this.contractWrapper);
this.signature = new Erc721WithQuantitySignatureMinting(
this.contractWrapper,
diff --git a/src/core/classes/delayed-reveal.ts b/src/core/classes/delayed-reveal.ts
index 858ea8303..57640d048 100644
--- a/src/core/classes/delayed-reveal.ts
+++ b/src/core/classes/delayed-reveal.ts
@@ -1,6 +1,6 @@
import { BigNumber, BigNumberish, ethers } from "ethers";
import { ContractWrapper } from "./contract-wrapper";
-import { DropERC721, SignatureDrop } from "contracts";
+import { DropERC721 } from "contracts";
import {
CommonNFTInput,
NFTMetadata,
@@ -11,12 +11,17 @@ import { fetchTokenMetadata } from "../../common/nft";
import { BatchToReveal } from "../../types/delayed-reveal";
import { TokensLazyMintedEvent } from "contracts/DropERC721";
import { UploadProgressEvent } from "../../types/events";
+import { BaseDelayedRevealERC721 } from "../../types/eips";
+import { hasFunction } from "../../common";
+import { FEATURE_NFT_REVEALABLE } from "../../constants/erc721-features";
/**
* Handles delayed reveal logic
* @public
*/
-export class DelayedReveal {
+export class DelayedReveal {
+ featureName = FEATURE_NFT_REVEALABLE.name;
+
private contractWrapper: ContractWrapper;
private storage: IStorage;
@@ -167,17 +172,26 @@ export class DelayedReveal {
const countRangeArray = Array.from(Array(count.toNumber()).keys());
- const contractType = ethers.utils.toUtf8String(
- await this.contractWrapper.readContract.contractType(),
- );
-
// map over to get the base uri indices, which should be the end token id of every batch
const uriIndices = await Promise.all(
- countRangeArray.map((i) =>
- this.isSignatureDrop(this.contractWrapper.readContract, contractType)
- ? this.contractWrapper.readContract.getBatchIdAtIndex(i)
- : this.contractWrapper.readContract.baseURIIndices(i),
- ),
+ countRangeArray.map((i) => {
+ if (
+ hasFunction(
+ "getBatchIdAtIndex",
+ this.contractWrapper,
+ )
+ ) {
+ return this.contractWrapper.readContract.getBatchIdAtIndex(i);
+ }
+
+ if (hasFunction("baseURIIndices", this.contractWrapper)) {
+ return this.contractWrapper.readContract.baseURIIndices(i);
+ }
+
+ throw new Error(
+ "Contract does not have getBatchIdAtIndex or baseURIIndices.",
+ );
+ }),
);
// first batch always start from 0. don't need to fetch the last batch so pop it from the range array
@@ -235,11 +249,4 @@ export class DelayedReveal {
const tokenUri = await this.contractWrapper.readContract.tokenURI(tokenId);
return fetchTokenMetadata(tokenId, tokenUri, this.storage);
}
-
- private isSignatureDrop(
- _contract: SignatureDrop | DropERC721,
- contractType: string,
- ): _contract is SignatureDrop {
- return contractType.includes("SignatureDrop");
- }
}
diff --git a/src/core/classes/erc-721.ts b/src/core/classes/erc-721.ts
index 2e290ed0a..78153dff8 100644
--- a/src/core/classes/erc-721.ts
+++ b/src/core/classes/erc-721.ts
@@ -22,10 +22,11 @@ import {
} from "contracts";
import { Erc721Supply } from "./erc-721-supply";
import { Erc721Mintable } from "./erc-721-mintable";
-import { BaseERC721 } from "../../types/eips";
+import { BaseDelayedRevealERC721, BaseERC721 } from "../../types/eips";
import { FEATURE_NFT } from "../../constants/erc721-features";
import { DetectableFeature } from "../interfaces/DetectableFeature";
import { Erc721LazyMintable } from "./erc-721-lazy-mintable";
+import { DelayedReveal } from "./delayed-reveal";
/**
* Standard ERC721 NFT functions
@@ -47,13 +48,15 @@ export class Erc721<
> implements UpdateableNetwork, DetectableFeature
{
featureName = FEATURE_NFT.name;
- protected contractWrapper: ContractWrapper;
- protected storage: IStorage;
- protected options: SDKOptions;
-
public query: Erc721Supply | undefined;
public mint: Erc721Mintable | undefined;
public lazy: Erc721LazyMintable | undefined;
+ public revealer:
+ | DelayedReveal
+ | undefined;
+ protected contractWrapper: ContractWrapper;
+ protected storage: IStorage;
+ protected options: SDKOptions;
constructor(
contractWrapper: ContractWrapper,
@@ -74,6 +77,7 @@ export class Erc721<
this.query = this.detectErc721Enumerable();
this.mint = this.detectErc721Mintable();
this.lazy = this.detectErc721LazyMintable();
+ this.revealer = this.detectErc721Revealable();
}
/**
@@ -273,4 +277,18 @@ export class Erc721<
}
return undefined;
}
+
+ private detectErc721Revealable():
+ | DelayedReveal
+ | undefined {
+ if (
+ detectContractFeature(
+ this.contractWrapper,
+ "ERC721Revealable",
+ )
+ ) {
+ return new DelayedReveal(this.contractWrapper, this.storage);
+ }
+ return undefined;
+ }
}
diff --git a/src/core/classes/index.ts b/src/core/classes/index.ts
index 47d4d4ba8..dbc44297e 100644
--- a/src/core/classes/index.ts
+++ b/src/core/classes/index.ts
@@ -5,6 +5,7 @@ export * from "./contract-metadata";
export * from "./contract-roles";
export * from "./contract-royalty";
export * from "./contract-sales";
+export * from "./delayed-reveal";
export * from "./drop-claim-conditions";
export * from "./drop-erc1155-claim-conditions";
export * from "./drop-erc1155-history";
diff --git a/src/types/eips.ts b/src/types/eips.ts
index e426f93bc..508649e13 100644
--- a/src/types/eips.ts
+++ b/src/types/eips.ts
@@ -1,4 +1,6 @@
import {
+ DelayedReveal,
+ DropERC721,
IERC1155,
IERC1155Metadata,
IERC1155Supply,
@@ -6,8 +8,13 @@ import {
IERC20Metadata,
IERC721,
IERC721Metadata,
+ LazyMintERC721,
} from "contracts";
export type BaseERC20 = IERC20 & IERC20Metadata;
export type BaseERC721 = IERC721 & IERC721Metadata;
export type BaseERC1155 = IERC1155 & IERC1155Metadata & IERC1155Supply;
+export type BaseDelayedRevealERC721 = BaseERC721 &
+ DelayedReveal &
+ LazyMintERC721 &
+ DropERC721;
diff --git a/test/custom.test.ts b/test/custom.test.ts
index 184954f25..8619e826a 100644
--- a/test/custom.test.ts
+++ b/test/custom.test.ts
@@ -2,7 +2,6 @@ import { signers } from "./before-setup";
import { expect } from "chai";
import invariant from "tiny-invariant";
import {
- DropERC721__factory,
SignatureDrop__factory,
TokenERC1155__factory,
TokenERC20__factory,
@@ -253,6 +252,27 @@ describe("Custom Contracts", async () => {
expect(nfts[0].metadata.name).to.eq("Custom NFT");
});
+ it("should detect feature: erc721 delay reveal", async () => {
+ const c = await sdk.getContractFromAbi(
+ sigDropContractAddress,
+ SignatureDrop__factory.abi,
+ );
+ invariant(c, "Contract undefined");
+ invariant(c.nft, "ERC721 undefined");
+ invariant(c.nft.revealer, "ERC721 query undefined");
+
+ await c.nft.revealer.createDelayedRevealBatch(
+ {
+ name: "Placeholder #1",
+ },
+ [{ name: "NFT #1" }, { name: "NFT #2" }, { name: "NFT #3" }],
+ "password",
+ );
+
+ await c.nft.revealer.reveal(0, "password");
+ expect((await c.nft.get(0)).metadata.name).to.be.equal("NFT #1");
+ });
+
it("should detect feature: erc1155", async () => {
const c = await sdk.getContractFromAbi(
editionContractAddress,