# Send and Cash Checks This example shows how to: 1. Send a check to transfer XRP or issued currency to another account. 2. Get a list of checks you have sent or received. 3. Cash a check received from another account. 4. Cancel a check you have sent. Checks offer another option for transferring funds between accounts. Checks have two particular advantages. 1. You can use a check to send funds to another account without first creating a trust line - the trust line is created automatically when the receiver chooses to accept the funds. 2. The receiver can choose to accept less than the full amount of the check. This allows you to authorize a maximum amount when the actual cost is not finalized. [![Empty Check Form](/assets/quickstart-py-checks1.fba2854e71f8ffb416991facbc682abc693a4d3dd966f8cdb2e2649338c8d504.ac57e6ef.png)](/assets/quickstart-py-checks1.fba2854e71f8ffb416991facbc682abc693a4d3dd966f8cdb2e2649338c8d504.ac57e6ef.png) ## Prerequisites If you haven't done so already, create a new folder on your local disk and install the Python library using `pip`. ``` pip3 install xrpl-py ``` Clone or download the [Modular Tutorial Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/). Without the Quickstart Samples, you will not be able to try the examples that follow. ## Usage To get test accounts: 1. Open and launch `lesson10-check.py`. 2. Click **Get Standby Account**. 3. Click **Get Operational Account**. 4. Click **Get Standby Account Info**. 5. Click **Get Operational Account Info**. 6. 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. [![Form with New Accounts](/assets/quickstart-py-checks2.85aa65bcabcee9922bbbbe975ac4ceda04560c3b9aec211f4995969a07a7e291.ac57e6ef.png)](/assets/quickstart-py-checks2.85aa65bcabcee9922bbbbe975ac4ceda04560c3b9aec211f4995969a07a7e291.ac57e6ef.png) You can transfer XRP between your new accounts. Each account has its own fields and buttons. div iframe ### Send a Check for XRP To send a check for 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 in drops. 2. Copy and paste the **Operational Account** field to the Standby **Destination** field. 3. Set the **Currency** to *XRP*. 4. Click **Send Check**. [![Send Check Settings](/assets/quickstart-py-checks3.b73c71c3acf00189dbca9a6b66a94b08e9cae940bca9bf7762f16087589c4266.ac57e6ef.png)](/assets/quickstart-py-checks3.b73c71c3acf00189dbca9a6b66a94b08e9cae940bca9bf7762f16087589c4266.ac57e6ef.png) ### Send a Check for an Issued Currency To send a check for an issued currency token from the Standby account to the Operational account: 1. On the Standby side of the form, enter the **Amount** of currency to send. 2. Copy and paste the **Operational Account** field to the Standby **Destination** field. 3. Copy the **Standby Account** field and paste the value in the **Issuer** field. 4. Enter the **Currency** code for your token. 5. Click **Send Check**. [![Send Token Check Settings](/assets/quickstart-py-checks4.82973b7247758e7c5e2a43f387463726cc1d81c2dc8d18bb2b4fb2a620b5c86f.ac57e6ef.png)](/assets/quickstart-py-checks4.82973b7247758e7c5e2a43f387463726cc1d81c2dc8d18bb2b4fb2a620b5c86f.ac57e6ef.png) ### Get Checks Click **Get Checks** to get a list of the current checks you have sent or received. To uniquely identify a check (for existence, when cashing a check), capture the **index** value for the check. [![Get Checks with index highlighted](/assets/quickstart-py-checks5.97bde8f85d0c93810bc499066da8f4688aa9d5f7e46bb8a3bd4a43e55b62f602.ac57e6ef.png)](/assets/quickstart-py-checks5.97bde8f85d0c93810bc499066da8f4688aa9d5f7e46bb8a3bd4a43e55b62f602.ac57e6ef.png) ### Cash Check To cash a check you have received: 1. Enter the **Check ID** (**index** value). 2. Enter the **Amount** you want to collect, up to the full amount of the check. 3. Enter the currency code. a. If you cashing a check for XRP, enter *XRP* in the **Currency** field. b. If you are cashing a check for an issued currency token: 1. Enter the **Issuer** of the token. 2. Enter the **Currency** code for the token. 4. Click **Cash Check**. [![Cashed check results](/assets/quickstart-py-checks6.c65c7cd48f61cd61c8278a31699418b8f3ab095d6f84937ebbb5d75a7da11873.ac57e6ef.png)](/assets/quickstart-py-checks6.c65c7cd48f61cd61c8278a31699418b8f3ab095d6f84937ebbb5d75a7da11873.ac57e6ef.png) ### Get Balances Click **Get Balances** to get a list of obligations and assets for each account. [![Account Balances](/assets/quickstart-py-checks7.8b6ca5df3354012beb7281276f5fefafc7d52eb83126e501cc00607acb3b8a07.ac57e6ef.png)](/assets/quickstart-py-checks7.8b6ca5df3354012beb7281276f5fefafc7d52eb83126e501cc00607acb3b8a07.ac57e6ef.png) ### Cancel Check To cancel a check you have previously sent to another account. 1. Enter the **Check ID** (**index** value). 2. Click **Cancel Check**. [![Canceled check results](/assets/quickstart-py-checks8.7cfc461bb6176e2e95c8b79f3fc43e22317852296780bc98a78d0d799b58f41a.ac57e6ef.png)](/assets/quickstart-py-checks8.7cfc461bb6176e2e95c8b79f3fc43e22317852296780bc98a78d0d799b58f41a.ac57e6ef.png) # Code Walkthrough You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/py/) in the source repository for this website. ## mod10.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 CheckCreate, CheckCash, CheckCancel from xrpl.models.requests import AccountObjects, AccountTx, GatewayBalances ``` Set the TestNet URL. ```python testnet_url = "https://s.altnet.rippletest.net:51234" ``` ### send_check Pass the arguments for the account seed, check amount, and destination account. Set the currency type to *XRP*, or if it is an issued currency token provide the currency type and issuer. ```python def send_check(seed, amount, destination, currency, issuer): """send_check""" ``` Instantiate the account wallet and create a client connection. ```python wallet=Wallet.from_seed(seed) client=JsonRpcClient(testnet_url) ``` Create the amount variable. If you are sending XRP, the amount variable is fine as is. If you are sending issued currency, you need to create an amount object that includes the currency and the issuer. ```python if currency != "XRP": amount = {"value": amount, "currency": currency, "issuer": issuer } ``` Define the `CheckCreate` transaction. ```python check_tx=xrpl.models.transactions.CheckCreate( account=wallet.address, send_max=amount, destination=destination ) ``` Submit the transaction and report the results. ```python reply="" try: response=xrpl.transaction.submit_and_wait(check_tx,client,wallet) reply=response.result except xrpl.transaction.XRPLReliableSubmissionException as e: reply=f"Submit failed: {e}" return reply ``` ### cash_check Pass the values for seed, amount, and check_id. Set the currency type to *XRP*, or include the currency type and issuer. ```python def cash_check(seed, amount, check_id, currency, issuer): """cash_check""" ``` Instantiate the account wallet and create a client connection. ```python wallet=Wallet.from_seed(seed) client=JsonRpcClient(testnet_url) ``` If using an issued currency token, create an amount object that includes the currency type and issuer. ```python if currency != "XRP": amount = { "value": amount, "currency": currency, "issuer": issuer } ``` Define the CheckCash transaction. ```python finish_tx=xrpl.models.transactions.CheckCash( account=wallet.address, amount=amount, check_id=check_id ) ``` 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 ``` ### cancel_check Pass the values for the account seed and the check ID. ```python def cancel_check(seed, check_id): """cancel_check""" ``` Instantiate the account wallet and create a client connection. ```python wallet=Wallet.from_seed(seed) client=JsonRpcClient(testnet_url) ``` Define the CheckCancel transaction. ```python cancel_tx=xrpl.models.transactions.CheckCancel( account=wallet.address, check_id=check_id ) ``` 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_checks ```python def get_checks(account): """get_checks""" ``` Create a client connection. ```python client=JsonRpcClient(testnet_url) ``` Define the AccountObjects request, specifying the type *check*. ```python acct_checks=AccountObjects( account=account, ledger_index="validated", type="check" ) ``` Send the request and report the results. ```python response=client.request(acct_checks) return response.result ``` ## lesson10-check.py This example builds on `lesson2-send-currency.py`. Changes are noted below. ```python import tkinter as tk import xrpl import json from mod1 import get_account, get_account_info, send_xrp from mod2 import get_balance ``` Import check-specific functions. ```python from mod10 import send_check, cash_check, cancel_check, get_checks ############################################# ## Handlers ################################# ############################################# ``` Add handlers for module 10. ```python ## Mod 10 Handlers def standby_send_check(): results=send_check( ent_standby_seed.get(), ent_standby_amount.get(), ent_standby_destination.get(), ent_standby_currency.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 standby_cash_check(): results=cash_check( ent_standby_seed.get(), ent_standby_amount.get(), ent_standby_check_id.get(), ent_standby_currency.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 standby_cancel_check(): results=cancel_check( ent_standby_seed.get(), ent_standby_check_id.get() ) text_standby_results.delete("1.0", tk.END) text_standby_results.insert("1.0", json.dumps(results, indent=4)) def standby_get_checks(): results=get_checks( 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_get_balance(): results=get_balance( ent_standby_seed.get(), ent_operational_seed.get() ) text_standby_results.delete("1.0", tk.END) text_standby_results.insert("1.0", json.dumps(results, indent=4)) def operational_send_check(): results=send_check( ent_operational_seed.get(), ent_operational_amount.get(), ent_operational_destination.get(), ent_operational_currency.get(), ent_operational_issuer.get() ) text_operational_results.delete("1.0", tk.END) text_operational_results.insert("1.0", json.dumps(results, indent=4)) def operational_cash_check(): results=cash_check( ent_operational_seed.get(), ent_operational_amount.get(), ent_operational_check_id.get(), ent_operational_currency.get(), ent_operational_issuer.get() ) text_operational_results.delete("1.0", tk.END) text_operational_results.insert("1.0", json.dumps(results, indent=4)) def operational_cancel_check(): results=cancel_check( ent_operational_seed.get(), ent_operational_check_id.get() ) text_operational_results.delete("1.0", tk.END) text_standby_results.insert("1.0", json.dumps(results, indent=4)) def operational_get_checks(): results=get_checks( 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_get_balance(): results=get_balance( ent_operational_seed.get(), ent_standby_seed.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 "Check Example" window=tk.Tk() window.title("Check 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_standby_balance=tk.Label(master=frm_form, text="XRP Balance") ent_standby_balance=tk.Entry(master=frm_form, width=50) lbl_standy_amount=tk.Label(master=frm_form, text="Amount") ent_standby_amount=tk.Entry(master=frm_form, width=50) lbl_standby_destination=tk.Label(master=frm_form, text="Destination") ent_standby_destination=tk.Entry(master=frm_form, width=50) ``` Add fields for *Issuer* and *Check ID*. ```python lbl_standby_issuer=tk.Label(master=frm_form, text="Issuer") ent_standby_issuer=tk.Entry(master=frm_form, width=50) lbl_standby_check_id=tk.Label(master=frm_form, text="Check ID") ent_standby_check_id=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) 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_standby_balance.grid(row=3, column=0, sticky="e") ent_standby_balance.grid(row=3, column=1) lbl_standy_amount.grid(row=4, column=0, sticky="e") ent_standby_amount.grid(row=4, column=1) lbl_standby_destination.grid(row=5, column=0, sticky="e") ent_standby_destination.grid(row=5, column=1) ``` Place the *Issuer* and *Check ID* fields in the grid. ```python lbl_standby_issuer.grid(row=6, column=0, sticky="e") ent_standby_issuer.grid(row=6, column=1) lbl_standby_check_id.grid(row=7, column=0, sticky="e") ent_standby_check_id.grid(row=7, column=1) lbl_standby_currency.grid(row=8, column=0, sticky="e") ent_standby_currency.grid(row=8, column=1) lbl_standby_results.grid(row=9, column=0, sticky="ne") text_standby_results.grid(row=9, 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_balance=tk.Label(master=frm_form, text="XRP Balance") ent_operational_balance=tk.Entry(master=frm_form, width=50) lbl_operational_amount=tk.Label(master=frm_form, text="Amount") ent_operational_amount=tk.Entry(master=frm_form, width=50) lbl_operational_destination=tk.Label(master=frm_form, text="Destination") ent_operational_destination=tk.Entry(master=frm_form, width=50) ``` Add fields for the *Issuer* and *Check ID*. ```python lbl_operational_issuer=tk.Label(master=frm_form, text="Issuer") ent_operational_issuer=tk.Entry(master=frm_form, width=50) lbl_operational_check_id=tk.Label(master=frm_form, text="Check ID") ent_operational_check_id=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) 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_balance.grid(row=3, column=4, sticky="e") ent_operational_balance.grid(row=3, column=5, sticky="w") lbl_operational_amount.grid(row=4, column=4, sticky="e") ent_operational_amount.grid(row=4, column=5, sticky="w") lbl_operational_destination.grid(row=5, column=4, sticky="e") ent_operational_destination.grid(row=5, column=5, sticky="w") ``` Place the *Issuer* and *Check ID* fields in the grid. ```python lbl_operational_issuer.grid(row=6, column=4, sticky="e") ent_operational_issuer.grid(row=6, column=5, sticky="w") lbl_operational_check_id.grid(row=7, column=4, sticky="e") ent_operational_check_id.grid(row=7, column=5, sticky="w") lbl_operational_currency.grid(row=8, column=4, sticky="e") ent_operational_currency.grid(row=8, column=5) lbl_operational_results.grid(row=9, column=4, sticky="ne") text_operational_results.grid(row=9, 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 standby buttons for **Send Check**, **Get Checks**, **Cash Check**, **Cancel Check**, and **Get Balances**. ```python btn_standby_send_check=tk.Button(master=frm_form, text="Send Check", command=standby_send_check) btn_standby_send_check.grid(row=4, column=2, sticky="nsew") btn_standby_get_checks=tk.Button(master=frm_form, text="Get Checks", command=standby_get_checks) btn_standby_get_checks.grid(row=5, column=2, sticky="nsew") btn_standby_cash_check=tk.Button(master=frm_form, text="Cash Check", command=standby_cash_check) btn_standby_cash_check.grid(row=6, column=2, sticky="nsew") btn_standby_cancel_check=tk.Button(master=frm_form, text="Cancel Check", command=standby_cancel_check) btn_standby_cancel_check.grid(row=7, column=2, sticky="nsew") btn_standby_get_balances=tk.Button(master=frm_form, text="Get Balances", command=standby_get_balance) btn_standby_get_balances.grid(row=8, 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 operational buttons for **Send Check**, **Get Checks**, **Cash Check**, **Cancel Check**, and **Get Balances**. ```javascript btn_op_send_check=tk.Button(master=frm_form, text="Send Check", command=operational_send_check) btn_op_send_check.grid(row=4, column=3, sticky="nsew") btn_op_get_checks=tk.Button(master=frm_form, text="Get Checks", command=operational_get_checks) btn_op_get_checks.grid(row=5, column=3, sticky="nsew") btn_op_cash_check=tk.Button(master=frm_form, text="Cash Check", command=operational_cash_check) btn_op_cash_check.grid(row=6, column=3, sticky="nsew") btn_op_cancel_check=tk.Button(master=frm_form, text="Cancel Check", command=operational_cancel_check) btn_op_cancel_check.grid(row=7, column=3, sticky="nsew") btn_op_get_balances=tk.Button(master=frm_form, text="Get Balances", command=operational_get_balance) btn_op_get_balances.grid(row=8, column=3, sticky="nsew") # Start the application window.mainloop() ```