# Batch Mint NFTs Using JavaScript You can create an application that mints multiple NFTs at one time. You can use a `for` loop to send one transaction after another. A best practice is to use `Tickets` to reserve the transaction sequence numbers. If you create an application that creates NFTs without using tickets, if any transaction fails for any reason, the application stops with an error. If you use tickets, the application continues to send transactions, and you can look into the reason for any individual failures afterward. [![Batch Mint](/assets/mt-batch-mint-1-empty-form.c65da18a0b5b21fe73588990159c82d1b3944bfc64c7a98373bf4c76acba9eca.ac57e6ef.png)](/assets/mt-batch-mint-1-empty-form.c65da18a0b5b21fe73588990159c82d1b3944bfc64c7a98373bf4c76acba9eca.ac57e6ef.png) ## Usage You can download the [NFT Modular Samples](/assets/nft-modular-tutorials.0f7eb22b2ca15eaf6397b7c614a7c020f1ab844da76fa9bf842e720bfc80f1fe.4057f33c.zip)) archive to try the sample in your own browser. ## Get an Account 1. Open `batch-minting.html` in a browser. 2. Get a test account. 1. If you want to use an existing account seed: 1. Paste the account seed in the **Seed** field. 2. Click **Get Account from Seed**. 2. If you do not want to use an existing account seed, click **Get New Account 1**. ## Batch Mint NFTs This example lets you mint multiple NFTs for a single unique item. The NFT might represent "prints" of an original artwork, tickets to an event, or another limited set of unique items. To batch mint NFTs: 1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form. 2. Set the **Flags** field. For testing purposes, we recommend setting the value to *8*. This sets the *tsTransferable* flag, meaning that the NFT object can be transferred to another account. Otherwise, the NFT object can only be transferred back to the issuing account. See [NFTokenMint](/docs/references/protocol/transactions/types/nftokenmint) for information about all of the available flags for minting NFTs. 3. Enter the **NFT URL**. This is a URI that points to the data or metadata associated with the NFT object. You can use the sample URI provided if you do not have one of your own. 4. Set the **NFT Taxon**. If you don't have a use for this field, set it to *0*. 5. Enter an **NFT Count** of up to 200 NFTs to create in one batch. 6. Enter the **Transfer Fee**, a percentage of the proceeds that the original creator receives from future sales of the NFT. This is a value of 0-50000 inclusive, allowing transfer fees between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFT to be transferrable, set this field to 0. 7. Click **Batch Mint NFTs**. [![Batch Mint](/assets/mt-batch-mint-2-batch-mint.93bee76d835e385c27f044fd65e2ee522f010ae43e5522572642d1cf115bab2d.ac57e6ef.png)](/assets/mt-batch-mint-2-batch-mint.93bee76d835e385c27f044fd65e2ee522f010ae43e5522572642d1cf115bab2d.ac57e6ef.png) ## Get Batch NFTs Click **Get Batch NFTs** to get the current list of NFTs for the selected account. The difference between this function and the `getTokens()` function used earlier is that it allows for larger lists of tokens, and sends multiple requests if the tokens exceed the number of objects allowed in a single request. [![Batch Mint](/assets/mt-batch-mint-3-get-batch-mint.d3d75f8d26df1796ccd21b0ceb3883164502f776da42d74d5dad563093f60680.ac57e6ef.png)](/assets/mt-batch-mint-3-get-batch-mint.d3d75f8d26df1796ccd21b0ceb3883164502f776da42d74d5dad563093f60680.ac57e6ef.png) # Code Walkthrough You can download the [NFT Modular Tutorials](/assets/nft-modular-tutorials.0f7eb22b2ca15eaf6397b7c614a7c020f1ab844da76fa9bf842e720bfc80f1fe.4057f33c.zip) archive to try each of the samples in your own browser. ## batchMintNFTs() ```javascript // ******************************************************* // ***************** Batch Mint NFTs ********************* // ******************************************************* async function batchMintNFTs() { ``` Connect to the XRP Ledger and get the account wallet. ```javascript let client; try { let net = getNet(); client = new xrpl.Client(net); // Assign client results = 'Connecting to ' + getNet() + '....'; resultField.value = results; await client.connect(); results += '\nConnected, finding wallet.'; resultField.value = results; let wallet; try { wallet = xrpl.Wallet.fromSeed(accountSeedField.value); } catch (error) { results += '\nError: Invalid account seed. Please check your seed.'; resultField.value = results; return; // Stop execution if wallet cannot be derived } resultField.value = results; ``` Get the Sequence number from the most recent transaction with an account information request. ```javascript let account_info; try { account_info = await client.request({ "command": "account_info", "account": wallet.address }); } catch (error) { results += `\nError retrieving account info for ${wallet.address}: ${error.message}`; resultField.value = results; return; } let my_sequence = account_info.result.account_data.Sequence; results += "\n\nSequence Number: " + my_sequence + "\n\n"; resultField.value = results; ``` Create ticket numbers for the batch. Without tickets, if one transaction fails, all others in the batch fail. With tickets, there can be failures, but the rest will continue, and you can investigate any problems afterward. Start by parsing the **NFT Count**. ```javascript const nftCount = parseInt(nftCountField.value); if (isNaN(nftCount) || nftCount <= 0) { results += '\nError: Please enter a valid number of NFTs to mint.'; resultField.value = results; return; } ``` Create the transaction JSON object. ```javascript let ticketTransaction; try { ticketTransaction = await client.autofill({ "TransactionType": "TicketCreate", "Account": wallet.address, "TicketCount": nftCount, "Sequence": my_sequence }); } catch (error) { results += `\nError autofilling ticket creation transaction: ${error.message}`; resultField.value = results; return; } ``` Sign the ticket transaction. ```javascript //---------------------------------------------------- Sign the transaction. const signedTransaction = wallet.sign(ticketTransaction); ``` Submit the transaction and wait for the result. ```javascript let tx; try { tx = await client.submitAndWait(signedTransaction.tx_blob); } catch (error) { results += `\nError submitting ticket creation transaction: ${error.message}`; resultField.value = results; return; } ``` Verify the transaction succeeded and report the result. ```javascript if (tx.result.meta.TransactionResult !== 'tesSUCCESS') { results += `\nError creating tickets. Transaction failed with result: ${tx.result.meta.TransactionResult}`; resultField.value = results; return; } results += `\nTickets created successfully. Transaction result: ${tx.result.meta.TransactionResult}\n\n`; resultField.value = results; ``` Get the generated tickets. ```javascript let response; try { response = await client.request({ "command": "account_objects", "account": wallet.address, "type": "ticket" }); } catch (error) { results += `\nError retrieving account tickets: ${error.message}`; resultField.value = results; return; } ``` Populate an array variable with the tickets and report the results. ```javascript let tickets = []; if (response.result.account_objects && response.result.account_objects.length > 0) { for (let i = 0; i < nftCount; i++) { if (response.result.account_objects[i]) { tickets[i] = response.result.account_objects[i].TicketSequence; } else { results += `\nWarning: Fewer tickets found than requested. Expected ${nftCount}, found ${response.result.account_objects.length}.`; resultField.value = results; break; // Exit loop if tickets run out } } } else { results += '\nError: No tickets found for the account.'; resultField.value = results; return; } results += "Tickets generated, minting NFTs.\n\n"; resultField.value = results; ``` Mint the NFTs by looping through the available tickets and creating NFTs one at a time. ```javascript let mintedNFTsCount = 0; for (let i = 0; i < tickets.length; i++) { const transactionParams = { "TransactionType": "NFTokenMint", "Account": wallet.classicAddress, "URI": xrpl.convertStringToHex(nftURLfield.value), "Flags": parseInt(flagsField.value), "TransferFee": parseInt(transferFeeField.value), "Sequence": 0, // Sequence is 0 when using TicketSequence "TicketSequence": tickets[i], "LastLedgerSequence": null, // Optional, can be used for time limits "NFTokenTaxon": nftTaxonField.value, }; ``` Add optional fields, as needed. ```javascript // Add optional fields if (amountField.value) { transactionParams.Amount = configureAmount(amountField.value); } if (expirationField.value) { transactionParams.Expiration = configureExpiration(expirationField.value); } if (destinationField.value) { transactionParams.Destination = destinationField.value; } ``` Submit the transaction and wait for the result. ```javascript try { const mintTx = await client.submitAndWait(transactionParams, { wallet: wallet }); results += `\nNFT ${i+1} minted successfully.`; mintedNFTsCount++; console.log(mintTx.result.nfts) resultField.value = results; } catch (error) { console.log(error); } // Add a small delay to avoid hitting rate limits if many NFTs are being minted await new Promise(resolve => setTimeout(resolve, 500)); } ``` Report the results. ```javascript results += `\n\nAttempted to mint ${nftCount} NFTs. Successfully minted ${mintedNFTsCount} NFTs.`; ``` Display the minted NFTs. ```javascript results += "\n\nFetching minted NFTs...\n"; let nfts; try { nfts = await client.request({ method: "account_nfts", account: wallet.classicAddress, limit: 400 }); results += JSON.stringify(nfts, null, 2); ``` Continue to retrieve NFTs 400 at a time until all NFTs are fetched. ```javascript while (nfts.result.marker) { nfts = await client.request({ method: "account_nfts", account: wallet.classicAddress, limit: 400, marker: nfts.result.marker }); results += '\n' + JSON.stringify(nfts, null, 2); } } catch (error) { results += `\nError fetching account NFTs: ${error.message}`; } ``` Update the **XRP Balance** field. ```javascript try { xrpBalanceField.value = (await client.getXrpBalance(wallet.address)); } catch (error) { results += `\nError fetching XRP balance: ${error.message}`; } resultField.value = results; ``` Catch and report any errors. ```javascript } catch (error) { results += `\nAn unexpected error occurred during batch minting: ${error.message}`; resultField.value = results; ``` Disconnect from the XRP Ledger. ```javascript } finally { if (client && client.isConnected()) { client.disconnect(); results += '\nDisconnected from XRP Ledger.'; resultField.value = results; } } } // End of batchMint() ``` ## getBatchNFTs Retrieve the NFTs for an account in batches of 400. Get the account wallet and connect to the XRP Ledger. ```javascript async function getBatchNFTs() { let client; // Declare client here for finally block access try { const wallet = xrpl.Wallet.fromSeed(accountSeedField.value); let net = getNet(); client = new xrpl.Client(net); // Assign client results = 'Connecting to ' + net + '...'; resultField.value = results; await client.connect(); results += '\nConnected. Getting NFTs...'; resultField.value = results; ``` Retrieve the first 400 NFTs and report the results. ```javascript results += "\n\nNFTs:\n"; let nfts; try { nfts = await client.request({ method: "account_nfts", account: wallet.classicAddress, limit: 400 }); results += JSON.stringify(nfts, null, 2); ``` While there are more NFTs, continue to retrieve them in batches of 400. ```javascript while (nfts.result.marker) { nfts = await client.request({ method: "account_nfts", account: wallet.classicAddress, limit: 400, marker: nfts.result.marker }); results += '\n' + JSON.stringify(nfts, null, 2); } ``` Catch and report any fetch errors. ```javascript } catch (error) { results += `\nError fetching account NFTs: ${error.message}`; } resultField.value = results; ``` Catch and report any general errors. ```javascript } catch (error) { results += `\nAn unexpected error occurred while getting batch NFTs: ${error.message}`; resultField.value = results; ``` Disconnect from the XRP Ledger. ```javascript } finally { if (client && client.isConnected()) { client.disconnect(); results += '\nDisconnected from XRP Ledger.'; resultField.value = results; } } } //End of getBatchNFTs() ``` ## batch-minting.html ```html Batch Mint NFTs

Batch Mint NFTs

Choose your ledger instance:      



  





```