mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-21 20:25:51 +00:00
664 lines
21 KiB
Markdown
664 lines
21 KiB
Markdown
---
|
|
labels:
|
|
- Accounts
|
|
- Modular Tutorials
|
|
- Transaction Sending
|
|
- Checks
|
|
- XRP
|
|
---
|
|
# 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 [tokens](../../../concepts/tokens/index.md) to someone who has not already created 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.
|
|
|
|
|
|
[](/docs/img/mt-send-checks-1-empty-form.png)
|
|
|
|
## Prerequisites
|
|
|
|
Download and expand the [Modular Tutorials](../../../../_code-samples/modular-tutorials/payment-modular-tutorials.zip)<!-- {.github-code-download} --> archive.
|
|
|
|
{% admonition type="info" name="Note" %}
|
|
Without the Modular Tutorial Samples, you will not be able to try the examples that follow.
|
|
{% /admonition %}
|
|
|
|
## Usage
|
|
|
|
To get test accounts:
|
|
|
|
1. Open `send-checks.html` in a browser.
|
|
2. Get test accounts.
|
|
1. If you copied the gathered information from another tutorial:
|
|
1. Paste the gathered information to the **Result** field.
|
|
2. Click **Distribute Account Info**.
|
|
2. If you have an existing account seed:
|
|
1. Paste the account seed to the **Account 1 Seed** or **Account 2 Seed** field.
|
|
2. Click **Get Account 1 from Seed** or **Get Account 2 from Seed**.
|
|
2. If you do not have existing accounts:
|
|
1. Click **Get New Account 1**.
|
|
2. Click **Get New Account 2**.
|
|
|
|
[](/docs/img/mt-send-checks-2-form-with-accounts.png)
|
|
|
|
### Send a Check for XRP
|
|
|
|
To send a check for XRP:
|
|
|
|
1. Select **Account 1** or **Account 2**.
|
|
2. Enter the **Amount** of XRP to send, in drops.
|
|
2. Enter the receiving account address in the **Destination** field.
|
|
3. Set the **Currency Code** to _XRP_.
|
|
4. Click **Send Check**.
|
|
|
|
[](/docs/img/mt-send-checks-3-send-xrp.png)
|
|
|
|
### Send a Check for an Issued Currency
|
|
|
|
To send a check for an issued currency token:
|
|
|
|
1. Choose **Account 1** or **Account 2**.
|
|
2. Enter the **Amount** of currency to send.
|
|
3. Enter the receiving account address in the **Destination** field.
|
|
4. Enter the issuing account in the **Issuer** field (for example, the account sending the check).
|
|
5. Enter the **Currency** code for your issued currency token.
|
|
6. Click **Send Check**.
|
|
|
|
[](/docs/img/mt-send-checks-4-send-currency.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 example, when cashing a check), use the check's ledger entry ID, in the `index` field.
|
|
|
|
[](/docs/img/mt-send-checks-5-get-checks.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 are cashing a check for XRP, enter _XRP_ in the **Currency Code** 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** code for the token.
|
|
4. Click **Cash Check**.
|
|
|
|
[](/docs/img/mt-send-checks-6-cash-check.png)
|
|
|
|
### Get Token Balance
|
|
|
|
Click **Get Token Balance** to get a list of obligations and assets for the account.
|
|
|
|
[](/docs/img/mt-send-checks-7-get-balance.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**.
|
|
|
|
[](/docs/img/mt-send-checks-8-cancel-check.png)
|
|
|
|
# Code Walkthrough
|
|
|
|
Download and expand the [Modular Tutorials](../../../../_code-samples/modular-tutorials/payment-modular-tutorials.zip)<!-- {.github-code-download} --> archive.
|
|
|
|
## send-checks.js
|
|
|
|
### sendCheck()
|
|
|
|
Connect to the XRP ledger.
|
|
|
|
```javascript
|
|
async function sendCheck() {
|
|
let net = getNet()
|
|
const client = new xrpl.Client(net)
|
|
await client.connect()
|
|
results = `\n===Connected to ${net}.===\n===Sending check.===\n`
|
|
resultField.value = results
|
|
```
|
|
|
|
Prepare the transaction. Set the *check_amount* variable to the value in the **Amount** field.
|
|
|
|
```javascript
|
|
try {
|
|
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
|
let check_amount = amountField.value
|
|
```
|
|
|
|
If the currency field is not _XRP_, create an `amount` object with the _currency_, _value_, and _issuer_. Otherwise, use the *check_amount* value as is.
|
|
|
|
```javascript
|
|
if (currencyField.value != "XRP") {
|
|
check_amount = {
|
|
"currency": currencyField.value,
|
|
"value": amountField.value,
|
|
"issuer": wallet.address
|
|
}
|
|
}
|
|
```
|
|
|
|
Create the transaction object.
|
|
|
|
```javascript
|
|
const send_check_tx = {
|
|
"TransactionType": "CheckCreate",
|
|
"Account": wallet.address,
|
|
"SendMax": check_amount,
|
|
"Destination": destinationField.value
|
|
}
|
|
```
|
|
|
|
Autofill the remaining values and sign the prepared transaction.
|
|
|
|
```javascript
|
|
const check_prepared = await client.autofill(send_check_tx)
|
|
const check_signed = wallet.sign(check_prepared)
|
|
```
|
|
|
|
Send the transaction and wait for the results.
|
|
|
|
```javascript
|
|
results += '\n===Sending ' + amountField.value + ' ' + currencyField.
|
|
value + ' to ' + destinationField.value + '.===\n'
|
|
resultField.value = results
|
|
const check_result = await client.submitAndWait(check_signed.tx_blob)
|
|
```
|
|
|
|
Report the results.
|
|
|
|
```javascript
|
|
if (check_result.result.meta.TransactionResult == "tesSUCCESS") {
|
|
results = '===Transaction succeeded===\n\n'
|
|
resultField.value += results + JSON.stringify(check_result.result, null, 2)
|
|
}
|
|
```
|
|
|
|
Update the **XRP Balance** field.
|
|
|
|
```javascript
|
|
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
|
```
|
|
|
|
Report any errors, then disconnect from the XRP ledger.
|
|
|
|
```javascript
|
|
} catch (error) {
|
|
results = `Error sending transaction: ${error}`
|
|
resultField.value += results
|
|
}
|
|
finally {
|
|
client.disconnect()
|
|
}
|
|
}//end of sendCheck()
|
|
```
|
|
|
|
## getChecks()
|
|
|
|
Connect to the XRP Ledger.
|
|
```javascript
|
|
async function getChecks() {
|
|
let net = getNet()
|
|
const client = new xrpl.Client(net)
|
|
await client.connect()
|
|
let results = `\n===Connected to ${net}.===\n===Getting account checks.===\n\n`
|
|
resultField.value = results
|
|
```
|
|
|
|
Define an `account_objects` query, filtering for the _check_ object type.
|
|
|
|
```javascript
|
|
try {
|
|
const check_objects = await client.request({
|
|
"id": 5,
|
|
"command": "account_objects",
|
|
"account": accountAddressField.value,
|
|
"ledger_index": "validated",
|
|
"type": "check"
|
|
})
|
|
```
|
|
Display the retrieved `Check` objects in the result field.
|
|
|
|
```javascript
|
|
resultField.value += JSON.stringify(check_objects.result, null, 2)
|
|
```
|
|
|
|
Catch and report any errors, then disconnect from the XRP Ledger.
|
|
|
|
```javascript
|
|
} catch (error) {
|
|
results = `Error getting checks: ${error}`
|
|
resultField.value += results
|
|
}
|
|
finally {
|
|
client.disconnect()
|
|
}
|
|
} // End of getChecks()
|
|
```
|
|
|
|
## cashCheck()
|
|
|
|
Connect to the XRP Ledger and get the account wallet
|
|
|
|
```javascript
|
|
async function cashCheck() {
|
|
let net = getNet()
|
|
const client = new xrpl.Client(net)
|
|
await client.connect()
|
|
results = `\n===Connected to ${net}.===\n===Cashing check.===\n`
|
|
resultField.value = results
|
|
```
|
|
|
|
Set the check amount.
|
|
|
|
```javascript
|
|
try {
|
|
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
|
let check_amount = amountField.value
|
|
```
|
|
|
|
If the currency is not _XRP_, create an `amount` object with _value_, _currency_, and _issuer_.
|
|
|
|
```javascript
|
|
if (currencyField.value != "XRP") {
|
|
check_amount = {
|
|
"value": amountField.value,
|
|
"currency": currencyField.value,
|
|
"issuer": issuerField.value
|
|
}
|
|
}
|
|
```
|
|
|
|
Create the `CheckCash` transaction object.
|
|
|
|
```javascript
|
|
const cash_check_tx = {
|
|
"TransactionType": "CheckCash",
|
|
"Account": wallet.address,
|
|
"Amount": check_amount,
|
|
"CheckID": checkIdField.value
|
|
}
|
|
```
|
|
|
|
Autofill the transaction details.
|
|
|
|
```javascript
|
|
const cash_prepared = await client.autofill(cash_check_tx)
|
|
```
|
|
|
|
Sign the prepared transaction.
|
|
|
|
```javascript
|
|
const cash_signed = wallet.sign(cash_prepared)
|
|
results = ' Receiving ' + amountField.value + ' ' + currencyField.value + '.\n'
|
|
resultField.value += results
|
|
```
|
|
|
|
Submit the transaction and wait for the result.
|
|
|
|
```javascript
|
|
const check_result = await client.submitAndWait(cash_signed.tx_blob)
|
|
```
|
|
|
|
Report the transaction results.
|
|
|
|
```javascript
|
|
if (check_result.result.meta.TransactionResult == "tesSUCCESS") {
|
|
results = '===Transaction succeeded===\n' + JSON.stringify(check_result.result, null, 2)
|
|
resultField.value += results
|
|
}
|
|
```
|
|
|
|
Update the XRP Balance field.
|
|
|
|
```javascript
|
|
xrpBalanceField.value = (await client.getXrpBalance(wallet.address));
|
|
```
|
|
|
|
Catch and report any errors, then disconnect from the XRP ledger.
|
|
|
|
```javascript
|
|
} catch (error) {
|
|
results = `Error sending transaction: ${error}`
|
|
resultField.value += results
|
|
}
|
|
finally {
|
|
client.disconnect()
|
|
} // end of cashCheck()
|
|
```
|
|
|
|
## cancelCheck()
|
|
|
|
Connect to the XRP Ledger.
|
|
|
|
```javascript
|
|
async function cancelCheck() {
|
|
let net = getNet()
|
|
const client = new xrpl.Client(net)
|
|
await client.connect()
|
|
results = `\n===Connected to ${net}.===\n===Cancelling check.===\n`
|
|
resultField.value = results
|
|
```
|
|
|
|
Create the CheckCancel transaction object, passing the wallet address and the Check ID value (the _Index_).
|
|
|
|
```javascript
|
|
try {
|
|
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
|
const cancel_check_tx = {
|
|
"TransactionType": "CheckCancel",
|
|
"Account": wallet.address,
|
|
"CheckID": checkIdField.value
|
|
}
|
|
```
|
|
|
|
Autofill the transaction details.
|
|
|
|
```javascript
|
|
const cancel_prepared = await client.autofill(cancel_check_tx)
|
|
```
|
|
|
|
Sign the prepared transaction.
|
|
|
|
```javascript
|
|
const cancel_signed = wallet.sign(cancel_prepared)
|
|
```
|
|
|
|
Submit the transaction and wait for the results.
|
|
|
|
```javascript
|
|
const check_result = await client.submitAndWait(cancel_signed.tx_blob)
|
|
```
|
|
|
|
Report the transaction results.
|
|
|
|
```javascript
|
|
if (check_result.result.meta.TransactionResult == "tesSUCCESS") {
|
|
results += `===Transaction succeeded===\n${check_result.result.meta.TransactionResult}`
|
|
resultField.value = results
|
|
}
|
|
```
|
|
|
|
Update the XRP Balance field.
|
|
|
|
```javascript
|
|
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
|
```
|
|
|
|
Catch and report any errors, then disconnect from the XRP ledger.
|
|
|
|
```javascript
|
|
} catch (error) {
|
|
results = `Error sending transaction: ${error}`
|
|
resultField.value += results
|
|
}
|
|
finally {
|
|
client.disconnect()
|
|
}
|
|
} // end of cancelCheck()
|
|
```
|
|
|
|
## 10.send-checks.html
|
|
|
|
```html
|
|
<html>
|
|
<head>
|
|
<title>Send Checks</title>
|
|
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
|
<link href="modular-tutorials.css" rel="stylesheet">
|
|
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
|
<script src="account-support.js"></script>
|
|
<script src='send-xrp.js'></script>
|
|
<script src='send-currency.js'></script>
|
|
<script src='send-checks.js'></script>
|
|
<script>
|
|
if (typeof module !== "undefined") {
|
|
const xrpl = require('xrpl')
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
<!-- ************************************************************** -->
|
|
<!-- ********************** The Form ****************************** -->
|
|
<!-- ************************************************************** -->
|
|
|
|
<body>
|
|
<h1>Send Checks</h1>
|
|
<form id="theForm">
|
|
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
|
Choose your ledger instance:
|
|
</span>
|
|
|
|
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
|
<label for="dn">Devnet</label>
|
|
|
|
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
|
<label for="tn">Testnet</label>
|
|
<br /><br />
|
|
<table>
|
|
<tr>
|
|
<td>
|
|
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
|
</td>
|
|
<td>
|
|
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
|
</td>
|
|
<td>
|
|
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
|
</td>
|
|
<td>
|
|
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="account1name" size="40"></input>
|
|
</td>
|
|
<td>
|
|
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
|
<label for="account2name">Account 2 Name</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="account2name" size="40"></input>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
|
<label for="account1address">Account 1 Address</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="account1address" size="40"></input>
|
|
</td>
|
|
<td>
|
|
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
|
<label for="account2address">Account 2 Address</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="account2address" size="40"></input>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
|
<label for="account1seed">Account 1 Seed</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="account1seed" size="40"></input>
|
|
</td>
|
|
<td>
|
|
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
|
<label for="account2seed">Account 2 Seed</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="account2seed" size="40"></input>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<hr />
|
|
<table>
|
|
<tr valign="top">
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
|
<label for="accountNameField">Account Name</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="accountNameField" size="40" readonly></input>
|
|
<input type="radio" id="account1" name="accounts" value="account1">
|
|
<label for="account1">Account 1</label>
|
|
</td>
|
|
</tr>
|
|
<tr valign="top">
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
|
<label for="accountAddressField">Account Address</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="accountAddressField" size="40" readonly></input>
|
|
<input type="radio" id="account2" name="accounts" value="account2">
|
|
<label for="account2">Account 2</label>
|
|
</td>
|
|
</tr>
|
|
<tr valign="top">
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
|
<label for="accountSeedField">Account Seed</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="accountSeedField" size="40" readonly></input>
|
|
<br>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
|
<label for="xrpBalanceField">XRP Balance</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Currency code for the check.">
|
|
<lable for="currencyField">Currency Code</lable>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="currencyField" size="40"></input>
|
|
<br>
|
|
</td>
|
|
<td>
|
|
<button type="button" onClick="sendCheck()">Send Check</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Issuing account for the currency.">
|
|
<lable for="issuerField">Issuer</lable>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="issuerField" size="40"></input>
|
|
<br>
|
|
</td>
|
|
<td>
|
|
<button type="button" onClick="cashCheck()">Cash Check</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
|
<label for="amountField">Amount</label>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="amountField" size="40"></input>
|
|
<br>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
<button type="button" onClick="getChecks()">Get Checks</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
|
<lable for="destinationField">Destination</lable>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="destinationField" size="40"></input>
|
|
<br>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
<button type="button" onClick="cancelCheck()">Cancel Check</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="right">
|
|
<span class="tooltip" tooltip-data="Check ID.">
|
|
<lable for="checkIdField">Check ID</lable>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<input type="text" id="checkIdField" size="40"></input>
|
|
<br>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
<button type="button" onClick="getTokenBalance()">Get Token Balance</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<p align="right">
|
|
<textarea id="resultField" cols="80" rows="20"></textarea>
|
|
</p>
|
|
</td>
|
|
<td align="left" valign="top">
|
|
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
|
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</form>
|
|
</body>
|
|
<script>
|
|
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
|
radioButtons.forEach(radio => {
|
|
radio.addEventListener('change', function() {
|
|
if (this.value === 'account1') {
|
|
populate1()
|
|
} else if (this.value === 'account2') {
|
|
populate2()
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</html>
|
|
```
|