mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-27 23:25:51 +00:00
Merge pull request #1390 from XRPLF/DD-quickstart
Add Quickstart Tutorial
This commit is contained in:
20
content/_code-samples/quickstart/README.md
Normal file
20
content/_code-samples/quickstart/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Quickstart Samples Archive
|
||||
|
||||
This folder contains the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) archive, which includes 4 iterative HTML pages as a test harness for XRPL features, with accompanying JavaScript files. The archive includes the following files:
|
||||
|
||||
1.get-accounts-send--xrp.html
|
||||
|
||||
2.create-trustline-send-currency.html
|
||||
|
||||
3.mint-nfts.html
|
||||
|
||||
4.transfer-nfts.html
|
||||
|
||||
|
||||
ripplex1-send-xrp.js
|
||||
|
||||
ripplex2-send-currency.js
|
||||
|
||||
ripplex3-mint-nfts.js
|
||||
|
||||
ripplex4-transfer-nfts.js
|
||||
BIN
content/_code-samples/quickstart/quickstart.zip
Normal file
BIN
content/_code-samples/quickstart/quickstart.zip
Normal file
Binary file not shown.
743
content/tutorials/quickstart/create-accounts-send-xrp.md
Normal file
743
content/tutorials/quickstart/create-accounts-send-xrp.md
Normal file
@@ -0,0 +1,743 @@
|
||||
---
|
||||
html: create-accounts-send-xrp.html
|
||||
parent: xrpl-quickstart.html
|
||||
blurb: Quickstart 1, create two accounts and transfer XRP between them.
|
||||
labels:
|
||||
- Accounts
|
||||
- Quickstart
|
||||
- Transaction Sending
|
||||
- XRP
|
||||
---
|
||||
# 1. Create Accounts and Send XRP
|
||||
|
||||
|
||||
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. It does not appear on the ledger until it is funded with XRP. This example shows how to create an account for Testnet, but not how to create an account that you can use on Mainnet.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To get started, create a new folder on your local disk and install the JavaScript library using `npm`.
|
||||
|
||||
|
||||
```
|
||||
npm install xrpl
|
||||
```
|
||||
|
||||
|
||||
Download and expand the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) archive.
|
||||
|
||||
## Usage
|
||||
|
||||
To get test accounts:
|
||||
|
||||
|
||||
|
||||
1. Open `1.get-accounts-send-xrp.html` in a browser
|
||||
2. Choose **Testnet** or **Devnet**.
|
||||
3. Click **Get New Standby Account**.
|
||||
4. Click **Get New Operational Account.**
|
||||
5. Copy and paste the **Seeds** field in a persistent location, such as a Notepad, so that you can reuse the accounts after reloading the form.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
NOTE: The accounts in the test harness work on _Testnet_ and _Devnet_, but not on _NFT-Devnet_. To create accounts that can mint and trade NFTs:
|
||||
|
||||
|
||||
|
||||
1. Visit the [XRP Testnet Faucet](https://xrpl.org/xrp-testnet-faucet.html) page.
|
||||
2. Click **Generate NFT-Devnet credentials**.
|
||||
3. Copy the account **Secret**.
|
||||
4. Paste the secret in a persistent location, such as a notepad, and press return.
|
||||
5. Click **Generate NFT-Devnet credentials** to create a second account.
|
||||
6. Copy the account **Secret**.
|
||||
7. Paste the secret in the persistent location.
|
||||
8. Copy both secrets, separated by a return.
|
||||
9. Paste them in the **Account** **Seeds** field.
|
||||
10. Click **Get Accounts from Seeds**.
|
||||
|
||||
You can transfer XRP between your new accounts. Each account has its own fields and buttons.
|
||||
|
||||
To transfer XRP between accounts:
|
||||
|
||||
|
||||
|
||||
1. Enter the **Amount** of XRP to send.
|
||||
2. Click **Send XRP>** to transfer XRP from the standby account to the operational account, or **<Send XRP** to transfer XRP from the operational account to the standby account**.**
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) in the source repository for this website.
|
||||
|
||||
|
||||
|
||||
## ripplex-1-send-xrp.js
|
||||
|
||||
This example can be used with any XRP Ledger network. Currently, there are _Testnet_ and _Devnet,_ with the experimental _NFT-Devnet_ server with support for NFTs. You can update the code to choose different or additional XRP Ledger networks.
|
||||
|
||||
|
||||
### getNet()
|
||||
|
||||
|
||||
```
|
||||
// ******************************************************
|
||||
// ************* Get the Preferred Network **************
|
||||
// ******************************************************
|
||||
|
||||
function getNet() {
|
||||
```
|
||||
|
||||
|
||||
This function uses brute force `if` statements to discover the selected network instance and return the URI.
|
||||
|
||||
|
||||
```
|
||||
let net
|
||||
if (document.getElementById("xls").checked) net = "wss://xls20-sandbox.rippletest.net:51233"
|
||||
if (document.getElementById("tn").checked) net = "wss://s.altnet.rippletest.net:51233"
|
||||
if (document.getElementById("dn").checked) net = "wss://s.devnet.rippletest.net:51233"
|
||||
return net
|
||||
} // End of getNet()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### getAccount(type)
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ************* Get Account *****************************
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function getAccount(type) {
|
||||
```
|
||||
|
||||
|
||||
Get the selected ledger.
|
||||
|
||||
|
||||
```
|
||||
let net = getNet()
|
||||
```
|
||||
|
||||
|
||||
Instantiate a client.
|
||||
|
||||
|
||||
```
|
||||
const client = new xrpl.Client(net)
|
||||
```
|
||||
|
||||
|
||||
Use the _results_ variable to capture progress information.
|
||||
|
||||
|
||||
```
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
const walletServer = net
|
||||
```
|
||||
|
||||
|
||||
Report progress in the appropriate results field.
|
||||
|
||||
|
||||
```
|
||||
if (type == 'standby') {
|
||||
document.getElementById('standbyResultField').value = results
|
||||
} else {
|
||||
document.getElementById('operationalResultField').value = results
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Connect to the server.
|
||||
|
||||
|
||||
```
|
||||
await client.connect()
|
||||
|
||||
|
||||
results += '\nConnected, funding wallet.'
|
||||
if (type == 'standby') {
|
||||
document.getElementById('standbyResultField').value = results
|
||||
} else {
|
||||
document.getElementById('operationalResultField').value = results
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Create and fund a test account wallet.
|
||||
|
||||
|
||||
```
|
||||
const my_wallet = (await client.fundWallet(null, { faucetHost: walletServer})).wallet
|
||||
```
|
||||
|
||||
|
||||
Get the current XRP balance for the account.
|
||||
|
||||
|
||||
```
|
||||
const my_balance = (await client.getXrpBalance(my_wallet.address))
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
If this is a standby account, populate the standby account fields.
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
if (type == 'standby') {
|
||||
document.getElementById('standbyAccountField').value = my_wallet.address
|
||||
document.getElementById('standbyPubKeyField').value = my_wallet.publicKey
|
||||
document.getElementById('standbyPrivKeyField').value = my_wallet.privateKey
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(my_wallet.address))
|
||||
document.getElementById('standbySeedField').value = my_wallet.seed
|
||||
results += '\nStandby account created.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Otherwise, populate the operational account fields.
|
||||
|
||||
|
||||
```
|
||||
} else {
|
||||
document.getElementById('operationalAccountField').value = my_wallet.address
|
||||
document.getElementById('operationalPubKeyField').value = my_wallet.publicKey
|
||||
document.getElementById('operationalPrivKeyField').value = my_wallet.privateKey
|
||||
document.getElementById('operationalSeedField').value = my_wallet.seed
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(my_wallet.address))
|
||||
results += '\nOperational account created.'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Insert the seed values for both accounts as they are created to the **Seeds** field as a convenience. You can copy the values and store them offline, then paste them into the **Seeds** field to retrieve the accounts with the `getAccountsFromSeeds()` function.
|
||||
|
||||
|
||||
```
|
||||
document.getElementById('seeds').value = standbySeedField.value + '\n' + operationalSeedField.value
|
||||
```
|
||||
|
||||
|
||||
Disconnect from the XRP ledger.
|
||||
|
||||
|
||||
```
|
||||
client.disconnect()
|
||||
} // End of getAccount()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Get Accounts from Seeds
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ********** Get Accounts from Seeds ********************
|
||||
// *******************************************************
|
||||
|
||||
async function getAccountsFromSeeds() {
|
||||
```
|
||||
|
||||
|
||||
Connect to the selected network.
|
||||
|
||||
|
||||
```
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
await client.connect()
|
||||
results += '\nConnected, finding wallets.\n'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Parse the **seeds** field.
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
var lines = seeds.value.split('\n');
|
||||
```
|
||||
|
||||
|
||||
Get the `standby_wallet` based on the seed in the first line. Get the `operational_wallet` based on the seed in the second line.
|
||||
|
||||
|
||||
```
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(lines[0])
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(lines[1])
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Get the current XRP balances for the accounts.
|
||||
|
||||
|
||||
```
|
||||
const standby_balance = (await client.getXrpBalance(standby_wallet.address))
|
||||
const operational_balance = (await client.getXrpBalance(operational_wallet.address))
|
||||
```
|
||||
|
||||
|
||||
Populate the fields for the standby and operational accounts.
|
||||
|
||||
|
||||
```
|
||||
document.getElementById('standbyAccountField').value = standby_wallet.address
|
||||
document.getElementById('standbyPubKeyField').value = standby_wallet.publicKey
|
||||
document.getElementById('standbyPrivKeyField').value = standby_wallet.privateKey
|
||||
document.getElementById('standbySeedField').value = standby_wallet.seed
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
|
||||
|
||||
document.getElementById('operationalAccountField').value = operational_wallet.address
|
||||
document.getElementById('operationalPubKeyField').value = operational_wallet.publicKey
|
||||
document.getElementById('operationalPrivKeyField').value = operational_wallet.privateKey
|
||||
document.getElementById('operationalSeedField').value = operational_wallet.seed
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Disconnect from the XRP Ledger.
|
||||
|
||||
|
||||
```
|
||||
client.disconnect()
|
||||
|
||||
|
||||
} // End of getAccountsFromSeeds()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Send XRP
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ******************** Send XRP *************************
|
||||
// *******************************************************
|
||||
|
||||
async function sendXRP() {
|
||||
```
|
||||
|
||||
|
||||
Connect to your selected ledger.
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
results = "Connecting to the selected ledger.\n"
|
||||
document.getElementById('standbyResultField').value = results
|
||||
let net = getNet()
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
|
||||
|
||||
results += "\nConnected. Sending XRP.\n"
|
||||
document.getElementById('standbyResultField').value = results
|
||||
|
||||
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
const sendAmount = standbyAmountField.value
|
||||
|
||||
|
||||
results += "\nstandby_wallet.address: = " + standby_wallet.address
|
||||
document.getElementById('standbyResultField').value = results
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Prepare the transaction. This is a Payment transaction from the standby wallet to the operational wallet. You could add a **Destination** field to send to any account: this hardcoded example is for convenience in this tutorial.
|
||||
|
||||
The _Payment_ transaction expects the XRP to be expressed in drops, or 1/millionth of an XRP. You can use the xrpToDrops utility to convert the send amount for you (which beats having to type an extra 6 zeroes to send 1 XRP).
|
||||
|
||||
|
||||
```
|
||||
const prepared = await client.autofill({
|
||||
"TransactionType": "Payment",
|
||||
"Account": standby_wallet.address,
|
||||
"Amount": xrpl.xrpToDrops(sendAmount),
|
||||
"Destination": operational_wallet.address
|
||||
})
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Sign the prepared transaction.
|
||||
|
||||
|
||||
```
|
||||
const signed = standby_wallet.sign(prepared)
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Submit the transaction and wait for the results.
|
||||
|
||||
|
||||
```
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
```
|
||||
|
||||
|
||||
Request the balance changes caused by the transaction and report the results.
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
results += "\nBalance changes: " +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
document.getElementById('standbyResultField').value = results
|
||||
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
client.disconnect()
|
||||
|
||||
|
||||
} // End of sendXRP()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Reciprocal Transactions
|
||||
|
||||
For each of the transactions, there is an accompanying reciprocal transaction, with the prefix _oP,_ for the operational account. See the corresponding function for the standby account for code commentary.
|
||||
|
||||
|
||||
```
|
||||
// **********************************************************************
|
||||
// ****** Reciprocal Transactions ****************************************
|
||||
// **********************************************************************
|
||||
|
||||
|
||||
// *******************************************************
|
||||
// ********* Send XRP from Operational account ***********
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function oPsendXRP() {
|
||||
|
||||
|
||||
results = "Connecting to testnet.\n"
|
||||
document.getElementById('operationalResultField').value = results
|
||||
let net = getNet()
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
|
||||
|
||||
results += "\nConnected. Sending XRP.\n"
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const sendAmount = operationalAmountField.value
|
||||
|
||||
|
||||
results += "\noperational_wallet.address: = " + operational_wallet.address
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
// ---------------------------------- Prepare transaction
|
||||
// Note that the destination is hard coded.
|
||||
const prepared = await client.autofill({
|
||||
"TransactionType": "Payment",
|
||||
"Account": operational_wallet.address,
|
||||
"Amount": xrpl.xrpToDrops(operationalAmountField.value),
|
||||
"Destination": standby_wallet.address
|
||||
})
|
||||
|
||||
|
||||
// ---------------------------- Sign prepared instructions
|
||||
const signed = operational_wallet.sign(prepared)
|
||||
|
||||
|
||||
// ------------------------------------ Submit signed blob
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
|
||||
|
||||
results += "\nBalance changes: " +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
|
||||
|
||||
client.disconnect()
|
||||
|
||||
|
||||
} // End of oPsendXRP()
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 1.get-accounts-send-xrp.html
|
||||
|
||||
Create a standard HTML form to send transactions and requests, then display the results.
|
||||
|
||||
|
||||
```
|
||||
<html>
|
||||
<head>
|
||||
<title>Token Test Harness</title>
|
||||
<script src='https://unpkg.com/xrpl@2.1.1'></script>
|
||||
<script src='ripplex1-send-xrp.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Token Test Harness</h1>
|
||||
<form id="theForm">
|
||||
Choose your network:
|
||||
<input type="radio" id="xls" name="server"
|
||||
value="wss://xls20-sandbox.rippletest.net:51233" checked>
|
||||
<label for="xls20">XLS20-NFT</label>
|
||||
|
||||
<input type="radio" id="tn" name="server"
|
||||
value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="testnet">Testnet</label>
|
||||
|
||||
<input type="radio" id="dn" name="server"
|
||||
value="wss://s.devnet.rippletest.net:51233">
|
||||
<label for="devnet">Devnet</label>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="getAccountsFromSeeds()">Get Accounts From Seeds</button>
|
||||
<br/>
|
||||
<textarea id="seeds" cols="40" rows= "2"></textarea>
|
||||
<br/><br/>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccount('standby')">Get New Standby Account</button>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
Standby Account
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyAccountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Public Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyPubKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Private Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyPrivKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Seed
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbySeedField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
XRP Balance
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyBalanceField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Amount
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyAmountField" size="40" value="100"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p align="right">
|
||||
<textarea id="standbyResultField" cols="80" rows="20" ></textarea>
|
||||
</p>
|
||||
</td>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="sendXRP()">Send XRP></button>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="oPsendXRP()"><Send XRP</button>
|
||||
</td>
|
||||
<td align="right">
|
||||
<button type="button" onClick="getAccount('operational')">Get New Operational Account</button>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
Operational Account
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalAccountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Public Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalPubKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Private Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalPrivKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Seed
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalSeedField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
XRP Balance
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalBalanceField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Amount
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalAmountField" size="40" value="100"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p align="right">
|
||||
<textarea id="operationalResultField" cols="80" rows="20" ></textarea>
|
||||
</p>
|
||||
</td>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
| Previous | Next |
|
||||
| :--- | ---: |
|
||||
| [XRPL Quickstart](xrpl-quickstart.html) | 2. [Create TrustLine and Send Currency](create-trustline-send-currency.html). |
|
||||
|
||||
878
content/tutorials/quickstart/create-trustline-send-currency.md
Normal file
878
content/tutorials/quickstart/create-trustline-send-currency.md
Normal file
@@ -0,0 +1,878 @@
|
||||
---
|
||||
html: create-trustline-send-currency.html
|
||||
parent: xrpl-quickstart.html
|
||||
blurb: Quickstart step 2, create TrustLines and send currency.
|
||||
labels:
|
||||
- Cross-Currency
|
||||
- Payments
|
||||
- Quickstart
|
||||
- Tokens
|
||||
|
||||
---
|
||||
|
||||
# 2. Create TrustLine and Send Currency
|
||||
|
||||
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 TrustLine between the standby account and the operational account.
|
||||
4. Send issued currency between accounts.
|
||||
5. Display account balances for all currencies.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) archive to try each of the samples in your own browser.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Open the Token Test Harness and get accounts:
|
||||
|
||||
|
||||
|
||||
1. Open `2.create-trustline-send-currency.html` in a browser.
|
||||
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 TrustLine
|
||||
|
||||
To create a trustline between accounts:
|
||||
|
||||
|
||||
|
||||
3. Enter a [currency code](https://www.iban.com/currency-codes) in the **Currency** field.
|
||||
4. Enter the maximum transfer limit in the **Amount** field.
|
||||
5. Click **Create Trustline**.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## Send an Issued Currency Token
|
||||
|
||||
To transfer an issued currency token, once you have created a TrustLine:
|
||||
|
||||
|
||||
|
||||
1. Enter the **Amount**.
|
||||
2. Click **Send Currency**.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) archive to try each of the samples in your own browser.
|
||||
|
||||
## ripplex2-send-currency.js
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// **************** Configure Account ********************
|
||||
// *******************************************************
|
||||
```
|
||||
|
||||
|
||||
Connect to the ledger
|
||||
|
||||
|
||||
```
|
||||
async function configureAccount(type, rippleDefault) {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
await client.connect()
|
||||
results += '\nConnected, finding wallet.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Get the account wallets.
|
||||
|
||||
|
||||
```
|
||||
if (type=='standby') {
|
||||
my_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
} else {
|
||||
my_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
}
|
||||
results += '\Ripple Default Setting: ' + rippleDefault
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Prepare the transaction. If the _rippleDefault_ argument is true, set the `asfDefaultRipple` flag. If it is false, clear the `asfDefaultRipple` flag.
|
||||
|
||||
|
||||
```
|
||||
let settings_tx = {}
|
||||
if (rippleDefault) {
|
||||
settings_tx = {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": my_wallet.address,
|
||||
"SetFlag": xrpl.AccountSetAsfFlags.asfDefaultRipple
|
||||
}
|
||||
results += '\n Set Default Ripple flag.'
|
||||
} else {
|
||||
settings_tx = {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": my_wallet.address,
|
||||
"ClearFlag": xrpl.AccountSetAsfFlags.asfDefaultRipple
|
||||
}
|
||||
results += '\n Clear Default Ripple flag.'
|
||||
}
|
||||
results += '\nSending account setting.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Autofill the default values for the transaction.
|
||||
|
||||
|
||||
```
|
||||
|
||||
const cst_prepared = await client.autofill(settings_tx)
|
||||
```
|
||||
|
||||
|
||||
Sign the transaction.
|
||||
|
||||
|
||||
```
|
||||
const cst_signed = my_wallet.sign(cst_prepared)
|
||||
```
|
||||
|
||||
|
||||
Submit the transaction and wait for the result.
|
||||
|
||||
|
||||
```
|
||||
const cst_result = await client.submitAndWait(cst_signed.tx_blob)
|
||||
```
|
||||
|
||||
|
||||
Report the result.
|
||||
|
||||
|
||||
```
|
||||
if (cst_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += '\nAccount setting succeeded.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
} else {
|
||||
throw 'Error sending transaction: ${cst_result}'
|
||||
results += '\nAccount setting failed.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
}
|
||||
|
||||
|
||||
client.disconnect()
|
||||
} // End of configureAccount()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Create TrustLine
|
||||
|
||||
A TrustLine enables two accounts to trade a defined currency up to a set limit. This gives the participants assurance that any exchanges are between known entities at agreed upon maximum amounts.
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ***************** Create TrustLine ********************
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function createTrustline(type) {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
|
||||
|
||||
await client.connect()
|
||||
|
||||
|
||||
results += '\nConnected.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Get the standby and operational wallets.
|
||||
|
||||
|
||||
```
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
```
|
||||
|
||||
|
||||
Define the transaction, capturing the currency code and (limit) amount from the form fields.
|
||||
|
||||
|
||||
```
|
||||
const trustSet_tx = {
|
||||
"TransactionType": "TrustSet",
|
||||
"Account": operational_wallet.address,
|
||||
"LimitAmount": {
|
||||
"currency": standbyCurrencyField.value,
|
||||
"issuer": standby_wallet.address,
|
||||
"value": standbyAmountField.value
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Prepare the transaction by automatically filling the default parameters.
|
||||
|
||||
|
||||
```
|
||||
const ts_prepared = await client.autofill(trustSet_tx)
|
||||
```
|
||||
|
||||
|
||||
Sign the transaction.
|
||||
|
||||
|
||||
```
|
||||
const ts_signed = operational_wallet.sign(ts_prepared)
|
||||
results += '\nCreating trust line from operational account to standby account...'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Submit the transaction and wait for the results.
|
||||
|
||||
|
||||
```
|
||||
const ts_result = await client.submitAndWait(ts_signed.tx_blob)
|
||||
```
|
||||
|
||||
|
||||
Report the results.
|
||||
|
||||
|
||||
```
|
||||
if (ts_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += '\nTrustline established between account \n' + operational_wallet.address + ' \n and account\n' + standby_wallet.address + '.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
} else {
|
||||
results += '\nTrustLine failed. See JavaScript console for details.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
throw 'Error sending transaction: ${ts_result.result.meta.TransactionResult}'
|
||||
}
|
||||
} //End of createTrustline()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Send Issued Currency
|
||||
|
||||
Once you have created a TrustLine from an account to your own, you can send issued currency tokens to that account, up to the established limit.
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// *************** Send Issued Currency ******************
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function sendCurrency() {
|
||||
```
|
||||
|
||||
|
||||
Connect to the ledger.
|
||||
|
||||
|
||||
```
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
|
||||
|
||||
await client.connect()
|
||||
|
||||
|
||||
results += '\nConnected.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Get the account wallets.
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
const currency_code = standbyCurrencyField.value
|
||||
const issue_quantity = standbyAmountField.value
|
||||
|
||||
|
||||
const send_token_tx = {
|
||||
"TransactionType": "Payment",
|
||||
"Account": standby_wallet.address,
|
||||
"Amount": {
|
||||
"currency": currency_code,
|
||||
"value": issue_quantity,
|
||||
"issuer": standby_wallet.address
|
||||
},
|
||||
"Destination": operational_wallet.address
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Prepare the transaction by automatically filling default values.
|
||||
|
||||
|
||||
```
|
||||
const pay_prepared = await client.autofill(send_token_tx)
|
||||
```
|
||||
|
||||
|
||||
Sign the transaction.
|
||||
|
||||
|
||||
```
|
||||
const pay_signed = standby_wallet.sign(pay_prepared)
|
||||
results += 'Sending ${issue_quantity} ${currency_code} to ${operational_wallet.address}...'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Submit the transaction and wait for the results.
|
||||
|
||||
|
||||
```
|
||||
const pay_result = await client.submitAndWait(pay_signed.tx_blob)
|
||||
```
|
||||
|
||||
|
||||
Report the results.
|
||||
|
||||
|
||||
```
|
||||
if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += 'Transaction succeeded: https://testnet.xrpl.org/transactions/${pay_signed.hash}'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
} else {
|
||||
results += 'Transaction failed: See JavaScript console for details.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
throw 'Error sending transaction: ${pay_result.result.meta.TransactionResult}'
|
||||
}
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
client.disconnect()
|
||||
getBalances()
|
||||
|
||||
|
||||
} // end of sendCurrency()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Get Balances
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ****************** Get Balances ***********************
|
||||
// *******************************************************
|
||||
async function getBalances() {
|
||||
```
|
||||
|
||||
|
||||
Connect to the ledger.
|
||||
|
||||
|
||||
```
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
await client.connect()
|
||||
results += '\nConnected.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Get the account wallets.
|
||||
|
||||
|
||||
```
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
results= "\nGetting standby account balances...\n"
|
||||
```
|
||||
|
||||
|
||||
Define and send the request for the standby account, then wait for the results.
|
||||
|
||||
|
||||
```
|
||||
const standby_balances = await client.request({
|
||||
command: "gateway_balances",
|
||||
account: standby_wallet.address,
|
||||
ledger_index: "validated",
|
||||
hotwallet: [operational_wallet.address]
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Report the results.
|
||||
|
||||
|
||||
```
|
||||
results += JSON.stringify(standby_balances.result, null, 2)
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Define and send the request for the operational account, then wait for the results.
|
||||
|
||||
|
||||
```
|
||||
results= "\nGetting operational account balances...\n"
|
||||
const operational_balances = await client.request({
|
||||
command: "account_lines",
|
||||
account: operational_wallet.address,
|
||||
ledger_index: "validated"
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Report the results.
|
||||
|
||||
|
||||
```
|
||||
results += JSON.stringify(operational_balances.result, null, 2)
|
||||
document.getElementById('operationalResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Update the form with current XRP balances.
|
||||
|
||||
|
||||
```
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
```
|
||||
|
||||
|
||||
Disconnect from the ledger.
|
||||
|
||||
|
||||
```
|
||||
client.disconnect()
|
||||
} // End of getBalances()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Reciprocal Transactions
|
||||
|
||||
For each of the transactions, there is an accompanying reciprocal transaction, with the prefix _oP,_ for the operational account. See the corresponding function for the standby account for code commentary. The `getBalances()` request does not have a reciprocal transaction, because it reports balances for both accounts.
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ************ Create Operational TrustLine *************
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function oPcreateTrustline() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
await client.connect()
|
||||
|
||||
|
||||
results += '\nConnected.'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
const trustSet_tx = {
|
||||
"TransactionType": "TrustSet",
|
||||
"Account": standby_wallet.address,
|
||||
"LimitAmount": {
|
||||
"currency": operationalCurrencyField.value,
|
||||
"issuer": operational_wallet.address,
|
||||
"value": operationalAmountField.value
|
||||
}
|
||||
}
|
||||
const ts_prepared = await client.autofill(trustSet_tx)
|
||||
const ts_signed = standby_wallet.sign(ts_prepared)
|
||||
results += '\nCreating trust line from standby account to operational account...'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
const ts_result = await client.submitAndWait(ts_signed.tx_blob)
|
||||
if (ts_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += '\nTrustline established between account \n' + standby_wallet.address + ' \n and account\n' + operational_wallet.address + '.'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
} else {
|
||||
results += '\nTrustLine failed. See JavaScript console for details.'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
throw 'Error sending transaction: ${ts_result.result.meta.TransactionResult}'
|
||||
}
|
||||
} //End of oPcreateTrustline
|
||||
|
||||
|
||||
// *******************************************************
|
||||
// ************* Operational Send Issued Currency ********
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function oPsendCurrency() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
await client.connect()
|
||||
|
||||
|
||||
results += '\nConnected.'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
const currency_code = operationalCurrencyField.value
|
||||
const issue_quantity = operationalAmountField.value
|
||||
|
||||
|
||||
const send_token_tx = {
|
||||
"TransactionType": "Payment",
|
||||
"Account": operational_wallet.address,
|
||||
"Amount": {
|
||||
"currency": currency_code,
|
||||
"value": issue_quantity,
|
||||
"issuer": operational_wallet.address
|
||||
},
|
||||
"Destination": standby_wallet.address
|
||||
}
|
||||
|
||||
|
||||
const pay_prepared = await client.autofill(send_token_tx)
|
||||
const pay_signed = operational_wallet.sign(pay_prepared)
|
||||
results += 'Sending ${issue_quantity} ${currency_code} to ${standby_wallet.address}...'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
const pay_result = await client.submitAndWait(pay_signed.tx_blob)
|
||||
if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += 'Transaction succeeded: https://testnet.xrpl.org/transactions/${pay_signed.hash}'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
} else {
|
||||
results += 'Transaction failed: See JavaScript console for details.'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
throw 'Error sending transaction: ${pay_result.result.meta.TransactionResult}'
|
||||
}
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
client.disconnect()
|
||||
getBalances()
|
||||
|
||||
|
||||
} // end of oPsendCurrency()
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 2.create-trustline-send-currency.html
|
||||
|
||||
Update the form to support the new functions.
|
||||
|
||||
|
||||
```
|
||||
<html>
|
||||
<head>
|
||||
<title>Token Test Harness</title>
|
||||
<script src='https://unpkg.com/xrpl@2.1.1'></script>
|
||||
<script src='ripplex1-send-xrp.js'></script>
|
||||
<script src='ripplex2-send-currency.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Token Test Harness</h1>
|
||||
<form id="theForm">
|
||||
Choose your ledger instance:
|
||||
<input type="radio" id="xls" name="server"
|
||||
value="wss://xls20-sandbox.rippletest.net:51233" checked>
|
||||
<label for="xls20">XLS20-NFT</label>
|
||||
|
||||
<input type="radio" id="tn" name="server"
|
||||
value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="testnet">Testnet</label>
|
||||
|
||||
<input type="radio" id="dn" name="server"
|
||||
value="wss://s.devnet.rippletest.net:51233">
|
||||
<label for="devnet">Devnet</label>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="getAccountsFromSeeds()">Get Accounts From Seeds</button>
|
||||
<br/>
|
||||
<textarea id="seeds" cols="40" rows= "2"></textarea>
|
||||
<br/><br/>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccount('standby')">Get New Standby Account</button>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
Standby Account
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyAccountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Public Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyPubKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Private Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyPrivKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Seed
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbySeedField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
XRP Balance
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyBalanceField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Amount
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyAmountField" size="40" value="100"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td><button type="button" onClick="configureAccount('standby',document.querySelector('#standbyDefault').checked)">Configure Account</button></td>
|
||||
<td>
|
||||
<input type="checkbox" id="standbyDefault" checked="true"/>
|
||||
<label for="standbyDefault">Allow Rippling</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Currency
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyCurrencyField" size="40" value="USD"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p align="left">
|
||||
<textarea id="standbyResultField" cols="80" rows="20" ></textarea>
|
||||
</p>
|
||||
</td>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="sendXRP()">Send XRP></button>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="createTrustline()">Create TrustLine</button>
|
||||
<br/>
|
||||
<button type="button" onClick="sendCurrency()">Send Currency</button>
|
||||
<br/>
|
||||
<button type="button" onClick="getBalances()">Get Balances</button>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="oPsendXRP()">< Send XRP</button>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="oPcreateTrustline()">Create TrustLine</button>
|
||||
<br/>
|
||||
<button type="button" onClick="oPsendCurrency()">Send Currency</button>
|
||||
<br/>
|
||||
<button type="button" onClick="getBalances()">Get Balances</button>
|
||||
</td>
|
||||
<td valign="top" align="right">
|
||||
<button type="button" onClick="getAccount('operational')">Get New Operational Account</button>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
Operational Account
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalAccountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Public Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalPubKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Private Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalPrivKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Seed
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalSeedField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
XRP Balance
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalBalanceField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Amount
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalAmountField" size="40" value="100"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<input type="checkbox" id="operationalDefault" checked="true"/>
|
||||
<label for="operationalDefault">Allow Rippling</label>
|
||||
<button type="button" onClick="configureAccount('operational',document.querySelector('#operationalDefault').checked)">Configure Account</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Currency
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalCurrencyField" size="40" value="USD"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p align="right">
|
||||
<textarea id="operationalResultField" cols="80" rows="20" ></textarea>
|
||||
</p>
|
||||
</td>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
| Previous | Next |
|
||||
| :--- | ---: |
|
||||
| 1. [Create Accounts and Send XRP](create-accounts-send-xrp.html) | 3. [Mint and Burn NFTokens](mint-and-burn-nftokens.html) |
|
||||
|
||||
779
content/tutorials/quickstart/mint-and-burn-nftokens.md
Normal file
779
content/tutorials/quickstart/mint-and-burn-nftokens.md
Normal file
@@ -0,0 +1,779 @@
|
||||
---
|
||||
html: mint-and-burn-nftokens.html
|
||||
parent: xrpl-quickstart.html
|
||||
blurb: Quickstart step 3, mint and burn NFTokens.
|
||||
labels:
|
||||
- Quickstart
|
||||
- Tokens
|
||||
- Non-fungible tokens, NFTs
|
||||
---
|
||||
|
||||
# 3. Mint and Burn NFTokens
|
||||
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
This example shows how to:
|
||||
|
||||
|
||||
1. Mint new Non-fungible Tokens (NFTokens).
|
||||
2. Get a list of existing NFTokens.
|
||||
3. Delete (Burn) a NFToken.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) archive to try the sample in your own browser.
|
||||
|
||||
## Get Accounts
|
||||
|
||||
|
||||
|
||||
1. Open `3.mint-nfts.html` in a browser.
|
||||
2. Get test accounts.
|
||||
1. If you have existing NFT-Devnet account seeds
|
||||
1. Paste account seeds in the **Seeds** field.
|
||||
2. Click **Get Accounts from Seeds**.
|
||||
2. If you do not have NFT-Devnet account seeds:
|
||||
1. Visit the [XRP Testnet Faucet](https://xrpl.org/xrp-testnet-faucet.html) page.
|
||||
2. Click **Generate NFT-Devnet credentials**.
|
||||
3. Copy the account **Secret**.
|
||||
4. Paste the secret in a persistent location, such as a notepad, and press return.
|
||||
5. Click **Generate NFT-Devnet credentials** to create a second account.
|
||||
6. Copy the account **Secret**.
|
||||
7. Paste the secret in the persistent location.
|
||||
8. Copy both secrets, separated by a return.
|
||||
9. Paste them in the **Account** **Seeds** field.
|
||||
10. Click **Get Accounts from Seeds**.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## Mint a NFToken
|
||||
|
||||
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 NFToken object can be transferred to another account. Otherwise, the NFToken object can only be transferred back to the issuing account. See [NFToken Mint](https://xrpl.org/nftokenmint.html#:~:text=Example%20NFTokenMint%20JSON-,NFTokenMint%20Fields,-NFTokenMint%20Flags) for information about all of the available flags for minting NFTokens.
|
||||
2. Enter the **Token URL**. This is a URI that points to the data or metadata associated with the NFToken object. You can use the sample URI provided if you do not have one of your own.
|
||||
3. Click **Mint Token**.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Get Tokens
|
||||
|
||||
Click **Get Tokens** to get a list of NFTokens owned by the account.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## Burn a Token
|
||||
|
||||
The current owner of a NFToken can always destroy (or _burn)_ a NFToken object.
|
||||
|
||||
To permanently destroy a NFToken:
|
||||
|
||||
|
||||
|
||||
1. Enter the **Token ID**.
|
||||
2. Click **Burn Token**.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
# Code Walkthrough
|
||||
|
||||
You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) archive to examine the code samples.
|
||||
|
||||
## ripplex3-mint-nfts.js
|
||||
|
||||
|
||||
### Mint Token
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ********************** Mint Token *********************
|
||||
// *******************************************************
|
||||
async function mintToken() {
|
||||
```
|
||||
|
||||
|
||||
Connect to the ledger and get the account wallets.
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
let net = getNet()
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
results += '\nConnected. Minting NFToken.'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Define the transaction.
|
||||
|
||||
|
||||
```
|
||||
const transactionBlob = {
|
||||
TransactionType: "NFTokenMint",
|
||||
Account: standby_wallet.classicAddress,
|
||||
```
|
||||
|
||||
|
||||
Note that the URI field expects a hexadecimal value rather than the literal URI string. You can use the `convertStringToHex` utility to transform the URI in real time.
|
||||
|
||||
|
||||
```
|
||||
URI: xrpl.convertStringToHex(standbyTokenUrlField.value),
|
||||
Flags: parseInt(standbyFlagsField.value),
|
||||
```
|
||||
|
||||
|
||||
The TokenTaxon is a required value. It is an arbitrary value defined by the issuer. If you do not have a use for the field, you can set it to _0_.
|
||||
|
||||
|
||||
```
|
||||
TokenTaxon: 0 //Required, but if you have no use for it, set to zero.
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Send the transaction and wait for the response.
|
||||
|
||||
|
||||
```
|
||||
const tx = await client.submitAndWait(transactionBlob, { wallet: standby_wallet} )
|
||||
```
|
||||
|
||||
|
||||
Request a list of NFTs owned by the account.
|
||||
|
||||
|
||||
```
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: standby_wallet.classicAddress
|
||||
})
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Report the results.
|
||||
|
||||
|
||||
```
|
||||
results += '\n\nTransaction result: '+ tx.result.meta.TransactionResult
|
||||
results += '\n\nnfts: ' + JSON.stringify(nfts, null, 2)
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
document.getElementById('operationalBalanceField').value = results
|
||||
```
|
||||
|
||||
|
||||
Disconnect from the ledger.
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
client.disconnect()
|
||||
} //End of mintToken()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Get Tokens
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ******************* Get Tokens ************************
|
||||
// *******************************************************
|
||||
|
||||
async function getTokens() {
|
||||
```
|
||||
|
||||
|
||||
Connect to the ledger and get the account wallet.
|
||||
|
||||
|
||||
```
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '...'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
await client.connect()
|
||||
results += '\nConnected. Getting NFTokens...'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Request a list of NFTs owned by the account.
|
||||
|
||||
|
||||
```
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: standby_wallet.classicAddress
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Report the results.
|
||||
|
||||
|
||||
```
|
||||
results += '\nNFTs:\n ' + JSON.stringify(nfts,null,2)
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Disconnect from the ledger.
|
||||
|
||||
|
||||
```
|
||||
client.disconnect()
|
||||
} //End of getTokens()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Burn Token
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ********************* Burn Token **********************
|
||||
// *******************************************************
|
||||
```
|
||||
|
||||
|
||||
Connect to the ledger and get the account wallets.
|
||||
|
||||
|
||||
```
|
||||
async function burnToken() {
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '...'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
await client.connect()
|
||||
results += '\nConnected. Burning NFToken...'
|
||||
document.getElementById('standbyResultField').value = results
|
||||
```
|
||||
|
||||
|
||||
Define the transaction.
|
||||
|
||||
|
||||
```
|
||||
const transactionBlob = {
|
||||
"TransactionType": "NFTokenBurn",
|
||||
"Account": standby_wallet.classicAddress,
|
||||
"TokenID": standbyTokenIdField.value
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Submit the transaction and wait for the results.
|
||||
|
||||
|
||||
```
|
||||
const tx = await client.submitAndWait(transactionBlob,{wallet: standby_wallet})
|
||||
```
|
||||
|
||||
|
||||
Request a list of NFTokens owned by the client.
|
||||
|
||||
|
||||
```
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: standby_wallet.classicAddress
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Report the results.
|
||||
|
||||
|
||||
```
|
||||
results += '\nTransaction result: '+ tx.result.meta.TransactionResult
|
||||
results += '\nBalance changes: ' +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
document.getElementById('standbyResultField').value = results
|
||||
document.getElementById('standbyBalanceField').value =
|
||||
(await client.getXrpBalance(standby_wallet.address))
|
||||
results += '\nNFTs: \n' + JSON.stringify(nfts,null,2)
|
||||
document.getElementById('standbyResultField').value = results
|
||||
client.disconnect()
|
||||
}
|
||||
// End of burnToken()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Reciprocal Transactions
|
||||
|
||||
|
||||
```
|
||||
// *******************************************************
|
||||
// ************** Operational Mint Token *****************
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function oPmintToken() {
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
let net = getNet()
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
results += '\nConnected. Minting NFToken.'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
// Note that you must convert the token URL to a hexadecimal
|
||||
// value for this transaction.
|
||||
// ------------------------------------------------------------------------
|
||||
const transactionBlob = {
|
||||
TransactionType: "NFTokenMint",
|
||||
Account: operational_wallet.classicAddress,
|
||||
URI: xrpl.convertStringToHex(operationalTokenUrlField.value),
|
||||
Flags: parseInt(operationalFlagsField.value),
|
||||
TokenTaxon: 0 //Required, but if you have no use for it, set to zero.
|
||||
}
|
||||
|
||||
|
||||
// ------------------- Submit transaction and wait for results
|
||||
const tx = await client.submitAndWait(transactionBlob, { wallet: operational_wallet} )
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: operational_wallet.classicAddress
|
||||
})
|
||||
|
||||
|
||||
// ------------------------------------------------------- Report results
|
||||
results += '\n\nTransaction result: '+ tx.result.meta.TransactionResult
|
||||
results += '\n\nnfts: ' + JSON.stringify(nfts, null, 2)
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
client.disconnect()
|
||||
} //End of oPmintToken
|
||||
|
||||
|
||||
// *******************************************************
|
||||
// ************** Operational Get Tokens *****************
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function oPgetTokens() {
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '...'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
await client.connect()
|
||||
results += '\nConnected. Getting NFTokens...'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: operational_wallet.classicAddress
|
||||
})
|
||||
results += '\nNFTs:\n ' + JSON.stringify(nfts,null,2)
|
||||
document.getElementById('operationalResultField').value = results
|
||||
client.disconnect()
|
||||
} //End of oPgetTokens
|
||||
|
||||
|
||||
// *******************************************************
|
||||
// ************* Operational Burn Token ******************
|
||||
// *******************************************************
|
||||
|
||||
|
||||
async function oPburnToken() {
|
||||
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
|
||||
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '...'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
await client.connect()
|
||||
results += '\nConnected. Burning NFToken...'
|
||||
document.getElementById('operationalResultField').value = results
|
||||
|
||||
|
||||
// ------------------------------------------------------- Prepare transaction
|
||||
const transactionBlob = {
|
||||
"TransactionType": "NFTokenBurn",
|
||||
"Account": operational_wallet.classicAddress,
|
||||
"TokenID": operationalTokenIdField.value
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------- Submit signed blob
|
||||
const tx = await client.submitAndWait(transactionBlob,{wallet: operational_wallet})
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: operational_wallet.classicAddress
|
||||
})
|
||||
results += '\nTransaction result: '+ tx.result.meta.TransactionResult
|
||||
results += '\nBalance changes: ' +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
document.getElementById('operationalResultField').value = results
|
||||
document.getElementById('operationalBalanceField').value =
|
||||
(await client.getXrpBalance(operational_wallet.address))
|
||||
results += '\nNFTs: \n' + JSON.stringify(nfts,null,2)
|
||||
document.getElementById('operationalResultField').value = results
|
||||
client.disconnect()
|
||||
}
|
||||
// End of oPburnToken()
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3.mint-nfts.html
|
||||
|
||||
Bold text in the following indicates changes to the form that support the new functions.
|
||||
|
||||
|
||||
```
|
||||
<html>
|
||||
<head>
|
||||
<title>Token Test Harness</title>
|
||||
<script src='https://unpkg.com/xrpl@2.1.1'></script>
|
||||
<script src='ripplex1-send-xrp.js'></script>
|
||||
<script src='ripplex2-send-currency.js'></script>
|
||||
<script src='ripplex3-mint-nfts.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Token Test Harness</h1>
|
||||
<form id="theForm">
|
||||
Choose your ledger instance:
|
||||
<input type="radio" id="xls" name="server"
|
||||
value="wss://xls20-sandbox.rippletest.net:51233" checked>
|
||||
<label for="xls20">XLS20-NFT</label>
|
||||
|
||||
<input type="radio" id="tn" name="server"
|
||||
value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="testnet">Testnet</label>
|
||||
|
||||
<input type="radio" id="dn" name="server"
|
||||
value="wss://s.devnet.rippletest.net:51233">
|
||||
<label for="devnet">Devnet</label>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="getAccountsFromSeeds()">Get Accounts From Seeds</button>
|
||||
<br/>
|
||||
<textarea id="seeds" cols="40" rows= "2"></textarea>
|
||||
<br/><br/>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccount('standby')">Get New Standby Account</button>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
Standby Account
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyAccountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Public Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyPubKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Private Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyPrivKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Seed
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbySeedField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
XRP Balance
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyBalanceField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Amount
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyAmountField" size="40" value="100"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td><button type="button" onClick="configureAccount('standby',document.querySelector('#standbyDefault').checked)">Configure Account</button></td>
|
||||
<td>
|
||||
<input type="checkbox" id="standbyDefault" checked="true"/>
|
||||
<label for="standbyDefault">Allow Rippling</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Currency
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="standbyCurrencyField" size="40" value="USD"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Token URL</td>
|
||||
<td><input type="text" id="standbyTokenUrlField"
|
||||
value = "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" size="80"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Flags</td>
|
||||
<td><input type="text" id="standbyFlagsField" value="1" size="10"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Token ID</td>
|
||||
<td><input type="text" id="standbyTokenIdField" value="" size="80"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p align="left">
|
||||
<textarea id="standbyResultField" cols="80" rows="20" ></textarea>
|
||||
</p>
|
||||
</td>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="sendXRP()">Send XRP></button>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="createTrustline()">Create TrustLine</button>
|
||||
<br/>
|
||||
<button type="button" onClick="sendCurrency()">Send Currency</button>
|
||||
<br/>
|
||||
<button type="button" onClick="getBalances()">Get Balances</button>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="mintToken()">Mint NFToken</button>
|
||||
<br/>
|
||||
<button type="button" onClick="getTokens()">Get NFTokens</button>
|
||||
<br/>
|
||||
<button type="button" onClick="burnToken()">Burn NFToken</button>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="oPsendXRP()">< Send XRP</button>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="oPcreateTrustline()">Create TrustLine</button>
|
||||
<br/>
|
||||
<button type="button" onClick="oPsendCurrency()">Send Currency</button>
|
||||
<br/>
|
||||
<button type="button" onClick="getBalances()">Get Balances</button>
|
||||
<br/><br/>
|
||||
<button type="button" onClick="oPmintToken()">Mint NFToken</button>
|
||||
<br/>
|
||||
<button type="button" onClick="oPgetTokens()">Get NFTokens</button>
|
||||
<br/>
|
||||
<button type="button" onClick="oPburnToken()">Burn NFToken</button>
|
||||
<td valign="top" align="right">
|
||||
<button type="button" onClick="getAccount('operational')">Get New Operational Account</button>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
Operational Account
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalAccountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Public Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalPubKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Private Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalPrivKeyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Seed
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalSeedField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
XRP Balance
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalBalanceField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Amount
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalAmountField" size="40" value="100"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td align="right">
|
||||
<input type="checkbox" id="operationalDefault" checked="true"/>
|
||||
<label for="operationalDefault">Allow Rippling</label>
|
||||
<button type="button" onClick="configureAccount('operational',document.querySelector('#operationalDefault').checked)">Configure Account</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
Currency
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="operationalCurrencyField" size="40" value="USD"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Token URL</td>
|
||||
<td><input type="text" id="operationalTokenUrlField"
|
||||
value = "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" size="80"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Flags</td>
|
||||
<td><input type="text" id="operationalFlagsField" value="1" size="10"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Token ID</td>
|
||||
<td><input type="text" id="operationalTokenIdField" value="" size="80"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p align="right">
|
||||
<textarea id="operationalResultField" cols="80" rows="20" ></textarea>
|
||||
</p>
|
||||
</td>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
| Previous | Next |
|
||||
| :--- | ---: |
|
||||
| 2. [Create TrustLine and Send Currency](create-trustline-send-currency.html). | 4. [Transfer NFTokens](transfer-nftokens.html). |
|
||||
1514
content/tutorials/quickstart/transfer-nftokens.md
Normal file
1514
content/tutorials/quickstart/transfer-nftokens.md
Normal file
File diff suppressed because it is too large
Load Diff
61
content/tutorials/quickstart/xrpl-quickstart.md
Normal file
61
content/tutorials/quickstart/xrpl-quickstart.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
html: xrpl-quickstart.html
|
||||
parent: tutorials.html
|
||||
blurb: Use a JavaScript test harness to send XRP, trade currencies, and mint and trade NFTokens.
|
||||
labels:
|
||||
- Accounts
|
||||
- Cross-Currency
|
||||
- Non-fungible Tokens, NFTs
|
||||
- Payments
|
||||
- Quickstart
|
||||
- Tokens
|
||||
- XRP
|
||||
---
|
||||
# XRPL Quickstart
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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 JavaScript and HTML 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 browser. If you just cannot wait, you can follow the prerequisites below, then jump to lesson 4, [Transfer NFTokens](transfer-nftokens.html), and try out the complete test harness right away.
|
||||
|
||||
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 JavaScript file and the supporting UI. We anticipate that the applications you build 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.html)
|
||||
2. [Create TrustLine and Send Currency](create-trustline-send-currency.html).
|
||||
3. [Mint and Burn NFTokens](mint-and-burn-nftokens.html).
|
||||
4. [Transfer NFTokens](transfer-nftokens.html).
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To get started, create a new folder on your local disk and install the JavaScript library using `npm`.
|
||||
|
||||
|
||||
```
|
||||
npm install xrpl
|
||||
```
|
||||
|
||||
|
||||
Download and expand the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/quickstart/quickstart.zip) archive.
|
||||
|
||||
---
|
||||
|
||||
| Previous | Next |
|
||||
| :--- | ---: |
|
||||
| | 1. [Create Accounts and Send XRP](create-accounts-send-xrp.html) |
|
||||
Reference in New Issue
Block a user