Skip to content

Commit

Permalink
[SDK] ERC1155 extension: mintToBatch (#5032)
Browse files Browse the repository at this point in the history
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR adds the `mintToBatch` function to the `ERC1155` extension, allowing multiple tokens to be minted in a single transaction. It includes new tests to ensure the functionality works as expected.

### Detailed summary
- Introduced `mintToBatch` function in `mintToBatch.ts`.
- Added `MintToBatchParams` type definition.
- Updated `erc1155.ts` to export `mintToBatch` and `MintToBatchParams`.
- Created tests for `mintToBatch` in `mintToBatch.test.ts` to validate minting multiple tokens.

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

<!-- end pr-codex -->
  • Loading branch information
kien-ngo committed Oct 15, 2024
1 parent 1994d9e commit 3fe33a6
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/six-drinks-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": minor
---

Add ERC1155 extension: mintToBatch
5 changes: 5 additions & 0 deletions packages/thirdweb/src/exports/extensions/erc1155.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,8 @@ export {

// Zora 1155 contract
export { nextTokenId } from "../../extensions/erc1155/__generated__/Zora1155/read/nextTokenId.js";

export {
mintToBatch,
type MintToBatchParams,
} from "../../extensions/erc1155/write/mintToBatch.js";
74 changes: 74 additions & 0 deletions packages/thirdweb/src/extensions/erc1155/write/mintToBatch.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { describe, expect, it } from "vitest";
import { ANVIL_CHAIN } from "~test/chains.js";
import { TEST_CONTRACT_URI } from "~test/ipfs-uris.js";
import { TEST_CLIENT } from "~test/test-clients.js";
import { TEST_ACCOUNT_C } from "~test/test-wallets.js";
import { getContract } from "../../../contract/contract.js";
import { deployERC1155Contract } from "../../../extensions/prebuilts/deploy-erc1155.js";
import { sendAndConfirmTransaction } from "../../../transaction/actions/send-and-confirm-transaction.js";
import { getNFTs } from "../read/getNFTs.js";
import { mintToBatch } from "./mintToBatch.js";

const chain = ANVIL_CHAIN;
const client = TEST_CLIENT;
const account = TEST_ACCOUNT_C;

describe("ERC1155 Edition: mintToBatch", () => {
it("should mint multiple tokens in one tx", async () => {
const contract = getContract({
chain,
client,
address: await deployERC1155Contract({
chain,
client,
account,
type: "TokenERC1155",
params: {
name: "edition",
contractURI: TEST_CONTRACT_URI,
},
}),
});

await sendAndConfirmTransaction({
account,
transaction: mintToBatch({
contract,
to: account.address,
nfts: [
{ metadata: { name: "token 0" }, supply: 1n },
{ metadata: { name: "token 1" }, supply: 2n },
{ metadata: { name: "token 2" }, supply: 3n },
],
}),
});

const nfts = await getNFTs({ contract });
expect(nfts).toStrictEqual([
{
metadata: { name: "token 0" },
owner: null,
id: 0n,
tokenURI: "ipfs://QmPZ6LpGqMuFbHKTXrNW1NRNLHf1nrxS4dtoFqdZZTKvPX/0",
type: "ERC1155",
supply: 1n,
},
{
metadata: { name: "token 1" },
owner: null,
id: 1n,
tokenURI: "ipfs://QmRFPyc3yEYxR4pQxwyTQWTine51TxWCoD6nzJWR3eX45b/0",
type: "ERC1155",
supply: 2n,
},
{
metadata: { name: "token 2" },
owner: null,
id: 2n,
tokenURI: "ipfs://QmesQiRLHCgqWZM2GFCs7Nb7rr2S72hU1BVQc7xiTyKZtT/0",
type: "ERC1155",
supply: 3n,
},
]);
});
});
117 changes: 117 additions & 0 deletions packages/thirdweb/src/extensions/erc1155/write/mintToBatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { maxUint256 } from "viem";
import { multicall } from "../../../extensions/common/__generated__/IMulticall/write/multicall.js";
import { upload } from "../../../storage/upload.js";
import type {
BaseTransactionOptions,
WithOverrides,
} from "../../../transaction/types.js";
import type { NFTInput } from "../../../utils/nft/parseNft.js";
import { encodeMintTo } from "../__generated__/IMintableERC1155/write/mintTo.js";

/**
* @extension ERC1155
*/
export type MintToBatchParams = WithOverrides<{
/**
* The wallet that the NFTs will be minted to
*/
to: string;
/**
* An array of NFT metadata & supply to mint
* @example
* ```ts
* const nfts = [
* {
* metadata: { name: "token 0" },
* supply: 1n,
* },
* {
* metadata: { name: "token 1" },
* supply: 10n,
* },
* ]
* ```
*/
nfts: Array<{
supply: bigint;
metadata: NFTInput | string;
}>;
}>;

/**
* This extension batches multiple `mintTo` extensions into one single multicall.
* Keep in mind that there is a limit of how many NFTs you can mint per transaction.
* This limit varies depends on the network that you are transacting on.
*
* You are recommended to experiment with the number to figure out the best number for your chain of choice.
* @param options - the transaction options
* @returns A promise that resolves to the transaction result.
* @extension ERC1155
* @example
* ```ts
* import { mintBatchTo } from "thirdweb/extension/erc1155";
*
* const transaction = mintToBatch({
* contract: editionContract,
* to: "0x...",
* nfts: [
* {
* metadata: {
* name: "Token #0",
* image: "...",
* attributes: [],
* },
* supply: 100n,
* },
* {
* metadata: {
* name: "Token #1",
* image: "...",
* attributes: [],
* },
* supply: 111n,
* },
* ],
* });
*
* await sendTransaction({ transaction, account });
* ```
*/
export function mintToBatch(
options: BaseTransactionOptions<MintToBatchParams>,
) {
return multicall({
contract: options.contract,
asyncParams: async () => {
const uris = await Promise.all(
options.nfts.map((item) => {
if (typeof item.metadata === "string") {
return item.metadata;
}

Check warning on line 90 in packages/thirdweb/src/extensions/erc1155/write/mintToBatch.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/extensions/erc1155/write/mintToBatch.ts#L89-L90

Added lines #L89 - L90 were not covered by tests
return upload({
client: options.contract.client,
files: [item.metadata],
});
}),
);

const data = uris.map((uri, index) => {
const item = options.nfts[index];
if (!item) {
// Should not happen
throw new Error("Index mismatch");
}

Check warning on line 103 in packages/thirdweb/src/extensions/erc1155/write/mintToBatch.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/extensions/erc1155/write/mintToBatch.ts#L102-L103

Added lines #L102 - L103 were not covered by tests
return encodeMintTo({
to: options.to,
// maxUint256 is used to indicate that this is a NEW token!
tokenId: maxUint256,
uri,
amount: item.supply,
});
});

return { data };
},
overrides: options.overrides,
});
}

0 comments on commit 3fe33a6

Please sign in to comment.