mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-21 12:15:50 +00:00
405 lines
14 KiB
Markdown
405 lines
14 KiB
Markdown
---
|
|
html: py-batch-minting.html
|
|
parent: quickstart-python.html
|
|
blurb: Mint multiple NFTs with the press of a button.
|
|
labels:
|
|
- Accounts
|
|
- Quickstart
|
|
- NFTs
|
|
- XRP
|
|
---
|
|
|
|
# Batch Mint NFTs
|
|
|
|
You can create an application that mints multiple NFTs at one time, using 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.
|
|
|
|
[](img/quickstart-py36.png)
|
|
|
|
## Usage
|
|
|
|
You can download or clone the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/){.github-code-download} to try the sample in your own browser.
|
|
|
|
## Get an Account
|
|
|
|
1. Open and run `lesson7-batch-minting.py`.
|
|
2. Get a test account.
|
|
1. If you want to use an existing account seed:
|
|
1. Paste the account seed in the **Standby Seed** field.
|
|
2. Click **Get Standby Account**.
|
|
2. If you do not want to use an existing account seed, click **Get Standby Account**.
|
|
|
|
|
|
## 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 non-fungible token objects:
|
|
|
|
1. 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](nftokenmint.html) for available NFT minting flags.
|
|
2. Enter the **NFT URI**. 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.
|
|
3. Enter an **NFT Count** of up to 200 NFTs to create in one batch.
|
|
4. 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.
|
|
5. Click **Batch Mint NFTs**.
|
|
|
|
## Get Batch NFTs
|
|
|
|
Click **Get Batch NFTs** to get the current list of NFTs for your account.
|
|
|
|
The difference between this function and the `getTokens()` function used earlier is that it allows for larger lists of tokens, sending multiple requests if the tokens exceed the number of objects allowed in a single request.
|
|
|
|
# Code Walkthrough
|
|
|
|
You can download or clone the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/){.github-code-download} to try each of the samples locally.
|
|
|
|
Import dependencies and define the testnet_url variable.
|
|
|
|
```python
|
|
import xrpl
|
|
from xrpl.clients import JsonRpcClient
|
|
from xrpl.wallet import Wallet
|
|
from xrpl.models.requests import AccountNFTs
|
|
|
|
testnet_url = "https://s.altnet.rippletest.net:51234"
|
|
```
|
|
|
|
## Batch Mint
|
|
|
|
Pass the values `seed`, `uri`, `flags`, `transfer_fee`, `taxon`, and `count`.
|
|
|
|
```python
|
|
def batch_mint(seed, uri, flags, transfer_fee, taxon, count):
|
|
"""batch_mint"""
|
|
```
|
|
|
|
Get the account wallet and a client instance.
|
|
|
|
```python
|
|
wallet=Wallet.from_seed(seed)
|
|
client=JsonRpcClient(testnet_url)
|
|
```
|
|
|
|
Request the full account info.
|
|
|
|
```python
|
|
acct_info = xrpl.models.requests.account_info.AccountInfo(
|
|
account=wallet.classic_address,
|
|
ledger_index='validated'
|
|
)
|
|
get_seq_request = client.request(acct_info)
|
|
|
|
```
|
|
|
|
Parse the current sequence value.
|
|
|
|
```python
|
|
current_sequence=get_seq_request.result['account_data']['Sequence']
|
|
```
|
|
|
|
Create a transaction to create tickets, starting at the current sequence number.
|
|
|
|
```python
|
|
ticket_tx=xrpl.models.transactions.TicketCreate(
|
|
account=wallet.address,
|
|
ticket_count=int(count),
|
|
sequence=current_sequence
|
|
)
|
|
```
|
|
|
|
Submit the ticket transaction and wait for the result.
|
|
|
|
```python
|
|
response=xrpl.transaction.submit_and_wait(ticket_tx,client,wallet)
|
|
```
|
|
|
|
Create a request to obtain the next ticket number.
|
|
|
|
```python
|
|
ticket_numbers_req=xrpl.models.requests.AccountObjects(
|
|
account=wallet.address,
|
|
type='ticket'
|
|
)
|
|
ticket_response=client.request(ticket_numbers_req)
|
|
```
|
|
|
|
Create the `tickets` variable to store an array of tickets.
|
|
|
|
```python
|
|
tickets=[int(0)] * int(count)
|
|
acct_objs= ticket_response.result['account_objects']
|
|
```
|
|
|
|
Create an array of ticket numbers.
|
|
|
|
```python
|
|
for x in range(int(count)):
|
|
tickets[x] = acct_objs[x]['TicketSequence']
|
|
```
|
|
|
|
Initialize variables to be used in the mint loop.
|
|
|
|
```python
|
|
reply=""
|
|
create_count=0
|
|
```
|
|
|
|
Use a `for` loop to send repeated mint requests, using the `ticket_sequence` field to uniquely identify the mint transactions.
|
|
|
|
```python
|
|
for x in range(int(count)):
|
|
mint_tx=xrpl.models.transactions.NFTokenMint(
|
|
account=wallet.classic_address,
|
|
uri=xrpl.utils.str_to_hex(uri),
|
|
flags=int(flags),
|
|
transfer_fee=int(transfer_fee),
|
|
ticket_sequence=tickets[x],
|
|
sequence=0,
|
|
nftoken_taxon=int(taxon)
|
|
)
|
|
```
|
|
Submit each transaction and report the results.
|
|
|
|
```python
|
|
try:
|
|
response=xrpl.transaction.submit_and_wait(mint_tx,client,
|
|
wallet)
|
|
create_count+=1
|
|
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
|
reply+=f"Submit failed: {e}\n"
|
|
reply+=str(create_count)+' NFTs generated.'
|
|
return reply
|
|
```
|
|
|
|
### Get Batch
|
|
|
|
This version of `getTokens()` allows for a larger set of NFTs by watching for a `marker` at the end of each batch of NFTs. Subsequent requests get the next batch of NFTs starting at the previous marker, until all NFTs are retrieved.
|
|
|
|
```python
|
|
def get_batch(seed, account):
|
|
"""get_batch"""
|
|
```
|
|
|
|
Get a client instance. Since this is a request for publicly available information, no wallet is required.
|
|
|
|
```python
|
|
client=JsonRpcClient(testnet_url)
|
|
```
|
|
|
|
Define the request for account NFTs. Set a return limit of 400 objects.
|
|
|
|
```python
|
|
acct_nfts=AccountNFTs(
|
|
account=account,
|
|
limit=400
|
|
)
|
|
```
|
|
|
|
Send the request.
|
|
|
|
```python
|
|
response=client.request(acct_nfts)
|
|
```
|
|
|
|
Capture the result in the _responses_ variable.
|
|
|
|
```python
|
|
responses=response.result
|
|
```
|
|
|
|
While there is a _marker_ value in the response, continue to define and send requests for 400 account NFTs at a time. Capture the _result_ from each request in the _responses_ variable.
|
|
|
|
```python
|
|
while(acct_nfts.marker):
|
|
acct_nfts=AccountNFTs(
|
|
account=account,
|
|
limit=400,
|
|
marker=acct_nfts.marker
|
|
)
|
|
response=client.request(acct_nfts)
|
|
responses+=response.result
|
|
```
|
|
|
|
Return the _responses_ variable.
|
|
|
|
```python
|
|
return responses
|
|
```
|
|
|
|
## lesson7-batch-minting.py
|
|
|
|
This form is based on earlier examples, with unused fields, handlers, and buttons removed. Additions are highlighted below.
|
|
|
|
```python
|
|
import tkinter as tk
|
|
import xrpl
|
|
import json
|
|
|
|
from mod1 import get_account, get_account_info, send_xrp
|
|
from mod2 import (
|
|
get_balance,
|
|
configure_account,
|
|
)
|
|
```
|
|
|
|
Import dependencies from `mod7.py`.
|
|
|
|
```python
|
|
from mod7 import batch_mint, get_batch
|
|
|
|
```
|
|
|
|
Add Module 7 handlers.
|
|
|
|
```python
|
|
|
|
def batch_mint_nfts():
|
|
results = batch_mint(
|
|
ent_standby_seed.get(),
|
|
ent_standby_uri.get(),
|
|
ent_standby_flags.get(),
|
|
ent_standby_transfer_fee.get(),
|
|
ent_standby_taxon.get(),
|
|
ent_standby_nft_count.get()
|
|
)
|
|
text_standby_results.delete("1.0", tk.END)
|
|
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
|
|
|
def get_batch_nfts():
|
|
results = get_batch(ent_standby_seed.get(), ent_standby_account.get())
|
|
text_standby_results.delete("1.0", tk.END)
|
|
text_standby_results.insert("1.0",json.dumps(results, indent=4))
|
|
|
|
# Module 2 Handlers
|
|
|
|
def standby_configure_account():
|
|
results = configure_account(
|
|
ent_standby_seed.get(),
|
|
standbyRippling)
|
|
text_standby_results.delete("1.0", tk.END)
|
|
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
|
|
|
# Module 1 Handlers
|
|
def get_standby_account():
|
|
new_wallet = get_account(ent_standby_seed.get())
|
|
ent_standby_account.delete(0, tk.END)
|
|
ent_standby_seed.delete(0, tk.END)
|
|
ent_standby_account.insert(0, new_wallet.classic_address)
|
|
ent_standby_seed.insert(0, new_wallet.seed)
|
|
|
|
def get_standby_account_info():
|
|
accountInfo = get_account_info(ent_standby_account.get())
|
|
ent_standby_balance.delete(0, tk.END)
|
|
ent_standby_balance.insert(0,accountInfo['Balance'])
|
|
text_standby_results.delete("1.0", tk.END)
|
|
text_standby_results.insert("1.0",json.dumps(accountInfo, indent=4))
|
|
```
|
|
|
|
Rename the window for Module 7.
|
|
|
|
```python
|
|
# Create a new window with the title "Quickstart Module 7"
|
|
window = tk.Tk()
|
|
window.title("Quickstart Module 7")
|
|
|
|
standbyRippling = tk.BooleanVar()
|
|
operationalRippling = tk.BooleanVar()
|
|
|
|
|
|
# Form frame
|
|
frm_form = tk.Frame(relief=tk.SUNKEN, borderwidth=3)
|
|
frm_form.pack()
|
|
|
|
# Create the Label and Entry widgets for "Standby Account"
|
|
lbl_standy_seed = tk.Label(master=frm_form, text="Standby Seed")
|
|
ent_standby_seed = tk.Entry(master=frm_form, width=50)
|
|
lbl_standby_account = tk.Label(master=frm_form, text="Standby Account")
|
|
ent_standby_account = tk.Entry(master=frm_form, width=50)
|
|
lbl_standy_amount = tk.Label(master=frm_form, text="Amount")
|
|
ent_standby_amount = tk.Entry(master=frm_form, width=50)
|
|
lbl_standby_balance = tk.Label(master=frm_form, text="XRP Balance")
|
|
ent_standby_balance = tk.Entry(master=frm_form, width=50)
|
|
cb_standby_allow_rippling = tk.Checkbutton(master=frm_form, text="Allow Rippling", variable=standbyRippling, onvalue=True, offvalue=False)
|
|
lbl_standby_uri = tk.Label(master=frm_form, text="NFT URI")
|
|
ent_standby_uri = tk.Entry(master=frm_form, width=50)
|
|
lbl_standby_flags = tk.Label(master=frm_form, text="Flags")
|
|
ent_standby_flags = tk.Entry(master=frm_form, width=50)
|
|
lbl_standby_transfer_fee = tk.Label(master=frm_form, text="Transfer Fee")
|
|
ent_standby_transfer_fee = tk.Entry(master=frm_form, width="50")
|
|
lbl_standby_taxon = tk.Label(master=frm_form, text="Taxon")
|
|
ent_standby_taxon = tk.Entry(master=frm_form, width="50")
|
|
lbl_standby_nft_id = tk.Label(master=frm_form, text="NFT ID")
|
|
ent_standby_nft_id = tk.Entry(master=frm_form, width="50")
|
|
```
|
|
|
|
Add the **NFT Count** field for batch minting.
|
|
|
|
```python
|
|
lbl_standby_nft_count=tk.Label(master=frm_form, text="NFT Count")
|
|
ent_standby_nft_count=tk.Entry(master=frm_form, width="50")
|
|
lbl_standby_results = tk.Label(master=frm_form,text="Results")
|
|
text_standby_results = tk.Text(master=frm_form, height = 20, width = 65)
|
|
|
|
# Place field in a grid.
|
|
lbl_standy_seed.grid(row=0, column=0, sticky="w")
|
|
ent_standby_seed.grid(row=0, column=1)
|
|
lbl_standby_account.grid(row=2, column=0, sticky="e")
|
|
ent_standby_account.grid(row=2, column=1)
|
|
lbl_standy_amount.grid(row=3, column=0, sticky="e")
|
|
ent_standby_amount.grid(row=3, column=1)
|
|
lbl_standby_balance.grid(row=5, column=0, sticky="e")
|
|
ent_standby_balance.grid(row=5, column=1)
|
|
cb_standby_allow_rippling.grid(row=7,column=1, sticky="w")
|
|
lbl_standby_uri.grid(row=8, column=0, sticky="e")
|
|
ent_standby_uri.grid(row=8, column=1, sticky="w")
|
|
lbl_standby_flags.grid(row=9, column=0, sticky="e")
|
|
ent_standby_flags.grid(row=9, column=1, sticky="w")
|
|
lbl_standby_transfer_fee.grid(row=10, column=0, sticky="e")
|
|
ent_standby_transfer_fee.grid(row=10, column=1, sticky="w")
|
|
lbl_standby_taxon.grid(row=11, column=0, sticky="e")
|
|
ent_standby_taxon.grid(row=11, column=1, sticky="w")
|
|
lbl_standby_nft_id.grid(row=12, column=0, sticky="e")
|
|
ent_standby_nft_id.grid(row=12, column=1, sticky="w")
|
|
```
|
|
|
|
Place the **NFT Count** field in the grid.
|
|
|
|
```python
|
|
lbl_standby_nft_count.grid(row=13, column=0, sticky="e")
|
|
ent_standby_nft_count.grid(row=13, column=1, sticky="w")
|
|
lbl_standby_results.grid(row=14, column=0, sticky="ne")
|
|
text_standby_results.grid(row=14, column=1, sticky="nw")
|
|
cb_standby_allow_rippling.select()
|
|
|
|
#############################################
|
|
## Buttons ##################################
|
|
#############################################
|
|
|
|
# Create the Standby Account Buttons
|
|
btn_get_standby_account = tk.Button(master=frm_form, text="Get Standby Account",
|
|
command = get_standby_account)
|
|
btn_get_standby_account.grid(row=0, column=2, sticky = "nsew")
|
|
btn_get_standby_account_info = tk.Button(master=frm_form,
|
|
text="Get Standby Account Info",
|
|
command = get_standby_account_info)
|
|
btn_get_standby_account_info.grid(row=1, column=2, sticky = "nsew")
|
|
btn_standby_configure_account = tk.Button(master=frm_form,
|
|
text="Configure Account",
|
|
command = standby_configure_account)
|
|
btn_standby_configure_account.grid(row=7,column=0, sticky = "nsew")
|
|
```
|
|
|
|
Add the **Batch Mint NFTs** and **Get Batch NFTs** buttons.
|
|
|
|
```python
|
|
btn_standby_mint_token = tk.Button(master=frm_form, text="Batch Mint NFTs",
|
|
command = batch_mint_nfts)
|
|
btn_standby_mint_token.grid(row=8, column=2, sticky="nsew")
|
|
btn_standby_get_tokens = tk.Button(master=frm_form, text="Get Batch NFTs",
|
|
command = get_batch_nfts)
|
|
btn_standby_get_tokens.grid(row=9, column=2, sticky="nsew")
|
|
|
|
# Start the application
|
|
window.mainloop()
|
|
|
|
``` |