Quickstart Python draft

This commit is contained in:
ddawson
2023-05-17 17:26:37 -07:00
parent e5bcfdae9a
commit ace77f4660
18 changed files with 1609 additions and 1 deletions

View File

@@ -55,7 +55,7 @@ To transfer XRP from the Standby account to the Operational account:
To transfer XRP from the Operational account to the Standby account:
1. On the Operational (right) side of the form, enter the **Amount** of XRP to send.
2. Copy and paste the **Standby Account** field to the Standby **Destination** field.
2. Copy and paste the **Standby Account** field to the Operational **Destination** field.
3. Click **<Send XRP** to transfer XRP from the Operational account to the Standby account.
[![Transferred XRP](img/quickstart4.png)](img/quickstart4.png)

View File

@@ -0,0 +1,432 @@
---
html: py-create-accounts-send-xrp.html
parent: xrpl-quickstart.html
blurb: Quickstart 1, create two accounts and transfer XRP between them.
labels:
- Accounts
- Quickstart
- Transaction Sending
- XRP
---
# 1. Create Accounts and Send XRP (Python)
This example shows how to:
1. Create accounts on the Testnet, funded with 1000 test XRP with no actual value.
2. Retrieve the accounts from seed values.
3. Transfer XRP between accounts.
When you create an account, you receive a public/private key pair offline. Your account does not appear on the ledger until it is funded with XRP. This example shows how to create accounts for Testnet, but not how to create an account that you can use on Mainnet.
[![Token Test Harness](img/quickstart-py2.png)](img/quickstart-py2.png)
## Prerequisites
To get started, create a new folder on your local disk and install the Python library using `pip`.
```
pip3 install xrpl-py
```
Download and expand the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/js/quickstart.zip){.github-code-download} archive.
**Note:** Without the Quickstart Samples, you will not be able to try the examples that follow.
## Usage
To get test accounts:
1. Open and launch `lesson1-send-xrp.py`.
2. Click **Get Standby Account**.
3. Click **Get Operational Account**.
4. Click **Get Standby Account Info**.
5. Click **Get Operational Account Info**.
5. Copy and paste the **Standby Seed** and **Operational Seed** fields to a persistent location, such as a Notepad, so that you can reuse the accounts after reloading the form.
[![Standby and Operational Accounts](img/quickstart-py3.png)](img/quickstart-py3.png)
You can transfer XRP between your new accounts. Each account has its own fields and buttons.
To transfer XRP from the Standby account to the Operational account:
1. On the Standby (left) side of the form, enter the **Amount** of XRP to send.
2. Copy and paste the **Operational Account** field to the Standby **Destination** field.
3. Click **Send XRP>** to transfer XRP from the standby account to the operational account
[![Transferred XRP](img/quickstart-py4.png)](img/quickstart-py4.png)
To transfer XRP from the Operational account to the Standby account:
1. On the Operational (right) side of the form, enter the **Amount** of XRP to send.
2. Copy and paste the **Standby Account** field to the Operational **Destination** field.
3. Click **<Send XRP** to transfer XRP from the Operational account to the Standby account.
# Code Walkthrough
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/js/quickstart.zip){.github-code-download} in the source repository for this website.
## mod1.py
The mod1.py module contains the business logic for interacting with the XRP Ledger.
Import the XRPL and JSON libraries.
```python
import xrpl
import json
```
### getAccount
This method lets you get an existing account by providing a seed value. If you provide no seed value, the method creates a new account for you.
Import required methods.
```python
def getAccount(_seed):
from xrpl.clients import JsonRpcClient
from xrpl.wallet import Wallet
```
This example uses the _Testnet_ ledger. You can update the URI to choose a different XRP Ledger instance.
```python
JSON_RPC_URL = "https://s.altnet.rippletest.net:51234/"
```
Request a new client from the XRP Ledger.
```python
client = JsonRpcClient(JSON_RPC_URL)
```
If you do not enter a seed, generate and return a new wallet. If you provide a seed value, return the wallet for that seed.
```python
if (_seed == ''):
new_wallet = xrpl.wallet.generate_faucet_wallet(client)
else:
new_wallet = Wallet(_seed, sequence = 79396029)
return(new_wallet)
```
### getAccountInfo
Pass the account ID to the getAccountInfo method.
```python
def getAccountInfo(_accountId):
```
Import required methods and the JSON library.
```python
from xrpl.clients import JsonRpcClient
from xrpl.models.requests.account_info import AccountInfo
import json
```
Get a client instance from Testnet.
```python
JSON_RPC_URL = 'wss://s.altnet.rippletest.net:51234'
client = JsonRpcClient(JSON_RPC_URL)
```
Create the account info request, passing the account ID and the ledger index (in this case, the latest validated ledger).
```python
acct_info = AccountInfo(
account=_accountId,
ledger_index="validated"
)
```
Send the request to the XRP Ledger instance.
```python
response = client.request(acct_info)
```
Return the account data.
```python
return response.result['account_data']
```
### sendXRP
Transfer XRP to another account by passing the client seed, amount to transfer, and the destination account.
```python
def sendXRP(_seed, _amount, _destination):
```
Get the sending wallet.
```python
from xrpl.clients import JsonRpcClient
from xrpl.wallet import Wallet
sending_wallet = Wallet(_seed, sequence = 16237283)
testnet_url = "https://s.altnet.rippletest.net:51234"
client = JsonRpcClient(testnet_url)
```
Create a transaction request, passing the sending account, amount, and destination account.
```python
payment = xrpl.models.transactions.Payment(
account=sending_wallet.classic_address,
amount=xrpl.utils.xrp_to_drops(int(_amount)),
destination=_destination,
)
```
Sign the transaction.
```python
signed_tx = xrpl.transaction.safe_sign_and_autofill_transaction(
payment, sending_wallet, client)
```
Submit the transaction and return the response. If the transaction fails, return the error message.
```python
try:
tx_response = xrpl.transaction.send_reliable_submission(signed_tx,client)
response = tx_response
except xrpl.transaction.XRPLReliableSubmissionException as e:
response = f"Submit failed: {e}"
return response
```
## lesson1-send-xrp.py
This module handles the UI for the application, providing fields for entering and reporting results of transactions and requests.
Import the tkinter, xrpl, and json modules.
```python
import tkinter as tk
import xrpl
import json
```
Import the methods from mod1.py.
```python
from mod1 import getAccount
from mod1 import getAccountInfo
from mod1 import sendXRP
```
### getStandbyAccount
```python
def getStandbyAccount():
```
Use the value in the standby Seed field (or an empty value) to request a new account.
```python
new_wallet = getAccount(ent_standby_seed.get())
```
Clear the **Standby Seed** and **Standby Account** fields.
```python
ent_standby_account.delete(0, tk.END)
ent_standby_seed.delete(0, tk.END)
```
Insert the account ID and seed values in the standby fields.
```python
ent_standby_account.insert(0, new_wallet.classic_address)
ent_standby_seed.insert(0, new_wallet.seed)
```
### get StandbyAccountInfo
With an account ID, anyone can request information about the account. Get the standby account value and use it to populate a `getAccountInfo` request.
```python
def getStandbyAccountInfo():
accountInfo = getAccountInfo(ent_standby_account.get())
```
Clear the Standby **Balance** field and insert the value from the account info response.
```python
ent_standby_balance.delete(0, tk.END)
ent_standby_balance.insert(0,accountInfo['Balance'])
```
Clear the Standby **Results** text area and fill it with the full JSON response.
```python
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0",json.dumps(accountInfo, indent=4))
```
### standbySendXRP
```python
def standbySendXRP():
```
```python
Call the sendXRP method, passing the standby seed, the amount, and the destination value.
response = sendXRP(ent_standby_seed.get(),ent_standby_amount.get(),
ent_standby_destination.get())
```
Clear the standby **Results** field and insert the JSON response.
```python
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0",json.dumps(response.result, indent=4))
```
Use `getStandbyAccountInfo()` and `getOperationalAccountInfo()` to update the balance field for both accounts.
```python
getStandbyAccountInfo()
getOperationalAccountInfo()
```
### Reciprocal Transactions and Requests
The following four methods are the same as the previous standby transactions, but for the operational account.
```python
def getOperationalAccount():
new_wallet = getAccount(ent_operational_seed.get())
ent_operational_account.delete(0, tk.END)
ent_operational_account.insert(0, new_wallet.classic_address)
ent_operational_seed.delete(0, tk.END)
ent_operational_seed.insert(0, new_wallet.seed)
def getOperationalAccountInfo():
accountInfo = getAccountInfo(ent_operational_account.get())
ent_operational_balance.delete(0, tk.END)
ent_operational_balance.insert(0,accountInfo['Balance'])
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0",json.dumps(accountInfo, indent=4))
def operationalSendXRP():
response = sendXRP(ent_operational_seed.get(),ent_operational_amount.get(), ent_operational_destination.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0",json.dumps(response.result,indent=4))
getStandbyAccountInfo()
getOperationalAccountInfo()
```
Create UI elements, starting with the main window.
```python
window = tk.Tk()
window.title("Quickstart Module 1")
```
Add a frame for the form.
```python
frm_form = tk.Frame(relief=tk.SUNKEN, borderwidth=3)
frm_form.pack()
```
Create the `Label` and `Entry` widgets for the standby account.
```python
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_standby_balance = tk.Label(master=frm_form, text="XRP Balance")
ent_standby_balance = 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_destination = tk.Label(master=frm_form, text="Destination")
ent_standby_destination = 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 the fields in a grid.
```python
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_destination.grid(row=4, column=0, sticky="e")
ent_standby_destination.grid(row=4, column=1)
lbl_standby_balance.grid(row=5, column=0, sticky="e")
ent_standby_balance.grid(row=5, column=1)
lbl_standby_results.grid(row=6, column=0, sticky="ne")
text_standby_results.grid(row=6, column=1, sticky="nw")
```
Create the `Label` and `Entry` widgets for the operational account
```python
lbl_operational_seed = tk.Label(master=frm_form, text="Operational Seed")
ent_operational_seed = tk.Entry(master=frm_form, width=50)
lbl_operational_account = tk.Label(master=frm_form, text="Operational Account")
ent_operational_account = tk.Entry(master=frm_form, width=50)
lbl_operational_balance = tk.Label(master=frm_form, text="XRP Balance")
ent_operational_balance = tk.Entry(master=frm_form, width=50)
lbl_operational_amount = tk.Label(master=frm_form, text="Amount")
ent_operational_amount = tk.Entry(master=frm_form, width=50)
lbl_operational_destination = tk.Label(master=frm_form, text="Destination")
ent_operational_destination = tk.Entry(master=frm_form, width=50)
lbl_operational_results = tk.Label(master=frm_form,text='Results')
text_operational_results = tk.Text(master=frm_form, height = 20, width = 65)
```
Place the operational widgets in a grid.
```python
lbl_operational_seed.grid(row=0, column=4, sticky="e")
ent_operational_seed.grid(row=0, column=5, sticky="w")
lbl_operational_account.grid(row=2,column=4, sticky="e")
ent_operational_account.grid(row=2,column=5, sticky="w")
lbl_operational_amount.grid(row=3, column=4, sticky="e")
ent_operational_amount.grid(row=3, column=5, sticky="w")
lbl_operational_destination.grid(row=4, column=4, sticky="e")
ent_operational_destination.grid(row=4, column=5, sticky="w")
lbl_operational_balance.grid(row=5, column=4, sticky="e")
ent_operational_balance.grid(row=5, column=5, sticky="w")
lbl_operational_results.grid(row=6, column=4, sticky="ne")
text_operational_results.grid(row=6, column=5, sticky="nw")
```
Create the standby account buttons and add them to the grid.
```python
btn_get_standby_account = tk.Button(master=frm_form, text="Get Standby Account", command = getStandbyAccount)
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 = getStandbyAccountInfo)
btn_get_standby_account_info.grid(row=1, column=2, sticky = "nsew")
btn_standby_send_xrp = tk.Button(master=frm_form, text="Send XRP >", command = standbySendXRP)
btn_standby_send_xrp.grid(row=2, column = 2, sticky = "nsew")
```
Create the operational account buttons and add them to the grid.
```python
btn_get_operational_account = tk.Button(master=frm_form, text="Get Operational Account", command = getOperationalAccount)
btn_get_operational_account.grid(row=0, column=3, sticky = "nsew")
btn_get_op_account_info = tk.Button(master=frm_form, text="Get Op Account Info", command = getOperationalAccountInfo)
btn_get_op_account_info.grid(row=1, column=3, sticky = "nsew")
btn_op_send_xrp = tk.Button(master=frm_form, text="< Send XRP", command = operationalSendXRP)
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
```
Start the application.
```python
window.mainloop()
```

View File

@@ -0,0 +1,574 @@
---
html: py-create-trustline-send-currency.html
parent: xrpl-quickstart.html
blurb: Quickstart step 2, create trust lines and send currency.
labels:
- Cross-Currency
- Payments
- Quickstart
- Tokens
---
# 2. Create Trust Line and Send Currency (Python)
This example shows how to:
1. Configure accounts to allow transfer of funds to third party accounts.
2. Set a currency type for transactions.
3. Create a trust line between the standby account and the operational account.
4. Send issued currency between accounts.
5. Display account balances for all currencies.
[![Test harness with currency transfer](img/quickstart-py5.png)](img/quickstart-py5.png)
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/js/quickstart.zip){.github-code-download} archive to try each of the samples in your own browser.
**Note:** Without the Quickstart Samples, you will not be able to try the examples that follow.
## Usage
Open the Quickstart window and get accounts:
1. Open and run `lesson2-send-currency.py`.
2. Get test accounts.
1. If you have existing account seeds
1. Paste account seeds in the **Seeds** field.
2. Click **Get Accounts from Seeds**.
2. If you do not have account seeds:
1. Click **Get New Standby Account**.
2. Click **Get New Operational Account**.
## Create Trust Line
To create a trust line between accounts:
1. Enter a [currency code](https://www.iban.com/currency-codes) in the **Currency** field.
2. Enter the maximum transfer limit in the **Amount** field.
3. Enter the destination account value in the **Destination** field.
4. Click **Create Trust Line**.
[![Trust line results](img/quickstart-py6.png)](img/quickstart-py6.png)
## Send an Issued Currency Token
To transfer an issued currency token, once you have created a trust line:
1. Enter the **Amount**.
2. Enter the **Destination**.
3. Enter the **Currency** type.
4. Click **Send Currency**.
[![Currency transfer](img/quickstart-py7.png)](img/quickstart-py7.png)
### Configure Account
When transferring fiat currency, the actual transfer of funds is not simultaneous, as it is with XRP. If currency is transferred to a third party for a different currency, there can be a devaluation of the currency that impacts the originating account. To avoid this situation, this up and down valuation of currency, known as _rippling_, is not allowed by default. Currency transferred from one account can only be transferred back to the same account. To enable currency transfer to third parties, you need to set the `rippleDefault` value to true. The Token Test Harness provides a checkbox to enable or disable rippling.
To enable rippling:
1. Select the **Allow Rippling** checkbox.
2. Click **Configure Account**.
Verify the setting by looking for the _Set Flag_ value in the response, which should show a flag setting of _8_.
[![Configure Account - Enable Rippling](img/quickstart-py8.png)](img/quickstart-py8.png)
To disable rippling:
1. Deselect the **Allow Rippling** checkbox.
2. Click **Configure Account**.
Verify the setting by looking for the _Clear Flag_ value in the response, which shold show a flag setting of _8_.
[![Configure Account - Disable Rippling](img/quickstart-py9.png)](img/quickstart-py9.png)
# Code Walkthrough
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/js/quickstart.zip){.github-code-download} archive to try each of the samples.
## mod2.py
Module 2 provides the logic for creating trust lines and sending currency tokens between accounts.
Import dependencies and set the _testnet___url_.
```python
import xrpl
import json
from xrpl.clients import JsonRpcClient
from xrpl.wallet import Wallet
testnet_url = "https://s.altnet.rippletest.net:51234"
```
### Create Trust Line
Pass the wallet seed, the issuer account, the currency code, and the maximum amount of currency to send.
```python
def createTrustline(_seed, _issuer, _currency, _amount):
```
Get the wallet and a new client instance.
```python
receiving_wallet = Wallet(_seed, sequence = 16237283)
client = JsonRpcClient(testnet_url)
```
Define the `TrustSet` transaction.
```python
trustline_tx = xrpl.models.transactions.TrustSet(
account = receiving_wallet.classic_address,
limit_amount = xrpl.models.amounts.IssuedCurrencyAmount(
currency = _currency,
issuer = _issuer,
value = int(_amount)
)
)
```
Sign the transaction.
```python
signed_tx = xrpl.transaction.safe_sign_and_autofill_transaction(
trustline_tx, receiving_wallet, client)
```
Submit the transaction to the XRP Ledger.
```python
try:
response = xrpl.transaction.send_reliable_submission(signed_tx,client)
except xrpl.transaction.XRPLReliableSubmissionException as e:
response = f"Submit failed: {e}"
```
Return the results.
```python
return response.result
```
## sendCurrency
Send currency to another account based on the sender wallet, destination account, the currency type, and the amount of the currency.
```python
def sendCurrency(_seed, _destination, _currency, _amount):
```
Get the sending wallet and a client instance on Testnet.
```python
sending_wallet = Wallet(_seed, sequence = 16237283)
client = JsonRpcClient(testnet_url)
```
Define the payment transaction. The amount requires further description to identify the type of currency and issuer.
```python
send_currency_tx = xrpl.models.transactions.Payment(
account = sending_wallet.classic_address,
amount = xrpl.models.amounts.IssuedCurrencyAmount(
currency = _currency,
value = int(_amount),
issuer = sending_wallet.classic_address
),
destination=_destination
)
```
Sign and fill the transaction.
```python
signed_tx = xrpl.transaction.safe_sign_and_autofill_transaction(
send_currency_tx, sending_wallet, client)
```
Submit the transaction and get the response.
```python
try:
response = xrpl.transaction.send_reliable_submission(signed_tx,client)
except xrpl.transaction.XRPLReliableSubmissionException as e:
response = f"Submit failed: {e}"
```
Return the JSON response, or an error message if the transaction fails.
```python
return response.result
```
### getBalances
Update the **XRP Balance** fields and list the balance information for issued currencies in the **Results** text areas.
```python
def getBalance(_sb_account_id, _op_account_id):
```
Import the `account_info` request model.
```python
from xrpl.models.requests.account_info import AccountInfo
```
Connect to the XRP Ledger and instantiate a client.
```python
JSON_RPC_URL = 'wss://s.altnet.rippletest.net:51234'
client = JsonRpcClient(JSON_RPC_URL)
```
Create the `GatewayBalances` request.
```python
balance = xrpl.models.requests.GatewayBalances(
account=_sb_account_id ,
strict=True,
ledger_index="validated",
hotwallet=[_op_account_id]
)
```
Return the result.
```python
response = client.request(balance)
return response.result
```
### configureAccount
This example shows how to set and clear configuration flags using the `AccountSet` method. The `ASF_DEFAULT_RIPPLE` flag is pertinent to experimentation with transfer of issued currencies to third-party accounts, so it is demonstrated here. You can set any of the configuration flags using the same structure, substituting the particular flags you want to set. See [AccountSet Flags](accountset.html).
Send the account seed and a Boolean value for whether to enable or disable rippling.
```python
def configureAccount(_seed, _default_setting):
```
Get the account wallet and instantiate a client.
```python
wallet = Wallet(_seed, sequence = 16237283)
client = JsonRpcClient(testnet_url)
```
If `_default_setting` is true, create a `set_flag` transaction to enable rippling. If false, create a `clear_flag` transaction to disable rippling.
```python
if (_default_setting.get()):
setting_tx = xrpl.models.transactions.AccountSet(
account = wallet.classic_address,
set_flag=xrpl.models.transactions.AccountSetFlag.ASF_DEFAULT_RIPPLE
)
else:
setting_tx = xrpl.models.transactions.AccountSet(
account = wallet.classic_address,
clear_flag = xrpl.models.transactions.AccountSetFlag.ASF_DEFAULT_RIPPLE
)
```
Sign and fill the transaction.
```python
signed_tx = xrpl.transaction.safe_sign_and_autofill_transaction(
setting_tx, wallet, client)
```
Submit the transaction and get results.
```python
try:
response = xrpl.transaction.send_reliable_submission(signed_tx,client)
except xrpl.transaction.XRPLReliableSubmissionException as e:
response.result = f"Submit failed: {e}"
```
Return the results.
```python
return response.result
```
## lesson2-send-currency.py
This module builds on `lesson1-send-xrp.py`. Changes are noted below.
```python
import tkinter as tk
import xrpl
import json
```
Import methods from `mod2.py`.
```python
from mod2 import createTrustLine
from mod2 import sendCurrency
from mod2 import getBalance
from mod2 import configureAccount
from mod1 import getAccount
from mod1 import getAccountInfo
from mod1 import sendXRP
#############################################
## Handlers #################################
#############################################
```
Module 2 Handlers.
```python
def standbyCreateTrustLine():
results = createTrustLine(ent_standby_seed.get(),
ent_standby_destination.get(),
ent_standby_currency.get(),
ent_standby_amount.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def standbySendCurrency():
results = sendCurrency(ent_standby_seed.get(),
ent_standby_destination.get(),
ent_standby_currency.get(),
ent_standby_amount.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def standbyConfigureAccount():
results = configureAccount(
ent_standby_seed.get(),
standbyRippling)
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def operationalCreateTrustLine():
results = createTrustLine(ent_operational_seed.get(),
ent_operational_destination.get(),
ent_operational_currency.get(),
ent_operational_amount.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def operationalSendCurrency():
results = sendCurrency(ent_operational_seed.get(),
ent_operational_destination.get(),
ent_operational_currency.get(),
ent_operational_amount.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def operationalConfigureAccount():
results = configureAccount(
ent_operational_seed.get(),
operationalRippling)
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def getBalances():
results = getBalance(ent_operational_account.get(), ent_standby_account.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
results = getBalance(ent_standby_account.get(), ent_operational_account.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
# Module 1 Handlers
def getStandbyAccount():
new_wallet = getAccount(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 getStandbyAccountInfo():
accountInfo = getAccountInfo(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))
def standbySendXRP():
response = sendXRP(ent_standby_seed.get(),ent_standby_amount.get(), ent_standby_destination.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0",json.dumps(response.result, indent=4))
getStandbyAccountInfo()
getOperationalAccountInfo()
def getOperationalAccount():
new_wallet = getAccount(ent_operational_seed.get())
ent_operational_account.delete(0, tk.END)
ent_operational_account.insert(0, new_wallet.classic_address)
ent_operational_seed.delete(0, tk.END)
ent_operational_seed.insert(0, new_wallet.seed)
def getOperationalAccountInfo():
accountInfo = getAccountInfo(ent_operational_account.get())
ent_operational_balance.delete(0, tk.END)
ent_operational_balance.insert(0,accountInfo['Balance'])
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0",json.dumps(accountInfo, indent=4))
def operationalSendXRP():
response = sendXRP(ent_operational_seed.get(),ent_operational_amount.get(), ent_operational_destination.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0",json.dumps(response.result,indent=4))
getStandbyAccountInfo()
getOperationalAccountInfo()
# Create a new window with the title "Quickstart Module 2"
window = tk.Tk()
window.title("Quickstart Module 2")
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_standby_balance = tk.Label(master=frm_form, text="XRP Balance")
ent_standby_balance = 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_destination = tk.Label(master=frm_form, text="Destination")
ent_standby_destination = tk.Entry(master=frm_form, width=50)
```
Add **Currency** field.
```python
lbl_standby_currency = tk.Label(master=frm_form, text="Currency")
ent_standby_currency = tk.Entry(master=frm_form, width=50)
```
Add checkbox to **Allow Rippling**.
```python
cb_standby_allow_rippling = tk.Checkbutton(master=frm_form, text="Allow Rippling", variable=standbyRippling, onvalue=True, offvalue=False)
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_destination.grid(row=4, column=0, sticky="e")
ent_standby_destination.grid(row=4, column=1)
lbl_standby_balance.grid(row=5, column=0, sticky="e")
ent_standby_balance.grid(row=5, column=1)
```
Place new UI elements.
```python
lbl_standby_currency.grid(row=6, column=0, sticky="e")
ent_standby_currency.grid(row=6, column=1)
cb_standby_allow_rippling.grid(row=7,column=1, sticky="w")
lbl_standby_results.grid(row=8, column=0, sticky="ne")
text_standby_results.grid(row=8, column=1, sticky="nw")
cb_standby_allow_rippling.select()
###############################################
## Operational Account ########################
###############################################
# Create the Label and Entry widgets for "Operational Account"
lbl_operational_seed = tk.Label(master=frm_form, text="Operational Seed")
ent_operational_seed = tk.Entry(master=frm_form, width=50)
lbl_operational_account = tk.Label(master=frm_form, text="Operational Account")
ent_operational_account = tk.Entry(master=frm_form, width=50)
lbl_operational_balance = tk.Label(master=frm_form, text="XRP Balance")
ent_operational_balance = tk.Entry(master=frm_form, width=50)
lbl_operational_amount = tk.Label(master=frm_form, text="Amount")
ent_operational_amount = tk.Entry(master=frm_form, width=50)
lbl_operational_destination = tk.Label(master=frm_form, text="Destination")
ent_operational_destination = tk.Entry(master=frm_form, width=50)
```
Add field for **Currency** and checkbox to **Allow Rippling**.
```python
lbl_operational_currency = tk.Label(master=frm_form, text="Currency")
ent_operational_currency = tk.Entry(master=frm_form, width=50)
cb_operational_allow_rippling = tk.Checkbutton(master=frm_form, text="Allow Rippling", variable=operationalRippling, onvalue=True, offvalue=False)
lbl_operational_results = tk.Label(master=frm_form,text='Results')
text_operational_results = tk.Text(master=frm_form, height = 20, width = 65)
#Place the widgets in a grid
lbl_operational_seed.grid(row=0, column=4, sticky="e")
ent_operational_seed.grid(row=0, column=5, sticky="w")
lbl_operational_account.grid(row=2,column=4, sticky="e")
ent_operational_account.grid(row=2,column=5, sticky="w")
lbl_operational_amount.grid(row=3, column=4, sticky="e")
ent_operational_amount.grid(row=3, column=5, sticky="w")
lbl_operational_destination.grid(row=4, column=4, sticky="e")
ent_operational_destination.grid(row=4, column=5, sticky="w")
lbl_operational_balance.grid(row=5, column=4, sticky="e")
ent_operational_balance.grid(row=5, column=5, sticky="w")
```
Add elements to the UI.
```python
lbl_operational_currency.grid(row=6, column=4, sticky="e")
ent_operational_currency.grid(row=6, column=5)
cb_operational_allow_rippling.grid(row=7,column=5, sticky="w")
lbl_operational_results.grid(row=8, column=4, sticky="ne")
text_operational_results.grid(row=8, column=5, sticky="nw")
cb_operational_allow_rippling.select()
#############################################
## Buttons ##################################
#############################################
# Create the Standby Account Buttons
btn_get_standby_account = tk.Button(master=frm_form, text="Get Standby Account", command = getStandbyAccount)
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 = getStandbyAccountInfo)
btn_get_standby_account_info.grid(row=1, column=2, sticky = "nsew")
btn_standby_send_xrp = tk.Button(master=frm_form, text="Send XRP >", command = standbySendXRP)
btn_standby_send_xrp.grid(row=2, column=2, sticky = "nsew")
```
Add buttons **Create Trust Line**, **Send Currency**, **Get Balances**, and **Configure Account**.
```python
btn_standby_create_trustline = tk.Button(master=frm_form, text="Create Trust Line", command = standbyCreateTrustLine)
btn_standby_create_trustline.grid(row=3, column=2, sticky = "nsew")
btn_standby_send_currency = tk.Button(master=frm_form, text="Send Currency >", command = standbySendCurrency)
btn_standby_send_currency.grid(row=4, column=2, sticky = "nsew")
btn_standby_send_currency = tk.Button(master=frm_form, text="Get Balances", command = getBalances)
btn_standby_send_currency.grid(row=5, column=2, sticky = "nsew")
btn_standby_configure_account = tk.Button(master=frm_form, text="Configure Account", command = standbyConfigureAccount)
btn_standby_configure_account.grid(row=7,column=0, sticky = "nsew")
# Create the Operational Account Buttons
btn_get_operational_account = tk.Button(master=frm_form, text="Get Operational Account", command = getOperationalAccount)
btn_get_operational_account.grid(row=0, column=3, sticky = "nsew")
btn_get_op_account_info = tk.Button(master=frm_form, text="Get Op Account Info", command = getOperationalAccountInfo)
btn_get_op_account_info.grid(row=1, column=3, sticky = "nsew")
btn_op_send_xrp = tk.Button(master=frm_form, text="< Send XRP", command = operationalSendXRP)
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
```
Add operational buttons **Create Trust Line**, **Send Currency**, **Get Balances**, and **Configure Account**.
```python
btn_op_create_trustline = tk.Button(master=frm_form, text="Create Trust Line", command = operationalCreateTrustLine)
btn_op_create_trustline.grid(row=3, column=3, sticky = "nsew")
btn_op_send_currency = tk.Button(master=frm_form, text="< Send Currency", command = operationalSendCurrency)
btn_op_send_currency.grid(row=4, column=3, sticky = "nsew")
btn_op_get_balances = tk.Button(master=frm_form, text="Get Balances", command = getBalances)
btn_op_get_balances.grid(row=5, column=3, sticky = "nsew")
btn_op_configure_account = tk.Button(master=frm_form, text="Configure Account", command = operationalConfigureAccount)
btn_op_configure_account.grid(row=7,column=4, sticky = "nsew")
# Start the application
window.mainloop()
```

View File

@@ -0,0 +1,584 @@
---
html: py-mint-and-burn-nftokens.html
parent: xrpl-quickstart.html
blurb: Quickstart step 3, mint and burn NFTokens.
labels:
- Quickstart
- Tokens
- Non-fungible tokens, NFTs
---
# 3. Mint and Burn NFTokens (Python)
This example shows how to:
1. Mint new Non-fungible Tokens (NFTs).
2. Get a list of existing NFTs.
3. Delete (Burn) an NFT.
[![Quickstart 3 interface with mint NFT fields](img/quickstart-py10.png)](img/quickstart-py10.png)
# Usage
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/js/quickstart.zip){.github-code-download} archive to try the sample in your own browser.
## Get Accounts
1. Open and run `lesson3-mint-token.py`.
2. Get test accounts.
1. If you have existing Testnet account seeds:
1. Paste the account seeds in the **Seed** fields.
2. Click **Get Standby Account**.
3. Click **Get Operational Account**.
2. If you do not have existing Testnet accounts:
1. Click **Get New Standby Account**.
2. Click **Get New Operational Account**.
3. Click **Get Standby Account Info**.
4. Click **Get Op Account Info**.
[![Get accounts](img/quickstart-py11.png)](img/quickstart-py11.png)
## Mint an NFT
To mint a non-fungible token object:
1. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_. This sets the _tsTransferable_ flag, meaning that the NFT can be transferred to another account. Otherwise, the NFT can only be transferred back to the issuing account. See [NFToken Mint](https://xrpl.org/nftokenmint.html#:~:text=Example%20NFTokenMint%20JSON-,NFTokenMint%20Fields,-NFTokenMint%20Flags) for information about all of the available flags for minting NFTokens.
2. Enter the **NFT URI**. This is a URI that points to the data or metadata associated with the NFT. You can use the sample URI provided if you do not have one of your own.
3. Enter the **Transfer Fee**, a percentage of the proceeds from future sales of the NFToken that will be returned to the original creator. This is a value of 0-50000 inclusive, allowing transfer rates between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFToken to be transferrable, set this field to 0.
4. Optionally a **Taxon** value as an integer. If you choose not to use a taxon, enter _0_.
4. Click **Mint NFToken**.
[![Mint NFToken fields](img/quickstart-py12.png)](img/quickstart-py12.png)
## Get Tokens
Click **Get NFTokens** to get a list of NFTokens owned by the account.
[![Get NFTokens](img/quickstart-py13.png)](img/quickstart-py13.png)
## Burn a Token
The current owner of an NFT can always destroy (or _burn_) an NFT.
To permanently destroy an NFT:
1. Enter the **Token ID**.
2. Click **Burn NFToken**.
[![Burn NFTokens](img/quickstart-py14.png)](img/quickstart-py14.png)
# Code Walkthrough
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/js/quickstart.zip){.github-code-download} archive to examine the code samples.
## mod3.py
This module contains the new methods `mintToken()`, `getTokens()`, and `burnToken()`.
Import dependencies and set global variable.
```python
import xrpl
import json
from xrpl.clients import JsonRpcClient
from xrpl.wallet import Wallet
testnet_url = "https://s.altnet.rippletest.net:51234"
```
## mintToken
Pass the arguments account seed, NFT URI, transaction flags, the transfer fee, and optional taxon.
```python
def mintToken(_seed, _uri, _flags, _transfer_fee, _taxon):
```
Get the account wallet and a client instance.
```python
mint_wallet = Wallet(_seed, sequence = 16237283)
client = JsonRpcClient(testnet_url)
```
Define the mint transaction. Note that the NFT URI must be converted to a hex string.
```python
mint_tx = xrpl.models.transactions.NFTokenMint(
account = mint_wallet.classic_address,
uri = xrpl.utils.str_to_hex(_uri),
flags = int(_flags),
transfer_fee = int(_transfer_fee),
nftoken_taxon = int(_taxon)
)
```
Sign and fill the transaction.
```python
signed_tx = xrpl.transaction.safe_sign_and_autofill_transaction(
mint_tx, mint_wallet, client)
```
Submit the transaction and return results.
```python
try:
response = xrpl.transaction.send_reliable_submission(signed_tx,client)
except xrpl.transaction.XRPLReliableSubmissionException as e:
response = f"Submit failed: {e}"
return response.result
```
## getTokens
```python
def getTokens(_account):
```
Import dependencies and declare variable.
```python
from xrpl.clients import JsonRpcClient
from xrpl.models.requests import AccountNFTs
import json
```
Instantiate a client.
```python
client = JsonRpcClient(testnet_url)
```
Prepare the `AccountNFTs` request.
```python
acct_nfts = AccountNFTs(
account=_account
)
```
Send the request and return the result.
```python
response = client.request(acct_nfts)
return response.result
```
## burnToken
Pass the owner's seed value and the NFT ID.
```python
def burnToken(_seed, _nftoken_id):
```
Get the owner wallet and client instance.
```python
owner_wallet = Wallet(_seed, sequence = 16237283)
client = JsonRpcClient(testnet_url)
```
Define the NFTokenBurn transaction.
```python
burn_tx = xrpl.models.transactions.NFTokenBurn(
account = owner_wallet.classic_address,
nftoken_id = _nftoken_id
)
```
Sign and fill the transaction.
```python
signed_tx = xrpl.transaction.safe_sign_and_autofill_transaction(
burn_tx, owner_wallet, client)
```
Submit the transaction and return results.
```python
try:
response = xrpl.transaction.send_reliable_submission(signed_tx,client)
except xrpl.transaction.XRPLReliableSubmissionException as e:
response = f"Submit failed: {e}"
return response.result
```
## lesson3-mint-token.py
<!-- SPELLING_IGNORE: lesson3 -->
This module builds on `lesson2-create-trustline-send-currency.py`. Changes are noted below.
```python
import tkinter as tk
import xrpl
import json
```
Import methods from `mod3.py`.
```python
from mod3 import mintToken
from mod3 import getTokens
from mod3 import burnToken
from mod2 import createTrustLine
from mod2 import sendCurrency
from mod2 import getBalance
from mod2 import configureAccount
from mod1 import getAccount
from mod1 import getAccountInfo
from mod1 import sendXRP
#############################################
## Handlers #################################
#############################################
```
Module 3 Handlers
```python
def standbyMintToken():
results = mintToken(
ent_standby_seed.get(),
ent_standby_uri.get(),
ent_standby_flags.get(),
ent_standby_transfer_fee.get(),
ent_standby_taxon.get()
)
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def standbyGetTokens():
results = getTokens(ent_standby_account.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def standbyBurnToken():
results = burnToken(
ent_standby_seed.get(),
ent_standby_nft_id.get()
)
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def operationalMintToken():
results = mintToken(
ent_operational_seed.get(),
ent_operational_uri.get(),
ent_operational_flags.get(),
ent_operational_transfer_fee.get(),
ent_operational_taxon.get()
)
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def operationalGetTokens():
results = getTokens(ent_operational_account.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def operationalBurnToken():
results = burnToken(
ent_operational_seed.get(),
ent_operational_nft_id.get()
)
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
# Module 2 Handlers
def standbyCreateTrustline():
results = createTrustline(ent_standby_seed.get(),
ent_standby_destination.get(),
ent_standby_currency.get(),
ent_standby_amount.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def standbySendCurrency():
results = sendCurrency(ent_standby_seed.get(),
ent_standby_destination.get(),
ent_standby_currency.get(),
ent_standby_amount.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def standbyConfigureAccount():
results = configureAccount(
ent_standby_seed.get(),
standbyRippling)
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
def operationalCreateTrustline():
results = createTrustline(ent_operational_seed.get(),
ent_operational_destination.get(),
ent_operational_currency.get(),
ent_operational_amount.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def operationalSendCurrency():
results = sendCurrency(ent_operational_seed.get(),
ent_operational_destination.get(),
ent_operational_currency.get(),
ent_operational_amount.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def operationalConfigureAccount():
results = configureAccount(
ent_operational_seed.get(),
operationalRippling)
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
def getBalances():
results = getBalance(ent_operational_account.get(), ent_standby_account.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0", json.dumps(results, indent=4))
results = getBalance(ent_standby_account.get(), ent_operational_account.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0", json.dumps(results, indent=4))
# Module 1 Handlers
def getStandbyAccount():
new_wallet = getAccount(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 getStandbyAccountInfo():
accountInfo = getAccountInfo(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))
def standbySendXRP():
response = sendXRP(ent_standby_seed.get(),ent_standby_amount.get(), ent_standby_destination.get())
text_standby_results.delete("1.0", tk.END)
text_standby_results.insert("1.0",json.dumps(response.result, indent=4))
getStandbyAccountInfo()
getOperationalAccountInfo()
def getOperationalAccount():
new_wallet = getAccount(ent_operational_seed.get())
ent_operational_account.delete(0, tk.END)
ent_operational_account.insert(0, new_wallet.classic_address)
ent_operational_seed.delete(0, tk.END)
ent_operational_seed.insert(0, new_wallet.seed)
def getOperationalAccountInfo():
accountInfo = getAccountInfo(ent_operational_account.get())
ent_operational_balance.delete(0, tk.END)
ent_operational_balance.insert(0,accountInfo['Balance'])
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0",json.dumps(accountInfo, indent=4))
def operationalSendXRP():
response = sendXRP(ent_operational_seed.get(),ent_operational_amount.get(), ent_operational_destination.get())
text_operational_results.delete("1.0", tk.END)
text_operational_results.insert("1.0",json.dumps(response.result,indent=4))
getStandbyAccountInfo()
getOperationalAccountInfo()
# Create a new window with the title "Quickstart Module 3"
window = tk.Tk()
window.title("Quickstart Module 3")
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_standby_balance = tk.Label(master=frm_form, text="XRP Balance")
ent_standby_balance = 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_destination = tk.Label(master=frm_form, text="Destination")
ent_standby_destination = tk.Entry(master=frm_form, width=50)
lbl_standby_currency = tk.Label(master=frm_form, text="Currency")
ent_standby_currency = 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)
```
Add **NFT URI**, **Flags**, **Transfer Fee**, **Taxon**, **NFToken ID** fields.
```python
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="NFToken ID")
ent_standby_nft_id = 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_destination.grid(row=4, column=0, sticky="e")
ent_standby_destination.grid(row=4, column=1)
lbl_standby_balance.grid(row=5, column=0, sticky="e")
ent_standby_balance.grid(row=5, column=1)
lbl_standby_currency.grid(row=6, column=0, sticky="e")
ent_standby_currency.grid(row=6, column=1)
cb_standby_allow_rippling.grid(row=7,column=1, sticky="w")
```
Place new UI elements in the grid.
```python
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")
lbl_standby_results.grid(row=13, column=0, sticky="ne")
text_standby_results.grid(row=13, column=1, sticky="nw")
cb_standby_allow_rippling.select()
###############################################
## Operational Account ########################
###############################################
# Create the Label and Entry widgets for "Operational Account"
lbl_operational_seed = tk.Label(master=frm_form, text="Operational Seed")
ent_operational_seed = tk.Entry(master=frm_form, width=50)
lbl_operational_account = tk.Label(master=frm_form, text="Operational Account")
ent_operational_account = tk.Entry(master=frm_form, width=50)
lbl_operational_balance = tk.Label(master=frm_form, text="XRP Balance")
ent_operational_balance = tk.Entry(master=frm_form, width=50)
lbl_operational_amount = tk.Label(master=frm_form, text="Amount")
ent_operational_amount = tk.Entry(master=frm_form, width=50)
lbl_operational_destination = tk.Label(master=frm_form, text="Destination")
ent_operational_destination = tk.Entry(master=frm_form, width=50)
lbl_operational_currency = tk.Label(master=frm_form, text="Currency")
ent_operational_currency = tk.Entry(master=frm_form, width=50)
cb_operational_allow_rippling = tk.Checkbutton(master=frm_form, text="Allow Rippling", variable=operationalRippling, onvalue=True, offvalue=False)
```
Add fields for **NFT URI**, **Flags**, **Transfer Fee**, **Taxon**, and **NFToken ID**.
```python
lbl_operational_uri = tk.Label(master=frm_form, text="NFT URI")
ent_operational_uri = tk.Entry(master=frm_form, width=50)
lbl_operational_flags = tk.Label(master=frm_form, text="Flags")
ent_operational_flags = tk.Entry(master=frm_form, width=50)
lbl_operational_transfer_fee = tk.Label(master=frm_form, text="Transfer Fee")
ent_operational_transfer_fee = tk.Entry(master=frm_form, width="50")
lbl_operational_taxon = tk.Label(master=frm_form, text="Taxon")
ent_operational_taxon = tk.Entry(master=frm_form, width="50")
lbl_operational_nft_id = tk.Label(master=frm_form, text="NFToken ID")
ent_operational_nft_id = tk.Entry(master=frm_form, width="50")
lbl_operational_results = tk.Label(master=frm_form,text='Results')
text_operational_results = tk.Text(master=frm_form, height = 20, width = 65)
#Place the widgets in a grid
lbl_operational_seed.grid(row=0, column=4, sticky="e")
ent_operational_seed.grid(row=0, column=5, sticky="w")
lbl_operational_account.grid(row=2,column=4, sticky="e")
ent_operational_account.grid(row=2,column=5, sticky="w")
lbl_operational_amount.grid(row=3, column=4, sticky="e")
ent_operational_amount.grid(row=3, column=5, sticky="w")
lbl_operational_destination.grid(row=4, column=4, sticky="e")
ent_operational_destination.grid(row=4, column=5, sticky="w")
lbl_operational_balance.grid(row=5, column=4, sticky="e")
ent_operational_balance.grid(row=5, column=5, sticky="w")
lbl_operational_currency.grid(row=6, column=4, sticky="e")
ent_operational_currency.grid(row=6, column=5)
cb_operational_allow_rippling.grid(row=7,column=5, sticky="w")
```
Place new UI elements in the grid.
```python
lbl_operational_uri.grid(row=8, column=4, sticky="e")
ent_operational_uri.grid(row=8, column=5, sticky="w")
lbl_operational_flags.grid(row=9, column=4, sticky="e")
ent_operational_flags.grid(row=9, column=5, sticky="w")
lbl_operational_transfer_fee.grid(row=10, column=4, sticky="e")
ent_operational_transfer_fee.grid(row=10, column=5, sticky="w")
lbl_operational_taxon.grid(row=11, column=4, sticky="e")
ent_operational_taxon.grid(row=11, column=5, sticky="w")
lbl_operational_nft_id.grid(row=12, column=4, sticky="e")
ent_operational_nft_id.grid(row=12, column=5, sticky="w")
lbl_operational_results.grid(row=13, column=4, sticky="ne")
text_operational_results.grid(row=13, column=5, sticky="nw")
cb_operational_allow_rippling.select()
#############################################
## Buttons ##################################
#############################################
# Create the Standby Account Buttons
btn_get_standby_account = tk.Button(master=frm_form, text="Get Standby Account", command = getStandbyAccount)
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 = getStandbyAccountInfo)
btn_get_standby_account_info.grid(row=1, column=2, sticky = "nsew")
btn_standby_send_xrp = tk.Button(master=frm_form, text="Send XRP >", command = standbySendXRP)
btn_standby_send_xrp.grid(row=2, column=2, sticky = "nsew")
btn_standby_create_trustline = tk.Button(master=frm_form, text="Create Trustine", command = standbyCreateTrustline)
btn_standby_create_trustline.grid(row=3, column=2, sticky = "nsew")
btn_standby_send_currency = tk.Button(master=frm_form, text="Send Currency >", command = standbySendCurrency)
btn_standby_send_currency.grid(row=4, column=2, sticky = "nsew")
btn_standby_send_currency = tk.Button(master=frm_form, text="Get Balances", command = getBalances)
btn_standby_send_currency.grid(row=5, column=2, sticky = "nsew")
btn_standby_configure_account = tk.Button(master=frm_form, text="Configure Account", command = standbyConfigureAccount)
btn_standby_configure_account.grid(row=7,column=0, sticky = "nsew")
```
Add buttons for **Mint NFToken**, **Get NFTokens**, and **Burn NFToken**.
```python
btn_standby_mint_token = tk.Button(master=frm_form, text="Mint NFToken", command = standbyMintToken)
btn_standby_mint_token.grid(row=8, column=2, sticky="nsew")
btn_standby_get_tokens = tk.Button(master=frm_form, text="Get NFTokens", command = standbyGetTokens)
btn_standby_get_tokens.grid(row=9, column=2, sticky="nsew")
btn_standby_burn_token = tk.Button(master=frm_form, text="Burn NFToken", command = standbyBurnToken)
btn_standby_burn_token.grid(row=10, column=2, sticky="nsew")
# Create the Operational Account Buttons
btn_get_operational_account = tk.Button(master=frm_form, text="Get Operational Account", command = getOperationalAccount)
btn_get_operational_account.grid(row=0, column=3, sticky = "nsew")
btn_get_op_account_info = tk.Button(master=frm_form, text="Get Op Account Info", command = getOperationalAccountInfo)
btn_get_op_account_info.grid(row=1, column=3, sticky = "nsew")
btn_op_send_xrp = tk.Button(master=frm_form, text="< Send XRP", command = operationalSendXRP)
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
btn_op_create_trustline = tk.Button(master=frm_form, text="Create Trustine", command = operationalCreateTrustline)
btn_op_create_trustline.grid(row=3, column=3, sticky = "nsew")
btn_op_send_currency = tk.Button(master=frm_form, text="< Send Currency", command = operationalSendCurrency)
btn_op_send_currency.grid(row=4, column=3, sticky = "nsew")
btn_op_get_balances = tk.Button(master=frm_form, text="Get Balances", command = getBalances)
btn_op_get_balances.grid(row=5, column=3, sticky = "nsew")
btn_op_configure_account = tk.Button(master=frm_form, text="Configure Account", command = operationalConfigureAccount)
btn_op_configure_account.grid(row=7,column=4, sticky = "nsew")
```
Add buttons for **Mint NFToken**, **Get NFTokens**, and **Burn NFToken**.
```python
btn_op_mint_token = tk.Button(master=frm_form, text="Mint NFToken", command = operationalMintToken)
btn_op_mint_token.grid(row=8, column=3, sticky="nsew")
btn_op_get_tokens = tk.Button(master=frm_form, text="Get NFTokens", command = operationalGetTokens)
btn_op_get_tokens.grid(row=9, column=3, sticky="nsew")
btn_op_burn_token = tk.Button(master=frm_form, text="Burn NFToken", command = operationalBurnToken)
btn_op_burn_token.grid(row=10, column=3, sticky="nsew")
# Start the application
window.mainloop()
```