run prettier

This commit is contained in:
Mayukha Vadari
2026-01-12 14:19:31 -05:00
parent cae2019eb7
commit 0b247281eb
1661 changed files with 378338 additions and 65894 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,6 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
Without the Quickstart Samples, you will not be able to try the examples that follow.
{% /admonition %}
## Usage
### Get Accounts
@@ -32,7 +31,6 @@ Without the Quickstart Samples, you will not be able to try the examples that fo
[![Get account results](/docs/img/quickstart-create-amm2.png)](/docs/img/quickstart-create-amm2.png)
### Check AMM
Check if an AMM pair already exists. An AMM holds two different assets: at most one of these can be XRP, and one or both of them can be [tokens](/docs/concepts/tokens).
@@ -44,7 +42,6 @@ Check if an AMM pair already exists. An AMM holds two different assets: at most
[![Check AMM results](/docs/img/quickstart-create-amm3.png)](/docs/img/quickstart-create-amm3.png)
### Create Trustline
Create a trustline from the operational account to the standby account. In the standby account fields:
@@ -56,15 +53,14 @@ Create a trustline from the operational account to the standby account. In the s
[![Create trustline results](/docs/img/quickstart-create-amm4.png)](/docs/img/quickstart-create-amm4.png)
### Issue Tokens
Send issued tokens from the operational account to the standby account. In the operational account fields:
1. Select **Allow Rippling** and click **Configure Account**.
{% admonition type="info" name="Note" %}
This enables the `defaultRipple` flag on the issuing account, which is set to `false` by default. You need to enable this in order to trade tokens issued by the account. See [Configure Issuer Settings](../../how-tos/use-tokens/issue-a-fungible-token.md#3-configure-issuer-settings) to learn more.
{% /admonition %}
1. Select **Allow Rippling** and click **Configure Account**.
{% admonition type="info" name="Note" %}
This enables the `defaultRipple` flag on the issuing account, which is set to `false` by default. You need to enable this in order to trade tokens issued by the account. See [Configure Issuer Settings](../../how-tos/use-tokens/issue-a-fungible-token.md#3-configure-issuer-settings) to learn more.
{% /admonition %}
2. Enter a value in the **Amount** field, up to the maximum transfer amount you set in the trustline.
3. Enter the standby account address in the **Destination** field.
4. Enter the currency code from the trustline in the **Currency** field.
@@ -72,7 +68,6 @@ Send issued tokens from the operational account to the standby account. In the o
[![Issue token results](/docs/img/quickstart-create-amm5.png)](/docs/img/quickstart-create-amm5.png)
### Create an XRP/Token AMM
Create a new AMM pool with XRP and the issued tokens.
@@ -90,7 +85,6 @@ Save the seed values of the standby and operational accounts for subsequent AMM
[![Create AMM results](/docs/img/quickstart-create-amm6.png)](/docs/img/quickstart-create-amm6.png)
### Create a Token/Token AMM
Create a second AMM pool with two issued tokens.
@@ -107,7 +101,6 @@ Create a second AMM pool with two issued tokens.
[![Create AMM results](/docs/img/quickstart-create-amm7.png)](/docs/img/quickstart-create-amm7.png)
## Code Walkthrough
You can open `ripplex11-create-amm.js` from the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/js/) to view the source code.
@@ -123,127 +116,121 @@ async function createAMM() {
Connect to the XRP Ledger.
```javascript
let net = getNet()
let net = getNet()
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
```
Get the AMM information fields.
```javascript
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const asset1_currency = asset1CurrencyField.value
const asset1_issuer = asset1IssuerField.value
const asset1_amount = asset1AmountField.value
const asset1_currency = asset1CurrencyField.value
const asset1_issuer = asset1IssuerField.value
const asset1_amount = asset1AmountField.value
const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
const asset2_amount = asset2AmountField.value
const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
const asset2_amount = asset2AmountField.value
```
Format the `AMMCreate` transaction based on the combination of `XRP` and tokens.
```javascript
let ammCreate = null
results += '\n\nCreating AMM ...'
standbyResultField.value = results
// AMMCreate requires burning one owner reserve. We can look up that amount
// (in drops) on the current network using server_state:
const ss = await client.request({"command": "server_state"})
const amm_fee_drops = ss.result.state.validated_ledger.reserve_inc.toString()
let ammCreate = null
if (asset1_currency == 'XRP') {
results += '\n\nCreating AMM ...'
standbyResultField.value = results
ammCreate = {
"TransactionType": "AMMCreate",
"Account": standby_wallet.address,
"Amount": JSON.stringify(asset1_amount * 1000000), // convert XRP to drops
"Amount2": {
"currency": asset2_currency,
"issuer": asset2_issuer,
"value": asset2_amount
},
"TradingFee": 500, // 500 = 0.5%
"Fee": amm_fee_drops
}
// AMMCreate requires burning one owner reserve. We can look up that amount
// (in drops) on the current network using server_state:
const ss = await client.request({ command: 'server_state' })
const amm_fee_drops = ss.result.state.validated_ledger.reserve_inc.toString()
} else if (asset2_currency =='XRP') {
ammCreate = {
"TransactionType": "AMMCreate",
"Account": standby_wallet.address,
"Amount": {
"currency": asset1_currency,
"issuer": asset1_issuer,
"value": asset1_amount
},
"Amount2": JSON.stringify(asset2_amount * 1000000), // convert XRP to drops
"TradingFee": 500, // 500 = 0.5%
"Fee": amm_fee_drops
}
} else {
ammCreate = {
"TransactionType": "AMMCreate",
"Account": standby_wallet.address,
"Amount": {
"currency": asset1_currency,
"issuer": asset1_issuer,
"value": asset1_amount
},
"Amount2": {
"currency": asset2_currency,
"issuer": asset2_issuer,
"value": asset2_amount
},
"TradingFee": 500, // 500 = 0.5%
"Fee": amm_fee_drops
}
if (asset1_currency == 'XRP') {
ammCreate = {
TransactionType: 'AMMCreate',
Account: standby_wallet.address,
Amount: JSON.stringify(asset1_amount * 1000000), // convert XRP to drops
Amount2: {
currency: asset2_currency,
issuer: asset2_issuer,
value: asset2_amount,
},
TradingFee: 500, // 500 = 0.5%
Fee: amm_fee_drops,
}
} else if (asset2_currency == 'XRP') {
ammCreate = {
TransactionType: 'AMMCreate',
Account: standby_wallet.address,
Amount: {
currency: asset1_currency,
issuer: asset1_issuer,
value: asset1_amount,
},
Amount2: JSON.stringify(asset2_amount * 1000000), // convert XRP to drops
TradingFee: 500, // 500 = 0.5%
Fee: amm_fee_drops,
}
} else {
ammCreate = {
TransactionType: 'AMMCreate',
Account: standby_wallet.address,
Amount: {
currency: asset1_currency,
issuer: asset1_issuer,
value: asset1_amount,
},
Amount2: {
currency: asset2_currency,
issuer: asset2_issuer,
value: asset2_amount,
},
TradingFee: 500, // 500 = 0.5%
Fee: amm_fee_drops,
}
}
```
Prepare the transaction for submission. Wrap the submission in a `try-catch` block to handle any errors.
```javascript
try {
const prepared_create = await client.autofill(ammCreate)
results += `\n\nPrepared transaction:\n${JSON.stringify(prepared_create, null, 2)}`
standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight
standbyResultField.scrollTop = standbyResultField.scrollHeight
```
Sign the prepared transaction using the standy account wallet.
```javascript
const signed_create = standby_wallet.sign(prepared_create)
results += `\n\nSending AMMCreate transaction ...`
standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight
const signed_create = standby_wallet.sign(prepared_create)
results += `\n\nSending AMMCreate transaction ...`
standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight
```
Submit the signed transaction to the XRPL.
```javascript
const amm_create = await client.submitAndWait(signed_create.tx_blob)
if (amm_create.result.meta.TransactionResult == "tesSUCCESS") {
results += `\n\nTransaction succeeded.`
} else {
results += `\n\nError sending transaction: ${JSON.stringify(amm_create.result.meta.TransactionResult, null, 2)}`
}
} catch (error) {
results += `\n\n${error.message}`
}
@@ -256,13 +243,12 @@ Report the transaction results in the standby account log. Run the `checkAMM()`
standbyResultField.scrollTop = standbyResultField.scrollHeight
checkAMM()
client.disconnect()
}
```
### Check AMM
This checks if an AMM already exists. While multiple tokens can share the same currency code, each issuer makes them unique. If the AMM pair exists, this responds with the AMM information, such as token pair, trading fees, etc.
@@ -274,73 +260,67 @@ async function checkAMM() {
Connect to the XRP Ledger.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
```
Get the AMM info fields. When checking an AMM, you only need the currency code and issuer.
```javascript
// Gets the issuer and currency code
const asset1_currency = asset1CurrencyField.value
const asset1_issuer = asset1IssuerField.value
// Gets the issuer and currency code
const asset1_currency = asset1CurrencyField.value
const asset1_issuer = asset1IssuerField.value
const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
```
Format the `amm_info` command based on the combination of `XRP` and tokens.
```javascript
let amm_info_request = null
let amm_info_request = null
// Get AMM info transaction
// Get AMM info transaction
if (asset1_currency == 'XRP') {
amm_info_request = {
"command": "amm_info",
"asset": {
"currency": "XRP"
},
"asset2": {
"currency": asset2_currency,
"issuer": asset2_issuer
},
"ledger_index": "validated"
}
} else if (asset2_currency =='XRP') {
amm_info_request = {
"command": "amm_info",
"asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"asset2": {
"currency": "XRP"
},
"ledger_index": "validated"
}
} else {
amm_info_request = {
"command": "amm_info",
"asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"asset2": {
"currency": asset2_currency,
"issuer": asset2_issuer
},
"ledger_index": "validated"
}
if (asset1_currency == 'XRP') {
amm_info_request = {
command: 'amm_info',
asset: {
currency: 'XRP',
},
asset2: {
currency: asset2_currency,
issuer: asset2_issuer,
},
ledger_index: 'validated',
}
} else if (asset2_currency == 'XRP') {
amm_info_request = {
command: 'amm_info',
asset: {
currency: asset1_currency,
issuer: asset1_issuer,
},
asset2: {
currency: 'XRP',
},
ledger_index: 'validated',
}
} else {
amm_info_request = {
command: 'amm_info',
asset: {
currency: asset1_currency,
issuer: asset1_issuer,
},
asset2: {
currency: asset2_currency,
issuer: asset2_issuer,
},
ledger_index: 'validated',
}
}
```
Submit the request in a `try-catch` block and update the AMM log.
@@ -352,10 +332,10 @@ Submit the request in a `try-catch` block and update the AMM log.
} catch(error) {
ammInfo = `AMM Info:\n\n${error}`
}
ammInfoField.value = ammInfo
client.disconnect()
}
```

View File

@@ -4,9 +4,9 @@ top_nav_grouping: Article Types
metadata:
indexPage: true
---
# AMMs Using JavaScript
Create and interact with Automated Market Makers (AMMs) on the XRP Ledger using JavaScript.
{% child-pages /%}

View File

@@ -17,7 +17,6 @@ You can download the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-port
Without the Quickstart Samples, you will not be able to try the examples that follow.
{% /admonition %}
## Usage
### Get Accounts
@@ -34,7 +33,6 @@ Without the Quickstart Samples, you will not be able to try the examples that fo
[![Get account results](/docs/img/quickstart-trade-auction-slot2.png)](/docs/img/quickstart-trade-auction-slot2.png)
### Get the AMM
Use the information from either the XRP/Token or Token/Token AMM you created in [Create an AMM](/docs/tutorials/javascript/amm/create-an-amm/#create-an-xrp/token-amm).
@@ -46,7 +44,6 @@ Use the information from either the XRP/Token or Token/Token AMM you created in
[![Get AMM results](/docs/img/quickstart-trade-auction-slot3.png)](/docs/img/quickstart-trade-auction-slot3.png)
### Estimate Costs
Get a new standby account to ensure you aren't using an account with an auction slot already.
@@ -62,7 +59,6 @@ Get a new standby account to ensure you aren't using an account with an auction
[![Estimate costs results](/docs/img/quickstart-trade-auction-slot4.png)](/docs/img/quickstart-trade-auction-slot4.png)
### Bid for the Auction Slot
Make a single-asset deposit to the AMM to receive the required LP tokens for the auction slot bid. You can deposit either asset from the cost estimator.
@@ -74,7 +70,6 @@ Make a single-asset deposit to the AMM to receive the required LP tokens for the
[![Bid auction slot results](/docs/img/quickstart-trade-auction-slot5.png)](/docs/img/quickstart-trade-auction-slot5.png)
### Swap Tokens with the AMM
Get a new estimate to update the expected cost for swapping tokens.
@@ -85,12 +80,10 @@ Get a new estimate to update the expected cost for swapping tokens.
[![Swap tokens with AMM results](/docs/img/quickstart-trade-auction-slot6.png)](/docs/img/quickstart-trade-auction-slot6.png)
## Code Walkthrough (ripplex13a-trade-with-auction-slot.js)
You can open `ripplex13a-trade-with-auction-slot.js` from the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/js/) to view the source code.
### Estimate AMM Costs
This function checks the cost of interactions with the AMM, such as deposits, auction slot bids, and token swaps.
@@ -102,15 +95,15 @@ async function estimateCost() {
Connect to the XRP Ledger.
```javascript
let net = getNet()
let net = getNet()
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
```
Format the `amm_info` command and get the AMM information. This code is wrapped in a `try-catch` block to handle any errors.
@@ -153,7 +146,7 @@ Format the `amm_info` command and get the AMM information. This code is wrapped
}
const amm_info = (await client.request({
"command": "amm_info",
"command": "amm_info",
"asset": asset1_info,
"asset2": asset2_info
}))
@@ -174,70 +167,70 @@ Format the `amm_info` command and get the AMM information. This code is wrapped
Save the taker pays and taker gets fields; use these values to get the total amount of each asset in the AMM pool, using large significant digits for precise calculations. This also checks if the requested token amount is larger than what is available in the AMM pool, stopping the code if `true`.
```javascript
// Save taker pays and gets values.
const takerPays = {
"currency": standbyTakerPaysCurrencyField.value,
"issuer": standbyTakerPaysIssuerField.value,
"amount": standbyTakerPaysAmountField.value
}
// Save taker pays and gets values.
const takerGets = {
"currency": standbyTakerGetsCurrencyField.value,
"issuer": standbyTakerGetsIssuerField.value,
"amount": standbyTakerGetsAmountField.value
}
const takerPays = {
currency: standbyTakerPaysCurrencyField.value,
issuer: standbyTakerPaysIssuerField.value,
amount: standbyTakerPaysAmountField.value,
}
// Get amount of assets in the pool.
// Convert values to BigNumbers with the appropriate precision.
// Tokens always have 15 significant digits;
// XRP is precise to integer drops, which can be as high as 10^17
const takerGets = {
currency: standbyTakerGetsCurrencyField.value,
issuer: standbyTakerGetsIssuerField.value,
amount: standbyTakerGetsAmountField.value,
}
let asset_out_bn = null
let pool_in_bn = null
let pool_out_bn = null
let isAmmAsset1Xrp = false
let isAmmAsset2Xrp = false
// Get amount of assets in the pool.
// Convert values to BigNumbers with the appropriate precision.
// Tokens always have 15 significant digits;
// XRP is precise to integer drops, which can be as high as 10^17
if ( takerPays.currency == 'XRP' ) {
asset_out_bn = BigNumber(xrpl.xrpToDrops(takerPays.amount)).precision(17)
} else {
asset_out_bn = BigNumber(takerPays.amount).precision(15)
}
let asset_out_bn = null
let pool_in_bn = null
let pool_out_bn = null
let isAmmAsset1Xrp = false
let isAmmAsset2Xrp = false
if ( takerGets.currency == 'XRP' && asset1_currency == 'XRP' ) {
pool_in_bn = BigNumber(pool_asset1).precision(17)
isAmmAsset1Xrp = true
} else if ( takerGets.currency == 'XRP' && asset2_currency == 'XRP' ) {
pool_in_bn = BigNumber(pool_asset2).precision(17)
isAmmAsset2Xrp = true
} else if ( takerGets.currency == asset1_currency ) {
pool_in_bn = BigNumber(pool_asset1.value).precision(15)
} else {
pool_in_bn = BigNumber(pool_asset2.value).precision(15)
}
if (takerPays.currency == 'XRP') {
asset_out_bn = BigNumber(xrpl.xrpToDrops(takerPays.amount)).precision(17)
} else {
asset_out_bn = BigNumber(takerPays.amount).precision(15)
}
if (takerPays.currency == 'XRP' && asset1_currency == 'XRP' ) {
pool_out_bn = BigNumber(pool_asset1).precision(17)
} else if ( takerPays.currency == 'XRP' && asset2_currency == 'XRP' ) {
pool_out_bn = BigNumber(pool_asset2).precision(17)
} else if ( takerPays.currency == asset1_currency ) {
pool_out_bn = BigNumber(pool_asset1.value).precision(15)
} else {
pool_out_bn = BigNumber(pool_asset2.value).precision(15)
}
if (takerGets.currency == 'XRP' && asset1_currency == 'XRP') {
pool_in_bn = BigNumber(pool_asset1).precision(17)
isAmmAsset1Xrp = true
} else if (takerGets.currency == 'XRP' && asset2_currency == 'XRP') {
pool_in_bn = BigNumber(pool_asset2).precision(17)
isAmmAsset2Xrp = true
} else if (takerGets.currency == asset1_currency) {
pool_in_bn = BigNumber(pool_asset1.value).precision(15)
} else {
pool_in_bn = BigNumber(pool_asset2.value).precision(15)
}
if ( takerPays.currency == 'XRP' && parseFloat(takerPays.amount) > parseFloat(xrpl.dropsToXrp(pool_out_bn)) ) {
results += `\n\nRequested ${takerPays.amount} ${takerPays.currency}, but AMM only holds ${xrpl.dropsToXrp(pool_out_bn)}. Quitting.`
standbyResultField.value = results
client.disconnect()
return
} else if ( parseFloat(takerPays.amount) > parseFloat(pool_out_bn) ) {
results += `\n\nRequested ${takerPays.amount} ${takerPays.currency}, but AMM only holds ${pool_out_bn}. Quitting.`
standbyResultField.value = results
client.disconnect()
return
}
if (takerPays.currency == 'XRP' && asset1_currency == 'XRP') {
pool_out_bn = BigNumber(pool_asset1).precision(17)
} else if (takerPays.currency == 'XRP' && asset2_currency == 'XRP') {
pool_out_bn = BigNumber(pool_asset2).precision(17)
} else if (takerPays.currency == asset1_currency) {
pool_out_bn = BigNumber(pool_asset1.value).precision(15)
} else {
pool_out_bn = BigNumber(pool_asset2.value).precision(15)
}
if (takerPays.currency == 'XRP' && parseFloat(takerPays.amount) > parseFloat(xrpl.dropsToXrp(pool_out_bn))) {
results += `\n\nRequested ${takerPays.amount} ${takerPays.currency}, but AMM only holds ${xrpl.dropsToXrp(pool_out_bn)}. Quitting.`
standbyResultField.value = results
client.disconnect()
return
} else if (parseFloat(takerPays.amount) > parseFloat(pool_out_bn)) {
results += `\n\nRequested ${takerPays.amount} ${takerPays.currency}, but AMM only holds ${pool_out_bn}. Quitting.`
standbyResultField.value = results
client.disconnect()
return
}
```
Implement [AMM formulas](https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/misc/detail/AMMHelpers.cpp) to estimate values for:
@@ -266,7 +259,7 @@ Implement [AMM formulas](https://github.com/XRPLF/rippled/blob/master/src/xrpld/
// Use SwapOut to calculate discounted swap amount with auction slot
const raw_discounted = swapOut(asset_out_bn, pool_in_bn, pool_out_bn, discounted_fee)
const discounted_swap_amount = raw_discounted.dp(0, BigNumber.ROUND_CEIL)
const discounted_swap_amount = raw_discounted.dp(0, BigNumber.ROUND_CEIL)
results += `\n\nExpected cost with auction slot for ${takerPays.amount} ${takerPays.currency}: ${convert(takerGets.currency, discounted_swap_amount)} ${takerGets.currency}`
// Calculate savings by using auction slot
@@ -316,7 +309,6 @@ Report the estimated values and close the client connection.
}
```
### Bid on the Auction Slot
This function bids on the AMM auction slot, using LP tokens.
@@ -328,15 +320,15 @@ async function bidAuction() {
Connect to the ledger.
```javascript
let net = getNet()
let net = getNet()
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
```
Format the asset values, depending on if it's `XRP` or a token. Wrap the code in a `try-catch` block to handle any errors.
@@ -381,7 +373,7 @@ Format the asset values, depending on if it's `XRP` or a token. Wrap the code in
}
const amm_info = (await client.request({
"command": "amm_info",
"command": "amm_info",
"asset": asset1_info,
"asset2": asset2_info
}))
@@ -413,13 +405,13 @@ Submit the `AMMBid` transaction.
"value": valueLPT
} // So rounding doesn't leave dust amounts of LPT
}, {autofill: true, wallet: standby_wallet})
if (bid_result.result.meta.TransactionResult == "tesSUCCESS") {
results += `\n\nTransaction succeeded.`
checkAMM()
} else {
results += `\n\nError sending transaction: ${JSON.stringify(bid_result.result.meta.TransactionResult, null, 2)}`
}
}
} catch (error) {
results += `\n\n${error.message}`
}
@@ -435,7 +427,6 @@ Report the results.
}
```
### Swap AMM Tokens
This function submits an `OfferCreate` transaction, using precise values to format the transaction and have the AMM completely consume the offer.
@@ -447,15 +438,15 @@ async function swapTokens() {
Connect to the XRP Ledger.
```javascript
let net = getNet()
let net = getNet()
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
```
Get the taker pays and taker gets fields and format the amounts depending on if it's `XRP` or a custom token. Wrap the code in a `try-catch` block to handle any errors.
@@ -509,13 +500,13 @@ Submit the `OfferCreate` transaction.
"TakerPays": takerPays,
"TakerGets": takerGets
}, {autofill: true, wallet: standby_wallet})
if (offer_result.result.meta.TransactionResult == "tesSUCCESS") {
results += `\n\nTransaction succeeded.`
checkAMM()
} else {
results += `\n\nError sending transaction: ${JSON.stringify(offer_result.result.meta.TransactionResult, null, 2)}`
}
}
} catch (error) {
results += `\n\n${error.message}`
}
@@ -531,35 +522,30 @@ Report the results.
}
```
## Code Walkthrough (ripplex13b-amm-formulas.js)
## Code Walkthrough (ripplex13b-amm-formulas.js)
You can open `ripplex13b-amm-formulas.js` from the [Quickstart Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/quickstart/js/) to view the source code. This code implements several core [AMM formulas](https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/misc/detail/AMMHelpers.cpp) defined by the protocol.
### swapOut()
The `swapOut()` function calculates how much of an asset you must deposit into an AMM to receive a specified amount of the paired asset. The input asset is what you're adding to the pool (paying), and the output asset is what you're receiving from the pool (buying).
The formula used is based on [AMM Swap](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0030-automated-market-maker#25-amm-swap), defined in XLS-30.
| Parameter | Type | Description |
|-----------|------|-------------|
| asset_out_bn | BigNumber | The target amount to receive from the AMM. |
| pool_in_bn | BigNumber | The amount of the input asset in the AMM's pool before the swap. |
| pool_out_bn | BigNumber | The amount of the output asset in the AMM's pool before the swap. |
| trading_fee | int | The trading fee as an integer {0, 1000} where 1000 represents a 1% fee. |
| Parameter | Type | Description |
| ------------ | --------- | ----------------------------------------------------------------------- |
| asset_out_bn | BigNumber | The target amount to receive from the AMM. |
| pool_in_bn | BigNumber | The amount of the input asset in the AMM's pool before the swap. |
| pool_out_bn | BigNumber | The amount of the output asset in the AMM's pool before the swap. |
| trading_fee | int | The trading fee as an integer {0, 1000} where 1000 represents a 1% fee. |
| Returns | Type | Description |
|---------|------|-------------|
| Returns | Type | Description |
| ------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Return Value | BigNumber | The amount of the input asset that must be swapped in to receive the target output amount. Unrounded, because the number of decimals depends on if this is drops of XRP or a decimal amount of a token; since this is a theoretical input to the pool, it should be rounded up (ceiling) to preserve the pool's constant product. |
```javascript
function swapOut(asset_out_bn, pool_in_bn, pool_out_bn, trading_fee) {
return ( ( pool_in_bn.multipliedBy(pool_out_bn) ).dividedBy(
pool_out_bn.minus(asset_out_bn)
).minus(pool_in_bn)
).dividedBy(feeMult(trading_fee))
return pool_in_bn.multipliedBy(pool_out_bn).dividedBy(pool_out_bn.minus(asset_out_bn)).minus(pool_in_bn).dividedBy(feeMult(trading_fee))
}
```
@@ -571,28 +557,25 @@ The formula used is based on the [slot pricing algorithm](https://github.com/XRP
```javascript
function auctionDeposit(old_bid, time_interval, trading_fee, lpt_balance) {
const tfee_decimal = feeDecimal(trading_fee)
const lptokens = BigNumber(lpt_balance)
const b = BigNumber(old_bid)
let outbidAmount = BigNumber(0) // This is the case if time_interval >= 20
if (time_interval == 0) {
outbidAmount = b.multipliedBy("1.05")
} else if (time_interval <= 19) {
const t60 = BigNumber(time_interval).multipliedBy("0.05").exponentiatedBy(60)
outbidAmount = b.multipliedBy("1.05").multipliedBy(BigNumber(1).minus(t60))
}
const tfee_decimal = feeDecimal(trading_fee)
const lptokens = BigNumber(lpt_balance)
const b = BigNumber(old_bid)
let outbidAmount = BigNumber(0) // This is the case if time_interval >= 20
if (time_interval == 0) {
outbidAmount = b.multipliedBy('1.05')
} else if (time_interval <= 19) {
const t60 = BigNumber(time_interval).multipliedBy('0.05').exponentiatedBy(60)
outbidAmount = b.multipliedBy('1.05').multipliedBy(BigNumber(1).minus(t60))
}
const new_bid = lptokens.plus(outbidAmount).dividedBy(
BigNumber(25).dividedBy(tfee_decimal).minus(1)
).plus(outbidAmount)
// Significant digits for the deposit are limited by total LPTokens issued
// so we calculate lptokens + deposit - lptokens to determine where the
// rounding occurs. We use ceiling/floor to make sure the amount we receive
// after rounding is still enough to win the auction slot.
const rounded_bid = new_bid.plus(lptokens).precision(15, BigNumber.CEILING
).minus(lptokens).precision(15, BigNumber.FLOOR)
return rounded_bid
const new_bid = lptokens.plus(outbidAmount).dividedBy(BigNumber(25).dividedBy(tfee_decimal).minus(1)).plus(outbidAmount)
// Significant digits for the deposit are limited by total LPTokens issued
// so we calculate lptokens + deposit - lptokens to determine where the
// rounding occurs. We use ceiling/floor to make sure the amount we receive
// after rounding is still enough to win the auction slot.
const rounded_bid = new_bid.plus(lptokens).precision(15, BigNumber.CEILING).minus(lptokens).precision(15, BigNumber.FLOOR)
return rounded_bid
}
```
@@ -600,41 +583,37 @@ function auctionDeposit(old_bid, time_interval, trading_fee, lpt_balance) {
The `ammAssetIn()` function calculates how much to add in a single-asset deposit to receive a specified amount of LP tokens.
| Parameter | Type | Description |
|-----------|------|-------------|
| pool_in | string | The quantity of the input asset the pool already has. |
| lpt_balance | string | The quantity of LP tokens already issued by the AMM. |
| desired_lpt | string | The quantity of new LP tokens you want to receive. |
| trading_fee | int | The trading fee as an integer {0, 1000} where 1000 represents a 1% fee. |
| Parameter | Type | Description |
| ----------- | ------ | ----------------------------------------------------------------------- |
| pool_in | string | The quantity of the input asset the pool already has. |
| lpt_balance | string | The quantity of LP tokens already issued by the AMM. |
| desired_lpt | string | The quantity of new LP tokens you want to receive. |
| trading_fee | int | The trading fee as an integer {0, 1000} where 1000 represents a 1% fee. |
```javascript
function ammAssetIn(pool_in, lpt_balance, desired_lpt, trading_fee) {
// convert inputs to BigNumber
const lpTokens = BigNumber(desired_lpt)
const lptAMMBalance = BigNumber(lpt_balance)
const asset1Balance = BigNumber(pool_in)
// convert inputs to BigNumber
const lpTokens = BigNumber(desired_lpt)
const lptAMMBalance = BigNumber(lpt_balance)
const asset1Balance = BigNumber(pool_in)
const f1 = feeMult(trading_fee)
const f2 = feeMultHalf(trading_fee).dividedBy(f1)
const t1 = lpTokens.dividedBy(lptAMMBalance)
const t2 = t1.plus(1)
const d = f2.minus( t1.dividedBy(t2) )
const a = BigNumber(1).dividedBy( t2.multipliedBy(t2))
const b = BigNumber(2).multipliedBy(d).dividedBy(t2).minus(
BigNumber(1).dividedBy(f1)
)
const c = d.multipliedBy(d).minus( f2.multipliedBy(f2) )
return asset1Balance.multipliedBy(solveQuadraticEq(a,b,c))
const f1 = feeMult(trading_fee)
const f2 = feeMultHalf(trading_fee).dividedBy(f1)
const t1 = lpTokens.dividedBy(lptAMMBalance)
const t2 = t1.plus(1)
const d = f2.minus(t1.dividedBy(t2))
const a = BigNumber(1).dividedBy(t2.multipliedBy(t2))
const b = BigNumber(2).multipliedBy(d).dividedBy(t2).minus(BigNumber(1).dividedBy(f1))
const c = d.multipliedBy(d).minus(f2.multipliedBy(f2))
return asset1Balance.multipliedBy(solveQuadraticEq(a, b, c))
}
```
Compute the quadratic formula. This is a helper function for `ammAssetIn()`. Parameters and return value are `BigNumber` instances.
```javascript
function solveQuadraticEq(a,b,c) {
const b2minus4ac = b.multipliedBy(b).minus(
a.multipliedBy(c).multipliedBy(4)
)
return ( b.negated().plus(b2minus4ac.sqrt()) ).dividedBy(a.multipliedBy(2))
function solveQuadraticEq(a, b, c) {
const b2minus4ac = b.multipliedBy(b).minus(a.multipliedBy(c).multipliedBy(4))
return b.negated().plus(b2minus4ac.sqrt()).dividedBy(a.multipliedBy(2))
}
```

View File

@@ -5,9 +5,11 @@ targets:
- en
- ja # TODO: translate this page
seo:
description: Build a graphical browser wallet for the XRPL using Javascript.
description: Build a graphical browser wallet for the XRPL using Javascript.
---
# Build a Browser Wallet in JavaScript
<!-- STYLE_OVERRIDE: wallet -->
This tutorial demonstrates how to build a browser wallet for the XRP Ledger using the Javascript programming language and various libraries. This application can be used as a starting point for building a more complete and powerful application, as a reference point for building comparable apps, or as a learning experience to better understand how to integrate XRP Ledger functionality into a larger project.
@@ -36,10 +38,10 @@ This application can:
- View any XRP Ledger account's activity, including showing how much XRP was delivered by each transaction.
- Show how much XRP is set aside for the account's [reserve requirement](../../../concepts/accounts/reserves.md).
- Send [direct XRP payments](../../../concepts/payment-types/direct-xrp-payments.md), and provide feedback about the intended destination address, including:
- Displaying your account's available balance
- Verifying that the destination address is valid
- Validating the account has enough XRP to send
- Allowing you to specify a destination tag
- Displaying your account's available balance
- Verifying that the destination address is valid
- Validating the account has enough XRP to send
- Allowing you to specify a destination tag
## Steps
@@ -60,7 +62,7 @@ yarn create vite simple-xrpl-wallet --template vanilla
{% code-snippet file="/_code-samples/build-a-browser-wallet/js/package.json" language="js" /%}
- Alternatively you can also do `yarn add <package-name>` for each individual package to add them to your `package.json` file.
- Alternatively you can also do `yarn add <package-name>` for each individual package to add them to your `package.json` file.
4. Install dependencies:
@@ -172,12 +174,12 @@ Destination Tag: (Not usually necessary unless you're paying an account tied to
Now that we have created the home page and the send XRP page, let's create the transactions page that will display the transaction history of the account. In order to see what's happening on the ledger, we're going to display the following fields:
- Account: The account that sent the transaction.
- Destination: The account that received the transaction.
- Transaction Type: The type of transaction.
- Result: The result of the transaction.
- Delivered amount: The amount of XRP or tokens delivered by the transaction, if applicable.
- Link: A link to the transaction on the XRP Ledger Explorer.
- Account: The account that sent the transaction.
- Destination: The account that received the transaction.
- Transaction Type: The type of transaction.
- Result: The result of the transaction.
- Delivered amount: The amount of XRP or tokens delivered by the transaction, if applicable.
- Link: A link to the transaction on the XRP Ledger Explorer.
{% admonition type="warning" name="Caution" %}When displaying how much money a transaction delivered, always use the `delivered_amount` field from the metadata, not the `Amount` field from the transaction instructions. [Partial Payments](../../../concepts/payment-types/partial-payments.md) can deliver much less than the stated `Amount` and still be successful.{% /admonition %}

View File

@@ -1,6 +1,6 @@
---
seo:
description: Build a credential issuing microservice with Javascript and Node.js.
description: Build a credential issuing microservice with Javascript and Node.js.
---
# Build a Credential Issuing Service
@@ -9,7 +9,6 @@ _(Requires the Credentials amendment. {% not-enabled /%})_
This tutorial demonstrates how to build and use a microservice that issues [Credentials](../../../concepts/decentralized-storage/credentials.md) on the XRP Ledger, in the form of a RESTlike API, using the [Express](https://expressjs.com/) framework for Node.js.
## Prerequisites
To complete this tutorial, you should meet the following guidelines:
@@ -18,7 +17,6 @@ To complete this tutorial, you should meet the following guidelines:
- You are somewhat familiar with modern JavaScript programming and have completed the [Get Started Using JavaScript tutorial](./get-started.md).
- You have some understanding of the XRP Ledger, its capabilities, and of cryptocurrency in general. Ideally you have completed the [Basic XRPL guide](https://learn.xrpl.org/).
## Setup
First, download the complete sample code for this tutorial from GitHub:
@@ -35,16 +33,15 @@ This should install appropriate versions of Express, xrpl.js and a few other dep
To use the API that this microservice provides, you also need an HTTP client such as [Postman](https://www.postman.com/downloads/), [RESTED](https://github.com/RESTEDClient/RESTED), or [cURL](https://curl.se/).
## Overview
The Credential Issuer microservice, mostly implemented in `issuer_service.js`, provides a RESTlike API with the following methods:
| Method | Description |
|---|----|
| `POST /credential` | Request that the issuer issue a specific credential to a specific account. |
| `GET /admin/credential` | List all credentials issued by the issuer's address, optionally filtering only for credentials that have or have not been accepted by their subject. |
| `DELETE /admin/credential` | Delete a specific credential from the XRP Ledger, which revokes it. |
| Method | Description |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /credential` | Request that the issuer issue a specific credential to a specific account. |
| `GET /admin/credential` | List all credentials issued by the issuer's address, optionally filtering only for credentials that have or have not been accepted by their subject. |
| `DELETE /admin/credential` | Delete a specific credential from the XRP Ledger, which revokes it. |
{% admonition type="info" name="Note" %}Some of the methods have `/admin` in the path because they are intended to be used by the microservice's administrator. However, the sample code does not implement any authentication.{% /admonition %}
@@ -52,7 +49,6 @@ The sample code also contains a simple commmandline interface for a user account
The other files contain helper code that is used by one or both tools.
## Usage
### 1. Get Accounts
@@ -86,12 +82,13 @@ To request a credential, make a request such as the following:
{% tabs %}
{% tab label="Summary" %}
* HTTP method: `POST`
* URL: `http://localhost:3005/credential`
* Headers:
* `Content-Type: application/json`
* Request Body:
```json
- HTTP method: `POST`
- URL: `http://localhost:3005/credential`
- Headers:
- `Content-Type: application/json`
- Request Body:
`json
{
"subject": "rBqPPjAW6ubfFdmwERgajvgP5LtM4iQSQG",
"credential": "TestCredential",
@@ -99,26 +96,28 @@ To request a credential, make a request such as the following:
"reason": "please"
}
}
```
{% /tab %}
`
{% /tab %}
{% tab label="cURL" %}
```sh
curl -H "Content-Type: application/json" -X POST -d '{"subject": "rBqPPjAW6ubfFdmwERgajvgP5LtM4iQSQG", "credential": "TestCredential", "documents": {"reason": "please"}}' http://localhost:3005/credential
```
{% /tab %}
{% /tabs %}
The parameters of the JSON request body should be as follows:
| Field | Type | Required? | Description |
|---|---|---|---|
| `subject` | String - Address | Yes | The XRPL classic address of the subject of the credential. Set this to the address that you generated at the start of this tutorial for the credential holder account. |
| `credential` | String | Yes | The type of credential to issue. The example microservice accepts any string consisting of alphanumeric characters as well as the special characters underscore (`_`), dash (`-`), and period (`.`), with a minimum length of 1 and a maximum length of 64 characters. |
| `documents` | Object | Yes | As a credential issuer, you typically need to verify some confidential information about someone before you issue them a credential. As a placeholder, the sample code checks for a nested field named `reason` that contains the string `please`. |
| `expiration` | String - ISO8601 Datetime | No | The time after which the credential expires, such as `2025-12-31T00:00:00Z`. |
| `uri` | String | No | Optional URI data to store with the credential. This data will become public on the XRP Ledger. If provided, this must be a string with minimum length 1 and max length 256, consisting of only characters that are valid in URIs, which are numbers, letters, and the following special characters: `-._~:/?#[]@!$&'()*+,;=%`. Conventionally, it should link to a Verifiable Credential document as defined by the W3C. |
| Field | Type | Required? | Description |
| ------------ | ------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `subject` | String - Address | Yes | The XRPL classic address of the subject of the credential. Set this to the address that you generated at the start of this tutorial for the credential holder account. |
| `credential` | String | Yes | The type of credential to issue. The example microservice accepts any string consisting of alphanumeric characters as well as the special characters underscore (`_`), dash (`-`), and period (`.`), with a minimum length of 1 and a maximum length of 64 characters. |
| `documents` | Object | Yes | As a credential issuer, you typically need to verify some confidential information about someone before you issue them a credential. As a placeholder, the sample code checks for a nested field named `reason` that contains the string `please`. |
| `expiration` | String - ISO8601 Datetime | No | The time after which the credential expires, such as `2025-12-31T00:00:00Z`. |
| `uri` | String | No | Optional URI data to store with the credential. This data will become public on the XRP Ledger. If provided, this must be a string with minimum length 1 and max length 256, consisting of only characters that are valid in URIs, which are numbers, letters, and the following special characters: `-._~:/?#[]@!$&'()*+,;=%`. Conventionally, it should link to a Verifiable Credential document as defined by the W3C. |
This microservice immediately issues any credential that the user requests. A successful response from the API uses the HTTP status code `201 Created` and has a response body with the result of submitting the transaction to the XRP Ledger. You can use the `hash` value from the response to look up the transaction using an explorer such as [https://devnet.xrpl.org/](https://devnet.xrpl.org/).
@@ -131,15 +130,18 @@ To show a list of credentials issued by the issuing account, make the following
{% tabs %}
{% tab label="Summary" %}
* HTTP method: `GET`
* URL: `http://localhost:3005/admin/credential`
* Query parameters (optional): Use `?accepted=yes` to filter results to only credentials that the subject has accepted, or `?accepted=no` for credentials the user has not accepted.
{% /tab %}
- HTTP method: `GET`
- URL: `http://localhost:3005/admin/credential`
- Query parameters (optional): Use `?accepted=yes` to filter results to only credentials that the subject has accepted, or `?accepted=no` for credentials the user has not accepted.
{% /tab %}
{% tab label="cURL" %}
```sh
curl http://localhost:3005/admin/credential
```
{% /tab %}
{% /tabs %}
@@ -148,7 +150,7 @@ A response could look like the following:
```json
{
"credentials": [
"credentials": [
{
"subject": "rBqPPjAW6ubfFdmwERgajvgP5LtM4iQSQG",
"credential": "TstCredential",
@@ -191,33 +193,36 @@ To revoke an issued credential, make a request such as the following:
{% tabs %}
{% tab label="Summary" %}
* HTTP method: `DELETE`
* URL: `http://localhost:3005/admin/credential`
* Headers:
* `Content-Type: application/json`
* Request Body:
```json
- HTTP method: `DELETE`
- URL: `http://localhost:3005/admin/credential`
- Headers:
- `Content-Type: application/json`
- Request Body:
`json
{
"subject": "rBqPPjAW6ubfFdmwERgajvgP5LtM4iQSQG",
"credential": "TestCredential"
}
```
{% /tab %}
`
{% /tab %}
{% tab label="cURL" %}
```sh
curl -H "Content-Type: application/json" -X DELETE -d '{"subject": "rBqPPjAW6ubfFdmwERgajvgP5LtM4iQSQG", "credential": "TestCredential"}' http://localhost:3005/admin/credential
```
{% /tab %}
{% /tabs %}
The parameters of the JSON request body should be as follows:
| Field | Type | Required? | Description |
|---|---|---|---|
| `subject` | String - Address | Yes | The XRPL classic address of the subject of the credential to revoke. |
| `credential` | String | Yes | The type of credential to revoke. This must match a credential type previously issued. |
| Field | Type | Required? | Description |
| ------------ | ---------------- | --------- | -------------------------------------------------------------------------------------- |
| `subject` | String - Address | Yes | The XRPL classic address of the subject of the credential to revoke. |
| `credential` | String | Yes | The type of credential to revoke. This must match a credential type previously issued. |
A successful response from the API uses the HTTP status code `200 OK` and has a response body with the result of submitting the transaction to the XRP Ledger. You can use the `hash` value from the response to look up the transaction using an explorer.
@@ -225,17 +230,17 @@ A successful response from the API uses the HTTP status code `200 OK` and has a
The code for this tutorial is divided among the following files:
| File | Purpose |
|---|---|
| `accept_credential.js` | Commandline interface for a credential subject to look up and accept Credentials. |
| `credential.js` | Provides functions that validate credential input, verify supporting documents, and convert between the microservices simplified Credential format and the full XRPL representation of Credentials. |
| `errors.js` | Custom error classes that standardize how the server reports validation errors and XRPL transaction failures. |
| `issuer_service.js` | Defines the microservice as an Express app, including API methods and error handling. |
| `look_up_credentials.js` | A helper function for looking up Credentials tied to an account, including pagination and filtering, used by both the credential issuer and holder. |
| File | Purpose |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accept_credential.js` | Commandline interface for a credential subject to look up and accept Credentials. |
| `credential.js` | Provides functions that validate credential input, verify supporting documents, and convert between the microservices simplified Credential format and the full XRPL representation of Credentials. |
| `errors.js` | Custom error classes that standardize how the server reports validation errors and XRPL transaction failures. |
| `issuer_service.js` | Defines the microservice as an Express app, including API methods and error handling. |
| `look_up_credentials.js` | A helper function for looking up Credentials tied to an account, including pagination and filtering, used by both the credential issuer and holder. |
### accept_credential.js
This file is meant to be run as a commandline tool so it starts with a [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)), followed by dependencies grouped by type: external packages (Node.js modules) first, and local modules last.
This file is meant to be run as a commandline tool so it starts with a [shebang](<https://en.wikipedia.org/wiki/Shebang_(Unix)>), followed by dependencies grouped by type: external packages (Node.js modules) first, and local modules last.
{% code-snippet file="/_code-samples/issue-credentials/js/accept_credential.js" language="js" before="const XRPL_SERVER =" /%}
@@ -321,7 +326,7 @@ The file starts with importing dependencies, grouped into external packages and
{% code-snippet file="/_code-samples/issue-credentials/js/credential.js" before="// Regex constants" language="js" /%}
It then defines regular expression constants that are used further on in the code to validate the credential and uri:
It then defines regular expression constants that are used further on in the code to validate the credential and uri:
{% code-snippet file="/_code-samples/issue-credentials/js/credential.js" from="// Regex constants" before="/**" language="js" /%}

View File

@@ -1,6 +1,6 @@
---
seo:
description: Build an entry-level JavaScript application for querying the XRP Ledger.
description: Build an entry-level JavaScript application for querying the XRP Ledger.
top_nav_name: JavaScript
top_nav_grouping: Get Started
labels:
@@ -10,12 +10,12 @@ showcase_icon: assets/img/logos/javascript.svg
{% code-walkthrough
filesets=[
{
{
"files": ["/_code-samples/get-started/js/get-acct-info.js"],
"downloadAssociatedFiles": ["/_code-samples/get-started/js/package.json", "/_code-samples/get-started/js/get-acct-info.js", "/_code-samples/get-started/js/README.md"],
"when": { "environment": "Node" }
},
{
{
"files": ["/_code-samples/get-started/js/index.html"],
"downloadAssociatedFiles": ["/_code-samples/get-started/js/index.html", "/_code-samples/get-started/js/README.md"],
"when": { "environment": "Web" }
@@ -63,7 +63,9 @@ Click **Download** on the top right of the code preview panel to download the so
Follow the steps to create a simple application with `xrpl.js`.
<!-- Web steps -->
{% step id="import-web-tag" when={ "environment": "Web" } %}
### 1. Install Dependencies
To load `xrpl.js` into your project, add a `<script>` tag to your HTML.
@@ -74,7 +76,9 @@ This loads the module into the top level as `xrpl`.
{% /step %}
<!-- Node.js steps -->
{% step id="import-node-tag" when={ "environment": "Node" } %}
### 1. Install Dependencies
Start a new project by creating an empty folder, then move into that folder and use [NPM](https://www.npmjs.com/) to install the latest version of xrpl.js:
@@ -93,6 +97,7 @@ Your `package.json` file should look something like this:
### 2. Connect to the XRP Ledger
{% step id="connect-tag" %}
#### Connect to the XRP Ledger Testnet
To make queries and submit transactions, you need to connect to the XRP Ledger. To do this with `xrpl.js`, you create an instance of the [`Client`](https://js.xrpl.org/classes/Client.html) class and use the [`connect()`](https://js.xrpl.org/classes/Client.html#connect) method.
@@ -103,74 +108,84 @@ The sample code shows you how to connect to the Testnet, which is one of the ava
{% /step %}
{% step id="connect-mainnet-tag"%}
#### Connect to the XRP Ledger Mainnet
When you're ready to move to production, you'll need to connect to the XRP Ledger Mainnet. You can do that in two ways:
When you're ready to move to production, you'll need to connect to the XRP Ledger Mainnet. You can do that in two ways:
- By [installing the core server](../../../infrastructure/installation/index.md) (`rippled`) and running a node yourself. The core server connects to the Mainnet by default, but you can [change the configuration to use Testnet or Devnet](../../../infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md). [There are good reasons to run your own core server](../../../concepts/networks-and-servers/index.md#reasons-to-run-your-own-server). If you run your own server, you can connect to it like so:
```javascript
const MY_SERVER = "ws://localhost:6006/"
const client = new xrpl.Client(MY_SERVER)
await client.connect()
```
```javascript
const MY_SERVER = 'ws://localhost:6006/'
const client = new xrpl.Client(MY_SERVER)
await client.connect()
```
See the example [core server config file](https://github.com/XRPLF/rippled/blob/c0a0b79d2d483b318ce1d82e526bd53df83a4a2c/cfg/rippled-example.cfg#L1562) for more information about default values.
See the example [core server config file](https://github.com/XRPLF/rippled/blob/c0a0b79d2d483b318ce1d82e526bd53df83a4a2c/cfg/rippled-example.cfg#L1562) for more information about default values.
- By using one of the available [public servers][]:
```javascript
const PUBLIC_SERVER = "wss://xrplcluster.com/"
const client = new xrpl.Client(PUBLIC_SERVER)
await client.connect()
```
{% /step %}
```javascript
const PUBLIC_SERVER = "wss://xrplcluster.com/"
const client = new xrpl.Client(PUBLIC_SERVER)
await client.connect()
```
{% /step %}
### 3. Get Account
{% step id="get-account-create-wallet-tag" %}
#### Create and Fund a Wallet
The `xrpl.js` library has a [`Wallet`](https://js.xrpl.org/classes/Wallet.html) class for handling the keys and address of an XRP Ledger account. On Testnet, you can fund a new account as shown in the example.
{% /step %}
{% step id="get-account-create-wallet-b-tag" %}
#### (Optional) Generate a Wallet Only
If you want to generate a wallet without funding it, you can create a new [`Wallet`](https://js.xrpl.org/classes/Wallet.html) instance. Keep in mind that you need to send XRP to the wallet for it to be a valid account on the ledger.
{% /step %}
{% step id="get-account-create-wallet-c-tag" %}
#### (Optional) Use Your Own Wallet Seed
To use an existing wallet seed encoded in [base58][], you can create a [`Wallet`](https://js.xrpl.org/classes/Wallet.html) instance from it.
{% /step %}
{% step id="query-xrpl-tag" %}
### 4. Query the XRP Ledger
Use the Client's [`request()`](https://js.xrpl.org/classes/Client.html#request) method to access the XRP Ledger's [WebSocket API](../../../references/http-websocket-apis/api-conventions/request-formatting.md).
{% /step %}
{% step id="listen-for-events-tag" %}
### 5. Listen for Events
You can set up handlers for various types of events in `xrpl.js`, such as whenever the XRP Ledger's [consensus process](../../../concepts/consensus-protocol/index.md) produces a new [ledger version](../../../concepts/ledgers/index.md). To do that, first call the [subscribe method][] to get the type of events you want, then attach an event handler using the [`on(eventType, callback)`](https://js.xrpl.org/classes/Client.html#on) method of the client.
{% /step %}
{% step id="disconnect-node-tag" when={ "environment": "Node" } %}
### 6. Disconnect
Call the [`disconnect()`](https://js.xrpl.org/classes/Client.html#disconnect) function so Node.js can end the process. The example code waits 10 seconds before disconnecting to allow time for the ledger event listener to receive and display events.
{% /step %}
{% step id="disconnect-web-tag" when={ "environment": "Web" } %}
### 6. Disconnect
Call the [`disconnect()`](https://js.xrpl.org/classes/Client.html#disconnect) function to disconnect from the ledger when done. The example code waits 10 seconds before disconnecting to allow time for the ledger event listener to receive and display events.
{% /step %}
{% step id="run-app-node-tag" when={ "environment": "Node" } %}
### 7. Run the Application
Finally, in your terminal, run the application like so:
@@ -188,7 +203,7 @@ Creating a new wallet and funding it with Testnet XRP...
Wallet: rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i
Balance: 10
Account Testnet Explorer URL:
Account Testnet Explorer URL:
https://testnet.xrpl.org/accounts/rMnXR9p2sZT9iZ6ew3iEqvBMyPts1ADc4i
Getting account info...
@@ -237,9 +252,11 @@ Ledger #9949271 validated with 0 transactions!
Disconnected
```
{% /step %}
{% step id="run-app-web-tag" when={ "environment": "Web" } %}
### 7. Run the Application
Open the `index.html` file in a web browser.
@@ -299,23 +316,24 @@ Ledger #9949613 validated with 0 transactions
Disconnected
```
{% /step %}
## See Also
- **Concepts:**
- [XRP Ledger Overview](/about/)
- [Client Libraries](../../../references/client-libraries.md)
- [XRP Ledger Overview](/about/)
- [Client Libraries](../../../references/client-libraries.md)
- **Tutorials:**
- [Send XRP](../../how-tos/send-xrp.md)
- [Issue a Fungible Token](../../how-tos/use-tokens/issue-a-fungible-token.md)
- [Set up Secure Signing](../../../concepts/transactions/secure-signing.md)
- [Send XRP](../../how-tos/send-xrp.md)
- [Issue a Fungible Token](../../how-tos/use-tokens/issue-a-fungible-token.md)
- [Set up Secure Signing](../../../concepts/transactions/secure-signing.md)
- **References:**
- [`xrpl.js` Reference](https://js.xrpl.org/)
- [Public API Methods](../../../references/http-websocket-apis/public-api-methods/index.md)
- [API Conventions](../../../references/http-websocket-apis/api-conventions/index.md)
- [base58 Encodings](../../../references/protocol/data-types/base58-encodings.md)
- [Transaction Formats](../../../references/protocol/transactions/index.md)
- [`xrpl.js` Reference](https://js.xrpl.org/)
- [Public API Methods](../../../references/http-websocket-apis/public-api-methods/index.md)
- [API Conventions](../../../references/http-websocket-apis/api-conventions/index.md)
- [base58 Encodings](../../../references/protocol/data-types/base58-encodings.md)
- [Transaction Formats](../../../references/protocol/transactions/index.md)
{% raw-partial file="/docs/_snippets/common-links.md" /%}

View File

@@ -5,9 +5,9 @@ top_nav_grouping: Article Types
metadata:
indexPage: true
---
# Build Applications with JavaScript Library
Build full-featured applications in JavaScript.
{% child-pages /%}

View File

@@ -1,10 +1,11 @@
---
seo:
description: Create a permissioned domain to restrict access to financial services that meet compliance requirements.
description: Create a permissioned domain to restrict access to financial services that meet compliance requirements.
labels:
- Decentralized Finance
- Permissioned Domains
---
# Create Permissioned Domains
Permissioned domains are controlled environments within the broader ecosystem of the XRP Ledger blockchain. Domains restrict access to other features such as Permissioned DEXes and Lending Protocols, only allowing access to them for accounts with specific credentials.
@@ -20,7 +21,7 @@ This example shows how to:
Download the [Modular Tutorials](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/modular-tutorials/) folder.
{% admonition type="info" name="Note" %}
Without the Modular Tutorial Samples, you will not be able to try the examples that follow.
Without the Modular Tutorial Samples, you will not be able to try the examples that follow.
{% /admonition %}
## Get Accounts
@@ -29,19 +30,18 @@ To get test accounts:
1. Open `create-permissioned-domains.html` in a browser.
2. Get test accounts.
- If you copied the gathered information from another tutorial:
1. Paste the gathered information to the **Result** field.
2. Click **Distribute Account Info**.
- 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**.
- If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
- If you copied the gathered information from another tutorial:
1. Paste the gathered information to the **Result** field.
2. Click **Distribute Account Info**.
- 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**.
- If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Created Accounts](/docs/img/create-permissioned-domain-2.png)](/docs/img/create-permissioned-domain-2.png)
## Issue a Credential
1. Click the **Account 1** radial button. This account will be the credential issuer.
@@ -51,7 +51,6 @@ To get test accounts:
[![Created Credential](/docs/img/create-permissioned-domain-3.png)](/docs/img/create-permissioned-domain-3.png)
## Create a Permissioned Domain
1. Click **Create Permissioned Domain**.
@@ -64,7 +63,6 @@ To get test accounts:
[![Created Domain](/docs/img/create-permissioned-domain-4.png)](/docs/img/create-permissioned-domain-4.png)
## Delete a Permissioned Domain
1. Copy the _LedgerIndex_ value into **DomainID**.
@@ -72,8 +70,6 @@ To get test accounts:
[![Deleted Domain](/docs/img/create-permissioned-domain-5.png)](/docs/img/create-permissioned-domain-5.png)
# Code Walkthrough
## credential-manager.js
@@ -92,7 +88,6 @@ Submit the `CredentialCreate` transaction and report the results. Parse the meta
{% code-snippet file="/_code-samples/modular-tutorials/credential-manager.js" language="js" from="// Submit transaction" /%}
## permissioned-domain-manager.js
### Create Permissioned Domain

View File

@@ -2,8 +2,9 @@
metadata:
indexPage: true
seo:
description: Transact with confidence using the XRP Ledger's suite of compliance features for following government regulations and security practices.
description: Transact with confidence using the XRP Ledger's suite of compliance features for following government regulations and security practices.
---
# Transact with Confidence Using Compliance Features
The XRP Ledger has a rich suite of features designed to help financial institutions of all sizes engage with DeFi technology while complying with government regulations domestically and internationally.

View File

@@ -1,9 +1,10 @@
---
seo:
description: Verify that an account holds a valid credential on the XRP Ledger.
description: Verify that an account holds a valid credential on the XRP Ledger.
labels:
- Credentials
- Credentials
---
# Verify Credentials
This tutorial describes how to verify that an account holds a valid [credential](/docs/concepts/decentralized-storage/credentials) on the XRP Ledger, which has different use cases depending on the type of credential and the meaning behind it. A few possible reasons to verify a credential include:
@@ -26,7 +27,7 @@ To complete this tutorial, you should:
- Have a basic understanding of the XRP Ledger.
- Have an XRP Ledger client library, such as [xrpl.js](../build-apps/get-started.md), installed.
- Know the issuer, subject, and credential type of the credential you want to verify. For purposes of this tutorial, you can use sample values of data that exists in the public network.
- For information on how to create your own credentials, see the [Build a Credential Issuing Service](../build-apps/credential-issuing-service.md) tutorial.
- For information on how to create your own credentials, see the [Build a Credential Issuing Service](../build-apps/credential-issuing-service.md) tutorial.
## Source Code
@@ -43,6 +44,7 @@ From the code sample folder, use `npm` to install dependencies:
```sh
npm i
```
{% /tab %}
<!-- re-add Python tab when merging the tutorials
@@ -56,6 +58,7 @@ pip install -r requirements.txt
```
{% /tab %}
-->
{% /tabs %}
### 2. Set up client and define constants
@@ -116,7 +119,6 @@ If the credential has passed all checks to this point, it is valid. In summary,
{% /tab %}
{% /tabs %}
## Next Steps
Now that you know how to use `xrpl.js` to verify credentials, you can try building this or related steps together into a bigger project. For example:
@@ -128,10 +130,10 @@ Now that you know how to use `xrpl.js` to verify credentials, you can try buildi
- [Verify Credentials in Python](../../python/compliance/verify-credential.md)
- **References:**
- API methods:
- [ledger_entry method][]
- [ledger method][]
- Ledger entries:
- [Credential entry][]
- API methods:
- [ledger_entry method][]
- [ledger method][]
- Ledger entries:
- [Credential entry][]
{% raw-partial file="/docs/_snippets/common-links.md" /%}

View File

@@ -3,6 +3,7 @@ top_nav_grouping: Article Types
metadata:
indexPage: true
---
# JavaScript
You can create your own interface to try out the capabilities and support your specific business needs. These tutorials use a consistent test harness interface to try out features of the XRP Ledger.
@@ -14,13 +15,14 @@ Typically, the example functions involve four steps.
- Get the state of accounts and tokens on the XRP Ledger using requests.
- Disconnect from the XRP Ledger.
Each lesson features complete JavaScript and HTML code samples and a code walkthrough. You can download the source code, manipulate it in a text editor, and run it in your favorite browser.
Each lesson features complete JavaScript and HTML code samples and a code walkthrough. You can download the source code, manipulate it in a text editor, and run it in your favorite browser.
Much of this is “brute force” code that sacrifices conciseness for readability. Most examples incorporate functions from earlier examples so that any new code is specific to the topic of that tutorial
Much of this is “brute force” code that sacrifices conciseness for readability. Most examples incorporate functions from earlier examples so that any new code is specific to the topic of that tutorial
Once familiar with the library functions, you can build sample applications in JavaScript. We anticipate that the applications you build greatly improve upon these examples. Your feedback and contributions are most welcome.
To get started:
- create a new folder on your local disk and install the JavaScript library using npm.
`npm install xrpl`
@@ -29,4 +31,4 @@ Download and expand the [Payment Modular Tutorial Samples](/_code-samples/modula
## Tutorial Modules
{% child-pages /%}
{% child-pages /%}

View File

@@ -2,13 +2,14 @@
html: assign-an-authorized-minter-using-javascript.html
parent: nfts-using-javascript.html
seo:
description: Authorize another account to mint NFTs for you.
description: Authorize another account to mint NFTs for you.
labels:
- Accounts
- Quickstart
- XRP
- NFTs, NFTokens
---
# Assign an Authorized Minter Using JavaScript
You can assign another account permission to mint NFTs for you.
@@ -29,16 +30,16 @@ You can download the [NFT Modular Sam;ples](../../../../_code-samples/nft-modula
1. Open `authorized-minter.html` in a browser.
2. Choose your preferred test network (**Devnet** or **Testnet**).
3. 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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
## Authorize an Account to Create NFTs
To authorize another account to create NFTs for your account:
@@ -54,7 +55,7 @@ To authorize another account to create NFTs for your account:
To mint a non-fungible token for another account:
1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form.
2. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_.
2. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_.
3. Enter the **NFT URL**. This is a URI that points to the data or metadata associated with the NFT object. You can use the sample URI provided if you do not have one of your own.
4. Enter the **Transfer Fee**, a percentage of the proceeds that the original creator receives from future sales of the NFT. This is a value of 0-50000 inclusive, allowing transfer rates between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFT to be transferrable, set this field to 0.
5. Enter the account number on whose behalf you are minting the NFT in the **NFT Issuer** field.
@@ -80,7 +81,7 @@ This function sets the authorized minter for an account. Each account can have 0
// **************** Authorize Minter *******************
// *******************************************************
async function authorizeMinter() {
async function authorizeMinter() {
```
Get the account wallet and connect to the XRP Ledger.
@@ -99,28 +100,28 @@ Get the account wallet and connect to the XRP Ledger.
Create the transaction JSON.
```javascript
tx_json = {
"TransactionType": "AccountSet",
"Account": wallet.address,
"NFTokenMinter": authorizedMinterField.value,
"SetFlag": xrpl.AccountSetAsfFlags.asfAuthorizedNFTokenMinter
}
tx_json = {
TransactionType: 'AccountSet',
Account: wallet.address,
NFTokenMinter: authorizedMinterField.value,
SetFlag: xrpl.AccountSetAsfFlags.asfAuthorizedNFTokenMinter,
}
```
Sign and send the prepared transaction, then wait for the results.
```javascript
const prepared = await client.autofill(tx_json)
const signed = wallet.sign(prepared)
const result = await client.submitAndWait(signed.tx_blob)
const prepared = await client.autofill(tx_json)
const signed = wallet.sign(prepared)
const result = await client.submitAndWait(signed.tx_blob)
```
Report the results.
```javascript
results += '\nAccount setting succeeded.\n'
results += JSON.stringify(result, null, 2)
resultField.value = results
results += '\nAccount setting succeeded.\n'
results += JSON.stringify(result, null, 2)
resultField.value = results
```
Catch and report any errors.
@@ -174,63 +175,63 @@ async function mintOther() {
Create the JSON transaction object.
```javascript
// ------------------------------------------------------------------------
const tx_json = {
"TransactionType": "NFTokenMint",
"Account": wallet.classicAddress,
"URI": xrpl.convertStringToHex(nftURLfield.value),
"Flags": parseInt(flagsField.value),
"TransferFee": parseInt(transferFeeField.value),
"Issuer": nftIssuerField.value,
"NFTokenTaxon": nftTaxonField.value //Required, but if you have no use for it, set to zero.
}
// ------------------------------------------------------------------------
const tx_json = {
TransactionType: 'NFTokenMint',
Account: wallet.classicAddress,
URI: xrpl.convertStringToHex(nftURLfield.value),
Flags: parseInt(flagsField.value),
TransferFee: parseInt(transferFeeField.value),
Issuer: nftIssuerField.value,
NFTokenTaxon: nftTaxonField.value, //Required, but if you have no use for it, set to zero.
}
```
If the **Amount** field is populated, configure and add the expected amount the NFT will sell for.
```javascript
if (amountField.value) {
tx_json.Amount = configureAmount(amountField.value);
}
if (amountField.value) {
tx_json.Amount = configureAmount(amountField.value)
}
```
If the **Expiration (days)** field is populated, configure and add the expiration date.
```javascript
if (expirationField.value) {
tx_json.Expiration = configureExpiration(expirationField.value);
}
if (expirationField.value) {
tx_json.Expiration = configureExpiration(expirationField.value)
}
```
If the **Destination** field is populated, add it to the transaction JSON object.
```javascript
if (destinationField.value) {
tx_json.Destination = destinationField.value;
}
if (destinationField.value) {
tx_json.Destination = destinationField.value
}
```
Submit the transaction and wait for the result.
```javascript
const tx = await client.submitAndWait(tx_json, { wallet: wallet })
const tx = await client.submitAndWait(tx_json, { wallet: wallet })
```
Request the list of NFTs for the current account.
```javascript
const nfts = await client.request({
method: "account_nfts",
account: wallet.classicAddress
})
const nfts = await client.request({
method: 'account_nfts',
account: wallet.classicAddress,
})
```
Report the results.
```javascript
results += '\n\n=== Transaction result: ' + tx.result.meta.TransactionResult
results += '\n\n=== NFTs: ' + JSON.stringify(nfts, null, 2)
resultField.value = results + (await client.getXrpBalance(wallet.address))
results += '\n\n=== Transaction result: ' + tx.result.meta.TransactionResult
results += '\n\n=== NFTs: ' + JSON.stringify(nfts, null, 2)
resultField.value = results + (await client.getXrpBalance(wallet.address))
```
Catch and report any errors.
@@ -255,7 +256,6 @@ Disconnect from the XRP Ledger.
} //End of mintOther()
```
## authorized-minter.html
```html

View File

@@ -1,12 +1,13 @@
---
seo:
description: Broker a sale between a sell offer and a buy offer.
description: Broker a sale between a sell offer and a buy offer.
labels:
- Accounts
- NFTs
- Batch
- XRP
---
# Batch Mint NFTs Using JavaScript
You can create an application that mints multiple NFTs at one time. You can use a `for` loop to send one transaction after another.
@@ -23,21 +24,21 @@ You can download the [NFT Modular Samples](../../../../_code-samples/nft-modular
1. Open `batch-minting.html` in a browser.
2. Get a test account.
1. If you want to use an existing account seed:
1. Paste the account seed in the **Seed** field.
2. Click **Get Account from Seed**.
2. If you do not want to use an existing account seed, click **Get New Account 1**.
1. If you want to use an existing account seed:
1. Paste the account seed in the **Seed** field.
2. Click **Get Account from Seed**.
2. If you do not want to use an existing account seed, click **Get New Account 1**.
## Batch Mint NFTs
This example lets you mint multiple NFTs for a single unique item. The NFT might represent "prints" of an original artwork, tickets to an event, or another limited set of unique items.
This example lets you mint multiple NFTs for a single unique item. The NFT might represent "prints" of an original artwork, tickets to an event, or another limited set of unique items.
To batch mint NFTs:
1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form.
2. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_. This sets the _tsTransferable_ flag, meaning that the NFT object can be transferred to another account. Otherwise, the NFT object can only be transferred back to the issuing account. See [NFTokenMint](../../../../docs/references/protocol/transactions/types/nftokenmint.md) for information about all of the available flags for minting NFTs.
3. Enter the **NFT URL**. This is a URI that points to the data or metadata associated with the NFT object. You can use the sample URI provided if you do not have one of your own.
4. Set the **NFT Taxon**. If you don't have a use for this field, set it to _0_.
4. Set the **NFT Taxon**. If you don't have a use for this field, set it to _0_.
5. Enter an **NFT Count** of up to 200 NFTs to create in one batch.
6. Enter the **Transfer Fee**, a percentage of the proceeds that the original creator receives from future sales of the NFT. This is a value of 0-50000 inclusive, allowing transfer fees between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFT to be transferrable, set this field to 0.
7. Click **Batch Mint NFTs**.
@@ -90,24 +91,24 @@ Connect to the XRP Ledger and get the account wallet.
resultField.value = results;
```
Get the Sequence number from the most recent transaction with an account information request.
Get the Sequence number from the most recent transaction with an account information request.
```javascript
let account_info;
try {
account_info = await client.request({
"command": "account_info",
"account": wallet.address
});
} catch (error) {
results += `\nError retrieving account info for ${wallet.address}: ${error.message}`;
resultField.value = results;
return;
}
let account_info
try {
account_info = await client.request({
command: 'account_info',
account: wallet.address,
})
} catch (error) {
results += `\nError retrieving account info for ${wallet.address}: ${error.message}`
resultField.value = results
return
}
let my_sequence = account_info.result.account_data.Sequence;
results += "\n\nSequence Number: " + my_sequence + "\n\n";
resultField.value = results;
let my_sequence = account_info.result.account_data.Sequence
results += '\n\nSequence Number: ' + my_sequence + '\n\n'
resultField.value = results
```
Create ticket numbers for the batch.
@@ -117,103 +118,102 @@ Without tickets, if one transaction fails, all others in the batch fail. With ti
Start by parsing the **NFT Count**.
```javascript
const nftCount = parseInt(nftCountField.value);
if (isNaN(nftCount) || nftCount <= 0) {
results += '\nError: Please enter a valid number of NFTs to mint.';
resultField.value = results;
return;
}
const nftCount = parseInt(nftCountField.value)
if (isNaN(nftCount) || nftCount <= 0) {
results += '\nError: Please enter a valid number of NFTs to mint.'
resultField.value = results
return
}
```
Create the transaction JSON object.
```javascript
let ticketTransaction;
try {
ticketTransaction = await client.autofill({
"TransactionType": "TicketCreate",
"Account": wallet.address,
"TicketCount": nftCount,
"Sequence": my_sequence
});
} catch (error) {
results += `\nError autofilling ticket creation transaction: ${error.message}`;
resultField.value = results;
return;
}
let ticketTransaction
try {
ticketTransaction = await client.autofill({
TransactionType: 'TicketCreate',
Account: wallet.address,
TicketCount: nftCount,
Sequence: my_sequence,
})
} catch (error) {
results += `\nError autofilling ticket creation transaction: ${error.message}`
resultField.value = results
return
}
```
Sign the ticket transaction.
```javascript
//---------------------------------------------------- Sign the transaction.
const signedTransaction = wallet.sign(ticketTransaction);
//---------------------------------------------------- Sign the transaction.
const signedTransaction = wallet.sign(ticketTransaction)
```
Submit the transaction and wait for the result.
```javascript
let tx;
try {
tx = await client.submitAndWait(signedTransaction.tx_blob);
} catch (error) {
results += `\nError submitting ticket creation transaction: ${error.message}`;
resultField.value = results;
return;
}
let tx
try {
tx = await client.submitAndWait(signedTransaction.tx_blob)
} catch (error) {
results += `\nError submitting ticket creation transaction: ${error.message}`
resultField.value = results
return
}
```
Verify the transaction succeeded and report the result.
```javascript
if (tx.result.meta.TransactionResult !== 'tesSUCCESS') {
results += `\nError creating tickets. Transaction failed with result: ${tx.result.meta.TransactionResult}`;
resultField.value = results;
return;
}
results += `\nTickets created successfully. Transaction result: ${tx.result.meta.TransactionResult}\n\n`;
resultField.value = results;
if (tx.result.meta.TransactionResult !== 'tesSUCCESS') {
results += `\nError creating tickets. Transaction failed with result: ${tx.result.meta.TransactionResult}`
resultField.value = results
return
}
results += `\nTickets created successfully. Transaction result: ${tx.result.meta.TransactionResult}\n\n`
resultField.value = results
```
Get the generated tickets.
```javascript
let response;
try {
response = await client.request({
"command": "account_objects",
"account": wallet.address,
"type": "ticket"
});
} catch (error) {
results += `\nError retrieving account tickets: ${error.message}`;
resultField.value = results;
return;
}
let response
try {
response = await client.request({
command: 'account_objects',
account: wallet.address,
type: 'ticket',
})
} catch (error) {
results += `\nError retrieving account tickets: ${error.message}`
resultField.value = results
return
}
```
Populate an array variable with the tickets and report the results.
```javascript
let tickets = [];
if (response.result.account_objects && response.result.account_objects.length > 0) {
for (let i = 0; i < nftCount; i++) {
if (response.result.account_objects[i]) {
tickets[i] = response.result.account_objects[i].TicketSequence;
} else {
results += `\nWarning: Fewer tickets found than requested. Expected ${nftCount}, found ${response.result.account_objects.length}.`;
resultField.value = results;
break; // Exit loop if tickets run out
}
}
let tickets = []
if (response.result.account_objects && response.result.account_objects.length > 0) {
for (let i = 0; i < nftCount; i++) {
if (response.result.account_objects[i]) {
tickets[i] = response.result.account_objects[i].TicketSequence
} else {
results += '\nError: No tickets found for the account.';
resultField.value = results;
return;
results += `\nWarning: Fewer tickets found than requested. Expected ${nftCount}, found ${response.result.account_objects.length}.`
resultField.value = results
break // Exit loop if tickets run out
}
results += "Tickets generated, minting NFTs.\n\n";
resultField.value = results;
}
} else {
results += '\nError: No tickets found for the account.'
resultField.value = results
return
}
results += 'Tickets generated, minting NFTs.\n\n'
resultField.value = results
```
Mint the NFTs by looping through the available tickets and creating NFTs one at a time.
@@ -237,23 +237,22 @@ Mint the NFTs by looping through the available tickets and creating NFTs one at
Add optional fields, as needed.
```javascript
// Add optional fields
if (amountField.value) {
transactionParams.Amount = configureAmount(amountField.value);
}
// Add optional fields
if (amountField.value) {
transactionParams.Amount = configureAmount(amountField.value)
}
if (expirationField.value) {
transactionParams.Expiration = configureExpiration(expirationField.value);
}
if (expirationField.value) {
transactionParams.Expiration = configureExpiration(expirationField.value)
}
if (destinationField.value) {
transactionParams.Destination = destinationField.value;
}
if (destinationField.value) {
transactionParams.Destination = destinationField.value
}
```
Submit the transaction and wait for the result.
```javascript
try {
const mintTx = await client.submitAndWait(transactionParams, {
@@ -271,14 +270,12 @@ Submit the transaction and wait for the result.
}
```
Report the results.
```javascript
results += `\n\nAttempted to mint ${nftCount} NFTs. Successfully minted ${mintedNFTsCount} NFTs.`;
results += `\n\nAttempted to mint ${nftCount} NFTs. Successfully minted ${mintedNFTsCount} NFTs.`
```
Display the minted NFTs.
```javascript
@@ -293,7 +290,7 @@ Display the minted NFTs.
results += JSON.stringify(nfts, null, 2);
```
Continue to retrieve NFTs 400 at a time until all NFTs are fetched.
Continue to retrieve NFTs 400 at a time until all NFTs are fetched.
```javascript
while (nfts.result.marker) {
@@ -313,13 +310,13 @@ Continue to retrieve NFTs 400 at a time until all NFTs are fetched.
Update the **XRP Balance** field.
```javascript
try {
xrpBalanceField.value = (await client.getXrpBalance(wallet.address));
} catch (error) {
results += `\nError fetching XRP balance: ${error.message}`;
}
try {
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
} catch (error) {
results += `\nError fetching XRP balance: ${error.message}`
}
resultField.value = results;
resultField.value = results
```
Catch and report any errors.
@@ -380,15 +377,15 @@ Retrieve the first 400 NFTs and report the results.
While there are more NFTs, continue to retrieve them in batches of 400.
```javascript
while (nfts.result.marker) {
nfts = await client.request({
method: "account_nfts",
account: wallet.classicAddress,
limit: 400,
marker: nfts.result.marker
});
results += '\n' + JSON.stringify(nfts, null, 2);
}
while (nfts.result.marker) {
nfts = await client.request({
method: 'account_nfts',
account: wallet.classicAddress,
limit: 400,
marker: nfts.result.marker,
})
results += '\n' + JSON.stringify(nfts, null, 2)
}
```
Catch and report any fetch errors.

View File

@@ -1,11 +1,12 @@
---
seo:
description: Broker a sale between a sell offer and a buy offer.
description: Broker a sale between a sell offer and a buy offer.
labels:
- Broker
- NFT
- XRP
---
# Broker an NFT Sale Using JavaScript
Earlier examples showed how to make buy and sell offers directly between two accounts. Another option is to use a third account as a broker for the sale. The broker acts on behalf of the NFT owner. The seller creates an offer with the broker account as its destination. The broker gathers and evaluates buy offers and chooses which one to accept, adding an agreed-upon fee for arranging the sale. When the broker account accepts a sell offer with a buy offer, the funds and ownership of the NFT are transferred simultaneously, completing the deal. This allows an account to act as a marketplace or personal agent for NFT creators and traders.
@@ -36,19 +37,18 @@ To create a brokered sale, you need a broker account, a Sell Offer with the brok
1. Open `broker-nfts.html` in a browser.
2. Choose your preferred test network (**Devnet** or **Testnet**).
3. Get test accounts.
1. If you copied the gathered information from another tutorial (in this case, it would be best to load the Broker account and the Issuer account from the Prerequisite step):
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**.
1. If you copied the gathered information from another tutorial (in this case, it would be best to load the Broker account and the Issuer account from the Prerequisite step):
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Broker NFTs form with Account Information](../../../img/mt-broker-nfts-2-broker-form-with-accounts.png)](../../../img/mt-broker-nfts-2-broker-form-with-accounts.png)
## Get Offers
1. Enter the **NFT ID**.
@@ -60,15 +60,14 @@ To create a brokered sale, you need a broker account, a Sell Offer with the brok
1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form.
1. Copy the _nft_offer_index_ of the sell offer and paste it in the **Sell Offer Index** field.
2. Copy the _nft_offer_index_ of the buy offer and paste it in the **Buy Offer Index** field.
3. Enter a **Broker Fee**, in drops.
4. Click **Broker Sale**.
1. Copy the _nft_offer_index_ of the buy offer and paste it in the **Buy Offer Index** field.
1. Enter a **Broker Fee**, in drops.
1. Click **Broker Sale**.
In this example, the sale succeeds with 25 XRP going to the issuer account (Felicia), 30 XRP taken from the buyer account (Unknown 3rd Pary), and 5 XRP minus the transaction cost going to the broker account (Hisham).
[![Brokered Sale](../../../img/mt-broker-nfts-4-broker-sale.png)](../../../img/mt-broker-nfts-4-broker-sale.png)
## Cancel Offer
After accepting a buy offer, a best practice for the broker is to cancel all other offers, if the broker has permissions to do so. Use the [Transfer NFTs](../../../../_code-samples/nft-modular-tutorials/transfer-nfts.html) form to get and cancel any existing Sell or Buy offers.
@@ -81,7 +80,7 @@ You can download the [NFT Modular Tutorials](../../../../_code-samples/nft-modul
## brokerSale()
```javascript
```javascript
// *******************************************************
// ******************* Broker Sale ***********************
// *******************************************************
@@ -106,32 +105,30 @@ Get the account wallet and connect to the XRP Ledger.
Prepare an NFTokenAcceptOffer, passing both the sell offer and the buy offer, and also the broker fee. With the additional arguments, the API interprets this as a brokered sale.
```javascript
const brokerTx = {
"TransactionType": "NFTokenAcceptOffer",
"Account": wallet.classicAddress,
"NFTokenSellOffer": nftSellOfferIndexField.value,
"NFTokenBuyOffer": nftBuyOfferIndexField.value,
"NFTokenBrokerFee": brokerFeeField.value
}
const brokerTx = {
TransactionType: 'NFTokenAcceptOffer',
Account: wallet.classicAddress,
NFTokenSellOffer: nftSellOfferIndexField.value,
NFTokenBuyOffer: nftBuyOfferIndexField.value,
NFTokenBrokerFee: brokerFeeField.value,
}
```
Display the transaction object in the console.
Display the transaction object in the console.
```javascript
console.log(JSON.stringify(brokerTx, null, 2));
console.log(JSON.stringify(brokerTx, null, 2))
```
Submit the transaction and report the results.
```javascript
const tx = await client.submitAndWait(brokerTx, { wallet: wallet })
const tx = await client.submitAndWait(brokerTx, { wallet: wallet })
results += "\n\nTransaction result:\n" +
JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += "\nBalance changes:\n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
resultField.value += results
results += '\n\nTransaction result:\n' + JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += '\nBalance changes:\n' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
resultField.value += results
```
Catch and report any errors.
@@ -152,7 +149,7 @@ Disconnect from the XRP Ledger.
await client.disconnect();
}
}
}// End of brokerSale()
}// End of brokerSale()
```
## broker-nfts.html
@@ -330,7 +327,7 @@ Disconnect from the XRP Ledger.
<td>
<input type="text" id="nftIdField" size="40"></input>
</td>
<td align="center" valign="top">
<button type="button" onClick="getNFTs()">Get NFTs</button>
</td>

View File

@@ -5,9 +5,9 @@ top_nav_grouping: Article Types
metadata:
indexPage: true
---
# NFTs Using JavaScript
Mint and sell NFTs on the XRP Ledger using JavaScript.
{% child-pages /%}

View File

@@ -1,10 +1,11 @@
---
seo:
description: Mint and burn NFTs.
description: Mint and burn NFTs.
labels:
- Tokens
- Non-fungible tokens, NFTs
---
# Mint and Burn NFTs Using JavaScript
This example shows how to:
@@ -24,15 +25,15 @@ You can download the [NFT Modular Tutorials](../../../../_code-samples/nft-modul
1. Open `mint-nfts.html` in a browser.
2. Choose your preferred test network (**Devnet** or **Testnet**).
3. 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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Get accounts](../../../img/mt-mint-token-2-accounts.png)](../../../img/mt-mint-token-2-accounts.png)
@@ -42,17 +43,16 @@ To mint a non-fungible token object:
1. Click the Account 1 or Account 2 radio button. The account information populates the uneditable fields of the form.
2. Set the **Flags** field. For testing purposes, we recommend setting the value to _8_. This sets the _tsTransferable_ flag, meaning that the NFT object can be transferred to another account. Otherwise, the NFT object can only be transferred back to the issuing account.
2. Enter the **NFT URL**. This is a URI that points to the data or metadata associated with the NFT object. You can use the sample URI provided if you do not have one of your own.
3. Enter the **Transfer Fee**, a percentage of the proceeds from future sales of the NFT that will be returned to the original creator. This is a value of 0-50000 inclusive, allowing transfer rates between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFT to be transferrable, set this field to 0. If you impose a transfer fee, your NFT can only be traded for tokens for which your account has a trust line. See [Trust Lines](../../../concepts/tokens/fungible-tokens/index.md#trust-lines).
4. Enter an **NFT Taxon**. This is a required value, but if you are not using the field to create an integer-based taxon entry, you can set the value to 0.
5. (Optional) You can set an expected price for the NFT. To set a price in XRP, enter the amount in drops in the **Amount** field. To use an issued currency, enter the **Currency**, **Issuer**, and **Amount**.
6. Optionally, you can enter a **Destination** address that will be the only account authorized to purchase the NFT.
7. Optionally, you can enter an **Expiration** value in days, after which the offer will no longer be available.
8. Click **Mint NFT**.
3. Enter the **NFT URL**. This is a URI that points to the data or metadata associated with the NFT object. You can use the sample URI provided if you do not have one of your own.
4. Enter the **Transfer Fee**, a percentage of the proceeds from future sales of the NFT that will be returned to the original creator. This is a value of 0-50000 inclusive, allowing transfer rates between 0.000% and 50.000% in increments of 0.001%. If you do not set the **Flags** field to allow the NFT to be transferrable, set this field to 0. If you impose a transfer fee, your NFT can only be traded for tokens for which your account has a trust line. See [Trust Lines](../../../concepts/tokens/fungible-tokens/index.md#trust-lines).
5. Enter an **NFT Taxon**. This is a required value, but if you are not using the field to create an integer-based taxon entry, you can set the value to 0.
6. (Optional) You can set an expected price for the NFT. To set a price in XRP, enter the amount in drops in the **Amount** field. To use an issued currency, enter the **Currency**, **Issuer**, and **Amount**.
7. Optionally, you can enter a **Destination** address that will be the only account authorized to purchase the NFT.
8. Optionally, you can enter an **Expiration** value in days, after which the offer will no longer be available.
9. Click **Mint NFT**.
[![Mint NFT fields](../../../img/mt-mint-token-3-mint-token.png)](../../../img/mt-mint-token-3-mint-token.png)
## Get Tokens
Click **Get NFTs** to get a list of NFTs owned by the currently selected account.
@@ -67,7 +67,7 @@ To permanently destroy an NFT:
1. Enter or select the account that owns the NFT.
2. Enter the **NFT ID**.
2. Click **Burn NFT**.
3. Click **Burn NFT**.
[![Burn NFTs](../../../img/mt-mint-token-5-burn-token.png)](../../../img/mt-mint-token-5-burn-token.png)
@@ -76,11 +76,13 @@ To permanently destroy an NFT:
You can download the [NFT Modular Tutorials](../../../../_code-samples/nft-modular-tutorials/nft-modular-tutorials.zip) archive to examine the code samples.
## mint-nfts.js
<!-- SPELLING_IGNORE: ripplex3 -->
### Mint NFT
Get the account wallet and connect to the XRP Ledger.
```javascript
async function mintNFT() {
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
@@ -93,65 +95,64 @@ async function mintNFT() {
await client.connect();
```
Prepare the transaction parameters.
Prepare the transaction parameters.
```javascript
const transactionParams = {
TransactionType: "NFTokenMint",
Account: wallet.classicAddress,
URI: xrpl.convertStringToHex(nftURLfield.value),
Flags: parseInt(flagsField.value, 10), // Parse to integer
TransferFee: parseInt(transferFeeField.value, 10), // Parse to integer
NFTokenTaxon: parseInt(nftTaxonField.value, 10), // Parse to integer
};
const transactionParams = {
TransactionType: 'NFTokenMint',
Account: wallet.classicAddress,
URI: xrpl.convertStringToHex(nftURLfield.value),
Flags: parseInt(flagsField.value, 10), // Parse to integer
TransferFee: parseInt(transferFeeField.value, 10), // Parse to integer
NFTokenTaxon: parseInt(nftTaxonField.value, 10), // Parse to integer
}
```
Add optional fields.
```javascript
// Add optional fields
if (amountField.value) {
transactionParams.Amount = configureAmount(amountField.value);
}
// Add optional fields
if (amountField.value) {
transactionParams.Amount = configureAmount(amountField.value)
}
if (expirationField.value) {
transactionParams.Expiration = configureExpiration(expirationField.value);
}
if (expirationField.value) {
transactionParams.Expiration = configureExpiration(expirationField.value)
}
if (destinationField.value) {
transactionParams.Destination = destinationField.value;
}
if (destinationField.value) {
transactionParams.Destination = destinationField.value
}
```
Log the transaction parameters before submission.
```javascript
console.log("Mint NFT Transaction Parameters:", transactionParams);
console.log('Mint NFT Transaction Parameters:', transactionParams)
```
Submit the transaction.
```javascript
const tx = await client.submitAndWait(transactionParams, { wallet });
const tx = await client.submitAndWait(transactionParams, { wallet })
```
Get the current list of NFTs owned by the account.
```javascript
const nfts = await client.request({
method: "account_nfts",
account: wallet.classicAddress,
});
const nfts = await client.request({
method: 'account_nfts',
account: wallet.classicAddress,
})
```
Report the results of the transaction.
```javascript
results = `\n\n=== Transaction result: ${tx.result.meta.TransactionResult} ===`;
results += `\n\n=== NFTs: ${JSON.stringify(nfts, null, 2)} ===`;
results += `\n\n=== XRP Balance: ${await client.getXrpBalance(wallet.address)} ===`; // Await here
resultField.value = results;
results = `\n\n=== Transaction result: ${tx.result.meta.TransactionResult} ===`
results += `\n\n=== NFTs: ${JSON.stringify(nfts, null, 2)} ===`
results += `\n\n=== XRP Balance: ${await client.getXrpBalance(wallet.address)} ===` // Await here
resultField.value = results
```
Catch and report any errors.
@@ -192,18 +193,17 @@ async function getNFTs() {
Prepare and send the `account_nfts` request.
```javascript
const nfts = await client.request({
method: "account_nfts",
account: wallet.classicAddress,
});
const nfts = await client.request({
method: 'account_nfts',
account: wallet.classicAddress,
})
```
Report the results.
```javascript
results = '\n=== NFTs:\n ' + JSON.stringify(nfts, null, 2) + ' ===';
resultField.value = results;
results = '\n=== NFTs:\n ' + JSON.stringify(nfts, null, 2) + ' ==='
resultField.value = results
```
Catch and report any errors.
@@ -244,34 +244,34 @@ async function burnNFT() {
Prepare the `NFTokenBurn` transaction.
```javascript
const transactionBlob = {
TransactionType: "NFTokenBurn",
Account: wallet.classicAddress,
NFTokenID: nftIdField.value,
};
const transactionBlob = {
TransactionType: 'NFTokenBurn',
Account: wallet.classicAddress,
NFTokenID: nftIdField.value,
}
console.log("Burn NFT Transaction Parameters:", transactionBlob); // Log before submit
console.log('Burn NFT Transaction Parameters:', transactionBlob) // Log before submit
```
Submit the transaction and wait for the results.
```javascript
const tx = await client.submitAndWait(transactionBlob, { wallet });
const nfts = await client.request({ // Get nfts after burning.
method: "account_nfts",
account: wallet.classicAddress,
});
const tx = await client.submitAndWait(transactionBlob, { wallet })
const nfts = await client.request({
// Get nfts after burning.
method: 'account_nfts',
account: wallet.classicAddress,
})
```
Report the results.
```javascript
results = `\n=== Transaction result: ${tx.result.meta.TransactionResult} ===`;
results += '\n\n=== Balance changes: ' +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2) + ' ===';
results += '\n\n=== NFTs: \n' + JSON.stringify(nfts, null, 2) + ' ===';
resultField.value = results;
xrpBalanceField.value = (await client.getXrpBalance(wallet.address)); // Await
results = `\n=== Transaction result: ${tx.result.meta.TransactionResult} ===`
results += '\n\n=== Balance changes: ' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2) + ' ==='
results += '\n\n=== NFTs: \n' + JSON.stringify(nfts, null, 2) + ' ==='
resultField.value = results
xrpBalanceField.value = await client.getXrpBalance(wallet.address) // Await
```
Catch and report any errors.

View File

@@ -1,10 +1,11 @@
---
seo:
description: Use a JavaScript test harness to send XRP, trade currencies, and mint and trade NFTs.
description: Use a JavaScript test harness to send XRP, trade currencies, and mint and trade NFTs.
labels:
- Tokens
- Non-fungible Tokens, NFTs
---
# Transfer NFTs Using JavaScript
This example shows how to:
@@ -27,15 +28,15 @@ You can download the [NFT Modular Tutorials](../../../../_code-samples/nft-modul
1. Open `transfer-nfts.html` in a browser.
2. Choose your preferred test network (**Devnet** or **Testnet**).
3. 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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Form with account information](../../../img/mt-transfer-nft-2-accounts-loaded.png)](../../../img/mt-transfer-nft-2-accounts-loaded.png)
@@ -57,10 +58,11 @@ To create an NFT sell offer:
## Get Offers
To list the buy and sell offers associated with an NFT:
1. Enter the **NFT ID**.
2. Click **Get Offers**.
The key piece of information is the NFT Offer ID (labeled as `nft_offer_index`), which you use to accept a sell or buy offer.
The key piece of information is the NFT Offer ID (labeled as `nft_offer_index`), which you use to accept a sell or buy offer.
[![Get offers](../../../img/mt-transfer-nfts-4-get-offers.png)](../../../img/mt-transfer-nfts-4-get-offers.png)
@@ -124,7 +126,7 @@ You can download the [NFT Modular Examples](../../../../_code-samples/nft-modula
// *******************************************************
// ****************** Create Sell Offer ******************
// *******************************************************
async function createSellOffer() {
```
@@ -144,55 +146,56 @@ Get the account wallet and connect to the XRP Ledger.
If the destination field is populated, capture the value.
```javascript
const destination = destinationField.value || undefined;
const destination = destinationField.value || undefined
```
If the **Expiration** field is populated, configure the expiration date for the sell offer.
```javascript
const expiration = expirationField.value ? configureExpiration() : undefined;
const expiration = expirationField.value ? configureExpiration() : undefined
```
Begin constructing the transaction JSON object.
```javascript
const transactionJson = {
TransactionType: "NFTokenCreateOffer",
Account: wallet.classicAddress,
NFTokenID: nftIdField.value,
Flags: 1,
};
const transactionJson = {
TransactionType: 'NFTokenCreateOffer',
Account: wallet.classicAddress,
NFTokenID: nftIdField.value,
Flags: 1,
}
```
Configure the amount. To give the NFT away, set the **Amount** to 0. `configureAmount()` determines whether the currency is XRP or an issued currency, and returns the properly formattted object to add to the JSON transaction object.
```javascript
const amount = configureAmount();
if (amount) { // Only add Amount if it's defined
transactionJson.Amount = amount;
} else {
console.warn("Amount is undefined. Sell offer might be invalid.");
resultField.value = results;
}
const amount = configureAmount()
if (amount) {
// Only add Amount if it's defined
transactionJson.Amount = amount
} else {
console.warn('Amount is undefined. Sell offer might be invalid.')
resultField.value = results
}
```
If you have an expiration date or specified destination, add them to the JSON transaction object.
```javascript
if (expiration) {
transactionJson.Expiration = expiration;
}
if (destination) {
transactionJson.Destination = destination;
}
if (expiration) {
transactionJson.Expiration = expiration
}
if (destination) {
transactionJson.Destination = destination
}
```
Submit the transaction, wait for and report the results.
```javascript
const tx = await client.submitAndWait(transactionJson, { wallet });
results += `\nSell offer created successfully!\nTransaction Hash: ${tx.result.hash}\nEngine Result: ${tx.result.engine_result}`;
resultField.value = results;
const tx = await client.submitAndWait(transactionJson, { wallet })
results += `\nSell offer created successfully!\nTransaction Hash: ${tx.result.hash}\nEngine Result: ${tx.result.engine_result}`
resultField.value = results
```
Disconnect from the XRP Ledger.
@@ -227,12 +230,12 @@ async function createBuyOffer() {
Get the account wallet and connect to the ledger.
```javascript
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
let net = getNet();
const client = new xrpl.Client(net);
await client.connect();
let results = '\n=== Connected. Creating buy offer. ===';
resultField.value = results;
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = '\n=== Connected. Creating buy offer. ==='
resultField.value = results
```
Configure the amount and expiration date, if present.
@@ -248,85 +251,84 @@ Configure the amount and expiration date, if present.
Start constructing the transactionJson object.
```javascript
let transactionJson = {
"TransactionType": "NFTokenCreateOffer",
"Account": wallet.classicAddress,
"Owner": nftOwnerField.value,
"NFTokenID": nftIdField.value,
"Flags": 0, // Ensure no tfSellNFToken flag for a buy offer
};
let transactionJson = {
TransactionType: 'NFTokenCreateOffer',
Account: wallet.classicAddress,
Owner: nftOwnerField.value,
NFTokenID: nftIdField.value,
Flags: 0, // Ensure no tfSellNFToken flag for a buy offer
}
```
Add the configured amount to the transaction.
```javascript
if (amount !== undefined && amount !== '') {
transactionJson.Amount = amount;
} else {
results += "\nError: Amount field is required for a buy offer.";
resultField.value = results;
client.disconnect();
return;
}
if (amount !== undefined && amount !== '') {
transactionJson.Amount = amount
} else {
results += '\nError: Amount field is required for a buy offer.'
resultField.value = results
client.disconnect()
return
}
```
Add the **Destination** value, if it is set.
```javascript
if (destinationField.value !== '') {
transactionJson.Destination = destinationField.value;
}
if (destinationField.value !== '') {
transactionJson.Destination = destinationField.value
}
```
Add the Expiration date if it's not an empty string.
```javascript
if (expiration > 0) {
transactionJson.Expiration = expiration;
}
if (expiration > 0) {
transactionJson.Expiration = expiration
}
```
Submit the transaction and wait for the results. List the sell offers and buy offers currently available.
```javascript
const tx = await client.submitAndWait(transactionJson, { wallet: wallet });
const tx = await client.submitAndWait(transactionJson, { wallet: wallet })
results += "\n\n=== Sell Offers ===\n";
let nftSellOffers;
try {
nftSellOffers = await client.request({
method: "nft_sell_offers",
nft_id: nftIdField.value
});
} catch (err) {
nftSellOffers = "=== No sell offers. ===";
}
results += JSON.stringify(nftSellOffers, null, 2);
results += "\n\n=== Buy Offers ===\n";
let nftBuyOffers;
try {
nftBuyOffers = await client.request({
method: "nft_buy_offers",
nft_id: nftIdField.value
});
results += JSON.stringify(nftBuyOffers, null, 2);
} catch (err) {
results += "=== No buy offers. ===";
}
results += '\n\n=== Sell Offers ===\n'
let nftSellOffers
try {
nftSellOffers = await client.request({
method: 'nft_sell_offers',
nft_id: nftIdField.value,
})
} catch (err) {
nftSellOffers = '=== No sell offers. ==='
}
results += JSON.stringify(nftSellOffers, null, 2)
results += '\n\n=== Buy Offers ===\n'
let nftBuyOffers
try {
nftBuyOffers = await client.request({
method: 'nft_buy_offers',
nft_id: nftIdField.value,
})
results += JSON.stringify(nftBuyOffers, null, 2)
} catch (err) {
results += '=== No buy offers. ==='
}
```
Report the results of the transaction.
```javascript
// Check transaction results -------------------------------------------------
results += "\n\n=== Transaction result:\n" +
JSON.stringify(tx.result.meta.TransactionResult, null, 2);
results += "\n\n=== Balance changes:\n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2);
resultField.value = results;
// Check transaction results -------------------------------------------------
results += '\n\n=== Transaction result:\n' + JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += '\n\n=== Balance changes:\n' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value = results
```
Catch and report any errors.
```javascript
} catch (error) {
console.error('Error creating buy offer:', error);
@@ -345,83 +347,81 @@ Disconnect from the XRP Ledger.
## Cancel Offer
```javascript
```javascript
// *******************************************************
// ******************** Cancel Offer *********************
// *******************************************************
async function cancelOffer() {
async function cancelOffer() {
```
Get the account wallet and connect to the ledger.
```javascript
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = "\n=== Connected. Cancelling offer. ==="
resultField.value = results
```javascript
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = '\n=== Connected. Cancelling offer. ==='
resultField.value = results
```
Store the token offer ID in the `NFTokenOffers` array parameter.
```javascript
const tokenOfferIDs = [nftOfferIdField.value]
const tokenOfferIDs = [nftOfferIdField.value]
```
Construct the NFTokenCancelOffer JSON transaction.
```javascript
const transactionJson = {
"TransactionType": "NFTokenCancelOffer",
"Account": wallet.classicAddress,
"NFTokenOffers": tokenOfferIDs
}
const transactionJson = {
TransactionType: 'NFTokenCancelOffer',
Account: wallet.classicAddress,
NFTokenOffers: tokenOfferIDs,
}
```
Submit the transaction and wait for the results.
```javascript
const tx = await client.submitAndWait(transactionJson, { wallet })
const tx = await client.submitAndWait(transactionJson, { wallet })
```
List the remaining sell offers and buy offers.
```javascript
results = "\n\n=== Sell Offers===\n"
let nftSellOffers
try {
nftSellOffers = await client.request({
method: "nft_sell_offers",
nft_id: nftIdField.value
})
} catch (err) {
nftSellOffers = '=== No sell offers. ===\n'
}
results += JSON.stringify(nftSellOffers, null, 2)
results += "\n\n=== Buy Offers ===\n"
let nftBuyOffers
try {
nftBuyOffers = await client.request({
method: "nft_buy_offers",
nft_id: nftIdField.value
})
} catch (err) {
nftBuyOffers = '=== No buy offers. ==='
}
results += JSON.stringify(nftBuyOffers, null, 2)
resultField.value += results
results = '\n\n=== Sell Offers===\n'
let nftSellOffers
try {
nftSellOffers = await client.request({
method: 'nft_sell_offers',
nft_id: nftIdField.value,
})
} catch (err) {
nftSellOffers = '=== No sell offers. ===\n'
}
results += JSON.stringify(nftSellOffers, null, 2)
results += '\n\n=== Buy Offers ===\n'
let nftBuyOffers
try {
nftBuyOffers = await client.request({
method: 'nft_buy_offers',
nft_id: nftIdField.value,
})
} catch (err) {
nftBuyOffers = '=== No buy offers. ==='
}
results += JSON.stringify(nftBuyOffers, null, 2)
resultField.value += results
```
Report the transaction results and XRP balance changes.
```javascript
results = "\n=== Transaction result:\n" +
JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += "\n\n=== Balance changes:\n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value += results
results = '\n=== Transaction result:\n' + JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += '\n\n=== Balance changes:\n' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value += results
```
Disconnect from the XRP Ledger.
@@ -433,7 +433,7 @@ Disconnect from the XRP Ledger.
## Get Offers
```javascript
```javascript
// *******************************************************
// ******************** Get Offers ***********************
// *******************************************************
@@ -444,52 +444,52 @@ async function getOffers() {
Get the account wallet and connect to the ledger.
```javascript
```javascript
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = '\nConnected. Getting offers...'
resultField.value = results
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
// --- Sell Offers ---
results += '\n\n=== Sell Offers ===\n'
let results = '\nConnected. Getting offers...'
resultField.value = results
// --- Sell Offers ---
results += '\n\n=== Sell Offers ===\n'
```
Prepare and an `nft_sell_offers` request for the selected NFT ID. Catch any errors and report the results.
```javascript
let nftSellOffers
try {
nftSellOffers = await client.request({
method: "nft_sell_offers",
nft_id: nftIdField.value
})
} catch (err) {
nftSellOffers = 'No sell offers found for this NFT ID.'
}
results += JSON.stringify(nftSellOffers, null, 2)
resultField.value = results
let nftSellOffers
try {
nftSellOffers = await client.request({
method: 'nft_sell_offers',
nft_id: nftIdField.value,
})
} catch (err) {
nftSellOffers = 'No sell offers found for this NFT ID.'
}
results += JSON.stringify(nftSellOffers, null, 2)
resultField.value = results
```
Prepare and an `nft_buy_offers` request for the selected NFT ID. Catch any errors and report the results.
```javascript
// --- Buy Offers ---
results = '\n\n=== Buy Offers ===\n'
let nftBuyOffers
try {
nftBuyOffers = await client.request({
method: "nft_buy_offers",
nft_id: nftIdField.value
})
} catch (err) {
// Log the actual error for debugging
nftBuyOffers = 'No buy offers found for this NFT ID.' // More descriptive
}
results += JSON.stringify(nftBuyOffers, null, 2) // Append the JSON string
resultField.value += results // Update the display with buy offers
// --- Buy Offers ---
results = '\n\n=== Buy Offers ===\n'
let nftBuyOffers
try {
nftBuyOffers = await client.request({
method: 'nft_buy_offers',
nft_id: nftIdField.value,
})
} catch (err) {
// Log the actual error for debugging
nftBuyOffers = 'No buy offers found for this NFT ID.' // More descriptive
}
results += JSON.stringify(nftBuyOffers, null, 2) // Append the JSON string
resultField.value += results // Update the display with buy offers
```
Disconnect from the XRP Ledger.
@@ -501,7 +501,7 @@ Disconnect from the XRP Ledger.
## Accept Sell Offer
```javascript
```javascript
// *******************************************************
// ****************** Accept Sell Offer ******************
// *******************************************************
@@ -512,7 +512,7 @@ async function acceptSellOffer() {
Get the account wallet and connect to the ledger.
```javascript
```javascript
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
let net = getNet()
const client = new xrpl.Client(net)
@@ -525,43 +525,43 @@ Get the account wallet and connect to the ledger.
Prepare the transaction JSON object.
```javascript
const transactionJson = {
"TransactionType": "NFTokenAcceptOffer",
"Account": wallet.classicAddress,
"NFTokenSellOffer": nftOfferIdField.value,
}
const transactionJson = {
TransactionType: 'NFTokenAcceptOffer',
Account: wallet.classicAddress,
NFTokenSellOffer: nftOfferIdField.value,
}
```
Submit the transaction and wait for the results.
```javascript
const tx = await client.submitAndWait(transactionJson, { wallet: wallet })
const tx = await client.submitAndWait(transactionJson, { wallet: wallet })
```
Get the current NFTs held by the account after the transaction.
```javascript
const nfts = await client.request({
method: "account_nfts",
account: wallet.classicAddress
})
const nfts = await client.request({
method: 'account_nfts',
account: wallet.classicAddress,
})
```
Get the new XRP balance after the transaction.
```javascript
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
```
Report the results.
```javascript
results += '=== Transaction result:\n'
results += JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += '\n=== Balance changes:'
results += JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
results += JSON.stringify(nfts, null, 2)
resultField.value += results
results += '=== Transaction result:\n'
results += JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += '\n=== Balance changes:'
results += JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
results += JSON.stringify(nfts, null, 2)
resultField.value += results
```
Catch and report any errors.
@@ -571,9 +571,10 @@ Catch and report any errors.
console.error('Error accepting sell offer:', error)
resultField.value = `Error: ${error.message || error}`
```
Disconnect from the XRP Ledger.
```javascript
````javascript
} finally {
client.disconnect()
}
@@ -587,7 +588,7 @@ Disconnect from the XRP Ledger.
// *******************************************************
async function acceptBuyOffer() {
```
````
Get the account wallet and connect to the XRP Ledger.
@@ -606,40 +607,38 @@ async function acceptBuyOffer() {
Create the transactionJson object, passing the account address and the buy offer ID.
```javascript
const transactionJson = {
"TransactionType": "NFTokenAcceptOffer",
"Account": wallet.classicAddress,
"NFTokenBuyOffer": nftOfferIdField.value
};
const transactionJson = {
TransactionType: 'NFTokenAcceptOffer',
Account: wallet.classicAddress,
NFTokenBuyOffer: nftOfferIdField.value,
}
```
Submit the transaction and wait for the results.
```javascript
const tx = await client.submitAndWait(transactionJson, { wallet: wallet });
const tx = await client.submitAndWait(transactionJson, { wallet: wallet })
```
Report the current list of account NFTs after the transaction.
```javascript
const nfts = await client.request({
method: "account_nfts",
account: wallet.classicAddress
});
const nfts = await client.request({
method: 'account_nfts',
account: wallet.classicAddress,
})
results += JSON.stringify(nfts, null, 2);
resultField.value = results;
results += JSON.stringify(nfts, null, 2)
resultField.value = results
```
Report the result of the transaction and update the XRP Balance field.
```javascript
results += "\n\nTransaction result:\n" +
JSON.stringify(tx.result.meta.TransactionResult, null, 2);
results += "\nBalance changes:\n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2);
xrpBalanceField.value = (await client.getXrpBalance(wallet.address));
resultField.value = results;
results += '\n\nTransaction result:\n' + JSON.stringify(tx.result.meta.TransactionResult, null, 2)
results += '\nBalance changes:\n' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
resultField.value = results
```
Catch and report any errors.
@@ -647,7 +646,7 @@ Catch and report any errors.
```javascript
} catch (error) {
console.error('Error in acceptBuyOffer:', error); // Log the full error
results = `\n=== Error accepting buy offer: ${error.message || 'Unknown error'} ===`;
results = `\n=== Error accepting buy offer: ${error.message || 'Unknown error'} ===`;
resultField.value = results;
```

View File

@@ -1,16 +1,17 @@
---
seo:
description: Create two accounts and transfer XRP between them.
description: Create two accounts and transfer XRP between them.
labels:
- Accounts
- Transaction Sending
- XRP
---
# Create Accounts and Send XRP Using JavaScript
This example shows how to:
1. Create accounts on the Testnet, funded with 1000 test XRP with no actual value.
1. Create accounts on the Testnet, funded with 1000 test XRP with no actual value.
2. Retrieve the accounts from seed values.
3. Transfer XRP between accounts.
@@ -46,10 +47,10 @@ The name fields are there for you to create an arbitrary label to make the accou
To transfer XRP from Account 1 to Account 2:
1. Click the **Account 1** radio button. The information about Account 1 populates the uneditable fields of the form.
1. Click the **Account 1** radio button. The information about Account 1 populates the uneditable fields of the form.
2. Enter the **Amount** of XRP to send.
2. Copy and paste the **Account 2 Address** value to the **Destination** field.
3. Click **Send XRP** to transfer XRP from Account 1 to Account 2.
3. Copy and paste the **Account 2 Address** value to the **Destination** field.
4. Click **Send XRP** to transfer XRP from Account 1 to Account 2.
The **Results** field shows the change in balance in each of the accounts. Note that sending the XRP cost an additional .000001 XRP as the transfer fee. The transfer fee is small enough to be no burden for legitimate users, but is there to stop spammers from making DDS attacks against the XRP Ledger (sending millions of false transactions will quickly add up to real money).
@@ -65,7 +66,6 @@ To transfer XRP from Account 2 back to Account 1:
4. Click **Send XRP** to transfer XRP from Account 1 to Account 2.
5. Click the **Account 1** radio button to see its new XRP balance.
[![Transferred XRP from Account 2 to Account 1](/docs/img/mt-send-xrp-4-account2-send-xrp.png)](/docs/img/mt-send-xrp-4-account2-send-xrp.png)
## Gather and Distribute Account Information
@@ -104,11 +104,12 @@ This function can be used with _Testnet_, or _Devnet_. It allows you to select b
```javascript
function getNet() {
let net
if (document.getElementById("tn").checked) net = "wss://s.altnet.rippletest.net:51233/"
if (document.getElementById("dn").checked) net = "wss://s.devnet.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()
The `getAccount()` function uses the faucet host to fund a new account wallet
@@ -120,10 +121,10 @@ async function getAccount() {
Get the selected network, create a new client, and connect to the XRPL serever.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
resultField.value = `===Getting Account===\n\nConnected to ${net}.`
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
resultField.value = `===Getting Account===\n\nConnected to ${net}.`
```
Request a new wallet funded with play-money XRP for experimentation.
@@ -162,18 +163,17 @@ These are wrapper functions that call the getAccount() function, then populate t
```javascript
async function getNewAccount1() {
account1address.value = "=== Getting new account. ===\n\n"
account1seed.value = ""
const accountInfo= await getAccount()
account1address.value = '=== Getting new account. ===\n\n'
account1seed.value = ''
const accountInfo = await getAccount()
account1address.value = accountInfo[0]
account1seed.value = accountInfo[1]
}
async function getNewAccount2() {
account2address.value = "=== Getting new account. ===\n\n"
account2seed.value = ""
const accountInfo= await getAccount()
account2address.value = '=== Getting new account. ===\n\n'
account2seed.value = ''
const accountInfo = await getAccount()
account2address.value = accountInfo[0]
account2seed.value = accountInfo[1]
}
@@ -199,6 +199,7 @@ async function getAccountFromSeed(my_seed) {
return (address)
}
```
Catch and report any errors.
```javascript
@@ -208,16 +209,17 @@ Catch and report any errors.
resultField.value = results
throw error; // Re-throw the error to be handled by the caller
}
```
```
Disconnect from the XRP Ledger and return the .
Disconnect from the XRP Ledger and return the .
```javascript
finally {
await client.disconnect();
}
```javascript
finally {
await client.disconnect();
}
} // End of getAccountFromSeed()
```
### getAccountFromSeed1 and getAccountFromSeed2
These wrapper functions populate the Account1 Address or Account2 address from a seed value, respectively.
@@ -238,8 +240,8 @@ This local function copies the name, account, and seed values for Account1 and A
```javascript
function gatherAccountInfo() {
let accountData = account1name.value + "\n" + account1address.value + "\n" + account1seed.value + "\n"
accountData += account2name.value + "\n" + account2address.value + "\n" + account2seed.value
let accountData = account1name.value + '\n' + account1address.value + '\n' + account1seed.value + '\n'
accountData += account2name.value + '\n' + account2address.value + '\n' + account2seed.value
resultField.value = accountData
}
```
@@ -250,7 +252,7 @@ This local function parses structured account information from the **Result** fi
```javascript
function distributeAccountInfo() {
let accountInfo = resultField.value.split("\n")
let accountInfo = resultField.value.split('\n')
account1name.value = accountInfo[0]
account1address.value = accountInfo[1]
account1seed.value = accountInfo[2]
@@ -298,22 +300,23 @@ async function getXrpBalance() {
xrpBalanceField.value = await client.getXrpBalance(accountAddressField.value)
resultField.value = results
}
```
Catch any errors and disconnect from the XRP Ledger.
```javascript
catch (error) {
console.error('Error getting XRP balance:', error);
results += `\nError: ${error.message}\n`
resultField.value = results
throw error; // Re-throw the error to be handled by the caller
}
finally {
// Disconnect from the client
await client.disconnect();
}
```
Catch any errors and disconnect from the XRP Ledger.
```javascript
catch (error) {
console.error('Error getting XRP balance:', error);
results += `\nError: ${error.message}\n`
resultField.value = results
throw error; // Re-throw the error to be handled by the caller
}
finally {
// Disconnect from the client
await client.disconnect();
}
```
### getTokenBalance()
Get the balance of all tokens for the current active account. This is a function that is used frequently in other modular tutorials that deal with currencies other than XRP.
@@ -325,11 +328,11 @@ async function getTokenBalance() {
Connect with the network.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `===Connected to ${net}.===\n===Getting account token balance...===\n\n`
resultField.value += results
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `===Connected to ${net}.===\n===Getting account token balance...===\n\n`
resultField.value += results
```
Send a request to get the account balance, then wait for the results.
@@ -362,12 +365,12 @@ Catch and report any errors, then disconnect from the XRP Ledger.
// Disconnect from the client
await client.disconnect();
}
}
}
```
## base-module.html
Create a standard HTML form to send transactions and requests, then display the results.
Create a standard HTML form to send transactions and requests, then display the results.
```html
<html>
@@ -435,7 +438,7 @@ Create a standard HTML form to send transactions and requests, then display the
<label for="account1address">Account 1 Address</label>
</span>
</td>
<td>
<td>
<input type="text" id="account1address" size="40"></input>
</td>
<td>

View File

@@ -1,6 +1,6 @@
---
seo:
description: Create, finish, or cancel condition-based escrow transactions.
description: Create, finish, or cancel condition-based escrow transactions.
labels:
- Accounts
- Modular Tutorials
@@ -8,6 +8,7 @@ labels:
- XRP
- Escrow
---
# Create Conditional Escrows Using JavaScript
This example shows how to:
@@ -20,7 +21,6 @@ This example shows how to:
[![Conditional Escrow Tester Form](/docs/img/mt-conditional-escrow-1-empty-form.png)](/docs/img/mt-conditional-escrow-1-empty-form.png)
## Prerequisites
Download and expand the [Modular Tutorials](../../../../_code-samples/modular-tutorials/payment-modular-tutorials.zip)<!-- {.github-code-download} --> archive.
@@ -29,7 +29,7 @@ Download and expand the [Modular Tutorials](../../../../_code-samples/modular-tu
### Create Escrow
You create a condition-based escrow using a fulfillment code associated with a condition code. Create the condition/fulfillment pair using the `five-bells-condition` application.
You create a condition-based escrow using a fulfillment code associated with a condition code. Create the condition/fulfillment pair using the `five-bells-condition` application.
Install `five-bells-condition`:
@@ -45,18 +45,18 @@ To create a condition/fulfillment pair:
[![Condition and Fulfillment](/docs/img/mt-conditional-escrow-2-getConditionAndFulfillment.png)](/docs/img/mt-conditional-escrow-2-getConditionAndFulfillment.png)
To get test accounts:
1. Open `create-conditional-escrow.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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Form with Accounts](/docs/img/mt-conditional-escrow-3-form-with-accounts.png)](/docs/img/mt-conditional-escrow-3-form-with-accounts.png)
@@ -67,11 +67,11 @@ When you create a conditional escrow, you need to specify the amount you want to
To create a conditional escrow:
1. Enter an **Amount** to transfer.
3. Enter the **Destination** field (for example, use Account 2 Address).
4. Enter the **Escrow Condition** value.
5. Enter the **Escrow Cancel (seconds)** value.
6. Click **Create Escrow**.
7. Copy and save the _Sequence Number_ of the escrow called out in the **Results** field.
2. Enter the **Destination** field (for example, use Account 2 Address).
3. Enter the **Escrow Condition** value.
4. Enter the **Escrow Cancel (seconds)** value.
5. Click **Create Escrow**.
6. Copy and save the _Sequence Number_ of the escrow called out in the **Results** field.
The escrow is created on the XRP Ledger instance, reserving your requested XRP amount plus the transaction cost.
@@ -97,7 +97,7 @@ The transaction is completed and balances adjusted for both accounts.
## Get Escrows
Click **Get Escrows** to see the current list of escrows generated by or destined for the current account.
Click **Get Escrows** to see the current list of escrows generated by or destined for the current account.
## Cancel Escrow
@@ -158,8 +158,7 @@ console.log('Fulfillment (hex):', fulfillmentHex)
## create-conditional-escrow.js
### createConditionalEscrow()
### createConditionalEscrow()
Connect to the ledger and get the account wallet.
@@ -177,43 +176,42 @@ async function createConditionalEscrow() {
Prepare the cancel date by adding the number of seconds in the **Escrow Cancel Date** field to the current date and time. In practice, the cancel date might be in days, weeks, months, or years. Using seconds allows you to test scenarios with expired escrows.
```javascript
let escrow_cancel_date = new Date()
escrow_cancel_date = addSeconds(parseInt(escrowCancelDateField.value))
let escrow_cancel_date = new Date()
escrow_cancel_date = addSeconds(parseInt(escrowCancelDateField.value))
```
Prepare the transaction object.
```javascript
const escrowTx = await client.autofill({
"TransactionType": "EscrowCreate",
"Account": wallet.address,
"Amount": xrpl.xrpToDrops(sendAmount),
"Destination": destinationField.value,
"CancelAfter": escrow_cancel_date,
"Condition": escrowConditionField.value
})
const escrowTx = await client.autofill({
TransactionType: 'EscrowCreate',
Account: wallet.address,
Amount: xrpl.xrpToDrops(sendAmount),
Destination: destinationField.value,
CancelAfter: escrow_cancel_date,
Condition: escrowConditionField.value,
})
```
Sign the prepared transaction object.
```javascript
const signed = wallet.sign(escrowTx)
const signed = wallet.sign(escrowTx)
```
Submit the signed object and wait for the results.
```javascript
const tx = await client.submitAndWait(signed.tx_blob)
const tx = await client.submitAndWait(signed.tx_blob)
```
Report the results, parsing the _Sequence Number_ for later use.
```javascript
results = "\n=== *** Sequence Number (Save!): " + tx.result.tx_json.Sequence
results += "\n\n===Balance changes===\n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
resultField.value += results
results = '\n=== *** Sequence Number (Save!): ' + tx.result.tx_json.Sequence
results += '\n\n===Balance changes===\n' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
resultField.value += results
```
Catch and report any errors, then disconnect from the XRP Ledger.
@@ -246,34 +244,33 @@ async function finishConditionalEscrow() {
Prepare the transaction object.
```javascript
const prepared = await client.autofill({
"TransactionType": "EscrowFinish",
"Account": accountAddressField.value,
"Owner": escrowOwnerField.value,
"OfferSequence": parseInt(escrowSequenceNumberField.value),
"Condition": escrowConditionField.value,
"Fulfillment": escrowFulfillmentField.value
})
const prepared = await client.autofill({
TransactionType: 'EscrowFinish',
Account: accountAddressField.value,
Owner: escrowOwnerField.value,
OfferSequence: parseInt(escrowSequenceNumberField.value),
Condition: escrowConditionField.value,
Fulfillment: escrowFulfillmentField.value,
})
```
Sign the prepared transaction object.
```javascript
const signed = wallet.sign(prepared)
const signed = wallet.sign(prepared)
```
Submit the signed transaction and wait for the results.
```javascript
const tx = await client.submitAndWait(signed.tx_blob)
const tx = await client.submitAndWait(signed.tx_blob)
```
Report the results
```javascript
results = "\n===Balance changes===" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value += results
results = '\n===Balance changes===' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value += results
```
Catch and report any errors, then disconnect from the XRP Ledger.
@@ -363,7 +360,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
<label for="account1address">Account 1 Address</label>
</span>
</td>
<td>
<td>
<input type="text" id="account1address" size="40"></input>
</td>
<td>
@@ -516,10 +513,10 @@ Catch and report any errors, then disconnect from the XRP Ledger.
<td>
<input type="text" id="escrowSequenceNumberField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="getTransaction()">Get Transaction</button>
</td>
</td>
</tr>
<tr>
<td align="right">
@@ -530,7 +527,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
<td>
<input type="text" id="escrowOwnerField" size="40"></input>
<br>
</td>
</td>
</tr>
<tr>
<td align="right">
@@ -541,9 +538,9 @@ Catch and report any errors, then disconnect from the XRP Ledger.
<td>
<input type="text" id="transactionField" size="40"></input>
<br>
</td>
</td>
<td>
</td>
</td>
</tr>
<tr>
<td colspan="2">

View File

@@ -1,27 +1,27 @@
---
seo:
description: Create offers to exchange issued currencies and XRP.
description: Create offers to exchange issued currencies and XRP.
labels:
- Accounts
- Transaction Sending
- XRP
- Issued Currencies
---
# Create Offers
This example shows how to:
1. Create currency offers.
1. Create currency offers.
2. Retrieve active offers.
3. Match a currency offer to exchange tokens.
4. Cancel an unsettled offer.
[![Offer Create Token Test Harness](/docs/img/mt-create-offers-1-empty-form-info.png)](/docs/img/mt-create-offers-1-empty-form-info.png)
Download and expand the [Modular Tutorials](../../../../_code-samples/modular-tutorials/payment-modular-tutorials.zip)<!-- {.github-code-download} --> archive.
**Note:** Without the Modular Tutorial Samples, you will not be able to try the examples that follow.
**Note:** Without the Modular Tutorial Samples, you will not be able to try the examples that follow.
## Usage
@@ -30,15 +30,15 @@ To get test accounts:
1. Open `create-offers.html` in a browser.
2. Choose your preferred test network (**Devnet** or **Testnet**).
3. 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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Created Accounts](/docs/img/mt-create-offers-2-form-with-account-info.png)](/docs/img/mt-create-offers-2-form-with-account-info.png)
@@ -50,11 +50,11 @@ To create an offer to exchange XRP for an issued currency:
1. Click **Account 1** or **Account 2**.
2. Enter _XRP_ as the Taker Pays **Currency Code**.
2. Enter the Taker Pays **Amount** in drops. For example, _50000000_.
3. Enter the Taker Gets **Currency**. For example, _USD_.
4. Copy the current **Account Address** and paste it in the Taker Gets **Issuer** field.
5. Enter the Taker Gets **Amount**. For example, _50_.
6. Click **Create Offer**.
3. Enter the Taker Pays **Amount** in drops. For example, _50000000_.
4. Enter the Taker Gets **Currency**. For example, _USD_.
5. Copy the current **Account Address** and paste it in the Taker Gets **Issuer** field.
6. Enter the Taker Gets **Amount**. For example, _50_.
7. Click **Create Offer**.
[![Created an offer for XRP and USD](/docs/img/mt-create-offers-3-xrp-for-usd-offer.png)](/docs/img/mt-create-offers-3-xrp-for-usd-offer.png)
@@ -69,11 +69,10 @@ Click **Get Offers** to get a list of offers issued by the corresponding account
1. Choose an account other than the Issuer. For example, **Account 2**.
2. Enter _XRP_ as the Taker Gets **Currency Code**.
3. Enter the Taker Gets **Amount**. For example, _50000000_.
3. Enter the Taker Pays **Currency Code**, for example _USD_.
4. Enter the Taker Pays **Issuer**. For example, the **Account 1 Address**.
5. Enter the Taker Pays **Amount** For example, _50_.
6. Click **Create Offer**.
4. Enter the Taker Pays **Currency Code**, for example _USD_.
5. Enter the Taker Pays **Issuer**. For example, the **Account 1 Address**.
6. Enter the Taker Pays **Amount** For example, _50_.
7. Click **Create Offer**.
[![Results of matching offers for XRP and USD](/docs/img/mt-create-offers-4-matching-offer.png)](/docs/img/mt-create-offers-4-matching-offer.png)
@@ -97,7 +96,7 @@ You can download the [Payment Modular Tutorials](/_code-samples/modular-tutorial
The functions in create-offer.html leverage functions from the base module. The functions that follow are solely focused on creating and handling offers.
### Create Offer
### Create Offer
Connect to the XRP Ledger and get the account wallet.
@@ -128,51 +127,48 @@ Gather the information for what the taker pays, and what the taker gets in retur
The same logic is used to create the value for the `takerPays` parameter.
```javascript
if (payCurrencyField.value == 'XRP') {
takerPays = xrpl.xrpToDrops(payAmountField.value)
} else {
takerPaysString = '{"currency": "' + payCurrencyField.value + '",\n' +
'"issuer": "' + payIssuerField.value + '",\n' +
'"value": "' + payAmountField.value + '"}'
takerPays = JSON.parse(takerPaysString)
}
```
if (payCurrencyField.value == 'XRP') {
takerPays = xrpl.xrpToDrops(payAmountField.value)
} else {
takerPaysString =
'{"currency": "' + payCurrencyField.value + '",\n' + '"issuer": "' + payIssuerField.value + '",\n' + '"value": "' + payAmountField.value + '"}'
takerPays = JSON.parse(takerPaysString)
}
```
Define the `OfferCreate` transaction, using the `takerPays` and `takerGets` parameters defined above.
```javascript
const prepared = await client.autofill({
"TransactionType": "OfferCreate",
"Account": wallet.address,
"TakerGets": takerGets,
"TakerPays": takerPays
})
```javascript
const prepared = await client.autofill({
TransactionType: 'OfferCreate',
Account: wallet.address,
TakerGets: takerGets,
TakerPays: takerPays,
})
```
Sign and send the prepared transaction, and wait for the results.
```javascript
const signed = wallet.sign(prepared)
const tx = await client.submitAndWait(signed.tx_blob)
const signed = wallet.sign(prepared)
const tx = await client.submitAndWait(signed.tx_blob)
```
Request the token balance changes after the transaction.
```javascript
results = '\n\n===Offer created===\n\n' +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value += results
results = '\n\n===Offer created===\n\n' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value += results
```
Get the new XRP balance, reflecting the payments and transaction fees.
```javascript
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
```
```javascript
getOffers()
getOffers()
```
Catch and report any errors, then disconnect from the XRP Ledger.
@@ -185,7 +181,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
throw err; // Re-throw the error to be handled by the caller
}
finally {
// Disconnect from the client
// Disconnect from the client
client.disconnect()
})
```
@@ -266,16 +262,15 @@ Prepare the `OfferCancel` transaction, passing the account address of the accoun
Sign and submit the transaction, then wait for the result.
```javascript
const signed = wallet.sign(prepared)
const tx = await client.submitAndWait(signed.tx_blob)
const signed = wallet.sign(prepared)
const tx = await client.submitAndWait(signed.tx_blob)
```
Report the results.
```javascript
results += "\nOffer canceled. Balance changes: \n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value = results
results += '\nOffer canceled. Balance changes: \n' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value = results
```
Catch and report any errors, then disconnect from the XRP Ledger.
@@ -368,7 +363,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
<label for="account1address">Account 1 Address</label>
</span>
</td>
<td>
<td>
<input type="text" id="account1address" size="40"></input>
</td>
<td>
@@ -468,11 +463,11 @@ Catch and report any errors, then disconnect from the XRP Ledger.
</td>
<td>
<input type="text" id="getCurrencyField" size="40"></input>
</td>
<td>
</td>
<td>
<button type="button" onClick="createOffer()">Create Offer</button>
</td>
</tr>
</td>
</tr>
<tr>
<td align="right">
<span class="tooltip" tooltip-data="Issuers of the offered currencies.">
@@ -481,14 +476,14 @@ Catch and report any errors, then disconnect from the XRP Ledger.
</td>
<td>
<input type="text" id="payIssuerField" size="40"></input>&nbsp;&nbsp;
</td>
</td>
<td>
<input type="text" id="getIssuerField" size="40"></input>&nbsp;&nbsp;
</td>
<td>
<button type="button" onClick="getOffers()">Get Offers</button>
</td>
</tr>
</tr>
<tr>
<td align="right">
<span class="tooltip" tooltip-data="Amounts of offered currencies.">
@@ -497,7 +492,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
</td>
<td>
<input type="text" id="payAmountField" size="40"></input>
</td>
</td>
<td>
<input type="text" id="getAmountField" size="40"></input>
</td>
@@ -513,12 +508,12 @@ Catch and report any errors, then disconnect from the XRP Ledger.
</td>
<td>
<input type="text" id="offerSequenceField" size="40"></input>
</td>
</td>
<td></td>
<td>
<button type="button" onClick="getTokenBalance()">Get Token Balance</button>
</td>
</tr>
</tr>
<tr>
<td colspan="3">
<p align="right">
@@ -547,5 +542,3 @@ Catch and report any errors, then disconnect from the XRP Ledger.
</script>
</html>
```

View File

@@ -1,21 +1,20 @@
---
seo:
description: Create, finish, or cancel time-based escrow transactions.
description: Create, finish, or cancel time-based escrow transactions.
labels:
- Accounts
- Transaction Sending
- XRP
---
# Create Time-based Escrows Using JavaScript
This example shows how to:
1. Create escrow payments that become available at a specified time and expire at a specified time.
2. Finish an escrow payment.
3. Retrieve information on escrows attached to an account.
3. Cancel an escrow payment and return the XRP to the sending account.
4. Cancel an escrow payment and return the XRP to the sending account.
[![Time-based Escrow Form](/docs/img/mt-time-escrow-1-empty-form.png)](/docs/img/mt-time-escrow-1-empty-form.png)
@@ -29,15 +28,15 @@ To get test accounts:
1. Open `create-time-based-escrows.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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Escrow Tester with Account Information](/docs/img/mt-time-escrow-2-form-with-accounts.png)](/docs/img/mt-time-escrow-2-form-with-accounts.png)
@@ -49,10 +48,10 @@ To create a time-based escrow:
1. Enter an **Amount** to transfer. For example, _10_.
2. Enter the **Destination**. (For example, the Account 2 address.)
4. Set the **Escrow Finish Time** value, in seconds. For example, enter _10_.
5. Set the **Escrow Cancel Time** value, in seconds. For example, enter _120_.
6. Click **Create Time-based Escrow**.
7. Copy the _Sequence Number_ of the escrow called out in the **Standby Result** field.
3. Set the **Escrow Finish Time** value, in seconds. For example, enter _10_.
4. Set the **Escrow Cancel Time** value, in seconds. For example, enter _120_.
5. Click **Create Time-based Escrow**.
6. Copy the _Sequence Number_ of the escrow called out in the **Standby Result** field.
The escrow is created on the XRP Ledger instance, reserving 10 XRP plus the transaction cost. When you create an escrow, capture and save the **Sequence Number** so that you can use it to finish the escrow transaction.
@@ -68,7 +67,7 @@ To finish a time-based escrow:
1. Paste the sequence number in the Operational account **Escrow Sequence Number** field.
2. Copy and paste the address that created the escrow in the **Escrow Owner** field.
2. Click **Finish Time-based Escrow**.
3. Click **Finish Time-based Escrow**.
The transaction completes and balances are updated for both the Standby and Operational accounts.
@@ -84,7 +83,6 @@ Click **Get Escrows**.
[![Get Escrows results](/docs/img/mt-time-escrow-5-get-escrows.png)](/docs/img/mt-time-escrow-5-get-escrows.png)
## Cancel Escrow
When the Escrow Cancel time passes, the escrow is no longer available to the recipient. The initiator of the escrow can reclaim the XRP, less the transaction fees. If you try to cancel the transaction prior to the **Escrow Cancel** time, you are charged for the transaction, but the actual escrow cannot be cancelled until the time limit is reached.
@@ -95,7 +93,7 @@ To cancel an expired escrow:
1. Enter the sequence number in the **Escrow Sequence Number** field.
2. Enter the address of the account that created the escrow in the **Escrow Owner** field.
2. Click **Cancel Escrow**.
3. Click **Cancel Escrow**.
The funds are returned to the owner account, less the initial transaction fee.
@@ -127,6 +125,7 @@ This example can be used with any XRP Ledger network, _Testnet_, or _Devnet_. Yo
This function accomplishes two things. It creates a new date object and adds the number of seconds taken from a form field. Then, it adjusts the date from the JavaScript format to the XRP Ledger format.
You provide the _numOfSeconds_ argument, the second parameter is a new Date object.
```javascript
function addSeconds(numOfSeconds, date = new Date()) {
```
@@ -134,19 +133,19 @@ function addSeconds(numOfSeconds, date = new Date()) {
Set the _seconds_ value to the date seconds plus the number of seconds you provide.
```javascript
date.setSeconds(date.getSeconds() + numOfSeconds);
date.setSeconds(date.getSeconds() + numOfSeconds)
```
JavaScript dates are in milliseconds. Divide the date by 1000 to base it on seconds.
```javascript
date = Math.floor(date / 1000)
date = Math.floor(date / 1000)
```
Subtract the number of seconds in the Ripple epoch to convert the value to an XRP Ledger compatible date value.
```javascript
date = date - 946684800
date = date - 946684800
```
Return the result.
@@ -165,20 +164,20 @@ async function createTimeBasedEscrow() {
Instantiate two new date objects, then set the dates to the current date plus the set number of seconds for the finish and cancel dates.
```javascript
let escrow_finish_date = new Date()
let escrow_cancel_date = new Date()
escrow_finish_date = addSeconds(parseInt(escrowFinishTimeField.value))
escrow_cancel_date = addSeconds(parseInt(escrowCancelTimeField.value))
let escrow_finish_date = new Date()
let escrow_cancel_date = new Date()
escrow_finish_date = addSeconds(parseInt(escrowFinishTimeField.value))
escrow_cancel_date = addSeconds(parseInt(escrowCancelTimeField.value))
```
Connect to the ledger and get the account wallet.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `===Connected to ${net}.===\n\n===Creating time-based escrow.===\n`
resultField.value = results
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `===Connected to ${net}.===\n\n===Creating time-based escrow.===\n`
resultField.value = results
```
Define the transaction object.
@@ -196,9 +195,9 @@ Define the transaction object.
"CancelAfter": escrow_cancel_date
})
```
```
Sign the prepared transaction object.
Sign the prepared transaction object.
```javascript
const signed = wallet.sign(escrowTx)
@@ -208,7 +207,7 @@ Define the transaction object.
Submit the signed transaction object and wait for the results.
```javascript
const tx = await client.submitAndWait(signed.tx_blob)
const tx = await client.submitAndWait(signed.tx_blob)
```
Report the results.
@@ -232,7 +231,6 @@ Catch and report any errors, then disconnect from the XRP Ledger.
}
```
### Finish Time-based Escrow
```javascript
@@ -242,49 +240,48 @@ async function finishEscrow() {
Connect to the XRP Ledger.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `===Connected to ${net}. Finishing escrow.===\n`
resultField.value = results
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `===Connected to ${net}. Finishing escrow.===\n`
resultField.value = results
```
Define the transaction. The _Owner_ is the account that created the escrow. The _OfferSequence_ is the sequence number of the escrow transaction. Automatically fill in the common fields for the transaction.
```javascript
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
const prepared = await client.autofill({
"TransactionType": "EscrowFinish",
"Account": accountAddressField.value,
"Owner": escrowOwnerField.value,
"OfferSequence": parseInt(escrowSequenceNumberField.value)
})
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
const prepared = await client.autofill({
TransactionType: 'EscrowFinish',
Account: accountAddressField.value,
Owner: escrowOwnerField.value,
OfferSequence: parseInt(escrowSequenceNumberField.value),
})
```
Sign the transaction definition.
```javascript
const signed = wallet.sign(prepared)
const signed = wallet.sign(prepared)
```
Submit the signed transaction to the XRP ledger.
```javascript
const tx = await client.submitAndWait(signed.tx_blob)
const tx = await client.submitAndWait(signed.tx_blob)
```
Report the results.
```javascript
results += "\n===Balance changes===" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value = results
results += '\n===Balance changes===' + JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
resultField.value = results
```
Update the **XRP Balance** field.
```javascript
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
```
Catch and report any errors, then disconnect from the XRP Ledger.
@@ -299,7 +296,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
}
```
### Get Escrows
### Get Escrows
Get the escrows created by or destined to the current account.
@@ -310,11 +307,11 @@ async function getEscrows() {
Connect to the network. The information you are looking for is public information, so there is no need to instantiate your wallet.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `\n===Connected to ${net}.\nGetting account escrows.===\n`
resultField.value = results
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `\n===Connected to ${net}.\nGetting account escrows.===\n`
resultField.value = results
```
Create the `account_objects` request. Specify that you want objects of the type _escrow_.
@@ -337,8 +334,8 @@ Report the results.
resultField.value = results
}
```
Catch and report any errors, then disconnect from the XRP Ledger.
Catch and report any errors, then disconnect from the XRP Ledger.
```javascript
catch (error) {
@@ -351,7 +348,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
}
```
### Get Transaction Info
### Get Transaction Info
```javascript
async function getTransaction() {
@@ -360,15 +357,15 @@ async function getTransaction() {
Connect to the XRP Ledger.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `\n===Connected to ${net}.===\n===Getting transaction information.===\n`
resultField.value = results
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `\n===Connected to ${net}.===\n===Getting transaction information.===\n`
resultField.value = results
```
Prepare and send the transaction information request. The only required parameter is the transaction ID.
```javascript
try {
const tx_info = await client.request({
@@ -377,16 +374,17 @@ Prepare and send the transaction information request. The only required paramete
"transaction": transactionField.value,
})
```
Report the results.
```javascript
results += JSON.stringify(tx_info.result, null, 2)
resultField.value = results
}
```
Catch and report any errors, then disconnect from the XRP Ledger.
Catch and report any errors, then disconnect from the XRP Ledger.
```javascript
catch (error) {
results += "\nError: " + error.message
@@ -409,11 +407,11 @@ async function cancelEscrow() {
Connect to the XRP Ledger instance and get the account wallet.
```javascript
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `\n===Connected to ${net}. Cancelling escrow.===`
resultField.value = results
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = `\n===Connected to ${net}. Cancelling escrow.===`
resultField.value = results
```
Prepare the EscrowCancel transaction, passing the escrow owner and offer sequence values.
@@ -431,14 +429,14 @@ Prepare the EscrowCancel transaction, passing the escrow owner and offer sequenc
Sign the transaction.
```javascript
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
const signed = wallet.sign(prepared)
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
const signed = wallet.sign(prepared)
```
Submit the transaction and wait for the response.
``` javascript
const tx = await client.submitAndWait(signed.tx_blob)
```javascript
const tx = await client.submitAndWait(signed.tx_blob)
```
Report the results.
@@ -537,7 +535,7 @@ Catch and report any errors, then disconnect from the XRP Ledger instance.
<label for="account1address">Account 1 Address</label>
</span>
</td>
<td>
<td>
<input type="text" id="account1address" size="40"></input>
</td>
<td>
@@ -677,10 +675,10 @@ Catch and report any errors, then disconnect from the XRP Ledger instance.
<td>
<input type="text" id="escrowSequenceNumberField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="cancelEscrow()">Cancel Escrow</button>
</td>
</td>
</tr>
<tr>
<td align="right">
@@ -691,10 +689,10 @@ Catch and report any errors, then disconnect from the XRP Ledger instance.
<td>
<input type="text" id="escrowOwnerField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="getTransaction()">Get Transaction</button>
</td>
</td>
</tr>
<tr>
<td align="right">
@@ -705,9 +703,9 @@ Catch and report any errors, then disconnect from the XRP Ledger instance.
<td>
<input type="text" id="transactionField" size="40"></input>
<br>
</td>
</td>
<td>
</td>
</td>
</tr>
<tr>
<td colspan="2">

View File

@@ -1,12 +1,12 @@
---
seo:
description: Create Trust Lines and send currency.
description: Create Trust Lines and send currency.
labels:
- Cross-Currency
- Payments
- Tokens
---
# Create Trust Line and Send Currency Using JavaScript
This example shows how to:
@@ -15,7 +15,7 @@ This example shows how to:
2. Send issued currency between accounts.
3. Display account balances for all currencies.
[![Send Currency test harness](/docs/img/mt-send-currency-1-empty-form-info.png )](/docs/img/mt-send-currency-1-empty-form-info.png)
[![Send Currency test harness](/docs/img/mt-send-currency-1-empty-form-info.png)](/docs/img/mt-send-currency-1-empty-form-info.png)
You can download the [Payment Modular Tutorials](/_code-samples/modular-tutorials/payment-modular-tutorials.zip) from the source repository for this website.
@@ -27,15 +27,15 @@ Open the Send Currency test harness and get accounts:
1. Open `send-currency.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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Distribute Account Information](/docs/img/mt-send-currency-2-distribute-accounts.png)](/docs/img/mt-send-currency-2-distribute-accounts.png)
@@ -62,11 +62,11 @@ To create a trust line between accounts:
To transfer an issued currency token, once you have created a trust line:
1. Click **Account 1**.
3. Enter the **Currency Code**.
4. Copy and paste the **Account 1 Address** to the **Issuer** field.
2. Enter the **Currency Code**.
3. Copy and paste the **Account 1 Address** to the **Issuer** field.
4. Enter the **Amount** of issued currency to send.
2. Copy and paste the **Account 2 Address** to the **Destination** field.
4. Click **Send Currency**.
5. Copy and paste the **Account 2 Address** to the **Destination** field.
6. Click **Send Currency**.
[![Currency transfer](/docs/img/mt-send-currency-4-send-currency.png)](/docs/img/mt-send-currency-4-send-currency.png)
@@ -101,7 +101,7 @@ Connect to the XRPL server.
```javascript
async function createTrustLine() {
const net = getNet()
const net = getNet()
const client = new xrpl.Client(net)
await client.connect()
let results = "\nConnected. Creating trust line.\n"
@@ -127,15 +127,15 @@ Create a `TrustSet` transaction, passing the currency code, issuer account, and
Autofill the remaining default transaction parameters.
```javascript
const ts_prepared = await client.autofill(trustSet_tx)
const ts_prepared = await client.autofill(trustSet_tx)
```
Sign and send the transaction to the XRPL server, then wait for the results.
```javascript
const ts_signed = wallet.sign(ts_prepared)
resultField.value = results
const ts_result = await client.submitAndWait(ts_signed.tx_blob)
const ts_signed = wallet.sign(ts_prepared)
resultField.value = results
const ts_result = await client.submitAndWait(ts_signed.tx_blob)
```
Report the results of the transaction.
@@ -147,7 +147,7 @@ Report the results of the transaction.
resultField.value = results
} else {
results += `\n===Transaction failed: ${ts_result.result.meta.TransactionResult}`
resultField.value = results
resultField.value = results
}
}
```
@@ -170,6 +170,7 @@ Catch and report any errors, then disconnect from the XRP Ledger.
```
### sendCurrency()
This transaction actually sends a transaction that changes balances on both sides of the trust line.
Connect to the XRP Ledger and get the account wallet.
@@ -200,12 +201,12 @@ Create a payment transaction to the destination account, specifying the amount u
},
"Destination": destinationField.value
}
```
```
Autofill the remaining default transaction parameters.
```javascript
const pay_prepared = await client.autofill(send_currency_tx)
const pay_prepared = await client.autofill(send_currency_tx)
```
Sign and send the prepared payment transaction to the XRP Ledger, then await and report the results.
@@ -319,7 +320,7 @@ Update the form to support the new functions.
<label for="account1address">Account 1 Address</label>
</span>
</td>
<td>
<td>
<input type="text" id="account1address" size="40"></input>
</td>
<td>
@@ -406,10 +407,10 @@ Update the form to support the new functions.
<td>
<input type="text" id="currencyField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="createTrustLine()">Create Trust Line</button>
</td>
</td>
</tr>
<tr>
<td align="right">
@@ -420,10 +421,10 @@ Update the form to support the new functions.
<td>
<input type="text" id="issuerField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="sendCurrency()">Send Currency</button>
</td>
</td>
</tr>
<tr>
<td align="right">

View File

@@ -1,7 +1,7 @@
---
top_nav_grouping: Article Types
seo:
description: Send XRP and Issued Currencies on the XRPL.
description: Send XRP and Issued Currencies on the XRPL.
labels:
- Accounts
- Transactions
@@ -10,11 +10,11 @@ labels:
metadata:
indexPage: true
---
# Send Payments Using JavaScript
Send XRP and issued currency on the XRP Ledger using JavaScript.
Download and expand the [Payment Modular Tutorial Samples](/_code-samples/modular-tutorials/payment-modular-tutorials.zip) archive.
{% child-pages /%}

View File

@@ -6,11 +6,12 @@ labels:
- Checks
- XRP
---
# Send and Cash Checks
This example shows how to:
1. Send a check to transfer XRP or issued currency to another account.
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.
@@ -18,8 +19,7 @@ This example shows how to:
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.
2. The receiver can choose to accept less than the full amount of the check. This allows you to authorize a maximum amount when the actual cost is not finalized.
[![Empty Check Form](/docs/img/mt-send-checks-1-empty-form.png)](/docs/img/mt-send-checks-1-empty-form.png)
@@ -37,15 +37,15 @@ 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**.
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**.
3. If you do not have existing accounts:
1. Click **Get New Account 1**.
2. Click **Get New Account 2**.
[![Form with Accounts](/docs/img/mt-send-checks-2-form-with-accounts.png)](/docs/img/mt-send-checks-2-form-with-accounts.png)
@@ -55,9 +55,9 @@ 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**.
3. Enter the receiving account address in the **Destination** field.
4. Set the **Currency Code** to _XRP_.
5. Click **Send Check**.
[![Send Check Settings](/docs/img/mt-send-checks-3-send-xrp.png)](/docs/img/mt-send-checks-3-send-xrp.png)
@@ -74,7 +74,6 @@ To send a check for an issued currency token:
[![Send Token Check Settings](/docs/img/mt-send-checks-4-send-currency.png)](/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.
@@ -88,10 +87,8 @@ 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.
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**.
[![Cashed check results](/docs/img/mt-send-checks-6-cash-check.png)](/docs/img/mt-send-checks-6-cash-check.png)
@@ -130,66 +127,65 @@ async function sendCheck() {
resultField.value = results
```
Prepare the transaction. Set the *check_amount* variable to the value in the **Amount** field.
Prepare the transaction. Set the _check_amount_ variable to the value in the **Amount** field.
```javascript
try {
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.
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
```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)
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)
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)
}
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))
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
```
Report any errors, then disconnect from the XRP ledger.
@@ -208,11 +204,12 @@ Report any errors, then disconnect from the XRP ledger.
## getChecks()
Connect to the XRP Ledger.
```javascript
async function getChecks() {
let net = getNet()
const client = new xrpl.Client(net)
await client.connect()
await client.connect()
let results = `\n===Connected to ${net}.===\n===Getting account checks.===\n\n`
resultField.value = results
```
@@ -229,10 +226,11 @@ Define an `account_objects` query, filtering for the _check_ object type.
"type": "check"
})
```
Display the retrieved `Check` objects in the result field.
```javascript
resultField.value += JSON.stringify(check_objects.result, null, 2)
resultField.value += JSON.stringify(check_objects.result, null, 2)
```
Catch and report any errors, then disconnect from the XRP Ledger.
@@ -272,59 +270,59 @@ Set the check amount.
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
}
}
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
}
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)
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
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)
```
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
}
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));
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
```
Catch and report any errors, then disconnect from the XRP ledger.
@@ -367,34 +365,34 @@ Create the CheckCancel transaction object, passing the wallet address and the Ch
Autofill the transaction details.
```javascript
const cancel_prepared = await client.autofill(cancel_check_tx)
const cancel_prepared = await client.autofill(cancel_check_tx)
```
Sign the prepared transaction.
```javascript
const cancel_signed = wallet.sign(cancel_prepared)
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)
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
}
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))
xrpBalanceField.value = await client.getXrpBalance(wallet.address)
```
Catch and report any errors, then disconnect from the XRP ledger.
@@ -485,7 +483,7 @@ Catch and report any errors, then disconnect from the XRP ledger.
<label for="account1address">Account 1 Address</label>
</span>
</td>
<td>
<td>
<input type="text" id="account1address" size="40"></input>
</td>
<td>
@@ -572,10 +570,10 @@ Catch and report any errors, then disconnect from the XRP ledger.
<td>
<input type="text" id="currencyField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="sendCheck()">Send Check</button>
</td>
</td>
</tr>
<tr>
<td align="right">
@@ -586,10 +584,10 @@ Catch and report any errors, then disconnect from the XRP ledger.
<td>
<input type="text" id="issuerField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="cashCheck()">Cash Check</button>
</td>
</td>
</tr>
<tr>
<td align="right">

View File

@@ -1,10 +1,11 @@
---
seo:
description: Issue an asset-backed token such as a US Treasury bill using multi-purpose tokens.
description: Issue an asset-backed token such as a US Treasury bill using multi-purpose tokens.
labels:
- Tokens
- MPT
- Tokens
- MPT
---
# Sending MPTs
To send an MPT to another account, the receiving account must first authorize the receipt of the MPT, based on its MPToken Issuance ID. This is to prevent malicious users from spamming accounts with unwanted tokens that could negatively impact storage and XRP reserves.
@@ -31,13 +32,13 @@ To get the accounts:
2. Choose your ledger instance (**Devnet** or **Testnet**).
3. If you used the MPT Generator:
1. Paste the gathered info in the **Result** field.
[![Gathered information in Result field](../../../img/mt-send-mpt-1-gathered-info.png)](../../../img/mt-send-mpt-1-gathered-info.png)
[![Gathered information in Result field](../../../img/mt-send-mpt-1-gathered-info.png)](../../../img/mt-send-mpt-1-gathered-info.png)
2. Cut and paste the MPT Issuance ID to the **MPT Issuance ID** field.
3. Click **Distribute Account Info** to populate the **Account 1** fields.<br/><br/>
If you did not use the MPT Generator, enter the **Account 1 Name**, **Account 1 Address**, **Account 1 Seed**, and **MPT Issuance ID** in the corresponding fields.)
If you did not use the MPT Generator, enter the **Account 1 Name**, **Account 1 Address**, **Account 1 Seed**, and **MPT Issuance ID** in the corresponding fields.)
4. Click **Get New Account 2**, or use a seed to **Get Account 2 from Seed**.
5. Optionally, add the **Account 2 Name**, an arbitrary human-readable name that helps to differentiate the accounts.
[![Get New Account 2](../../../img/mt-send-mpt-2-account-2.png)](../../../img/mt-send-mpt-2-account-2.png)
[![Get New Account 2](../../../img/mt-send-mpt-2-account-2.png)](../../../img/mt-send-mpt-2-account-2.png)
## Authorize MPT
@@ -47,19 +48,19 @@ To authorize Account 2 to accept MPTs:
1. Click the **Account 2** radio button.
2. Enter an **Amount**, the maximum number of MPTs the account will accept.
2. Click **Authorize MPTs**.
[![Authorize MPTs](../../../img/mt-send-mpt-2-authorize-mpt.png)](../../../img/mt-send-mpt-2-authorize-mpt.png)
3. Click **Authorize MPTs**.
[![Authorize MPTs](../../../img/mt-send-mpt-2-authorize-mpt.png)](../../../img/mt-send-mpt-2-authorize-mpt.png)
## Send MPT
To send an MPT:
1. Click the **Account 1** radio button.
3. Enter the **MPT Issuance ID**.
2. Enter an **Amount** of MPTs to send.
3. Enter the **Destination** (likely the value in the **Account 2 Address** field, but it can be any account on the same ledger instance).
4. Click **Send MPT**.
[![Send MPTs](../../../img/mt-send-mpt-3-send-mpt.png)](../../../img/mt-send-mpt-3-send-mpt.png)
2. Enter the **MPT Issuance ID**.
3. Enter an **Amount** of MPTs to send.
4. Enter the **Destination** (likely the value in the **Account 2 Address** field, but it can be any account on the same ledger instance).
5. Click **Send MPT**.
[![Send MPTs](../../../img/mt-send-mpt-3-send-mpt.png)](../../../img/mt-send-mpt-3-send-mpt.png)
## Get MPTs
@@ -67,7 +68,7 @@ To verify receipt of the MPTs:
1. Click the **Account 2** radio button.
2. Click **Get MPTs**.
[![Get MPTs](../../../img/mt-send-mpt-4-get-mpts.png)](../../../img/mt-send-mpt-4-get-mpts.png)
[![Get MPTs](../../../img/mt-send-mpt-4-get-mpts.png)](../../../img/mt-send-mpt-4-get-mpts.png)
# Code Walkthrough
@@ -81,7 +82,7 @@ The code that supports the MPT features is in the `send-mpt.js` file. Standard s
Connect to the XRP Ledger.
```javascript
```javascript
async function sendMPT() {
let net = getNet()
const client = new xrpl.Client(net)
@@ -102,22 +103,22 @@ Instantiate the parameter variables.
Create a Payment transaction using the MPT for the Amount.
```javascript
const send_mpt_tx = {
"TransactionType": "Payment",
"Account": wallet.address,
"Amount": {
"mpt_issuance_id": mpt_issuance_id,
"value": mpt_quantity,
},
"Destination": destinationField.value,
}
const send_mpt_tx = {
TransactionType: 'Payment',
Account: wallet.address,
Amount: {
mpt_issuance_id: mpt_issuance_id,
value: mpt_quantity,
},
Destination: destinationField.value,
}
```
Prepare and sign the transaction.
```javascript
const pay_prepared = await client.autofill(send_mpt_tx)
const pay_signed = wallet.sign(pay_prepared)
const pay_prepared = await client.autofill(send_mpt_tx)
const pay_signed = wallet.sign(pay_prepared)
```
Send the prepared transaction and report the results.
@@ -177,27 +178,27 @@ Send an `account_objects` request, specifying the type _mptoken_. Wait for the r
Stringify and parse the JSON result string.
```javascript
let JSONString = JSON.stringify(mpts.result, null, 2)
let JSONParse = JSON.parse(JSONString)
let numberOfMPTs = JSONParse.account_objects.length
let JSONString = JSON.stringify(mpts.result, null, 2)
let JSONParse = JSON.parse(JSONString)
let numberOfMPTs = JSONParse.account_objects.length
```
Loop through the filtered array of account_objects to list all of the MPTs held by the account.
```javascript
let x = 0
while (x < numberOfMPTs){
results += "\n\n===MPT Issuance ID: " + JSONParse.account_objects[x].MPTokenIssuanceID
+ "\n===MPT Amount: " + JSONParse.account_objects[x].MPTAmount
x++
}
let x = 0
while (x < numberOfMPTs) {
results +=
'\n\n===MPT Issuance ID: ' + JSONParse.account_objects[x].MPTokenIssuanceID + '\n===MPT Amount: ' + JSONParse.account_objects[x].MPTAmount
x++
}
```
Return the parsed results, followed by the raw results.
```javascript
results += "\n\n" + JSONString
resultField.value += results
results += '\n\n' + JSONString
resultField.value += results
```
Catch and report any errors, then disconnect from the XRP Ledger.
@@ -232,27 +233,27 @@ async function authorizeMPT() {
Capture the MPT issuance ID in a variable.
```javascript
const mpt_issuance_id = mptIdField.value
const mpt_issuance_id = mptIdField.value
```
Create the MPTokenAuthorize transaction, passing the target account's address and the MPT Issuance ID.
```javascript
const auth_mpt_tx = {
"TransactionType": "MPTokenAuthorize",
"Account": wallet.address,
"MPTokenIssuanceID": mpt_issuance_id,
}
const auth_mpt_tx = {
TransactionType: 'MPTokenAuthorize',
Account: wallet.address,
MPTokenIssuanceID: mpt_issuance_id,
}
```
Prepare, sign, and send the transaction.
```javascript
const auth_prepared = await client.autofill(auth_mpt_tx)
const auth_signed = wallet.sign(auth_prepared)
results += `\n\nSending authorization...`
resultField.value = results
const auth_result = await client.submitAndWait(auth_signed.tx_blob)
const auth_prepared = await client.autofill(auth_mpt_tx)
const auth_signed = wallet.sign(auth_prepared)
results += `\n\nSending authorization...`
resultField.value = results
const auth_result = await client.submitAndWait(auth_signed.tx_blob)
```
Report the results.
@@ -343,7 +344,7 @@ Report the results.
<label for="account1address">Account 1 Address</label>
</span>
</td>
<td>
<td>
<input type="text" id="account1address" size="40"></input>
</td>
<td>
@@ -430,10 +431,10 @@ Report the results.
<td>
<input type="text" id="mptIdField" size="40"></input>
<br>
</td>
</td>
<td>
<button type="button" onClick="authorizeMPT()">Authorize MPT</button>
</td>
</td>
</tr>
<tr>
<td align="right">
@@ -447,7 +448,7 @@ Report the results.
</td>
<td>
<button type="button" onClick="sendMPT()">Send MPT</button>
</td>
</td>
</tr>
<tr>
@@ -492,10 +493,11 @@ Report the results.
</script>
</html>
```
<!--
<div>
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
<script>
if (typeof module !== "undefined") {
const xrpl = require("xrpl")
@@ -513,7 +515,7 @@ function getNet() {
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()
} // End of getNet()
// *******************************************************
// ************* Get Account *****************************
// *******************************************************
@@ -547,11 +549,11 @@ function getNet() {
await client.connect()
results += '\nConnected, finding wallets.\n'
console.log(results)
// --------------------------------------------------Find the test account wallet.
const my_wallet = xrpl.Wallet.fromSeed(holderSeedField.value)
// --------------------------------------------------Find the test account wallet.
const my_wallet = xrpl.Wallet.fromSeed(holderSeedField.value)
// -------------------------------------------------------Get the current balance.
holderAccountField.value = my_wallet.address
holderSeedField.value = my_wallet.seed
holderSeedField.value = my_wallet.seed
client.disconnect()
} // End of getHolderFromSeed()
// **********************************************************
@@ -565,12 +567,12 @@ function getNet() {
await client.connect()
results += '\nConnected, finding wallets.\n'
resultsArea.value = results
// --------------------------------------------------Find the test account wallet.
const my_wallet = xrpl.Wallet.fromSeed(receiverSeedField.value)
// --------------------------------------------------Find the test account wallet.
const my_wallet = xrpl.Wallet.fromSeed(receiverSeedField.value)
// -------------------------------------------------------Get the current balance.
receiverAccountField.value = my_wallet.address
receiverSeedField.value = my_wallet.seed
resultsArea.value = results
receiverSeedField.value = my_wallet.seed
resultsArea.value = results
client.disconnect()
} // End of getReceiverFromSeed()
// *******************************************************
@@ -583,7 +585,7 @@ async function sendMPT() {
resultsArea.value = results
await client.connect()
results += '\nConnected.'
resultsArea.value = results
resultsArea.value = results
const holder_wallet = xrpl.Wallet.fromSeed(holderSeedField.value)
const mpt_issuance_id = mptIssuanceIDField.value
const mpt_quantity = quantityField.value
@@ -678,7 +680,7 @@ async function authorizeMPT() {
<div>
<form>
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
<!-- Required meta tags - - >
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@@ -841,4 +843,5 @@ async function authorizeMPT() {
<hr/>
-->
{% raw-partial file="/docs/_snippets/common-links.md" /%}