mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-23 13:15:49 +00:00
Reorg tutorials to match nav, and update links
This commit is contained in:
15
docs/tutorials/python/modular-tutorials/index.md
Normal file
15
docs/tutorials/python/modular-tutorials/index.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
html: modular-tutorials-in-python.html
|
||||
parent: python.html
|
||||
top_nav_grouping: Article Types
|
||||
metadata:
|
||||
indexPage: true
|
||||
seo:
|
||||
description: Modular XRPL tutorials in Python.
|
||||
---
|
||||
# Modular Tutorials in Python
|
||||
|
||||
These tutorials take an incremental approach to implementing functionality, so you can reuse parts from the earlier tutorials on your way to making more advanced software.
|
||||
|
||||
|
||||
{% child-pages /%}
|
||||
@@ -0,0 +1,896 @@
|
||||
---
|
||||
html: py-authorize-minter.html
|
||||
parent: nfts-using-python.html
|
||||
seo:
|
||||
description: Authorize another account to mint NFTs for you.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- XRP
|
||||
- NFTs, NFTokens
|
||||
---
|
||||
|
||||
# Assign an Authorized Minter Using Python
|
||||
|
||||
You can assign another account permission to mint NFTs for you.
|
||||
|
||||
This example shows how to:
|
||||
|
||||
1. Authorize an account to create NFTs for your account.
|
||||
2. Mint an NFT for another account, when authorized.
|
||||
|
||||
[](/docs/img/quickstart-py30.png)
|
||||
|
||||
# Usage
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive to try the sample in your own browser.
|
||||
|
||||
## Get Accounts
|
||||
|
||||
1. Open and run `py-authorize-minter.md`.
|
||||
2. Get accounts.
|
||||
1. If you have existing test account seeds:
|
||||
1. Paste a seed in the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info**.
|
||||
4. Paste a seed in the **Operational Seed** field.
|
||||
5. Click **Get Operational Account**.
|
||||
6. Click **Get Operational Account** info.
|
||||
2. If you do not have existing test accounts:
|
||||
1. Click **Get Standby Account**.
|
||||
2. Click **Get Standby Account Info**.
|
||||
3. Click **Get Operational Account**.
|
||||
4. Click **Get Operational Account Info**.
|
||||
|
||||
## Authorize an Account to Create NFTs
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/miVhXbph2ls?si=U1mRxlzul3k30R6O" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
To authorize another account to create NFTs for your account (for example, allow the operational account to mint NFTs for the standby account):
|
||||
|
||||
1. Copy the **Operational Account** value.
|
||||
2. Paste the **Operational Account** value in the standby **Authorized Minter** field.
|
||||
3. Click **Set Minter**.
|
||||
|
||||
[](/docs/img/quickstart-py31.png)
|
||||
|
||||
## Mint an NFT for Another Account
|
||||
|
||||
This example uses the Operational account, which was authorized in the previous step, to mint a token on behalf of the Standby account.
|
||||
|
||||
To mint a non-fungible token for another account:
|
||||
|
||||
1. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_.
|
||||
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 that the original creator receives from future sales of the NFT. 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 NFT to be transferrable, set this field to 0.
|
||||
4. Enter a **Taxon** for the NFT. If you don't have a use for the field, set it to _0_.
|
||||
4. Copy the **Standby Account** value.
|
||||
5. Paste the **Standby Account** value in the Operational account **Issuer** field.
|
||||
6. Click the Operational account **Mint Other** button.
|
||||
|
||||
[](/docs/img/quickstart-py32.png)
|
||||
|
||||
Once the item is minted, the authorized minter can sell the NFT normally. The proceeds go to the authorized minter, less the transfer fee. The minter and the issuer can settle up on a division of the price separately.
|
||||
|
||||
## Create a Sell Offer
|
||||
|
||||
To create a NFT sell offer:
|
||||
|
||||
1. On the Operational account side, enter the **Amount** of the sell offer in drops (millionths of an XRP), for example 100000000 (100 XRP).
|
||||
2. Set the **Flags** field to _1_.
|
||||
3. Enter the **NFT ID** of the minted NFT you want to sell.
|
||||
4. Optionally, enter a number of seconds until **Expiration**.
|
||||
5. Click **Create Sell Offer**.
|
||||
|
||||
The important piece of information in the response is the NFT Offer Index, labeled as `nft_offer_index`, which is used to accept the sell offer.
|
||||
|
||||
[](/docs/img/quickstart-py33.png)
|
||||
|
||||
## Accept Sell Offer
|
||||
|
||||
Once a sell offer is available, you can create a new account to accept the offer and buy the NFT.
|
||||
|
||||
To accept an available sell offer:
|
||||
|
||||
1. Clear the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info**.
|
||||
4. Enter the **NFT Offer Index** (labeled as `nft_offer_index` in the NFT offer results. This is different from the `nft_id`).
|
||||
5. Click **Accept Sell Offer**.
|
||||
|
||||
[](/docs/img/quickstart-py34.png)
|
||||
|
||||
The Buyer account was debited the 100 XRP price plus 10 drops as the transaction cost. The Seller (Authorized Minter) account is credited 90 XRP. the Issuer and the Seller can divide the proceeds per their agreement in a separate transaction. The original Standby account receives a transfer fee of 10 XRP.
|
||||
|
||||
[](/docs/img/quickstart-py35.png)
|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive to try each of the samples.
|
||||
|
||||
## mod6.py
|
||||
|
||||
`mod6.py` contains the new business logic for this example, the `set_minter` and `mint_other` methods.
|
||||
|
||||
Import dependencies and define the `testnet_url` global variable.
|
||||
|
||||
```python
|
||||
import xrpl
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.wallet import Wallet
|
||||
testnet_url="https://s.altnet.rippletest.net:51234"
|
||||
```
|
||||
|
||||
### Set Minter
|
||||
|
||||
This function sets the authorized minter for an account. Each account can have 0 or 1 authorized minter that can mint NFTs in its stead.
|
||||
|
||||
Get the wallet of the account granting permission and instantiate a client.
|
||||
|
||||
```python
|
||||
def set_minter(seed, minter):
|
||||
"""set_minter"""
|
||||
granter_wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the AccountSet transaction that grants permission to another account to mint tokens on behalf of the granter account.
|
||||
|
||||
```python
|
||||
set_minter_tx=xrpl.models.transactions.AccountSet(
|
||||
account=granter_wallet.address,
|
||||
nftoken_minter=minter,
|
||||
set_flag=xrpl.models.transactions.AccountSetAsfFlag.ASF_AUTHORIZED_NFTOKEN_MINTER
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and return the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(set_minter_tx,client,
|
||||
granter_wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### mint_other
|
||||
|
||||
Get the minter wallet and instantiate a client connection to the XRP ledger.
|
||||
|
||||
``` python
|
||||
def mint_other(seed, uri, flags, transfer_fee, taxon, issuer):
|
||||
"""mint_other"""
|
||||
minter_wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the `NFTokenMint` transaction. The new parameter in this method is the _issuer_ field, identifying the account on whose behalf the token is being minted.
|
||||
|
||||
```python
|
||||
mint_other_tx=xrpl.models.transactions.NFTokenMint(
|
||||
account=minter_wallet.address,
|
||||
uri=xrpl.utils.str_to_hex(uri),
|
||||
flags=int(flags),
|
||||
transfer_fee=int(transfer_fee),
|
||||
nftoken_taxon=int(taxon),
|
||||
issuer=issuer
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(mint_other_tx,client,
|
||||
minter_wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
## lesson6-auth-minter.py
|
||||
|
||||
This form is based on lesson4-transfer-tokens.py. Changes 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 (
|
||||
create_trust_line,
|
||||
send_currency,
|
||||
get_balance,
|
||||
configure_account,
|
||||
)
|
||||
from mod3 import (
|
||||
mint_token,
|
||||
get_tokens,
|
||||
burn_token,
|
||||
)
|
||||
from mod4 import (
|
||||
create_sell_offer,
|
||||
create_buy_offer,
|
||||
get_offers,
|
||||
cancel_offer,
|
||||
accept_sell_offer,
|
||||
accept_buy_offer,
|
||||
)
|
||||
```
|
||||
|
||||
Import dependencies from `mod6.py`.
|
||||
|
||||
```python
|
||||
from mod6 import set_minter, mint_other
|
||||
```
|
||||
|
||||
Add handlers for new Module 6 methods.
|
||||
|
||||
```python
|
||||
#############################################
|
||||
## Handlers #################################
|
||||
#############################################
|
||||
|
||||
# Module 6 Handlers
|
||||
|
||||
def standby_set_minter():
|
||||
results = set_minter(ent_standby_seed.get(),ent_standby_auth_minter.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def standby_mint_other():
|
||||
results = mint_other(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_uri.get(),
|
||||
ent_standby_flags.get(),
|
||||
ent_standby_transfer_fee.get(),
|
||||
ent_standby_taxon.get(),
|
||||
ent_standby_issuer.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_set_minter():
|
||||
results = set_minter(ent_operational_seed.get(),ent_operational_auth_minter.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_mint_other():
|
||||
results = mint_other(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_uri.get(),
|
||||
ent_operational_flags.get(),
|
||||
ent_operational_transfer_fee.get(),
|
||||
ent_operational_taxon.get(),
|
||||
ent_operational_issuer.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
# Module 4 Handlers
|
||||
|
||||
def standby_create_sell_offer():
|
||||
results = create_sell_offer(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_nft_id.get(),
|
||||
ent_standby_expiration.get(),
|
||||
ent_standby_destination.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_accept_sell_offer():
|
||||
results = accept_sell_offer (
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_nft_offer_index.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_create_buy_offer():
|
||||
results = create_buy_offer(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_nft_id.get(),
|
||||
ent_standby_owner.get(),
|
||||
ent_standby_expiration.get(),
|
||||
ent_standby_destination.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_accept_buy_offer():
|
||||
results = accept_buy_offer (
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_nft_offer_index.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_get_offers():
|
||||
results = get_offers(ent_standby_nft_id.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", results)
|
||||
|
||||
|
||||
def standby_cancel_offer():
|
||||
results = cancel_offer(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_nft_offer_index.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_create_sell_offer():
|
||||
results = create_sell_offer(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_amount.get(),
|
||||
ent_operational_nft_id.get(),
|
||||
ent_operational_expiration.get(),
|
||||
ent_operational_destination.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_accept_sell_offer():
|
||||
results = accept_sell_offer (
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_nft_offer_index.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_create_buy_offer():
|
||||
results = create_buy_offer(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_amount.get(),
|
||||
ent_operational_nft_id.get(),
|
||||
ent_operational_owner.get(),
|
||||
ent_operational_expiration.get(),
|
||||
ent_operational_destination.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_accept_buy_offer():
|
||||
results = accept_buy_offer (
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_nft_offer_index.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_get_offers():
|
||||
results = get_offers(ent_operational_nft_id.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", results)
|
||||
|
||||
|
||||
def op_cancel_offer():
|
||||
results = cancel_offer(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_nft_offer_index.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
|
||||
# Module 3 Handlers
|
||||
|
||||
def standby_mint_token():
|
||||
results = mint_token(
|
||||
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 standby_get_tokens():
|
||||
results = get_tokens(ent_standby_account.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_burn_token():
|
||||
results = burn_token(
|
||||
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 operational_mint_token():
|
||||
results = mint_token(
|
||||
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 operational_get_tokens():
|
||||
results = get_tokens(ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def operational_burn_token():
|
||||
results = burn_token(
|
||||
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 standby_create_trust_line():
|
||||
results = create_trust_line(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 standby_send_currency():
|
||||
results = send_currency(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 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))
|
||||
|
||||
|
||||
def operational_create_trust_line():
|
||||
results = create_trust_line(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 operational_send_currency():
|
||||
results = send_currency(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 operational_configure_account():
|
||||
results = configure_account(
|
||||
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 get_balances():
|
||||
results = get_balance(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 = get_balance(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 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))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(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 get_operational_account_info():
|
||||
accountInfo = get_account_info(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 operational_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
```
|
||||
|
||||
Rename the window for the Authorized Minter examples.
|
||||
|
||||
```python
|
||||
# Create a new window with the title "Quickstart - Authorized Minter"
|
||||
window = tk.Tk()
|
||||
window.title("Quickstart - Authorized Minter")
|
||||
|
||||
myscrollbar=tk.Scrollbar(window,orient="vertical")
|
||||
myscrollbar.pack(side="right",fill="y")
|
||||
|
||||
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_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_standby_destination = 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_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)
|
||||
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")
|
||||
lbl_standby_nft_offer_index = tk.Label(master=frm_form, text="NFT Offer Index")
|
||||
ent_standby_nft_offer_index = tk.Entry(master=frm_form, width="50")
|
||||
lbl_standby_owner = tk.Label(master=frm_form, text="Owner")
|
||||
ent_standby_owner = tk.Entry(master=frm_form, width="50")
|
||||
lbl_standby_expiration = tk.Label(master=frm_form, text="Expiration")
|
||||
ent_standby_expiration = tk.Entry(master=frm_form, width="50")
|
||||
```
|
||||
|
||||
Add fields for the **Authorized Minter** and **Issuer**.
|
||||
|
||||
```python
|
||||
lbl_standby_auth_minter = tk.Label(master=frm_form, text="Authorized Minter")
|
||||
ent_standby_auth_minter = tk.Entry(master=frm_form, width="50")
|
||||
lbl_standby_issuer = tk.Label(master=frm_form, text="Issuer")
|
||||
ent_standby_issuer = 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 = 50, 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")
|
||||
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_nft_offer_index.grid(row=13, column=0, sticky="ne")
|
||||
ent_standby_nft_offer_index.grid(row=13, column=1, sticky="w")
|
||||
lbl_standby_owner.grid(row=14, column=0, sticky="ne")
|
||||
ent_standby_owner.grid(row=14, column=1, sticky="w")
|
||||
lbl_standby_expiration.grid(row=15, column=0, sticky="ne")
|
||||
ent_standby_expiration.grid(row=15, column=1, sticky="w")
|
||||
```
|
||||
|
||||
Add the new fields to the form grid.
|
||||
|
||||
```python
|
||||
lbl_standby_auth_minter.grid(row=16,column=0, sticky="ne")
|
||||
ent_standby_auth_minter.grid(row=16,column=1, sticky="w")
|
||||
lbl_standby_issuer.grid(row=17,column=0, sticky="ne")
|
||||
ent_standby_issuer.grid(row=17,column=1, sticky="w")
|
||||
lbl_standby_results.grid(row=18, column=0, sticky="ne")
|
||||
text_standby_results.grid(row=18, 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = 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)
|
||||
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="NFT ID")
|
||||
ent_operational_nft_id = tk.Entry(master=frm_form, width="50")
|
||||
lbl_operational_nft_offer_index = tk.Label(master=frm_form, text="NFT Offer Index")
|
||||
ent_operational_nft_offer_index = tk.Entry(master=frm_form, width="50")
|
||||
lbl_operational_owner = tk.Label(master=frm_form, text="Owner")
|
||||
ent_operational_owner = tk.Entry(master=frm_form, width="50")
|
||||
lbl_operational_expiration = tk.Label(master=frm_form, text="Expiration")
|
||||
ent_operational_expiration = tk.Entry(master=frm_form, width="50")
|
||||
```
|
||||
|
||||
Add *Authorized Minter* and *Issuer* fields to the Operational side of the form.
|
||||
|
||||
```python
|
||||
lbl_operational_auth_minter = tk.Label(master=frm_form, text="Authorized Minter")
|
||||
ent_operational_auth_minter = tk.Entry(master=frm_form, width="50")
|
||||
lbl_operational_issuer = tk.Label(master=frm_form, text="Issuer")
|
||||
ent_operational_issuer = 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 = 50, 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")
|
||||
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_nft_offer_index.grid(row=13, column=4, sticky="ne")
|
||||
ent_operational_nft_offer_index.grid(row=13, column=5, sticky="w")
|
||||
lbl_operational_owner.grid(row=14, column=4, sticky="ne")
|
||||
ent_operational_owner.grid(row=14, column=5, sticky="w")
|
||||
lbl_operational_expiration.grid(row=15, column=4, sticky="ne")
|
||||
ent_operational_expiration.grid(row=15, column=5, sticky="w")
|
||||
```
|
||||
|
||||
Add *Authorized Minter* and *Issuer* fields to the Operational grid.
|
||||
|
||||
```python
|
||||
lbl_operational_auth_minter.grid(row=16, column=4, sticky="ne")
|
||||
ent_operational_auth_minter.grid(row=16, column=5, sticky="w")
|
||||
lbl_operational_issuer.grid(row=17, column=4, sticky="ne")
|
||||
ent_operational_issuer.grid(row=17, column=5, sticky="w")
|
||||
lbl_operational_results.grid(row=18, column=4, sticky="ne")
|
||||
text_operational_results.grid(row=18, 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 = 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_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
btn_standby_send_xrp.grid(row=2, column = 2, sticky = "nsew")
|
||||
btn_standby_create_trust_line = tk.Button(master=frm_form,
|
||||
text="Create Trust Line",
|
||||
command = standby_create_trust_line)
|
||||
btn_standby_create_trust_line.grid(row=4, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Send Currency >",
|
||||
command = standby_send_currency)
|
||||
btn_standby_send_currency.grid(row=5, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_standby_send_currency.grid(row=6, 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")
|
||||
btn_standby_mint_token = tk.Button(master=frm_form, text="Mint NFT",
|
||||
command = standby_mint_token)
|
||||
btn_standby_mint_token.grid(row=8, column=2, sticky="nsew")
|
||||
btn_standby_get_tokens = tk.Button(master=frm_form, text="Get NFTs",
|
||||
command = standby_get_tokens)
|
||||
btn_standby_get_tokens.grid(row=9, column=2, sticky="nsew")
|
||||
btn_standby_burn_token = tk.Button(master=frm_form, text="Burn NFT",
|
||||
command = standby_burn_token)
|
||||
btn_standby_burn_token.grid(row=10, column=2, sticky="nsew")
|
||||
btn_standby_create_sell_offer = tk.Button(master=frm_form, text="Create Sell Offer",
|
||||
command = standby_create_sell_offer)
|
||||
btn_standby_create_sell_offer.grid(row=11, column=2, sticky="nsew")
|
||||
btn_standby_accept_sell_offer = tk.Button(master=frm_form, text="Accept Sell Offer",
|
||||
command = standby_accept_sell_offer)
|
||||
btn_standby_accept_sell_offer.grid(row=12, column=2, sticky="nsew")
|
||||
btn_standby_create_buy_offer = tk.Button(master=frm_form, text="Create Buy Offer",
|
||||
command = standby_create_buy_offer)
|
||||
btn_standby_create_buy_offer.grid(row=13, column=2, sticky="nsew")
|
||||
btn_standby_accept_buy_offer = tk.Button(master=frm_form, text="Accept Buy Offer",
|
||||
command = standby_accept_buy_offer)
|
||||
btn_standby_accept_buy_offer.grid(row=14, column=2, sticky="nsew")
|
||||
btn_standby_get_offers = tk.Button(master=frm_form, text="Get Offers",
|
||||
command = standby_get_offers)
|
||||
btn_standby_get_offers.grid(row=15, column=2, sticky="nsew")
|
||||
btn_standby_cancel_offer = tk.Button(master=frm_form, text="Cancel Offer",
|
||||
command = standby_cancel_offer)
|
||||
btn_standby_cancel_offer.grid(row=16, column=2, sticky="nsew")
|
||||
```
|
||||
|
||||
Add buttons for *Set Minter* and *Mint Other* to the Standby side of the form.
|
||||
|
||||
```python
|
||||
btn_standby_set_minter = tk.Button(master=frm_form, text="Set Minter",
|
||||
command = standby_set_minter)
|
||||
btn_standby_set_minter.grid(row=17, column=2, sticky="nsew")
|
||||
btn_standby_mint_other = tk.Button(master=frm_form, text="Mint Other",
|
||||
command = standby_mint_other)
|
||||
btn_standby_mint_other.grid(row=18, column=2, sticky="new")
|
||||
|
||||
|
||||
|
||||
# Create the Operational Account Buttons
|
||||
btn_get_operational_account = tk.Button(master=frm_form,
|
||||
text="Get Operational Account",
|
||||
command = get_operational_account)
|
||||
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 = get_operational_account_info)
|
||||
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 = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
btn_op_create_trust_line = tk.Button(master=frm_form, text="Create Trust Line",
|
||||
command = operational_create_trust_line)
|
||||
btn_op_create_trust_line.grid(row=4, column=3, sticky = "nsew")
|
||||
btn_op_send_currency = tk.Button(master=frm_form, text="< Send Currency",
|
||||
command = operational_send_currency)
|
||||
btn_op_send_currency.grid(row=5, column=3, sticky = "nsew")
|
||||
btn_op_get_balances = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_op_get_balances.grid(row=6, column=3, sticky = "nsew")
|
||||
btn_op_configure_account = tk.Button(master=frm_form, text="Configure Account",
|
||||
command = operational_configure_account)
|
||||
btn_op_configure_account.grid(row=7,column=4, sticky = "nsew")
|
||||
btn_op_mint_token = tk.Button(master=frm_form, text="Mint NFT",
|
||||
command = operational_mint_token)
|
||||
btn_op_mint_token.grid(row=8, column=3, sticky="nsew")
|
||||
btn_op_get_tokens = tk.Button(master=frm_form, text="Get NFTs",
|
||||
command = operational_get_tokens)
|
||||
btn_op_get_tokens.grid(row=9, column=3, sticky="nsew")
|
||||
btn_op_burn_token = tk.Button(master=frm_form, text="Burn NFT",
|
||||
command = operational_burn_token)
|
||||
btn_op_burn_token.grid(row=10, column=3, sticky="nsew")
|
||||
btn_op_create_sell_offer = tk.Button(master=frm_form, text="Create Sell Offer",
|
||||
command = op_create_sell_offer)
|
||||
btn_op_create_sell_offer.grid(row=11, column=3, sticky="nsew")
|
||||
btn_op_accept_sell_offer = tk.Button(master=frm_form, text="Accept Sell Offer",
|
||||
command = op_accept_sell_offer)
|
||||
btn_op_accept_sell_offer.grid(row=12, column=3, sticky="nsew")
|
||||
btn_op_create_buy_offer = tk.Button(master=frm_form, text="Create Buy Offer",
|
||||
command = op_create_buy_offer)
|
||||
btn_op_create_buy_offer.grid(row=13, column=3, sticky="nsew")
|
||||
btn_op_accept_buy_offer = tk.Button(master=frm_form, text="Accept Buy Offer",
|
||||
command = op_accept_buy_offer)
|
||||
btn_op_accept_buy_offer.grid(row=14, column=3, sticky="nsew")
|
||||
btn_op_get_offers = tk.Button(master=frm_form, text="Get Offers",
|
||||
command = op_get_offers)
|
||||
btn_op_get_offers.grid(row=15, column=3, sticky="nsew")
|
||||
btn_op_cancel_offer = tk.Button(master=frm_form, text="Cancel Offer",
|
||||
command = op_cancel_offer)
|
||||
btn_op_cancel_offer.grid(row=16, column=3, sticky="nsew")
|
||||
```
|
||||
|
||||
Add *Set Minter* and *Mint Other* buttons to the Operational side of the form.
|
||||
|
||||
```python
|
||||
btn_op_set_minter = tk.Button(master=frm_form, text="Set Minter",
|
||||
command = operational_set_minter)
|
||||
btn_op_set_minter.grid(row=17, column=3, sticky="nsew")
|
||||
btn_op_mint_other = tk.Button(master=frm_form, text="Mint Other",
|
||||
command = operational_mint_other)
|
||||
btn_op_mint_other.grid(row=18, column=3, sticky="new")
|
||||
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
```
|
||||
390
docs/tutorials/python/modular-tutorials/nfts/batch-mint-nfts.md
Normal file
390
docs/tutorials/python/modular-tutorials/nfts/batch-mint-nfts.md
Normal file
@@ -0,0 +1,390 @@
|
||||
---
|
||||
html: py-batch-minting.html
|
||||
parent: nfts-using-python.html
|
||||
seo:
|
||||
description: 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.
|
||||
|
||||
[](/docs/img/quickstart-py36.png)
|
||||
|
||||
## Usage
|
||||
|
||||
You can download or clone the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_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, just click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info** to get the current XRP balance.
|
||||
|
||||
|
||||
## Batch Mint NFTs
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/NjEqEWcqhwc?si=E8ws75gts_7TtOuU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
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. Enter the **NFT URI**. This is a URI that points to the data or metadata associated with the NFT object. You can use this sample URI if you do not have one of your own: ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi.
|
||||
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](../../../../references/protocol/transactions/types/nftokenmint.md) for available NFT minting flags.
|
||||
3. 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.
|
||||
4. Enter the **Taxon** for the NFT. If you do not have a need for the Taxon field, set this value to 0.
|
||||
5. Enter an **NFT Count** of up to 200 NFTs to create in one batch.
|
||||
6. 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/_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
|
||||
```
|
||||
|
||||
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 standby_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 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 "Python Module - Batch Minting"
|
||||
window = tk.Tk()
|
||||
window.title("Python Module - Batch Minting")
|
||||
|
||||
|
||||
|
||||
# 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_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")
|
||||
lbl_standby_nft_offer_index = tk.Label(master=frm_form, text="NFT Offer Index")
|
||||
ent_standby_nft_offer_index = 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_standby_balance.grid(row=5, column=0, sticky="e")
|
||||
ent_standby_balance.grid(row=5, column=1)
|
||||
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")
|
||||
```
|
||||
|
||||
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")
|
||||
|
||||
#############################################
|
||||
## 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")
|
||||
```
|
||||
|
||||
Add the **Batch Mint NFTs** and **Get Batch NFTs** buttons.
|
||||
|
||||
```python
|
||||
btn_standby_batch_mint = tk.Button(master=frm_form,
|
||||
text="Batch Mint NFTs",
|
||||
command = standby_batch_mint)
|
||||
btn_standby_batch_mint.grid(row=5, column=2, sticky = "nsew")
|
||||
btn_standby_get_batch_nfts = tk.Button(master=frm_form,
|
||||
text="Get Batch NFTs",
|
||||
command = standby_get_batch_nfts)
|
||||
btn_standby_get_batch_nfts.grid(row=8, column=2, sticky = "nsew")
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
|
||||
```
|
||||
@@ -0,0 +1,883 @@
|
||||
---
|
||||
html: py-broker-sale.html
|
||||
parent: nfts-using-python.html
|
||||
seo:
|
||||
description: Broker a sale between a sell offer and a buy offer.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- Broker
|
||||
- XRP
|
||||
---
|
||||
|
||||
# Broker an NFT Sale Using Python
|
||||
|
||||
Earlier examples showed how to make buy and sell offers directly between two accounts. Another option is to use a third account as a broker for the sale. The broker acts on behalf of the NFT owner. The seller creates an offer with the broker account as its destination. The broker gathers and evaluates buy offers and chooses which one to accept, adding an agreed-upon fee for arranging the sale. When the broker account accepts a sell offer with a buy offer, the funds and ownership of the NFT are transferred simultaneously, completing the deal. This allows an account to act as a marketplace or personal agent for NFT creators and traders.
|
||||
|
||||
# Usage
|
||||
|
||||
This example shows how to:
|
||||
|
||||
1. Create a brokered sell offer.
|
||||
2. Get a list of offers for the brokered item.
|
||||
3. Broker a sale between two different accounts.
|
||||
|
||||
[](/docs/img/quickstart-py23.png)
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive to try each of the samples in your own browser.
|
||||
|
||||
## Get Accounts
|
||||
|
||||
1. Open and run `broker-nfts.py`.
|
||||
2. Get test accounts.
|
||||
1. If you have existing account seeds:
|
||||
1. Paste account seed in the **Broker Seed** field.
|
||||
2. Click **Get Broker Account**.
|
||||
3. Paste account seed in the **Standby Seed** field.
|
||||
4. Click **Get Standby Account**.
|
||||
5. Paste account seed in the **Operational Seed** field.
|
||||
6. Click **Get Operational Account**.
|
||||
2. If you do not have account seeds:
|
||||
1. Click **Get Broker Account**.
|
||||
2. Click **Get Standby Account**.
|
||||
2. Click **Get Operational Account**.
|
||||
3. Click **Get Broker Account Info**.
|
||||
4. Click **Get Standby Account Info**.
|
||||
5. Click **Get Operational Account Info**.
|
||||
|
||||
[](/docs/img/quickstart-py24.png)
|
||||
|
||||
## Prepare a Brokered Transaction
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/2dhWDnhCBuY?si=qpHSd6Y0ftVOe46E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
1. Use the Standby account to create an NFT Sell Offer with the Broker account as the destination.
|
||||
1. Enter the **Amount** of the sell offer in drops (millionths of an XRP).
|
||||
2. Enter the **NFT ID** of the NFT you want to sell.
|
||||
3. Optionally, enter a number of seconds until **Expiration**.
|
||||
4. Enter the Broker account number as the **Destination**.
|
||||
5. Click **Create Sell Offer**.
|
||||
6. Click **Get Offers** to see the new offer.
|
||||
|
||||
|
||||
[](/docs/img/quickstart25.png)
|
||||
|
||||
2. Use the Operational account to create a NFT Buy Offer.
|
||||
1. Enter the **Amount** of your offer.
|
||||
2. Enter the **NFT ID**.
|
||||
3. Enter the owner’s account string in the **Owner** field.
|
||||
4. Optionally enter the number of seconds until **Expiration**.
|
||||
5. Click **Create Buy Offer**.
|
||||
|
||||
[](/docs/img/quickstart-py26.png)
|
||||
|
||||
## Get Offers
|
||||
|
||||
1. Enter the **NFT ID**.
|
||||
2. Click **Get Offers**.
|
||||
|
||||
[](/docs/img/quickstart-py27.png)
|
||||
|
||||
## Broker the Sale
|
||||
|
||||
1. Copy the _nft_offer_index_ of the sell offer and paste it in the **Sell NFT Offer Index** field.
|
||||
2. Copy the _nft_offer_index_ of the buy offer and paste it in the **Buy NFT Offer Index** field.
|
||||
3. Enter a **Broker Fee**, in drops.
|
||||
4. Click **Broker Sale**.
|
||||
|
||||
[](/docs/img/quickstart-py28.png)
|
||||
|
||||
|
||||
## Cancel Offer
|
||||
|
||||
After accepting a buy offer, a best practice for the broker is to cancel all other offers, if the broker has permissions to do so. Use **Get Offers** to get the full list of buy offers. To cancel an offer:
|
||||
|
||||
1. Enter the _nft_offer_index_ of the buy offer you want to cancel in the **Buy NFT Offer Index** field.
|
||||
2. Click **Cancel Offer**.
|
||||
|
||||
[](/docs/img/quickstart-py29.png)
|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive to examine the code samples.
|
||||
|
||||
## ripplex5-broker-nfts.js
|
||||
<!-- SPELLING_IGNORE: ripplex5 -->
|
||||
|
||||
Four of the five buttons for the Broker are supported by existing methods. The only new method required is the Broker Sale method.
|
||||
|
||||
Import dependencies and create a global variable for `testnet_url`.
|
||||
|
||||
```python
|
||||
import xrpl
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.wallet import Wallet
|
||||
testnet_url = "https://s.altnet.rippletest.net:51234"
|
||||
```
|
||||
|
||||
## Broker Sale
|
||||
|
||||
Pass the _seed_, _sell___offer___index_, _buy___offer___index_, and _broker___fee_.
|
||||
|
||||
```python
|
||||
def broker_sale(seed, sell_offer_index, buy_offer_index, broker_fee):
|
||||
"""broker_sale"""
|
||||
```
|
||||
|
||||
Get the broker wallet and establish a client connection.
|
||||
|
||||
```python
|
||||
broker_wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the accept offer transaction, matching a sell offer with the selected buy offer.
|
||||
|
||||
```python
|
||||
accept_offer_tx=xrpl.models.transactions.NFTokenAcceptOffer(
|
||||
account=broker_wallet.classic_address,
|
||||
nftoken_sell_offer=sell_offer_index,
|
||||
nftoken_buy_offer=buy_offer_index,
|
||||
nftoken_broker_fee=broker_fee
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(accept_offer_tx,client,broker_wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
## lesson5-broker-nfts.py
|
||||
|
||||
Revise the form from lesson 4 to add a new Broker section at the top. Changes are highlighted below.
|
||||
|
||||
```python
|
||||
import tkinter as tk
|
||||
import xrpl
|
||||
import json
|
||||
```
|
||||
|
||||
Import the `broker_sale` method.
|
||||
|
||||
```python
|
||||
from mod1 import get_account, get_account_info, send_xrp
|
||||
from mod2 import (
|
||||
create_trust_line,
|
||||
send_currency,
|
||||
get_balance,
|
||||
configure_account,
|
||||
)
|
||||
from mod3 import (
|
||||
mint_token,
|
||||
get_tokens,
|
||||
burn_token,
|
||||
)
|
||||
from mod4 import (
|
||||
create_sell_offer,
|
||||
create_buy_offer,
|
||||
get_offers,
|
||||
cancel_offer,
|
||||
accept_sell_offer,
|
||||
accept_buy_offer,
|
||||
)
|
||||
from mod5 import broker_sale
|
||||
|
||||
#############################################
|
||||
## Handlers #################################
|
||||
#############################################
|
||||
```
|
||||
|
||||
Add handlers for the broker account buttons.
|
||||
|
||||
```python
|
||||
# Module 5 Handlers
|
||||
|
||||
def get_broker_account():
|
||||
new_wallet = get_account(ent_broker_seed.get())
|
||||
ent_broker_account.delete(0, tk.END)
|
||||
ent_broker_seed.delete(0, tk.END)
|
||||
ent_broker_account.insert(0, new_wallet.classic_address)
|
||||
ent_broker_seed.insert(0, new_wallet.seed)
|
||||
|
||||
|
||||
def get_broker_account_info():
|
||||
accountInfo = get_account_info(ent_broker_account.get())
|
||||
ent_broker_balance.delete(0, tk.END)
|
||||
ent_broker_balance.insert(0,accountInfo['Balance'])
|
||||
text_broker_results.delete("1.0", tk.END)
|
||||
text_broker_results.insert("1.0",json.dumps(accountInfo, indent=4))
|
||||
|
||||
|
||||
def broker_broker_sale():
|
||||
results = broker_sale(
|
||||
ent_broker_seed.get(),
|
||||
ent_broker_sell_nft_idx.get(),
|
||||
ent_broker_buy_nft_idx.get(),
|
||||
ent_broker_fee.get()
|
||||
)
|
||||
text_broker_results.delete("1.0", tk.END)
|
||||
text_broker_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def broker_get_offers():
|
||||
results = get_offers(ent_broker_nft_id.get())
|
||||
text_broker_results.delete("1.0", tk.END)
|
||||
text_broker_results.insert("1.0", results)
|
||||
|
||||
|
||||
def broker_cancel_offer():
|
||||
results = cancel_offer(
|
||||
ent_broker_seed.get(),
|
||||
ent_broker_buy_nft_idx.get()
|
||||
)
|
||||
text_broker_results.delete("1.0", tk.END)
|
||||
text_broker_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
# Module 4 Handlers
|
||||
|
||||
def standby_create_sell_offer():
|
||||
results = create_sell_offer(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_nft_id.get(),
|
||||
ent_standby_expiration.get(),
|
||||
ent_standby_destination.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_accept_sell_offer():
|
||||
results = accept_sell_offer (
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_nft_offer_index.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_create_buy_offer():
|
||||
results = create_buy_offer(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_nft_id.get(),
|
||||
ent_standby_owner.get(),
|
||||
ent_standby_expiration.get(),
|
||||
ent_standby_destination.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_accept_buy_offer():
|
||||
results = accept_buy_offer (
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_nft_offer_index.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_get_offers():
|
||||
results = get_offers(ent_standby_nft_id.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", results)
|
||||
|
||||
|
||||
def standby_cancel_offer():
|
||||
results = cancel_offer(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_nft_offer_index.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_create_sell_offer():
|
||||
results = create_sell_offer(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_amount.get(),
|
||||
ent_operational_nft_id.get(),
|
||||
ent_operational_expiration.get(),
|
||||
ent_operational_destination.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_accept_sell_offer():
|
||||
results = accept_sell_offer (
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_nft_offer_index.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_create_buy_offer():
|
||||
results = create_buy_offer(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_amount.get(),
|
||||
ent_operational_nft_id.get(),
|
||||
ent_operational_owner.get(),
|
||||
ent_operational_expiration.get(),
|
||||
ent_operational_destination.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_accept_buy_offer():
|
||||
results = accept_buy_offer (
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_nft_offer_index.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def op_get_offers():
|
||||
results = get_offers(ent_operational_nft_id.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", results)
|
||||
|
||||
|
||||
def op_cancel_offer():
|
||||
results = cancel_offer(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_nft_offer_index.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
|
||||
# Module 3 Handlers
|
||||
|
||||
def standby_mint_token():
|
||||
results = mint_token(
|
||||
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 standby_get_tokens():
|
||||
results = get_tokens(ent_standby_account.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_burn_token():
|
||||
results = burn_token(
|
||||
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 operational_mint_token():
|
||||
results = mint_token(
|
||||
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 operational_get_tokens():
|
||||
results = get_tokens(ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def operational_burn_token():
|
||||
results = burn_token(
|
||||
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 standby_create_trust_line():
|
||||
results = create_trust_line(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 standby_send_currency():
|
||||
results = send_currency(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 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))
|
||||
|
||||
|
||||
def operational_create_trust_line():
|
||||
results = create_trust_line(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 operational_send_currency():
|
||||
results = send_currency(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 operational_configure_account():
|
||||
results = configure_account(
|
||||
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 get_balances():
|
||||
results = get_balance(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 = get_balance(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 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))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(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 get_operational_account_info():
|
||||
accountInfo = get_account_info(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 operational_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
```
|
||||
|
||||
Create a new window with the title _Quickstart - Broker Sale_.
|
||||
|
||||
```python
|
||||
window = tk.Tk()
|
||||
window.title("Quickstart - Broker Sale")
|
||||
|
||||
myscrollbar=tk.Scrollbar(window,orient="vertical")
|
||||
myscrollbar.pack(side="right",fill="y")
|
||||
|
||||
|
||||
standbyRippling = tk.BooleanVar()
|
||||
operationalRippling = tk.BooleanVar()
|
||||
```
|
||||
|
||||
Add a new frame to hold the broker fields and buttons.
|
||||
|
||||
```python
|
||||
# Broker frame
|
||||
|
||||
frm_broker = tk.Frame(relief=tk.SUNKEN, borderwidth=3)
|
||||
frm_broker.pack()
|
||||
```
|
||||
|
||||
Define the broker entry fields.
|
||||
|
||||
```python
|
||||
lbl_broker_seed = tk.Label(master=frm_broker, text="Broker Seed")
|
||||
ent_broker_seed = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_account = tk.Label(master=frm_broker, text="Broker Account")
|
||||
ent_broker_account = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_balance = tk.Label(master=frm_broker, text="XRP Balance")
|
||||
ent_broker_balance = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_amount = tk.Label(master=frm_broker, text="Amount")
|
||||
ent_broker_amount = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_nft_id = tk.Label(master=frm_broker, text="NFT ID")
|
||||
ent_broker_nft_id = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_sell_nft_idx = tk.Label(master=frm_broker, text="Sell NFT Offer Index")
|
||||
ent_broker_sell_nft_idx = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_buy_nft_idx = tk.Label(master=frm_broker, text="Buy NFT Offer Index")
|
||||
ent_broker_buy_nft_idx = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_owner = tk.Label(master=frm_broker, text="Owner")
|
||||
ent_broker_owner = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_fee = tk.Label(master=frm_broker, text="Broker Fee")
|
||||
ent_broker_fee = tk.Entry(master=frm_broker, width=50)
|
||||
lbl_broker_results=tk.Label(master=frm_broker, text="Results")
|
||||
text_broker_results = tk.Text(master=frm_broker, height=10, width=65)
|
||||
```
|
||||
|
||||
Place the fields in a grid.
|
||||
|
||||
```python
|
||||
lbl_broker_seed.grid(row=0, column=0, sticky="w")
|
||||
ent_broker_seed.grid(row=0, column=1)
|
||||
lbl_broker_account.grid(row=1, column=0, sticky="w")
|
||||
ent_broker_account.grid(row=1, column=1)
|
||||
lbl_broker_balance.grid(row=2, column=0, sticky="w")
|
||||
ent_broker_balance.grid(row=2, column=1)
|
||||
lbl_broker_amount.grid(row=3, column=0, sticky="w")
|
||||
ent_broker_amount.grid(row=3, column=1)
|
||||
lbl_broker_nft_id.grid(row=4, column=0, sticky="w")
|
||||
ent_broker_nft_id.grid(row=4, column=1)
|
||||
lbl_broker_sell_nft_idx.grid(row=5, column=0, sticky="w")
|
||||
ent_broker_sell_nft_idx.grid(row=5, column=1)
|
||||
lbl_broker_buy_nft_idx.grid(row=6, column=0, sticky="w")
|
||||
ent_broker_buy_nft_idx.grid(row=6, column=1)
|
||||
lbl_broker_owner.grid(row=7, column=0, sticky="w")
|
||||
ent_broker_owner.grid(row=7, column=1)
|
||||
lbl_broker_fee.grid(row=8, column=0, sticky="w")
|
||||
ent_broker_fee.grid(row=8, column=1)
|
||||
lbl_broker_results.grid(row=9, column=0)
|
||||
text_broker_results.grid(row=9, column=1)
|
||||
```
|
||||
|
||||
Define and place the broker buttons.
|
||||
|
||||
```python
|
||||
btn_broker_get_account = tk.Button(master=frm_broker, text="Get Broker Account",
|
||||
command = get_broker_account)
|
||||
btn_broker_get_account.grid(row=0, column=2, sticky = "nsew")
|
||||
btn_broker_get_account_info = tk.Button(master=frm_broker, text="Get Broker Account Info",
|
||||
command = get_broker_account_info)
|
||||
btn_broker_get_account_info.grid(row=1, column=2, sticky = "nsew")
|
||||
btn_broker_sale = tk.Button(master=frm_broker, text="Broker Sale",
|
||||
command = broker_broker_sale)
|
||||
btn_broker_sale.grid(row=2, column=2, sticky = "nsew")
|
||||
btn_broker_get_offers = tk.Button(master=frm_broker, text="Get Offers",
|
||||
command = broker_get_offers)
|
||||
btn_broker_get_offers.grid(row=3, column=2, sticky = "nsew")
|
||||
btn_broker_cancel_offer = tk.Button(master=frm_broker, text="Cancel Offer",
|
||||
command = broker_cancel_offer)
|
||||
btn_broker_cancel_offer.grid(row=4, column=2, sticky="nsew")
|
||||
|
||||
# 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_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_standby_destination = 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_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)
|
||||
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")
|
||||
lbl_standby_nft_offer_index = tk.Label(master=frm_form, text="NFT Offer Index")
|
||||
ent_standby_nft_offer_index = tk.Entry(master=frm_form, width="50")
|
||||
lbl_standby_owner = tk.Label(master=frm_form, text="Owner")
|
||||
ent_standby_owner = tk.Entry(master=frm_form, width="50")
|
||||
lbl_standby_expiration = tk.Label(master=frm_form, text="Expiration")
|
||||
ent_standby_expiration = 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 = 10, 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")
|
||||
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_nft_offer_index.grid(row=13, column=0, sticky="ne")
|
||||
ent_standby_nft_offer_index.grid(row=13, column=1, sticky="w")
|
||||
lbl_standby_owner.grid(row=14, column=0, sticky="ne")
|
||||
ent_standby_owner.grid(row=14, column=1, sticky="w")
|
||||
lbl_standby_expiration.grid(row=15, column=0, sticky="ne")
|
||||
ent_standby_expiration.grid(row=15, column=1, sticky="w")
|
||||
lbl_standby_results.grid(row=17, column=0, sticky="ne")
|
||||
text_standby_results.grid(row=17, 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = 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)
|
||||
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="NFT ID")
|
||||
ent_operational_nft_id = tk.Entry(master=frm_form, width="50")
|
||||
lbl_operational_nft_offer_index = tk.Label(master=frm_form, text="NFT Offer Index")
|
||||
ent_operational_nft_offer_index = tk.Entry(master=frm_form, width="50")
|
||||
lbl_operational_owner = tk.Label(master=frm_form, text="Owner")
|
||||
ent_operational_owner = tk.Entry(master=frm_form, width="50")
|
||||
lbl_operational_expiration = tk.Label(master=frm_form, text="Expiration")
|
||||
ent_operational_expiration = 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 = 10, 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")
|
||||
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_nft_offer_index.grid(row=13, column=4, sticky="ne")
|
||||
ent_operational_nft_offer_index.grid(row=13, column=5, sticky="w")
|
||||
lbl_operational_owner.grid(row=14, column=4, sticky="ne")
|
||||
ent_operational_owner.grid(row=14, column=5, sticky="w")
|
||||
lbl_operational_expiration.grid(row=15, column=4, sticky="ne")
|
||||
ent_operational_expiration.grid(row=15, column=5, sticky="w")
|
||||
lbl_operational_results.grid(row=17, column=4, sticky="ne")
|
||||
text_operational_results.grid(row=17, 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 = 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_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
btn_standby_send_xrp.grid(row=2, column = 2, sticky = "nsew")
|
||||
btn_standby_create_trust_line = tk.Button(master=frm_form,
|
||||
text="Create Trust Line",
|
||||
command = standby_create_trust_line)
|
||||
btn_standby_create_trust_line.grid(row=4, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Send Currency >",
|
||||
command = standby_send_currency)
|
||||
btn_standby_send_currency.grid(row=5, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_standby_send_currency.grid(row=6, 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")
|
||||
btn_standby_mint_token = tk.Button(master=frm_form, text="Mint NFT",
|
||||
command = standby_mint_token)
|
||||
btn_standby_mint_token.grid(row=8, column=2, sticky="nsew")
|
||||
btn_standby_get_tokens = tk.Button(master=frm_form, text="Get NFTs",
|
||||
command = standby_get_tokens)
|
||||
btn_standby_get_tokens.grid(row=9, column=2, sticky="nsew")
|
||||
btn_standby_burn_token = tk.Button(master=frm_form, text="Burn NFT",
|
||||
command = standby_burn_token)
|
||||
btn_standby_burn_token.grid(row=10, column=2, sticky="nsew")
|
||||
btn_standby_create_sell_offer = tk.Button(master=frm_form, text="Create Sell Offer",
|
||||
command = standby_create_sell_offer)
|
||||
btn_standby_create_sell_offer.grid(row=11, column=2, sticky="nsew")
|
||||
btn_standby_accept_sell_offer = tk.Button(master=frm_form, text="Accept Sell Offer",
|
||||
command = standby_accept_sell_offer)
|
||||
btn_standby_accept_sell_offer.grid(row=12, column=2, sticky="nsew")
|
||||
btn_standby_create_buy_offer = tk.Button(master=frm_form, text="Create Buy Offer",
|
||||
command = standby_create_buy_offer)
|
||||
btn_standby_create_buy_offer.grid(row=13, column=2, sticky="nsew")
|
||||
btn_standby_accept_buy_offer = tk.Button(master=frm_form, text="Accept Buy Offer",
|
||||
command = standby_accept_buy_offer)
|
||||
btn_standby_accept_buy_offer.grid(row=14, column=2, sticky="nsew")
|
||||
btn_standby_get_offers = tk.Button(master=frm_form, text="Get Offers",
|
||||
command = standby_get_offers)
|
||||
btn_standby_get_offers.grid(row=15, column=2, sticky="nsew")
|
||||
btn_standby_cancel_offer = tk.Button(master=frm_form, text="Cancel Offer",
|
||||
command = standby_cancel_offer)
|
||||
btn_standby_cancel_offer.grid(row=16, column=2, sticky="nsew")
|
||||
|
||||
|
||||
|
||||
# Create the Operational Account Buttons
|
||||
btn_get_operational_account = tk.Button(master=frm_form,
|
||||
text="Get Operational Account",
|
||||
command = get_operational_account)
|
||||
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 = get_operational_account_info)
|
||||
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 = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
btn_op_create_trust_line = tk.Button(master=frm_form, text="Create Trust Line",
|
||||
command = operational_create_trust_line)
|
||||
btn_op_create_trust_line.grid(row=4, column=3, sticky = "nsew")
|
||||
btn_op_send_currency = tk.Button(master=frm_form, text="< Send Currency",
|
||||
command = operational_send_currency)
|
||||
btn_op_send_currency.grid(row=5, column=3, sticky = "nsew")
|
||||
btn_op_get_balances = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_op_get_balances.grid(row=6, column=3, sticky = "nsew")
|
||||
btn_op_configure_account = tk.Button(master=frm_form, text="Configure Account",
|
||||
command = operational_configure_account)
|
||||
btn_op_configure_account.grid(row=7,column=4, sticky = "nsew")
|
||||
btn_op_mint_token = tk.Button(master=frm_form, text="Mint NFT",
|
||||
command = operational_mint_token)
|
||||
btn_op_mint_token.grid(row=8, column=3, sticky="nsew")
|
||||
btn_op_get_tokens = tk.Button(master=frm_form, text="Get NFTs",
|
||||
command = operational_get_tokens)
|
||||
btn_op_get_tokens.grid(row=9, column=3, sticky="nsew")
|
||||
btn_op_burn_token = tk.Button(master=frm_form, text="Burn NFT",
|
||||
command = operational_burn_token)
|
||||
btn_op_burn_token.grid(row=10, column=3, sticky="nsew")
|
||||
btn_op_create_sell_offer = tk.Button(master=frm_form, text="Create Sell Offer",
|
||||
command = op_create_sell_offer)
|
||||
btn_op_create_sell_offer.grid(row=11, column=3, sticky="nsew")
|
||||
btn_op_accept_sell_offer = tk.Button(master=frm_form, text="Accept Sell Offer",
|
||||
command = op_accept_sell_offer)
|
||||
btn_op_accept_sell_offer.grid(row=12, column=3, sticky="nsew")
|
||||
btn_op_create_buy_offer = tk.Button(master=frm_form, text="Create Buy Offer",
|
||||
command = op_create_buy_offer)
|
||||
btn_op_create_buy_offer.grid(row=13, column=3, sticky="nsew")
|
||||
btn_op_accept_buy_offer = tk.Button(master=frm_form, text="Accept Buy Offer",
|
||||
command = op_accept_buy_offer)
|
||||
btn_op_accept_buy_offer.grid(row=14, column=3, sticky="nsew")
|
||||
btn_op_get_offers = tk.Button(master=frm_form, text="Get Offers",
|
||||
command = op_get_offers)
|
||||
btn_op_get_offers.grid(row=15, column=3, sticky="nsew")
|
||||
btn_op_cancel_offer = tk.Button(master=frm_form, text="Cancel Offer",
|
||||
command = op_cancel_offer)
|
||||
btn_op_cancel_offer.grid(row=16, column=3, sticky="nsew")
|
||||
|
||||
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
```x
|
||||
15
docs/tutorials/python/modular-tutorials/nfts/index.md
Normal file
15
docs/tutorials/python/modular-tutorials/nfts/index.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
html: nfts-using-python.html
|
||||
parent: modular-tutorials-in-python.html
|
||||
top_nav_grouping: Article Types
|
||||
metadata:
|
||||
indexPage: true
|
||||
seo:
|
||||
description: Mint and sell NFTs on the XRP Ledger using Python.
|
||||
---
|
||||
# NFTs Using Python
|
||||
|
||||
Mint and sell NFTs on the XRP Ledger using Python.
|
||||
|
||||
|
||||
{% child-pages /%}
|
||||
@@ -0,0 +1,637 @@
|
||||
---
|
||||
html: py-mint-and-burn-nfts.html
|
||||
parent: nfts-using-python.html
|
||||
seo:
|
||||
description: Mint and burn NFTs.
|
||||
labels:
|
||||
- Quickstart
|
||||
- Tokens
|
||||
- Non-fungible tokens, NFTs
|
||||
---
|
||||
|
||||
# Mint and Burn NFTs Using 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.
|
||||
|
||||
[](/docs/img/quickstart-py10.png)
|
||||
|
||||
# Usage
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.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 standby account seed in the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
3. Paste the operational account seed in the **Operational Seed** field.
|
||||
4. 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**.
|
||||
|
||||
[](/docs/img/quickstart-py11.png)
|
||||
|
||||
## Mint an NFT
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/StOLO9Bx9n8?si=IgMtoYRQlheaXzsG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
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](/docs/references/protocol/transactions/types/nftokenmint/#nftokenmint-flags) for information about all of the available flags for minting NFTs.
|
||||
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 NFT 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 NFT 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 NFT**.
|
||||
|
||||
[](/docs/img/quickstart-py12.png)
|
||||
|
||||
|
||||
## Get Tokens
|
||||
|
||||
Click **Get NFTs** to get a list of NFTs owned by the account.
|
||||
|
||||
[](/docs/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 NFT**.
|
||||
|
||||
[](/docs/img/quickstart-py14.png)
|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive to examine the code samples.
|
||||
|
||||
## mod3.py
|
||||
|
||||
This module contains the new methods `mint_token`, `get_tokens`, and `burn_token`.
|
||||
|
||||
Import dependencies and set global 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"
|
||||
```
|
||||
|
||||
## mintToken
|
||||
|
||||
Pass the arguments account seed, NFT URI, transaction flags, the transfer fee, and optional taxon.
|
||||
|
||||
```python
|
||||
def mint_token(seed, uri, flags, transfer_fee, taxon):
|
||||
"""mint_token"""
|
||||
```
|
||||
|
||||
Get the account wallet and a client instance.
|
||||
|
||||
```python
|
||||
minter_wallet=Wallet.from_seed(seed)
|
||||
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=minter_wallet.address,
|
||||
uri=xrpl.utils.str_to_hex(uri),
|
||||
flags=int(flags),
|
||||
transfer_fee=int(transfer_fee),
|
||||
nftoken_taxon=int(taxon)
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and return results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(mint_tx,client,minter_wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
## getTokens
|
||||
|
||||
```python
|
||||
def get_tokens(account):
|
||||
"""get_tokens"""
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
## burn_token
|
||||
|
||||
Pass the owner's seed value and the NFT ID.
|
||||
|
||||
```python
|
||||
def burn_token(seed, nftoken_id):
|
||||
"""burn_token"""
|
||||
```
|
||||
|
||||
Get the owner wallet and client instance.
|
||||
|
||||
```python
|
||||
owner_wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the NFTokenBurn transaction.
|
||||
|
||||
```python
|
||||
burn_tx=xrpl.models.transactions.NFTokenBurn(
|
||||
account=owner_wallet.address,
|
||||
nftoken_id=nftoken_id
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and return results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(burn_tx,client,owner_wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
## 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 tkinter as tk
|
||||
import xrpl
|
||||
import json
|
||||
|
||||
from mod1 import get_account, get_account_info, send_xrp
|
||||
from mod2 import (
|
||||
create_trust_line,
|
||||
send_currency,
|
||||
get_balance,
|
||||
configure_account,
|
||||
)
|
||||
```
|
||||
|
||||
Import methods from `mod3.py`.
|
||||
|
||||
```python
|
||||
from mod3 import (
|
||||
mint_token,
|
||||
get_tokens,
|
||||
burn_token,
|
||||
)
|
||||
|
||||
#############################################
|
||||
## Handlers #################################
|
||||
#############################################
|
||||
```
|
||||
|
||||
Module 3 Handlers
|
||||
|
||||
```python
|
||||
def standby_mint_token():
|
||||
results = mint_token(
|
||||
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 standby_get_tokens():
|
||||
results = get_tokens(ent_standby_account.get())
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def standby_burn_token():
|
||||
results = burn_token(
|
||||
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 operational_mint_token():
|
||||
results = mint_token(
|
||||
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 operational_get_tokens():
|
||||
results = get_tokens(ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
|
||||
def operational_burn_token():
|
||||
results = burn_token(
|
||||
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 standby_create_trust_line():
|
||||
results = create_trust_line(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 standby_send_currency():
|
||||
results = send_currency(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 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))
|
||||
|
||||
|
||||
def operational_create_trust_line():
|
||||
results = create_trust_line(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 operational_send_currency():
|
||||
results = send_currency(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 operational_configure_account():
|
||||
results = configure_account(
|
||||
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 get_balances():
|
||||
results = get_balance(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 = get_balance(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 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))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(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 get_operational_account_info():
|
||||
accountInfo = get_account_info(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 operational_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
```
|
||||
|
||||
Create a new window with the title "Quickstart Module 3."
|
||||
|
||||
```python
|
||||
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_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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = 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_standby_allow_rippling = tk.Checkbutton(master=frm_form, text="Allow Rippling", variable=standbyRippling, onvalue=True, offvalue=False)
|
||||
```
|
||||
|
||||
Add **NFT URI**, **Flags**, **Transfer Fee**, **Taxon**, and **NFT 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="NFT 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = 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 **NFT 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="NFT 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 = 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_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
btn_standby_send_xrp.grid(row=2, column = 2, sticky = "nsew")
|
||||
btn_standby_create_trust_line = tk.Button(master=frm_form,
|
||||
text="Create Trust Line",
|
||||
command = standby_create_trust_line)
|
||||
btn_standby_create_trust_line.grid(row=3, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Send Currency >",
|
||||
command = standby_send_currency)
|
||||
btn_standby_send_currency.grid(row=4, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_standby_send_currency.grid(row=5, column=2, sticky = "nsew")
|
||||
btn_standby_configure_account = tk.Button(master=frm_form,
|
||||
text="Configure Account",
|
||||
command = standby_configure_account)
|
||||
```
|
||||
|
||||
Add buttons for **Mint NFT**, **Get NFTs**, and **Burn NFT**.
|
||||
|
||||
```python
|
||||
btn_standby_mint_token = tk.Button(master=frm_form, text="Mint NFT",
|
||||
command = standby_mint_token)
|
||||
btn_standby_mint_token.grid(row=8, column=2, sticky="nsew")
|
||||
btn_standby_get_tokens = tk.Button(master=frm_form, text="Get NFTs",
|
||||
command = standby_get_tokens)
|
||||
btn_standby_get_tokens.grid(row=9, column=2, sticky="nsew")
|
||||
btn_standby_burn_token = tk.Button(master=frm_form, text="Burn NFT",
|
||||
command = standby_burn_token)
|
||||
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 = get_operational_account)
|
||||
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 = get_operational_account_info)
|
||||
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 = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
btn_op_create_trust_line = tk.Button(master=frm_form, text="Create Trust Line",
|
||||
command = operational_create_trust_line)
|
||||
btn_op_create_trust_line.grid(row=3, column=3, sticky = "nsew")
|
||||
btn_op_send_currency = tk.Button(master=frm_form, text="< Send Currency",
|
||||
command = operational_send_currency)
|
||||
btn_op_send_currency.grid(row=4, column=3, sticky = "nsew")
|
||||
btn_op_get_balances = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_op_get_balances.grid(row=5, column=3, sticky = "nsew")
|
||||
btn_op_configure_account = tk.Button(master=frm_form, text="Configure Account",
|
||||
command = operational_configure_account)
|
||||
btn_op_configure_account.grid(row=7,column=4, sticky = "nsew")
|
||||
```
|
||||
Add buttons for **Mint NFT**, **Get NFTs**, and **Burn NFT**.
|
||||
|
||||
```python
|
||||
btn_op_mint_token = tk.Button(master=frm_form, text="Mint NFT",
|
||||
command = operational_mint_token)
|
||||
btn_op_mint_token.grid(row=8, column=3, sticky="nsew")
|
||||
btn_op_get_tokens = tk.Button(master=frm_form, text="Get NFTs",
|
||||
command = operational_get_tokens)
|
||||
btn_op_get_tokens.grid(row=9, column=3, sticky="nsew")
|
||||
btn_op_burn_token = tk.Button(master=frm_form, text="Burn NFT",
|
||||
command = operational_burn_token)
|
||||
btn_op_burn_token.grid(row=10, column=3, sticky="nsew")
|
||||
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
```
|
||||
1024
docs/tutorials/python/modular-tutorials/nfts/transfer-nfts.md
Normal file
1024
docs/tutorials/python/modular-tutorials/nfts/transfer-nfts.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,428 @@
|
||||
---
|
||||
html: py-create-accounts-send-xrp.html
|
||||
parent: send-payments-using-python.html
|
||||
seo:
|
||||
description: Create two accounts and transfer XRP between them using Python.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- Transaction Sending
|
||||
- XRP
|
||||
---
|
||||
# Create Accounts and Send XRP Using Python
|
||||
|
||||
This example shows how to:
|
||||
|
||||
1. Create accounts on the Testnet, funded with 10000 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.
|
||||
|
||||
[](/docs/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/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive.
|
||||
|
||||
**Note:** Without the Quickstart Samples, you will not be able to try the examples that follow.
|
||||
|
||||
## Usage
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Uu36ga0iMv0?si=jUoxQDcmqXpg1c_5" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
||||
[](/docs/img/quickstart-py3.png)
|
||||
|
||||
You can transfer XRP between your new accounts. Each account has its own fields and buttons.
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/qUd-CTFdiks?si=chUPgcHZssL54x6U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
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
|
||||
|
||||
[](/docs/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/_code-samples/quickstart/py/)<!-- {.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 library.
|
||||
|
||||
```python
|
||||
import xrpl
|
||||
|
||||
```
|
||||
|
||||
Create a variable for the server URI. This example uses the _Testnet_ ledger. You can update the URI to choose a different XRP Ledger instance.
|
||||
|
||||
|
||||
```python
|
||||
testnet_url = "https://s.altnet.rippletest.net:51234/"
|
||||
```
|
||||
|
||||
### get_account
|
||||
|
||||
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 get_account(seed):
|
||||
"""get_account"""
|
||||
```
|
||||
|
||||
Request a new client from the XRP Ledger.
|
||||
|
||||
```python
|
||||
client = xrpl.clients.JsonRpcClient(testnet_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 = xrpl.wallet.Wallet.from_seed(seed)
|
||||
return new_wallet
|
||||
```
|
||||
|
||||
### get_account_info
|
||||
|
||||
Pass the account ID to the `get_account_info` method.
|
||||
|
||||
```python
|
||||
def get_account_info(accountId):
|
||||
"""get_account_info"""
|
||||
```
|
||||
|
||||
Get a client instance from Testnet.
|
||||
|
||||
```python
|
||||
client = xrpl.clients.JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create the account info request, passing the account ID and the ledger index (in this case, the latest validated ledger).
|
||||
|
||||
```python
|
||||
acct_info = xrpl.models.requests.account_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']
|
||||
```
|
||||
|
||||
### send_xrp
|
||||
|
||||
Transfer XRP to another account by passing the client seed, amount to transfer, and the destination account.
|
||||
|
||||
```python
|
||||
def send_xrp(seed, amount, destination):
|
||||
```
|
||||
|
||||
Get the sending wallet.
|
||||
|
||||
```python
|
||||
sending_wallet = xrpl.wallet.Wallet.from_seed(seed)
|
||||
client = xrpl.clients.JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create a transaction request, passing the sending account, amount, and destination account.
|
||||
|
||||
```python
|
||||
payment = xrpl.models.transactions.Payment(
|
||||
account=sending_wallet.address,
|
||||
amount=xrpl.utils.xrp_to_drops(int(amount)),
|
||||
destination=destination,
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and return the response. If the transaction fails, return the error message.
|
||||
|
||||
```python
|
||||
try:
|
||||
response = xrpl.transaction.submit_and_wait(payment, client, sending_wallet)
|
||||
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 get_account, get_account_info, send_xrp
|
||||
```
|
||||
|
||||
### getStandbyAccount
|
||||
|
||||
```python
|
||||
def get_standby_account():
|
||||
```
|
||||
|
||||
Use the value in the standby Seed field (or an empty value) to request a new account.
|
||||
|
||||
```python
|
||||
new_wallet = get_account(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_standby_account_info
|
||||
|
||||
With an account ID, anyone can request information about the account. Get the standby account value and use it to populate a `get_account_info` request.
|
||||
|
||||
```python
|
||||
def get_standby_account_info():
|
||||
accountInfo = get_account_info(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))
|
||||
```
|
||||
|
||||
### standby_send_xrp
|
||||
|
||||
```python
|
||||
def standby_send_xrp():
|
||||
```
|
||||
|
||||
Call the `send_xrp` method, passing the standby seed, the amount, and the destination value.
|
||||
|
||||
```python
|
||||
response = send_xrp(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 `get_standby_account_info()` and `get_operational_account_info()` to update the balance field for both accounts.
|
||||
|
||||
```python
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
```
|
||||
|
||||
### Reciprocal Transactions and Requests
|
||||
|
||||
The following four methods are the same as the previous standby transactions, but for the operational account.
|
||||
|
||||
```python
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(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 get_operational_account_info():
|
||||
account_info = get_account_info(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 operational_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
```
|
||||
|
||||
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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_standby_balance = 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = 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 = 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_send_xrp = tk.Button(master=frm_form, text="Send XRP >", command = standby_send_xrp)
|
||||
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 = get_operational_account)
|
||||
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 = get_operational_account_info)
|
||||
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 = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
```
|
||||
|
||||
Start the application.
|
||||
|
||||
```python
|
||||
window.mainloop()
|
||||
```
|
||||
@@ -0,0 +1,608 @@
|
||||
---
|
||||
html: py-create-conditional-escrows.html
|
||||
parent: send-payments-using-python.html
|
||||
seo:
|
||||
description: Create, finish, or cancel condition-based escrow transactions.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- Transaction Sending
|
||||
- XRP
|
||||
---
|
||||
# Create Conditional Escrows Using Python
|
||||
|
||||
This example shows how to:
|
||||
|
||||
1. Create escrow payments that become available when an account enters a fulfillment code.
|
||||
|
||||
2. Complete a conditional escrow transaction.
|
||||
|
||||
3. Cancel a conditional escrow transaction.
|
||||
|
||||
[](/docs/img/quickstart-py-conditional-escrow-1.png)
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download and expand the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive.
|
||||
|
||||
You need the `cryptoconditions` module to generate your condition/fulfillment pair. You can install the module using [pip](https://pip.pypa.io/en/stable/).
|
||||
|
||||
In a terminal window, install the `cryptoconditions` module with this command:
|
||||
|
||||
```bash
|
||||
pip install cryptoconditions
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Get Test Accounts
|
||||
|
||||
To get test accounts:
|
||||
|
||||
1. Open and run `lesson9-conditional-escrow.py`.
|
||||
2. Get test accounts.
|
||||
1. If you have existing account seeds
|
||||
1. Paste Standby account seed in the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info**.
|
||||
4. Paste Operational account seed in the **Operational Seed** field.
|
||||
5. Click **Get Operational Account**.
|
||||
6. Click **Get Op Account Info**.
|
||||
2. If you do not have account seeds:
|
||||
1. Click **Get Standby Account**.
|
||||
2. Click **Get Standby Account Info**.
|
||||
3. Click **Get Operational Account**.
|
||||
4. Click **Get Op Account Info**.
|
||||
|
||||
[](/docs/img/quickstart-py-conditional-escrow-2.png)
|
||||
|
||||
#### Get a Condition and Fulfillment
|
||||
|
||||
Click **Get Condition** to generate a condition/fulfillment pair and populate the fields on the form. You can copy the values and store them in a text file for safe keeping.
|
||||
|
||||
[](/docs/img/quickstart-py-conditional-escrow-3.png)
|
||||
|
||||
### Create Conditional Escrow
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/IUfSX5RKahs?si=7kV0T2NTtqsZfpvX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
When you create a conditional escrow, you need to specify the `Condition` value you generated above. You must also set a cancel date and time, after which the escrow is no longer available.
|
||||
|
||||
To create a conditional escrow:
|
||||
|
||||
1. Enter an **Amount** to transfer.
|
||||
2. Copy the **Operational Account** value.
|
||||
3. Paste it in the **Destination Account** field.
|
||||
4. Enter the **Escrow Cancel (seconds)** value.
|
||||
5. Click **Create Escrow**.
|
||||
6. Copy and save the _Sequence Number_ of the escrow called out in the **Standby Result** field.
|
||||
|
||||
The escrow is created on the XRP Ledger instance, reserving your requested XRP amount plus the transaction cost.
|
||||
|
||||
When you create an escrow, capture and save the _Sequence Number_ so that you can use it to finish the escrow transaction.
|
||||
|
||||
[](/docs/img/quickstart-py-conditional-escrow-4.png)
|
||||
|
||||
## Finish Conditional Escrow
|
||||
|
||||
Any account can finish the conditional escrow any time before the _Escrow Cancel_ time. Following on the example above, you can use the _Sequence Number_ to finish the transaction once the Escrow Cancel time has passed.
|
||||
|
||||
To finish a conditional escrow:
|
||||
|
||||
1. Paste the sequence number in the Operational account **Sequence Number** field.
|
||||
2. Enter the **Escrow Condition** value.
|
||||
3. Enter the **Escrow Fulfillment** code for the `Condition`.
|
||||
4. Copy the **Standby Account** value.
|
||||
5. Paste it into the **Escrow Owner** field.
|
||||
4. Click **Finish Conditional Escrow**.
|
||||
|
||||
The transaction completes and balances are updated for both the Standby and Operational accounts.
|
||||
|
||||
[](/docs/img/quickstart-py-conditional-escrow-5.png)
|
||||
|
||||
## Get Escrows
|
||||
|
||||
Click **Get Escrows** for either the Standby account or the Operational account to see their current list of escrows.
|
||||
|
||||
## Cancel Escrow
|
||||
|
||||
When the Escrow Cancel time passes, the escrow is no longer available to the recipient. The initiator of the escrow can reclaim the XRP, less the transaction fees. Any account can cancel an escrow once the cancel time has elapsed. Accounts that try to cancel the transaction prior to the **Escrow Cancel** time are charged the nominal transaction cost (about 10-15 drops), but the actual escrow cannot be cancelled until after the Escrow Cancel time.
|
||||
|
||||
## Oh No! I Forgot to Save the Sequence Number!
|
||||
|
||||
If you forget to save the sequence number, you can find it in the escrow transaction record.
|
||||
|
||||
1. Create a new escrow as described in [Create Conditional Escrow](#create-conditional-escrow), above.
|
||||
2. Click **Get Escrows** to get the escrow information.
|
||||
3. Copy the _PreviousTxnLgrSeq_ value from the results.
|
||||

|
||||
4. Paste the _PreviousTxnLgrSeq_ in the **Transaction to Look Up** field.
|
||||

|
||||
5. Click **Get Transaction**.
|
||||
6. Locate the _Sequence_ value in the results.
|
||||
|
||||

|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Modular Tutorials](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> in the source repository for this website.
|
||||
|
||||
## mod9.py
|
||||
|
||||
Import dependencies.
|
||||
|
||||
```python
|
||||
import xrpl
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.wallet import Wallet
|
||||
from datetime import datetime
|
||||
from xrpl.models.transactions import EscrowCreate, EscrowFinish
|
||||
from os import urandom
|
||||
from cryptoconditions import PreimageSha256
|
||||
```
|
||||
|
||||
Create a global variable pointing to Testnet.
|
||||
|
||||
```python
|
||||
testnet_url = "https://s.altnet.rippletest.net:51234"
|
||||
```
|
||||
|
||||
### generate_condition
|
||||
|
||||
Generate the _condition_ and _fulfillment_ values for the escrow.
|
||||
|
||||
```python
|
||||
def generate_condition():
|
||||
```
|
||||
|
||||
Set a variable to 32 random bytes.
|
||||
|
||||
```python
|
||||
randy = urandom(32)
|
||||
```
|
||||
|
||||
Use the 32-byte random variable as the argument for the `PreimageSha256` functino.
|
||||
|
||||
```python
|
||||
fulfillment = PreimageSha256(preimage=randy)
|
||||
```
|
||||
|
||||
Return the binary condition and the binary serialized (fulfillment) value.
|
||||
|
||||
```python
|
||||
return (fulfillment.condition_binary.hex().upper(),
|
||||
fulfillment.serialize_binary().hex().upper())
|
||||
```
|
||||
|
||||
### add_seconds
|
||||
|
||||
Create a date in the Ripple epoch, adding the specified number of seconds.
|
||||
|
||||
```python
|
||||
def add_seconds(numOfSeconds):
|
||||
```
|
||||
|
||||
Create a new_date variable.
|
||||
|
||||
```python
|
||||
new_date = datetime.now()
|
||||
```
|
||||
|
||||
Convert the date to a Ripple time object.
|
||||
|
||||
```python
|
||||
if new_date != '':
|
||||
new_date = xrpl.utils.datetime_to_ripple_time(new_date)
|
||||
```
|
||||
|
||||
Add the requested seconds to the Ripple formatted date variable.
|
||||
|
||||
```python
|
||||
new_date = new_date + int(numOfSeconds)
|
||||
```
|
||||
|
||||
Return the result.
|
||||
|
||||
```python
|
||||
return new_date
|
||||
```
|
||||
|
||||
### create_conditional_escrow
|
||||
|
||||
You create conditional escrows using the same **EscrowCreate** model you used for a time-based escrow, but instead of a finish time, you provide a condition that must be met to complete the transaction.
|
||||
|
||||
Pass the _seed_ for the sending account, the _amount_ to hold in escrow, the _destination_ account to receive the escrow funds, the number of seconds until the escrow will _cancel_, and a _condition_ value that will be matched with a _fulfillment_ value to complete the escrow.
|
||||
|
||||
```python
|
||||
def create_conditional_escrow(seed, amount, destination, cancel, condition):
|
||||
```
|
||||
|
||||
Instantiate a wallet and connect to Testnet.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create a *cancel_date* variable, adding your specified number of seconds to the current Ripple epoch date.
|
||||
|
||||
```python
|
||||
cancel_date = add_seconds(cancel)
|
||||
```
|
||||
|
||||
Define the transaction with your provided values.
|
||||
|
||||
```python
|
||||
escrow_tx=xrpl.models.transactions.EscrowCreate(
|
||||
account=wallet.address,
|
||||
amount=amount,
|
||||
destination=destination,
|
||||
cancel_after=cancel_date,
|
||||
condition=condition
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and return the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(escrow_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### finish_conditional_escrow
|
||||
|
||||
At any time prior to the cancel date, the destination account can fulfill the escrow.
|
||||
|
||||
Pass the _seed_ for the receiving account, the _owner_ (sending account), the _sequence_ number for the escrow, the _condition_ value, and the matching _fulfillment_ value.
|
||||
|
||||
```python
|
||||
def finish_conditional_escrow(seed, owner, sequence, condition, fulfillment):
|
||||
```
|
||||
|
||||
Instantiate the account wallet and connect to Testnet.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the **EscrowFinish** transaction, including both the condition and the fulfillment values.
|
||||
|
||||
```python
|
||||
finish_tx=xrpl.models.transactions.EscrowFinish(
|
||||
account=wallet.address,
|
||||
owner=owner,
|
||||
offer_sequence=int(sequence),
|
||||
condition=condition,
|
||||
fulfillment=fulfillment
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(finish_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
## lesson9-conditional-escrow.py
|
||||
|
||||
This example builds on `lesson8-time-escrow.py` to reuse fields, buttons, and functions that apply to both time-based and conditional escrows. Updates are highlighted below.
|
||||
|
||||
```python
|
||||
import tkinter as tk
|
||||
import xrpl
|
||||
import json
|
||||
|
||||
from mod1 import get_account, get_account_info, send_xrp
|
||||
from mod8 import get_escrows, cancel_time_escrow, get_transaction
|
||||
```
|
||||
|
||||
Import new functions for conditional escrows from module 9.
|
||||
|
||||
```python
|
||||
from mod9 import create_conditional_escrow, finish_conditional_escrow, generate_condition
|
||||
|
||||
```
|
||||
|
||||
Add handlers for creating and finishing conditional escrows.
|
||||
|
||||
```python
|
||||
def get_condition():
|
||||
results = generate_condition()
|
||||
ent_standby_escrow_condition.delete(0, tk.END)
|
||||
ent_standby_escrow_condition.insert(0, results[0])
|
||||
ent_operational_escrow_fulfillment.delete(0, tk.END)
|
||||
ent_operational_escrow_fulfillment.insert(0, results[1])
|
||||
|
||||
def standby_create_conditional_escrow():
|
||||
results = create_conditional_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_destination.get(),
|
||||
ent_standby_escrow_cancel.get(),
|
||||
ent_standby_escrow_condition.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_finish_conditional_escrow():
|
||||
results = finish_conditional_escrow(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_escrow_owner.get(),
|
||||
ent_operational_sequence_number.get(),
|
||||
ent_standby_escrow_condition.get(),
|
||||
ent_operational_escrow_fulfillment.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
## Mod 8 Handlers
|
||||
|
||||
def operational_get_escrows():
|
||||
results = get_escrows(ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def standby_cancel_time_escrow():
|
||||
results = cancel_time_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_escrow_owner.get(),
|
||||
ent_standby_escrow_sequence_number.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_get_transaction():
|
||||
results = get_transaction(ent_operational_account.get(),
|
||||
ent_operational_look_up.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
## Mod 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))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(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 get_operational_account_info():
|
||||
accountInfo = get_account_info(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 operational_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
```
|
||||
|
||||
Rename the window.
|
||||
|
||||
```python
|
||||
window = tk.Tk()
|
||||
window.title("Conditional Escrow Example")
|
||||
|
||||
# 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_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_standby_destination = 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)
|
||||
```
|
||||
|
||||
Add a field for the escrow condition.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_condition = tk.Label(master=frm_form, text="Escrow Condition")
|
||||
ent_standby_escrow_condition = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_cancel = tk.Label(master=frm_form, text="Escrow Cancel (seconds)")
|
||||
ent_standby_escrow_cancel = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_standby_escrow_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_owner = tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_standby_escrow_owner = 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 fields in a grid.
|
||||
lbl_standy_seed.grid(row=0, column=0, sticky="e")
|
||||
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)
|
||||
```
|
||||
|
||||
Insert the condition field in the standby grid.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_condition.grid(row=6, column=0, sticky="e")
|
||||
ent_standby_escrow_condition.grid(row=6, column=1)
|
||||
lbl_standby_escrow_cancel.grid(row=7, column=0, sticky="e")
|
||||
ent_standby_escrow_cancel.grid(row=7, column=1)
|
||||
lbl_standby_escrow_sequence_number.grid(row=8, column=0, sticky="e")
|
||||
ent_standby_escrow_sequence_number.grid(row=8, column=1)
|
||||
lbl_standby_escrow_owner.grid(row=9, column=0, sticky="e")
|
||||
ent_standby_escrow_owner.grid(row=9, column=1)
|
||||
lbl_standby_results.grid(row=10, column=0, sticky="ne")
|
||||
text_standby_results.grid(row=10, column=1, sticky="nw")
|
||||
|
||||
###############################################
|
||||
## 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = tk.Entry(master=frm_form, width=50)
|
||||
```
|
||||
|
||||
Add a field for the escrow fulfillment value.
|
||||
|
||||
```python
|
||||
lbl_operational_escrow_fulfillment = tk.Label(master=frm_form, text="Escrow Fulfillment")
|
||||
ent_operational_escrow_fulfillment = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_operational_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_escrow_owner=tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_operational_escrow_owner=tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_look_up = tk.Label(master=frm_form, text="Transaction to Look Up")
|
||||
ent_operational_look_up = 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")
|
||||
```
|
||||
|
||||
Insert the **Fulfillment** field in the operational grid, moving the other fields down so as to align the **Condition** and **Fulfillment** fields horizontally.
|
||||
|
||||
```python
|
||||
lbl_operational_escrow_fulfillment.grid(row=6, column=4, sticky="e")
|
||||
ent_operational_escrow_fulfillment.grid(row=6, column=5, sticky="w")
|
||||
lbl_operational_sequence_number.grid(row=7, column=4, sticky="e")
|
||||
ent_operational_sequence_number.grid(row=7, column=5, sticky="w")
|
||||
lbl_operational_escrow_owner.grid(row=8, column=4, sticky="e")
|
||||
ent_operational_escrow_owner.grid(row=8, column=5, sticky="w")
|
||||
lbl_operational_look_up.grid(row=9, column=4, sticky="e")
|
||||
ent_operational_look_up.grid(row=9, column=5, sticky="w")
|
||||
lbl_operational_results.grid(row=10, column=4, sticky="ne")
|
||||
text_operational_results.grid(row=10, column=5, sticky="nw")
|
||||
|
||||
#############################################
|
||||
## Buttons ##################################
|
||||
#############################################
|
||||
|
||||
# Create the Get 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_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
btn_standby_send_xrp.grid(row = 2, column = 2, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add a **Create Conditional Escrow** button to the Standby grid.
|
||||
|
||||
```python
|
||||
btn_standby_get_condition = tk.Button(master=frm_form, text="Get Condition",
|
||||
command = get_condition)
|
||||
btn_standby_get_condition.grid(row=4, column=2, sticky="nsew")
|
||||
btn_standby_create_escrow = tk.Button(master=frm_form, text="Create Conditional Escrow",
|
||||
command = standby_create_conditional_escrow)
|
||||
btn_standby_create_escrow.grid(row=5, column = 2, sticky="nsew")
|
||||
btn_standby_cancel_escrow = tk.Button(master=frm_form, text="Cancel Escrow",
|
||||
command = standby_cancel_time_escrow)
|
||||
btn_standby_cancel_escrow.grid(row=6,column = 2, sticky="nsew")
|
||||
|
||||
# Create the Operational Account Buttons
|
||||
btn_get_operational_account = tk.Button(master=frm_form,
|
||||
text="Get Operational Account",
|
||||
command = get_operational_account)
|
||||
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 = get_operational_account_info)
|
||||
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 = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add a **Finish Escrow** button to the operational grid.
|
||||
|
||||
```python
|
||||
btn_op_finish_escrow = tk.Button(master=frm_form, text="Finish Escrow",
|
||||
command = operational_finish_conditional_escrow)
|
||||
btn_op_finish_escrow.grid(row = 4, column = 3, sticky="nsew")
|
||||
btn_op_get_escrows = tk.Button(master=frm_form, text="Get Escrows",
|
||||
command = operational_get_escrows)
|
||||
btn_op_get_escrows.grid(row = 5, column = 3, sticky="nsew")
|
||||
btn_op_get_transaction = tk.Button(master=frm_form, text="Get Transaction",
|
||||
command = operational_get_transaction)
|
||||
btn_op_get_transaction.grid(row = 6, column = 3, sticky = "nsew")
|
||||
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
```
|
||||
@@ -0,0 +1,638 @@
|
||||
---
|
||||
html: py-create-time-based-escrows.html
|
||||
parent: send-payments-using-python.html
|
||||
seo:
|
||||
description: Create, finish, or cancel time-based escrow transactions.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- Transaction Sending
|
||||
- XRP
|
||||
---
|
||||
# Create Time-based Escrows Using Python
|
||||
|
||||
This example shows how to:
|
||||
|
||||
|
||||
1. Create escrow payments that become available at a specified time and expire at a specified time.
|
||||
2. Finish an escrow payment.
|
||||
3. Retrieve information on escrows attached to an account.
|
||||
3. Cancel an escrow payment and return the XRP to the sending account.
|
||||
|
||||
|
||||
[](/docs/img/quickstart-py-escrow1.png)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download the [Python Modular Code Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} -->.
|
||||
|
||||
## Usage
|
||||
|
||||
To get test accounts:
|
||||
|
||||
1. Open `lesson8-time-escrow.py.`
|
||||
2. Get test accounts.
|
||||
1. If you have existing account seeds
|
||||
1. Paste Standby account seed in the **Standby Seed** field.
|
||||
2. Click **Get Standby Account**.
|
||||
3. Click **Get Standby Account Info**.
|
||||
4. Paste Operational account seed in the **Operational Seed** field.
|
||||
5. Click **Get Operational Account**.
|
||||
6. Click **Get Op Account Info**.
|
||||
2. If you do not have account seeds:
|
||||
1. Click **Get Standby Account**.
|
||||
2. Click **Get Standby Account Info**.
|
||||
3. Click **Get Operational Account**.
|
||||
4. Click **Get Op Account Info**.
|
||||
|
||||
[](/docs/img/quickstart-py-escrow2.png)
|
||||
|
||||
## Create Escrow
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/L_2sKokW5E4?si=6r9vn4ojr6b42H2E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
You can create a time-based escrow with a minimum time to finish the escrow and a cancel time after which the funds in escrow are no longer available to the recipient. This is a test harness: while a practical scenario might express time in days or weeks, this form lets you set the finish and cancel times in seconds so that you can quickly run through a variety of scenarios. (There are 86,400 seconds in a day, if you want to play with longer term escrows.)
|
||||
|
||||
To create a time-based escrow:
|
||||
|
||||
1. Enter an **Amount** to transfer. For example, _100000000_.
|
||||
2. Copy the **Operational Account** value.
|
||||
3. Paste it in the **Destination Account** field.
|
||||
4. Set the **Escrow Finish (seconds)** value. For example, enter _10_.
|
||||
5. Set the **Escrow Cancel (seconds)** value. For example, enter _120_.
|
||||
6. Click **Create Time-based Escrow**.
|
||||
7. Copy the _Sequence Number_ of the escrow called out in the **Standby Result** field.
|
||||
|
||||
The escrow is created on the XRP Ledger instance, reserving 100 XRP plus the transaction cost and reserve requirements. When you create an escrow, capture and save the **Sequence Number** so that you can use it to finish the escrow transaction.
|
||||
|
||||
[](/docs/img/quickstart-py-escrow3.png)
|
||||
|
||||
## Finish Escrow
|
||||
|
||||
The recipient of the XRP held in escrow can finish the transaction any time within the time window after the Escrow Finish date and time but before the Escrow Cancel date and time. Following on the example above, you can use the _Sequence Number_ to finish the transaction once 10 seconds have passed.
|
||||
|
||||
To finish a time-based escrow:
|
||||
|
||||
1. Paste the sequence number in the Operational account **Sequence Number** field.
|
||||
2. Click **Finish Escrow**.
|
||||
3. Click **Get Op Account Info** and **Get Standby Account Info** to update their **XRP Balance**.
|
||||
|
||||
The transaction completes and balances are updated for both the Standby and Operational accounts.
|
||||
|
||||
[](/docs/img/quickstart-py-escrow4.png)
|
||||
|
||||
## Get Escrows
|
||||
|
||||
Click **Get Escrows** to see the current list of escrows for the Operational account. If you click the button now, there are no escrows at the moment.
|
||||
|
||||
For the purposes of this tutorial, you can follow the steps in [Create Escrow](#create-escrow), above, to create a new escrow transaction that you can then look up. Remember to capture the _Sequence Number_ from the transaction results.
|
||||
|
||||
[](/docs/img/quickstart-py-escrow5.png)
|
||||
|
||||
|
||||
## Cancel Escrow
|
||||
|
||||
When the Escrow Cancel time passes, the escrow is no longer available to the recipient. The initiator of the escrow can reclaim the XRP. If you try to cancel the transaction prior to the **Escrow Cancel** time, you are charged for the transaction, but the actual escrow cannot be cancelled until the time limit is reached.
|
||||
|
||||
You can wait the allotted time for the escrow you created in the previous step, then use it to try out the **Cancel Escrow** button
|
||||
|
||||
To cancel an expired escrow:
|
||||
|
||||
1. Enter the sequence number in the Standby **Sequence Number** field.
|
||||
2. Copy the **Standby Account** value and paste it in the **Escrow Owner** field.
|
||||
2. Click **Cancel Time-based Escrow**.
|
||||
|
||||
The funds are returned to the Standby account, less the initial transaction fee.
|
||||
|
||||
[](/docs/img/quickstart-py-escrow6.png)
|
||||
|
||||
## Oh No! I Forgot to Save the Sequence Number!
|
||||
|
||||
If you forget to save the sequence number, you can find it in the escrow transaction record.
|
||||
|
||||
1. Create a new escrow as described in [Create Escrow](#create-escrow), above.
|
||||
2. Click **Get Escrows** to get the escrow information.
|
||||
3. Copy the _PreviousTxnLgrSeq_ value from the results.
|
||||

|
||||
4. Paste the _PreviousTxnLgrSeq_ in the **Transaction to Look Up** field.
|
||||
5. Click **Get Transaction**.
|
||||
6. Locate the _Sequence_ value in the results.
|
||||

|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Python Modular Code Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> in the source repository for this website.
|
||||
|
||||
## mod8.py
|
||||
|
||||
This example can be used with the XRP Ledger network, _Testnet_. You can update the code to choose different or additional XRP Ledger networks.
|
||||
|
||||
### add_seconds
|
||||
|
||||
This function accomplishes two things. It creates a new date object and adds the number of seconds taken from a form field. Then, it adjusts the date from the Python format to the XRP Ledger format.
|
||||
|
||||
Provide the _numOfSeconds_ argument.
|
||||
|
||||
```python
|
||||
def add_seconds(numOfSeconds):
|
||||
```
|
||||
|
||||
Create a new Python date object.
|
||||
|
||||
```python
|
||||
new_date = datetime.now()
|
||||
```
|
||||
|
||||
Convert the date variable for the Ripple epoch.
|
||||
|
||||
```python
|
||||
if new_date != '':
|
||||
new_date = xrpl.utils.datetime_to_ripple_time(new_date)
|
||||
```
|
||||
|
||||
Add your seconds to the date.
|
||||
|
||||
```python
|
||||
new_date = new_date + int(numOfSeconds)
|
||||
```
|
||||
|
||||
Return the resulting date value.
|
||||
|
||||
```python
|
||||
return new_date
|
||||
```
|
||||
|
||||
### create_time_escrow
|
||||
|
||||
Call the create_time_escrow function, passing the _seed_, _amount_, _destination_, _finish_ interval, and _cancel_ interval.
|
||||
|
||||
```python
|
||||
def create_time_escrow(seed, amount, destination, finish, cancel):
|
||||
```
|
||||
|
||||
Get the client wallet.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
```
|
||||
|
||||
Connect to Testnet.
|
||||
|
||||
```python
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create variables for the finish and cancel dates using the add_seconds function.
|
||||
|
||||
```python
|
||||
finish_date = add_seconds(finish)
|
||||
cancel_date = add_seconds(cancel)
|
||||
```
|
||||
|
||||
Define the **EscrowCreate** transaction.
|
||||
|
||||
```python
|
||||
escrow_tx=xrpl.models.transactions.EscrowCreate(
|
||||
account=wallet.address,
|
||||
amount=amount,
|
||||
destination=destination,
|
||||
finish_after=finish_date,
|
||||
cancel_after=cancel_date
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(escrow_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### finish_time_escrow
|
||||
|
||||
Pass the operational account _seed_, escrow _owner_ (in these examples, the standby address), and the escrow _sequence_ number.
|
||||
|
||||
```python
|
||||
def finish_time_escrow(seed, owner, sequence):
|
||||
```
|
||||
|
||||
Instantiate the wallet and client.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the **EscrowFinish** transaction.
|
||||
|
||||
```python
|
||||
finish_tx=xrpl.models.transactions.EscrowFinish(
|
||||
account=wallet.address,
|
||||
owner=owner,
|
||||
offer_sequence=int(sequence)
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results.
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(finish_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### get_escrows
|
||||
|
||||
This request only requires the _account_ argument.
|
||||
|
||||
```python
|
||||
def get_escrows(account):
|
||||
```
|
||||
|
||||
Since this is a request, there's no need to sign in with an account to perform the query. You can just instantiate a client on Testnet.
|
||||
|
||||
```python
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the **AccountObjects** request, specifying objects of type _escrow_.
|
||||
|
||||
```python
|
||||
acct_escrows=AccountObjects(
|
||||
account=account,
|
||||
ledger_index="validated",
|
||||
type="escrow"
|
||||
)
|
||||
```
|
||||
|
||||
Submit the request and return the results.
|
||||
|
||||
```python
|
||||
response=client.request(acct_escrows)
|
||||
return response.result
|
||||
```
|
||||
|
||||
### cancel_time_escrows
|
||||
|
||||
Pass the issuer account _seed_, the _owner_ account, and the escrow _sequence_ number.
|
||||
|
||||
```python
|
||||
def cancel_time_escrow(seed, owner, sequence):
|
||||
```
|
||||
|
||||
Get the wallet and instantiate a client on _Testnet_.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the cancel transaction
|
||||
|
||||
```python
|
||||
cancel_tx=xrpl.models.transactions.EscrowCancel(
|
||||
account=wallet.address,
|
||||
owner=owner,
|
||||
offer_sequence=int(sequence)
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and report the results
|
||||
|
||||
```python
|
||||
reply=""
|
||||
try:
|
||||
response=xrpl.transaction.submit_and_wait(cancel_tx,client,wallet)
|
||||
reply=response.result
|
||||
except xrpl.transaction.XRPLReliableSubmissionException as e:
|
||||
reply=f"Submit failed: {e}"
|
||||
return reply
|
||||
```
|
||||
|
||||
### get_transaction
|
||||
|
||||
Pass the requesting account number and the previous transaction ledger sequence number.
|
||||
|
||||
```python
|
||||
def get_transaction(account, ledger_index):
|
||||
```
|
||||
|
||||
Create a client instance.
|
||||
|
||||
```python
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create the **AccountTx** request.
|
||||
|
||||
```python
|
||||
tx_info=AccountTx(
|
||||
account=account,
|
||||
ledger_index=int(ledger_index)
|
||||
)
|
||||
```
|
||||
|
||||
Send the request and report the results.
|
||||
|
||||
```python
|
||||
response=client.request(tx_info)
|
||||
return response.result
|
||||
```
|
||||
|
||||
## lesson8-time-escrow.py
|
||||
|
||||
This module builds on `lesson1-send-xrp.py`. Changes are noted below.
|
||||
|
||||
```python
|
||||
import tkinter as tk
|
||||
import xrpl
|
||||
import json
|
||||
|
||||
from mod1 import get_account, get_account_info, send_xrp
|
||||
```
|
||||
|
||||
Import new functions from mod8.py.
|
||||
|
||||
```python
|
||||
from mod8 import create_time_escrow, finish_time_escrow, get_escrows, cancel_time_escrow, get_transaction
|
||||
```
|
||||
|
||||
Module 8 Handlers
|
||||
|
||||
```python
|
||||
def standby_create_time_escrow():
|
||||
results = create_time_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_amount.get(),
|
||||
ent_standby_destination.get(),
|
||||
ent_standby_escrow_finish.get(),
|
||||
ent_standby_escrow_cancel.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_finish_time_escrow():
|
||||
results = finish_time_escrow(
|
||||
ent_operational_seed.get(),
|
||||
ent_operational_escrow_owner.get(),
|
||||
ent_operational_sequence_number.get()
|
||||
)
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_get_escrows():
|
||||
results = get_escrows(ent_operational_account.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def standby_cancel_time_escrow():
|
||||
results = cancel_time_escrow(
|
||||
ent_standby_seed.get(),
|
||||
ent_standby_escrow_owner.get(),
|
||||
ent_standby_escrow_sequence_number.get()
|
||||
)
|
||||
text_standby_results.delete("1.0", tk.END)
|
||||
text_standby_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
def operational_get_transaction():
|
||||
results = get_transaction(ent_operational_account.get(),
|
||||
ent_operational_look_up.get())
|
||||
text_operational_results.delete("1.0", tk.END)
|
||||
text_operational_results.insert("1.0", json.dumps(results, indent=4))
|
||||
|
||||
## Mod 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))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(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 get_operational_account_info():
|
||||
accountInfo = get_account_info(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 operational_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
# Create a new window with the title "Quickstart Module 1"
|
||||
window = tk.Tk()
|
||||
window.title("Time-based Escrow Example")
|
||||
|
||||
# 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_destination = tk.Label(master=frm_form, text="Destination")
|
||||
ent_standby_destination = 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)
|
||||
```
|
||||
|
||||
Add supporting fields for escrow commands.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_finish = tk.Label(master=frm_form, text="Escrow Finish (seconds)")
|
||||
ent_standby_escrow_finish = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_cancel = tk.Label(master=frm_form, text="Escrow Cancel (seconds)")
|
||||
ent_standby_escrow_cancel = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_standby_escrow_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_standby_escrow_owner = tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_standby_escrow_owner = 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 fields in a grid.
|
||||
lbl_standy_seed.grid(row=0, column=0, sticky="e")
|
||||
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)
|
||||
```
|
||||
|
||||
Add supporting fields for escrow to the standby side of the form.
|
||||
|
||||
```python
|
||||
lbl_standby_escrow_finish.grid(row=6, column=0, sticky="e")
|
||||
ent_standby_escrow_finish.grid(row=6, column=1)
|
||||
lbl_standby_escrow_cancel.grid(row=7, column=0, sticky="e")
|
||||
ent_standby_escrow_cancel.grid(row=7, column=1)
|
||||
lbl_standby_escrow_sequence_number.grid(row=8, column=0, sticky="e")
|
||||
ent_standby_escrow_sequence_number.grid(row=8, column=1)
|
||||
lbl_standby_escrow_owner.grid(row=9, column=0, sticky="e")
|
||||
ent_standby_escrow_owner.grid(row=9, column=1)
|
||||
lbl_standby_results.grid(row=10, column=0, sticky="ne")
|
||||
text_standby_results.grid(row=10, column=1, sticky="nw")
|
||||
|
||||
###############################################
|
||||
## 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = tk.Entry(master=frm_form, width=50)
|
||||
```
|
||||
|
||||
Define escrow supporting fields for the operational side of the form.
|
||||
|
||||
```python
|
||||
lbl_operational_sequence_number = tk.Label(master=frm_form, text="Sequence Number")
|
||||
ent_operational_sequence_number = tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_escrow_owner=tk.Label(master=frm_form, text="Escrow Owner")
|
||||
ent_operational_escrow_owner=tk.Entry(master=frm_form, width=50)
|
||||
lbl_operational_look_up = tk.Label(master=frm_form, text="Transaction to Look Up")
|
||||
ent_operational_look_up = 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")
|
||||
```
|
||||
|
||||
Add supporting fields for escrow to the operational side of the form.
|
||||
|
||||
```python
|
||||
lbl_operational_sequence_number.grid(row=6, column=4, sticky="e")
|
||||
ent_operational_sequence_number.grid(row=6, column=5, sticky="w")
|
||||
lbl_operational_escrow_owner.grid(row=7, column=4, sticky="e")
|
||||
ent_operational_escrow_owner.grid(row=7, column=5, sticky="w")
|
||||
lbl_operational_look_up.grid(row=8, column=4, sticky="e")
|
||||
ent_operational_look_up.grid(row=8, column=5, sticky="w")
|
||||
lbl_operational_results.grid(row=10, column=4, sticky="ne")
|
||||
text_operational_results.grid(row=10, column=5, sticky="nw")
|
||||
|
||||
#############################################
|
||||
## Buttons ##################################
|
||||
#############################################
|
||||
|
||||
# Create the Get 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_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
btn_standby_send_xrp.grid(row = 2, column = 2, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add buttons for escrow activity on the standby side of the form.
|
||||
|
||||
```python
|
||||
btn_standby_create_escrow = tk.Button(master=frm_form, text="Create Time-based Escrow",
|
||||
command = standby_create_time_escrow)
|
||||
btn_standby_create_escrow.grid(row = 4, column = 2, sticky="nsew")
|
||||
btn_standby_cancel_escrow = tk.Button(master=frm_form, text="Cancel Time-based Escrow",
|
||||
command = standby_cancel_time_escrow)
|
||||
btn_standby_cancel_escrow.grid(row=5,column = 2, sticky="nsew")
|
||||
|
||||
# Create the Operational Account Buttons
|
||||
btn_get_operational_account = tk.Button(master=frm_form,
|
||||
text="Get Operational Account",
|
||||
command = get_operational_account)
|
||||
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 = get_operational_account_info)
|
||||
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 = operational_send_xrp)
|
||||
btn_op_send_xrp.grid(row=2, column = 3, sticky = "nsew")
|
||||
```
|
||||
|
||||
Add buttons to support escrow activity on the operational side of the form.
|
||||
|
||||
```python
|
||||
btn_op_finish_escrow = tk.Button(master=frm_form, text="Finish Escrow",
|
||||
command = operational_finish_time_escrow)
|
||||
btn_op_finish_escrow.grid(row = 4, column = 3, sticky="nsew")
|
||||
btn_op_finish_escrow = tk.Button(master=frm_form, text="Get Escrows",
|
||||
command = operational_get_escrows)
|
||||
btn_op_finish_escrow.grid(row = 5, column = 3, sticky="nsew")
|
||||
btn_op_get_transaction = tk.Button(master=frm_form, text="Get Transaction",
|
||||
command = operational_get_transaction)
|
||||
btn_op_get_transaction.grid(row = 6, column = 3, sticky = "nsew")
|
||||
|
||||
|
||||
# Start the application
|
||||
window.mainloop()
|
||||
```
|
||||
@@ -0,0 +1,580 @@
|
||||
---
|
||||
html: py-create-trustline-send-currency.html
|
||||
parent: send-payments-using-python.html
|
||||
seo:
|
||||
description: Create trust lines and send currency.
|
||||
labels:
|
||||
- Cross-Currency
|
||||
- Payments
|
||||
- Quickstart
|
||||
- Tokens
|
||||
---
|
||||
# Create Trust Line and Send Currency Using 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.
|
||||
|
||||
[](/docs/img/quickstart-py5.png)
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.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
|
||||
|
||||
<div align="center">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/6KWP0PV6J8Y?si=SSxFGrvfTo6pOPLD" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
|
||||
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**.
|
||||
|
||||
[](/docs/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**.
|
||||
|
||||
[](/docs/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_.
|
||||
|
||||
[](/docs/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_.
|
||||
|
||||
[](/docs/img/quickstart-py9.png)
|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} --> archive to try each of the samples.
|
||||
|
||||
## mod2.py
|
||||
|
||||
Module 2 provides the logic for creating trust lines and sending issued currency tokens between accounts.
|
||||
|
||||
Import dependencies and set the `testnet_url`.
|
||||
|
||||
```python
|
||||
import xrpl
|
||||
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 create_trust_line(seed, issuer, currency, amount):
|
||||
"""create_trust_line"""
|
||||
```
|
||||
|
||||
Get the wallet and a new client instance.
|
||||
|
||||
```python
|
||||
receiving_wallet = Wallet.from_seed(seed)
|
||||
client = JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Define the `TrustSet` transaction.
|
||||
|
||||
```python
|
||||
trustline_tx=xrpl.models.transactions.TrustSet(
|
||||
account=receiving_wallet.address,
|
||||
limit_amount=xrpl.models.amounts.IssuedCurrencyAmount(
|
||||
currency=currency,
|
||||
issuer=issuer,
|
||||
value=int(amount)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction to the XRP Ledger.
|
||||
|
||||
```python
|
||||
response = xrpl.transaction.submit_and_wait(trustline_tx,
|
||||
client, receiving_wallet)
|
||||
```
|
||||
|
||||
Return the results.
|
||||
|
||||
```python
|
||||
return response.result
|
||||
```
|
||||
## send_currency
|
||||
|
||||
Send currency to another account based on the sender wallet, destination account, the currency type, and the amount of the currency.
|
||||
|
||||
```python
|
||||
def send_currency(seed, destination, currency, amount):
|
||||
"""send_currency"""
|
||||
```
|
||||
|
||||
Get the sending wallet and a client instance on Testnet.
|
||||
|
||||
```python
|
||||
sending_wallet=Wallet.from_seed(seed)
|
||||
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.address,
|
||||
amount=xrpl.models.amounts.IssuedCurrencyAmount(
|
||||
currency=currency,
|
||||
value=int(amount),
|
||||
issuer=sending_wallet.address
|
||||
),
|
||||
destination=destination
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and get the response.
|
||||
|
||||
```python
|
||||
response=xrpl.transaction.submit_and_wait(send_currency_tx, client, sending_wallet)```
|
||||
|
||||
Return the results.
|
||||
|
||||
```python
|
||||
return response.result
|
||||
```
|
||||
|
||||
### get_balance
|
||||
|
||||
Update the **XRP Balance** fields and list the balance information for issued currencies in the **Results** text areas.
|
||||
|
||||
```python
|
||||
def get_balance(sb_account_id, op_account_id):
|
||||
"""get_balance"""
|
||||
```
|
||||
|
||||
Connect to the XRP Ledger and instantiate a client.
|
||||
|
||||
```python
|
||||
client=JsonRpcClient(testnet_url)
|
||||
```
|
||||
|
||||
Create the `GatewayBalances` request.
|
||||
|
||||
```python
|
||||
balance=xrpl.models.requests.GatewayBalances(
|
||||
account=sb_account_id,
|
||||
ledger_index="validated",
|
||||
hotwallet=[op_account_id]
|
||||
)
|
||||
```
|
||||
|
||||
Return the result.
|
||||
|
||||
```python
|
||||
response = client.request(balance)
|
||||
return response.result
|
||||
```
|
||||
|
||||
### configure_account
|
||||
|
||||
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](../../../../references/protocol/transactions/types/accountset.md#accountset-flags).
|
||||
|
||||
Send the account seed and a Boolean value for whether to enable or disable rippling.
|
||||
```python
|
||||
def configure_account(seed, default_setting):
|
||||
"""configure_account"
|
||||
```
|
||||
|
||||
Get the account wallet and instantiate a client.
|
||||
|
||||
```python
|
||||
wallet=Wallet.from_seed(seed)
|
||||
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):
|
||||
setting_tx=xrpl.models.transactions.AccountSet(
|
||||
account=wallet.classic_address,
|
||||
set_flag=xrpl.models.transactions.AccountSetAsfFlag.ASF_DEFAULT_RIPPLE
|
||||
)
|
||||
else:
|
||||
setting_tx=xrpl.models.transactions.AccountSet(
|
||||
account=wallet.classic_address,
|
||||
set_flag=xrpl.models.transactions.AccountSetAsfFlag.ASF_DEFAULT_RIPPLE
|
||||
)
|
||||
```
|
||||
|
||||
Submit the transaction and get results.
|
||||
|
||||
```python
|
||||
response=xrpl.transaction.submit_and_wait(setting_tx,client,wallet)
|
||||
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 mod1 import get_account, get_account_info, send_xrp
|
||||
from mod2 import (
|
||||
create_trust_line,
|
||||
send_currency,
|
||||
get_balance,
|
||||
configure_account,
|
||||
)
|
||||
```
|
||||
|
||||
Module 2 Handlers.
|
||||
|
||||
```python
|
||||
def standby_create_trust_line():
|
||||
results = create_trust_line(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 standby_send_currency():
|
||||
results = send_currency(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 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))
|
||||
|
||||
|
||||
def operational_create_trust_line():
|
||||
results = create_trust_line(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 operational_send_currency():
|
||||
results = send_currency(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 operational_configure_account():
|
||||
results = configure_account(
|
||||
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 get_balances():
|
||||
results = get_balance(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 = get_balance(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 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))
|
||||
|
||||
|
||||
def standby_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
|
||||
def get_operational_account():
|
||||
new_wallet = get_account(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 get_operational_account_info():
|
||||
accountInfo = get_account_info(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 operational_send_xrp():
|
||||
response = send_xrp(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))
|
||||
get_standby_account_info()
|
||||
get_operational_account_info()
|
||||
|
||||
# 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_standby_balance = 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_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_balance = tk.Label(master=frm_form, text="XRP Balance")
|
||||
ent_operational_balance = 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()
|
||||
```
|
||||
|
||||
Create the Standby Account Buttons.
|
||||
|
||||
```python
|
||||
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_send_xrp = tk.Button(master=frm_form, text="Send XRP >",
|
||||
command = standby_send_xrp)
|
||||
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_trust_line = tk.Button(master=frm_form,
|
||||
text="Create Trust Line",
|
||||
command = standby_create_trust_line)
|
||||
btn_standby_create_trust_line.grid(row=3, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Send Currency >",
|
||||
command = standby_send_currency)
|
||||
btn_standby_send_currency.grid(row=4, column=2, sticky = "nsew")
|
||||
btn_standby_send_currency = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_standby_send_currency.grid(row=5, 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")
|
||||
```
|
||||
|
||||
Create the Operational Account buttons.
|
||||
|
||||
```python
|
||||
btn_get_operational_account = tk.Button(master=frm_form,
|
||||
text="Get Operational Account",
|
||||
command = get_operational_account)
|
||||
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 = get_operational_account_info)
|
||||
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 = operational_send_xrp)
|
||||
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_trust_line = tk.Button(master=frm_form, text="Create Trust Line",
|
||||
command = operational_create_trust_line)
|
||||
btn_op_create_trust_line.grid(row=3, column=3, sticky = "nsew")
|
||||
btn_op_send_currency = tk.Button(master=frm_form, text="< Send Currency",
|
||||
command = operational_send_currency)
|
||||
btn_op_send_currency.grid(row=4, column=3, sticky = "nsew")
|
||||
btn_op_get_balances = tk.Button(master=frm_form, text="Get Balances",
|
||||
command = get_balances)
|
||||
btn_op_get_balances.grid(row=5, column=3, sticky = "nsew")
|
||||
btn_op_configure_account = tk.Button(master=frm_form, text="Configure Account",
|
||||
command = operational_configure_account)
|
||||
btn_op_configure_account.grid(row=7,column=4, sticky = "nsew")
|
||||
```
|
||||
|
||||
# Start the application
|
||||
|
||||
```python
|
||||
window.mainloop()
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
html: send-payments-using-python.html
|
||||
parent: modular-tutorials-in-python.html
|
||||
seo:
|
||||
description: Use a Python test harness to send XRP,trade currencies, and more.
|
||||
labels:
|
||||
- Accounts
|
||||
- Cross-Currency
|
||||
- Non-fungible Tokens, NFTs
|
||||
- Payments
|
||||
- Quickstart
|
||||
- Tokens
|
||||
- XRP
|
||||
---
|
||||
# Send Payments Using Python
|
||||
|
||||
The XRP Ledger (XRPL) is a robust, secure, customizable service. You can create your own interface to try out the capabilities and support your specific business needs.
|
||||
|
||||
This quickstart describes a test harness interface you can build to try out the XRP Ledger. The test harness displays multiple accounts, so that you can transfer tokens from one account to the other and see the results in real time. The image below shows the Token Test Harness at the completion of step 4.
|
||||
|
||||
[](/docs/img/quickstart-py15.png)
|
||||
|
||||
That is a lot of fields and buttons, all working together to perform some significant practical tasks. But getting _started_ with the XRP Ledger is not that complicated. When you eat the elephant a bite at a time, none of the tasks are difficult to consume.
|
||||
|
||||
Typically, the example functions for interacting with the XRP Ledger involve four steps.
|
||||
|
||||
1. Connect to the XRP Ledger and instantiate your wallet.
|
||||
2. Make changes to the XRP Ledger using transactions.
|
||||
3. Get the state of accounts and tokens on the XRP Ledger using requests.
|
||||
4. Disconnect from the XRP Ledger.
|
||||
|
||||
Each lesson shows you how to build the Token Test Harness one section at a time. Each module lets you try out meaningful interactions with the test ledger, with complete Python code samples and a code walkthrough. There is also a link to the complete source code for each section that can be modified with a text editor and run in a Python environment. You can try out the examples in any order.
|
||||
|
||||
This quickstart tutorial introduces you to the API used to implement features and explore the capabilities of XRP Ledger. It does not represent _all_ of the capabilities of the API and this example is not intended for production or secure payment use.
|
||||
|
||||
Much of this is “brute force” code that sacrifices conciseness for readability. Each example builds on the previous step, adding a new Python UI file and a module to support the new behavior in the lesson. We expect the applications you build to greatly improve upon these examples. Your feedback and contributions are most welcome.
|
||||
|
||||
In this quickstart, you can:
|
||||
|
||||
1. [Create Accounts and Send XRP](create-accounts-send-xrp.md)
|
||||
2. [Create Trust Line and Send Currency](create-trust-line-send-currency.md).
|
||||
3. [Create Time-Based Escrows](create-time-based-escrows.md)
|
||||
4. [Create Conditional Escrows](create-conditional-escrows.md)
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To get started, create a new folder on your local disk and install the Python library (xrpl-py) using `pip`.
|
||||
|
||||
```
|
||||
pip3 install xrpl-py
|
||||
```
|
||||
|
||||
Download the python [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/py/)<!-- {.github-code-download} -->.
|
||||
|
||||
**Note:** Without the Quickstart Samples, you will not be able to try the examples that follow.
|
||||
Reference in New Issue
Block a user