diff --git a/docs/sdk.editiondrop.createbatch.md b/docs/sdk.editiondrop.createbatch.md
index 546500288..19b2a712d 100644
--- a/docs/sdk.editiondrop.createbatch.md
+++ b/docs/sdk.editiondrop.createbatch.md
@@ -9,14 +9,17 @@ Create a batch of NFTs to be claimed in the future
Signature:
```typescript
-createBatch(metadatas: NFTMetadataInput[]): Promise[]>;
+createBatch(metadatas: NFTMetadataOrUri[], options?: {
+ onProgress: (event: UploadProgressEvent) => void;
+ }): Promise[]>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
-| metadatas | [NFTMetadataInput](./sdk.nftmetadatainput.md)\[\] | |
+| metadatas | NFTMetadataOrUri\[\] | The metadata to include in the batch. |
+| options | { onProgress: (event: [UploadProgressEvent](./sdk.uploadprogressevent.md)) => void; } | (Optional) optional upload progress callback |
Returns:
diff --git a/docs/sdk.editiondrop.md b/docs/sdk.editiondrop.md
index c16da8d01..088c7358e 100644
--- a/docs/sdk.editiondrop.md
+++ b/docs/sdk.editiondrop.md
@@ -54,7 +54,7 @@ const contract = sdk.getEditionDrop("{{contract_address}}");
| [burn(tokenId, amount)](./sdk.editiondrop.burn.md) | | Burn a specified amount of a NFT |
| [claim(tokenId, quantity, proofs)](./sdk.editiondrop.claim.md) | | Claim a token to the connected wallet |
| [claimTo(destinationAddress, tokenId, quantity, proofs)](./sdk.editiondrop.claimto.md) | | Claim NFTs to a specific Wallet |
-| [createBatch(metadatas)](./sdk.editiondrop.createbatch.md) | | Create a batch of NFTs to be claimed in the future |
+| [createBatch(metadatas, options)](./sdk.editiondrop.createbatch.md) | | Create a batch of NFTs to be claimed in the future |
| [getAll(queryParams)](./sdk.editiondrop.getall.md) | | Get All Minted NFTs |
| [getOwned(walletAddress)](./sdk.editiondrop.getowned.md) | | Get Owned NFTs |
| [getTotalCount()](./sdk.editiondrop.gettotalcount.md) | | Get the number of NFTs minted |
diff --git a/docs/sdk.nftdrop.createbatch.md b/docs/sdk.nftdrop.createbatch.md
index 3c7134192..9a3ff5819 100644
--- a/docs/sdk.nftdrop.createbatch.md
+++ b/docs/sdk.nftdrop.createbatch.md
@@ -9,7 +9,7 @@ Create a batch of unique NFTs to be claimed in the future
Signature:
```typescript
-createBatch(metadatas: NFTMetadataInput[], options?: {
+createBatch(metadatas: NFTMetadataOrUri[], options?: {
onProgress: (event: UploadProgressEvent) => void;
}): Promise[]>;
```
@@ -18,7 +18,7 @@ createBatch(metadatas: NFTMetadataInput[], options?: {
| Parameter | Type | Description |
| --- | --- | --- |
-| metadatas | [NFTMetadataInput](./sdk.nftmetadatainput.md)\[\] | The metadata to include in the batch. |
+| metadatas | NFTMetadataOrUri\[\] | The metadata to include in the batch. |
| options | { onProgress: (event: [UploadProgressEvent](./sdk.uploadprogressevent.md)) => void; } | (Optional) optional upload progress callback |
Returns:
diff --git a/etc/sdk.api.md b/etc/sdk.api.md
index 83a9f8ecb..817f49fbe 100644
--- a/etc/sdk.api.md
+++ b/etc/sdk.api.md
@@ -1101,7 +1101,10 @@ export class EditionDrop extends Erc1155 {
static contractRoles: readonly ["admin", "minter", "transfer"];
// (undocumented)
static contractType: "edition-drop";
- createBatch(metadatas: NFTMetadataInput[]): Promise[]>;
+ // Warning: (ae-forgotten-export) The symbol "NFTMetadataOrUri" needs to be exported by the entry point index.d.ts
+ createBatch(metadatas: NFTMetadataOrUri[], options?: {
+ onProgress: (event: UploadProgressEvent) => void;
+ }): Promise[]>;
// (undocumented)
encoder: ContractEncoder;
// (undocumented)
@@ -1723,7 +1726,6 @@ export class Erc721BatchMintable implements DetectableFeature {
constructor(erc721: Erc721, contractWrapper: ContractWrapper, storage: IStorage);
// (undocumented)
featureName: "ERC721BatchMintable";
- // Warning: (ae-forgotten-export) The symbol "NFTMetadataOrUri" needs to be exported by the entry point index.d.ts
to(to: string, metadatas: NFTMetadataOrUri[]): Promise[]>;
}
@@ -2704,7 +2706,7 @@ export class NFTDrop extends Erc721 {
static contractRoles: readonly ["admin", "minter", "transfer"];
// (undocumented)
static contractType: "nft-drop";
- createBatch(metadatas: NFTMetadataInput[], options?: {
+ createBatch(metadatas: NFTMetadataOrUri[], options?: {
onProgress: (event: UploadProgressEvent) => void;
}): Promise[]>;
// (undocumented)
diff --git a/src/common/nft.ts b/src/common/nft.ts
index 181c75c02..84263daac 100644
--- a/src/common/nft.ts
+++ b/src/common/nft.ts
@@ -16,6 +16,7 @@ import {
import ERC721MetadataAbi from "../../abis/IERC721Metadata.json";
import ERC1155MetadataAbi from "../../abis/IERC1155Metadata.json";
import ERC165MetadataAbi from "../../abis/IERC165.json";
+import { UploadProgressEvent } from "../types/index";
const FALLBACK_METADATA = {
name: "Failed to load NFT metadata",
@@ -124,16 +125,30 @@ export async function uploadOrExtractURI(
* @internal
* @param metadatas
* @param storage
+ * @param startNumber
+ * @param contractAddress
+ * @param signerAddress
+ * @param options
*/
export async function uploadOrExtractURIs(
metadatas: NFTMetadataOrUri[],
storage: IStorage,
+ startNumber?: number,
+ contractAddress?: string,
+ signerAddress?: string,
+ options?: {
+ onProgress: (event: UploadProgressEvent) => void;
+ },
): Promise {
if (isUriList(metadatas)) {
return metadatas;
} else if (isMetadataList(metadatas)) {
const { uris } = await storage.uploadMetadataBatch(
metadatas.map((m) => CommonNFTInput.parse(m)),
+ startNumber,
+ contractAddress,
+ signerAddress,
+ options,
);
return uris;
} else {
diff --git a/src/contracts/edition-drop.ts b/src/contracts/edition-drop.ts
index 2c360b36b..90d3c64b2 100644
--- a/src/contracts/edition-drop.ts
+++ b/src/contracts/edition-drop.ts
@@ -13,18 +13,18 @@ import {
} from "../core/types";
import { SDKOptions } from "../schema/sdk-options";
import { ContractWrapper } from "../core/classes/contract-wrapper";
-import {
- CommonNFTInput,
- NFTMetadata,
- NFTMetadataInput,
-} from "../schema/tokens/common";
+import { NFTMetadata, NFTMetadataOrUri } from "../schema/tokens/common";
import { BigNumber, BigNumberish, BytesLike, constants, utils } from "ethers";
import { prepareClaim } from "../common/claim-conditions";
import { DropErc1155ClaimConditions } from "../core/classes/drop-erc1155-claim-conditions";
import { DropErc1155ContractSchema } from "../schema/contracts/drop-erc1155";
import { ContractEncoder } from "../core/classes/contract-encoder";
import { GasCostEstimator } from "../core/classes/gas-cost-estimator";
-import { ClaimVerification, QueryAllParams } from "../types";
+import {
+ ClaimVerification,
+ QueryAllParams,
+ UploadProgressEvent,
+} from "../types";
import { DropErc1155History } from "../core/classes/drop-erc1155-history";
import { ContractEvents } from "../core/classes/contract-events";
import { ContractPlatformFee } from "../core/classes/contract-platform-fee";
@@ -34,6 +34,7 @@ import { getRoleHash } from "../common";
import { EditionMetadata, EditionMetadataOwner } from "../schema";
import { ContractAnalytics } from "../core/classes/contract-analytics";
+import { uploadOrExtractURIs } from "../common/nft";
/**
* Setup a collection of NFTs with a customizable number of each NFT that are minted as users claim them.
@@ -253,21 +254,39 @@ export class EditionDrop extends Erc1155 {
* const firstTokenId = results[0].id; // token id of the first created NFT
* const firstNFT = await results[0].data(); // (optional) fetch details of the first created NFT
* ```
+ *
+ * @param metadatas - The metadata to include in the batch.
+ * @param options - optional upload progress callback
*/
public async createBatch(
- metadatas: NFTMetadataInput[],
+ metadatas: NFTMetadataOrUri[],
+ options?: {
+ onProgress: (event: UploadProgressEvent) => void;
+ },
): Promise[]> {
const startFileNumber =
await this.contractWrapper.readContract.nextTokenIdToMint();
- const batch = await this.storage.uploadMetadataBatch(
- metadatas.map((m) => CommonNFTInput.parse(m)),
+ const batch = await uploadOrExtractURIs(
+ metadatas,
+ this.storage,
startFileNumber.toNumber(),
this.contractWrapper.readContract.address,
await this.contractWrapper.getSigner()?.getAddress(),
+ options,
);
+ // ensure baseUri is the same for the entire batch
+ const baseUri = batch[0].substring(0, batch[0].lastIndexOf("/"));
+ for (let i = 0; i < batch.length; i++) {
+ const uri = batch[i].substring(0, batch[i].lastIndexOf("/"));
+ if (baseUri !== uri) {
+ throw new Error(
+ `Can only create batches with the same base URI for every entry in the batch. Expected '${baseUri}' but got '${uri}'`,
+ );
+ }
+ }
const receipt = await this.contractWrapper.sendTransaction("lazyMint", [
- batch.uris.length,
- `${batch.baseUri.endsWith("/") ? batch.baseUri : `${batch.baseUri}/`}`,
+ batch.length,
+ `${baseUri.endsWith("/") ? baseUri : `${baseUri}/`}`,
]);
const event = this.contractWrapper.parseLogs(
"TokensLazyMinted",
diff --git a/src/contracts/nft-drop.ts b/src/contracts/nft-drop.ts
index 20701564b..b0cc781a8 100644
--- a/src/contracts/nft-drop.ts
+++ b/src/contracts/nft-drop.ts
@@ -19,9 +19,8 @@ import {
import { DropErc721ContractSchema } from "../schema/contracts/drop-erc721";
import { SDKOptions } from "../schema/sdk-options";
import {
- CommonNFTInput,
NFTMetadata,
- NFTMetadataInput,
+ NFTMetadataOrUri,
NFTMetadataOwner,
} from "../schema/tokens/common";
import { DEFAULT_QUERY_ALL_COUNT, QueryAllParams } from "../types/QueryParams";
@@ -46,6 +45,7 @@ import {
} from "contracts/DropERC721";
import { ContractAnalytics } from "../core/classes/contract-analytics";
import { UploadProgressEvent } from "../types/events";
+import { uploadOrExtractURIs } from "../common/nft";
/**
* Setup a collection of one-of-one NFTs that are minted as users claim them.
@@ -413,23 +413,33 @@ export class NFTDrop extends Erc721 {
* @param options - optional upload progress callback
*/
public async createBatch(
- metadatas: NFTMetadataInput[],
+ metadatas: NFTMetadataOrUri[],
options?: {
onProgress: (event: UploadProgressEvent) => void;
},
): Promise[]> {
const startFileNumber =
await this.contractWrapper.readContract.nextTokenIdToMint();
- const batch = await this.storage.uploadMetadataBatch(
- metadatas.map((m) => CommonNFTInput.parse(m)),
+ const batch = await uploadOrExtractURIs(
+ metadatas,
+ this.storage,
startFileNumber.toNumber(),
this.contractWrapper.readContract.address,
await this.contractWrapper.getSigner()?.getAddress(),
options,
);
- const baseUri = batch.baseUri;
+ // ensure baseUri is the same for the entire batch
+ const baseUri = batch[0].substring(0, batch[0].lastIndexOf("/"));
+ for (let i = 0; i < batch.length; i++) {
+ const uri = batch[i].substring(0, batch[i].lastIndexOf("/"));
+ if (baseUri !== uri) {
+ throw new Error(
+ `Can only create batches with the same base URI for every entry in the batch. Expected '${baseUri}' but got '${uri}'`,
+ );
+ }
+ }
const receipt = await this.contractWrapper.sendTransaction("lazyMint", [
- batch.uris.length,
+ batch.length,
baseUri.endsWith("/") ? baseUri : `${baseUri}/`,
ethers.utils.toUtf8Bytes(""),
]);
diff --git a/test/nft-drop.test.ts b/test/nft-drop.test.ts
index e219af06f..3639e2379 100644
--- a/test/nft-drop.test.ts
+++ b/test/nft-drop.test.ts
@@ -40,6 +40,16 @@ describe("NFT Drop Contract", async () => {
dropContract = sdk.getNFTDrop(address);
});
+ it("should lazy mint with URI", async () => {
+ const uri = await storage.uploadMetadata({
+ name: "Test1",
+ });
+ await dropContract.createBatch([uri]);
+ const nft = await dropContract.get("0");
+ assert.isNotNull(nft);
+ assert.equal(nft.metadata.name, "Test1");
+ });
+
it("should allow a snapshot to be set", async () => {
await dropContract.claimConditions.set([
{