create offers tutorial

This commit is contained in:
ddawson
2024-09-05 11:14:08 -07:00
parent 069a218ff8
commit 546ea9f609
13 changed files with 1888 additions and 0 deletions

View File

@@ -0,0 +1,313 @@
<html>
<head>
<title>Token Test Harness</title>
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
<style>
body{font-family: "Work Sans", sans-serif;padding: 20px;background: #fafafa;}
h1{font-weight: bold;}
input, button {padding: 6px;margin-bottom: 8px;}
button{font-weight: bold;font-family: "Work Sans", sans-serif;}
td{vertical-align: middle;}
</style>
<script src='https://unpkg.com/xrpl@2.7.0/build/xrpl-latest-min.js'></script>
<script src='ripplex2-send-currency.js'></script>
<script src='ripplex3a-create-offers.js'></script>
<script src='ripplex3b-NameFieldSupport.js'></script>
<script>
if (typeof module !== "undefined") {
const xrpl = require('xrpl')
}
</script>
</head>
<!-- ************************************************************** -->
<!-- ********************** The Form ****************************** -->
<!-- ************************************************************** -->
<body>
<h1>Token Test Harness</h1>
<form id="theForm">
Choose your ledger instance:
&nbsp;&nbsp;
<input type="radio" id="tn" name="server"
value="wss://s.altnet.rippletest.net:51233" checked>
<label for="testnet">Testnet</label>
&nbsp;&nbsp;
<input type="radio" id="dn" name="server"
value="wss://s.devnet.rippletest.net:51233">
<label for="devnet">Devnet</label>
<br/><br/>
<button type="button" onClick="getAccountsFromSeeds()">Get Accounts From Seeds</button>
<br/>
<textarea id="seeds" cols="55" rows= "4"></textarea>
<table>
<tr valign="top">
<td>
<table>
<tr valign="top">
<td>
<button type="button" onClick="getAccount('standby')">Get New Account</button>
<table>
<tr valign="top">
<td align="right">
Account Name
</td>
<td>
<input type="text" id="standbyNameField" size="40"></input>
<br>
</td>
</tr>
<tr valign="top">
<td align="right">
Account
</td>
<td>
<input type="text" id="standbyAccountField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Seed
</td>
<td>
<input type="text" id="standbySeedField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
XRP Balance
</td>
<td>
<input type="text" id="standbyBalanceField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Amount
</td>
<td>
<input type="text" id="standbyAmountField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Destination
</td>
<td>
<input type="text" id="standbyDestinationField" size="40"></input>
<br>
</td>
</tr>
<tr valign="top">
<td><button type="button" onClick="configureAccount('standby',document.querySelector('#standbyDefault').checked)">Configure Account</button></td>
<td>
<input type="checkbox" id="standbyDefault" checked="false"/>
<label for="standbyDefault">Allow Rippling</label>
</td>
</tr>
<tr>
<td align="right">
Currency
</td>
<td>
<input type="text" id="standbyCurrencyField" size="40" value="USD"></input>
</td>
</tr>
<tr>
<td align="right">
Offer Sequence
</td>
<td>
<input type="text" id="standbyOfferSequenceField" size="10"></input>
</td>
</tr>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>
Taker Pays:<br/>
Currency: <input type="text" id="standbyTakerPaysCurrencyField" size="10"></input><br/>
Issuer: <input type="text" id="standbyTakerPaysIssuerField" size="35"></input><br/>
Value: <input type="text" id="standbyTakerPaysValueField" size="10"></input>
</td>
<td>
Taker Gets:<br/>
Currency: <input type="text" id="standbyTakerGetsCurrencyField" size="10"></input><br/>
Issuer: <input type="text" id="standbyTakerGetsIssuerField" size="35"></input><br/>
Value: <input type="text" id="standbyTakerGetsValueField" size="10"></input><br/>
</td>
</tr>
</table>
<p align="left">
<textarea id="standbyResultField" cols="80" rows="20" ></textarea>
</p>
</td>
</tr>
</table>
</td>
<!-- Standby Buttons, Column 2 -->
<td>
<table>
<tr valign="top">
<td align="center" valign="top">
<button type="button" onClick="sendXRP()">Send XRP&#62;</button>
<br/>
<button type="button" onClick="createTrustline()">Create Trust Line</button>
<br/>
<button type="button" onClick="getTrustLines()">Get Trust Lines</button>
<br/>
<button type="button" onClick="sendCurrency()">Send Currency</button>
<br/>
<button type="button" onClick="getBalances()">Get Balances</button>
<br/><br/>
<button type="button" onClick="createOffer()">Create Offer</button>
<br/>
<button type="button" onClick="getOffers()">Get Offers</button>
<br/>
<button type="button" onClick="cancelOffer()">Cancel Offer</button>
</td>
</tr>
</table>
</td>
<!-- Operational Buttons, Column 3 -->
<td>
<table>
<tr valign="bottom">
<td align="center" valign="middle">
<button type="button" onClick="oPsendXRP()">&#60; Send XRP</button>
<br/>
<button type="button" onClick="oPcreateTrustline()">Create Trust Line</button>
<br/>
<button type="button" onClick="oPgetTrustLines()">Get Trust Lines</button>
<br/>
<button type="button" onClick="oPsendCurrency()">Send Currency</button>
<br/>
<button type="button" onClick="getBalances()">Get Balances</button>
<br/><br/>
<button type="button" onClick="oPcreateOffer()">Create Offer</button>
<br/>
<button type="button" onClick="oPgetOffers()">Get Offers</button>
<br/>
<button type="button" onClick="oPcancelOffer()">Cancel Offer</button>
</td>
</tr>
</table>
</td>
<!-- Operational fields, Column 4 -->
<td valign="top" align="right">
<button type="button" onClick="getAccount('operational')">Get New Account</button>
<table>
<tr valign="top">
<td align="left">
Account Name
</td>
<td align="left">
<input type="text" id="operationalNameField" size="40"></input>
<br>
</td>
</tr>
<tr valign="top">
<td align="right">
Account
</td>
<td>
<input type="text" id="operationalAccountField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Seed
</td>
<td>
<input type="text" id="operationalSeedField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
XRP Balance
</td>
<td>
<input type="text" id="operationalBalanceField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Amount
</td>
<td>
<input type="text" id="operationalAmountField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Destination
</td>
<td>
<input type="text" id="operationalDestinationField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td></td>
<td align="right">
<input type="checkbox" id="operationalDefault" checked="false"/>
<label for="operationalDefault">Allow Rippling</label>
<button type="button" onClick="configureAccount('operational',document.querySelector('#operationalDefault').checked)">Configure Account</button>
</td>
</tr>
<tr>
<td align="right">
Currency
</td>
<td>
<input type="text" id="operationalCurrencyField" size="40" value="USD"></input>
</td>
</tr>
<tr>
<td align="right">
Offer Sequence
</td>
<td>
<input type="text" id="operationalOfferSequenceField" size="10"></input>
</td>
</tr>
</table>
<table>
<tr>
<td>
Taker Pays:<br/>
Currency: <input type="text" id="operationalTakerPaysCurrencyField" size="10"></input><br/>
Issuer: <input type="text" id="operationalTakerPaysIssuerField" size="35"></input><br/>
Value: <input type="text" id="operationalTakerPaysValueField" size="10"></input>
</td>
<td>
Taker Gets:<br/>
Currency: <input type="text" id="operationalTakerGetsCurrencyField" size="10"></input><br/>
Issuer: <input type="text" id="operationalTakerGetsIssuerField" size="35"></input><br/>
Value: <input type="text" id="operationalTakerGetsValueField" size="10"></input><br/>
</td>
</tr>
</table>
<p align="right">
<textarea id="operationalResultField" cols="80" rows="20" ></textarea>
</p>
</td>
</tr>
</table>
</form>
</body>
</html>

View File

@@ -0,0 +1,276 @@
/***********************************
*********** Create Offer **********
**********************************/
async function createOffer() {
let takerGets = ''
let takerPays = ''
let net = getNet()
let results = 'Connecting to ' + net + '....\n'
const client = new xrpl.Client(net)
await client.connect()
results += "Connected. Getting wallets.\n"
standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
results += standbyNameField.value + " account address: " + standby_wallet.address + "\n"
standbyResultField.value = results
if (standbyTakerGetsCurrencyField.value == 'XRP') {
takerGets = standbyTakerGetsValueField.value
} else {
takerGetsString = '{"currency": "' + standbyTakerGetsCurrencyField.value +'",\n' +
'"issuer": "' + standbyTakerGetsIssuerField.value + '",\n' +
'"value": "' + standbyTakerGetsValueField.value + '"}'
takerGets = JSON.parse(takerGetsString)
}
if (standbyTakerPaysCurrencyField.value == 'XRP') {
takerPays = standbyTakerPaysValueField.value
} else {
takerPaysString = '{"currency": "' + standbyTakerPaysCurrencyField.value + '",\n' +
'"issuer": "' + standbyTakerPaysIssuerField.value + '",\n' +
'"value": "' + standbyTakerPaysValueField.value + '"}'
takerPays = JSON.parse(takerPaysString)
}
// -------------------------------------------------------- Prepare transaction
const prepared = await client.autofill({
"TransactionType": "OfferCreate",
"Account": standby_wallet.address,
"TakerGets": takerGets,
"TakerPays": takerPays
})
// ------------------------------------------------- Sign prepared instructions
const signed = standby_wallet.sign(prepared)
results += "\nSubmitting transaction...."
// -------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += tx.results + "\n"
results += "\nBalance changes: " +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
standbyResultField.value = results
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
operationalBalanceField.value = (await client.getXrpBalance(operational_wallet.address))
getOffers()
client.disconnect()
} // End of createOffer()
/***********************************
************ Get Offers ***********
**********************************/
async function getOffers() {
let net = getNet()
let results = 'Connecting to ' + net + '....\n'
const client = new xrpl.Client(net)
await client.connect()
results += "Connected.\n"
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
results += standbyNameField.value + " acccount: " + standby_wallet.address
// -------------------------------------------------------- Prepare request
results += '\n\n*** Offers ***\n'
let offers
try {
const offers = await client.request({
method: "account_offers",
account: standby_wallet.address,
ledger_index: "validated"
})
results += JSON.stringify(offers,null,2)
} catch (err) {
results += err
}
results += JSON.stringify(offers,null,2)
standbyResultField.value = results
client.disconnect()
}// End of getOffers()
/***********************************
*********** Cancel Offer **********
**********************************/
async function cancelOffer() {
let results = "Connecting to the selected ledger.\n"
standbyResultField.value = results
let net = getNet()
results += 'Connecting to ' + net + '....\n'
const client = new xrpl.Client(net)
await client.connect()
results += "Connected.\n"
standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
results += "standby_wallet.address: = " + standby_wallet.address
standbyResultField.value = results
// -------------------------------------------------------- Prepare transaction
/* OfferSequence is the Seq value when you getOffers. */
const prepared = await client.autofill({
"TransactionType": "OfferCancel",
"Account": standby_wallet.address,
"OfferSequence": parseInt(standbyOfferSequenceField.value)
})
// ------------------------------------------------- Sign prepared instructions
const signed = standby_wallet.sign(prepared)
// -------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += "\nBalance changes: \n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
standbyResultField.value = results
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
client.disconnect()
} // End of cancelOffer()
/*********************************************
************* Reciprocal Functions **********
********************************************/
/***********************************
********* OP Create Offer *********
**********************************/
async function oPcreateOffer() {
let takerGets = ''
let takerPays = ''
operationalResultField.value = ''
let net = getNet()
let results = 'Connecting to ' + net + '....\n'
const client = new xrpl.Client(net)
await client.connect()
results += "Connected. Getting wallets.\n"
operationalResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
results += operationalNameField.value + " account address: " + operational_wallet.address + "\n"
operationalResultField.value = results
if (operationalTakerGetsCurrencyField.value == 'XRP') {
takerGets = operationalTakerGetsValueField.value
} else {
takerGetsString = '{"currency": "' + operationalTakerGetsCurrencyField.value +'",\n' +
'"issuer": "' + operationalTakerGetsIssuerField.value + '",\n' +
'"value": "' + operationalTakerGetsValueField.value + '"}'
takerGets = JSON.parse(takerGetsString)
}
if (operationalTakerPaysCurrencyField.value == 'XRP') {
takerPays = operationalTakerPaysValueField.value
} else {
takerPaysString = '{"currency": "' + operationalTakerPaysCurrencyField.value + '",\n' +
'"issuer": "' + operationalTakerPaysIssuerField.value + '",\n' +
'"value": "' + operationalTakerPaysValueField.value + '"}'
takerPays = JSON.parse(takerPaysString)
}
// -------------------------------------------------------- Prepare transaction
const prepared = await client.autofill({
"TransactionType": "OfferCreate",
"Account": operational_wallet.address,
"TakerGets": takerGets,
"TakerPays": takerPays
})
// ------------------------------------------------- Sign prepared instructions
const signed = operational_wallet.sign(prepared)
results += "\nSubmitting transaction...."
// -------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += tx.results + "\n"
results += "\nBalance changes: " +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
operationalResultField.value = results
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
operationalBalanceField.value = (await client.getXrpBalance(operational_wallet.address))
getOffers()
client.disconnect()
} // End of oPcreateOffer()
/***********************************
********** OP Get Offers ***********
***********************************/
async function oPgetOffers() {
let results = "Connecting to the selected ledger.\n"
operationalResultField.value = results
let net = getNet()
results = 'Connecting to ' + net + '....\n'
const client = new xrpl.Client(net)
await client.connect()
results += "Connected.\n"
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
results += operationalNameField.value + " account: " + operational_wallet.address
operationalResultField.value = results
// -------------------------------------------------------- Prepare request
results += '\n\n*** Offers ***\n'
let offers
try {
const offers = await client.request({
method: "account_offers",
account: operational_wallet.address,
ledger_index: "validated"
})
results += JSON.stringify(offers,null,2)
} catch (err) {
results += err
}
results += JSON.stringify(offers,null,2)
operationalResultField.value = results
client.disconnect()
}// End of oPgetOffers()
/************************************
********** Op Cancel Offer *********
***********************************/
async function oPcancelOffer() {
let net = getNet()
let results = 'Connecting to ' + net + '....\n'
const client = new xrpl.Client(net)
await client.connect()
results += "Connected.\n"
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
results += "wallet.address: = " + operational_wallet.address
operationalResultField.value = results
// -------------------------------------------------------- Prepare transaction
/* OfferSequence is the Seq value when you getOffers. */
const prepared = await client.autofill({
"TransactionType": "OfferCancel",
"Account": operational_wallet.address,
"OfferSequence": parseInt(operationalOfferSequenceField.value)
})
// ------------------------------------------------- Sign prepared instructions
const signed = operational_wallet.sign(prepared)
// -------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += "\nBalance changes: \n" + tx.result + "\n" +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
operationalResultField.value = results
operationalBalanceField.value = (await client.getXrpBalance(operational_wallet.address))
client.disconnect()
} // End of oPcancelOffer()

View File

@@ -0,0 +1,207 @@
// ******************************************************
// ************* Get the Preferred Network **************
// ******************************************************
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/"
return net
} // End of getNet()
// *******************************************************
// ************* Get Account *****************************
// *******************************************************
async function getAccount(type) {
let net = getNet()
const client = new xrpl.Client(net)
results = 'Connecting to ' + net + '....'
// This uses the default faucet for Testnet/Devnet
// let faucetHost = 'batch.faucet.nerdnest.xyz'
let faucetHost = null
if (type == 'standby') {
standbyResultField.value = results
} else {
operationalResultField.value = results
}
await client.connect()
results += '\nConnected, funding wallet.'
if (type == 'standby') {
standbyResultField.value = results
} else {
operationalResultField.value = results
}
// -----------------------------------Create and fund a test account wallet
const my_wallet = (await client.fundWallet(null, { faucetHost})).wallet
results += '\nGot a wallet.'
if (type == 'standby') {
standbyResultField.value = results
} else {
operationalResultField.value = results
}
// ------------------------------------------------------Get the current balance.
// const my_balance = (await client.getXrpBalance(my_wallet.address))
if (type == 'standby') {
standbyAccountField.value = my_wallet.address
standbyBalanceField.value = (await client.getXrpBalance(my_wallet.address))
standbySeedField.value = my_wallet.seed
results += '\nAccount created named ' + standbyNameField.value + '.'
standbyResultField.value = results
} else {
operationalAccountField.value = my_wallet.address
operationalSeedField.value = my_wallet.seed
operationalBalanceField.value = (await client.getXrpBalance(my_wallet.address))
results += '\nAccount created named ' + operationalNameField.value + '.'
operationalResultField.value = results
}
// --------------- Capture the seeds for both accounts for ease of reload.
seeds.value = standbySeedField.value + "." + standbyNameField.value + '\n' +
operationalSeedField.value + "." + operationalNameField.value
client.disconnect()
} // End of getAccount()
// *******************************************************
// ********** Get Accounts from Seeds ********************
// *******************************************************
async function getAccountsFromSeeds() {
let net = getNet()
const client = new xrpl.Client(net)
let results = 'Connecting to ' + getNet() + '....'
standbyResultField.value = results
await client.connect()
results += '\nConnected, finding wallets.\n'
standbyResultField.value = results
var lines = seeds.value.split('\n')
var first_line_value = lines[0]
var first_line = first_line_value.split('.')
var first_seed = first_line[0]
var first_name = first_line[1]
var second_line = lines[1].split('.')
var second_seed = second_line[0]
var second_name = second_line[1]
const standby_wallet = xrpl.Wallet.fromSeed(first_seed)
const operational_wallet = xrpl.Wallet.fromSeed(second_seed)
// ----------------------Populate the fields for Standby and Operational accounts.
standbyAccountField.value = standby_wallet.address
standbyNameField.value = first_name
standbySeedField.value = first_seed
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
operationalAccountField.value = operational_wallet.address
operationalNameField.value = second_name
operationalSeedField.value = second_seed
operationalBalanceField.value = (await client.getXrpBalance(operational_wallet.address))
client.disconnect()
} // End of getAccountsFromSeeds()
// *******************************************************
// ******************** Send XRP *************************
// *******************************************************
async function sendXRP() {
results = "Connecting to the selected ledger.\n"
standbyResultField.value = results
let net = getNet()
results = 'Connecting to ' + getNet() + '....'
const client = new xrpl.Client(net)
await client.connect()
results += "\nConnected. Sending XRP.\n"
standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const sendAmount = standbyAmountField.value
results += "\nstandby_wallet.address: = " + standby_wallet.address
standbyResultField.value = results
// -------------------------------------------------------- Prepare transaction
const prepared = await client.autofill({
"TransactionType": "Payment",
"Account": standby_wallet.address,
"Amount": xrpl.xrpToDrops(sendAmount),
"Destination": standbyDestinationField.value
})
// ------------------------------------------------- Sign prepared instructions
const signed = standby_wallet.sign(prepared)
// -------------------------------------------------------- Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += "\nBalance changes: " +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
standbyResultField.value = results
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
operationalBalanceField.value = (await client.getXrpBalance(operational_wallet.address))
client.disconnect()
} // End of sendXRP()
// **********************************************************************
// ****** Reciprocal Transactions ***************************************
// **********************************************************************
// *******************************************************
// ********* Send XRP from Operational account ***********
// *******************************************************
async function oPsendXRP() {
results = "Connecting to the selected ledger.\n"
operationalResultField.value = results
let net = getNet()
results = 'Connecting to ' + getNet() + '....'
const client = new xrpl.Client(net)
await client.connect()
results += "\nConnected. Sending XRP.\n"
operationalResultField.value = results
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const sendAmount = operationalAmountField.value
results += "\noperational_wallet.address: = " + operational_wallet.address
operationalResultField.value = results
// ---------------------------------------------------------- Prepare transaction
const prepared = await client.autofill({
"TransactionType": "Payment",
"Account": operational_wallet.address,
"Amount": xrpl.xrpToDrops(sendAmount),
"Destination": operationalDestinationField.value
})
// ---------------------------------------------------- Sign prepared instructions
const signed = operational_wallet.sign(prepared)
// ------------------------------------------------------------ Submit signed blob
const tx = await client.submitAndWait(signed.tx_blob)
results += "\nBalance changes: " +
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
operationalResultField.value = results
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
operationalBalanceField.value = (await client.getXrpBalance(operational_wallet.address))
client.disconnect()
} // End of oPsendXRP()

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -172,6 +172,7 @@
items:
- page: docs/tutorials/javascript/send-payments/create-accounts-send-xrp.md
- page: docs/tutorials/javascript/send-payments/create-trust-line-send-currency.md
- page: docs/tutorials/javascript/send-payments/create-offers.md
- page: docs/tutorials/javascript/send-payments/create-time-based-escrows.md
- page: docs/tutorials/javascript/send-payments/create-conditional-escrows.md
- page: docs/tutorials/javascript/send-payments/send-and-cash-checks.md