add better error handling and double token amm functionality

This commit is contained in:
Oliver Eggert
2024-09-06 14:02:44 -07:00
parent c9bb4102e0
commit 5336ef7e8d
18 changed files with 806 additions and 277 deletions

View File

@@ -44,7 +44,7 @@
<table> <table>
<tr valign="top"> <tr valign="top">
<td> <td>
<table> <table style="padding-bottom: 400px;">
<tr valign="top"> <tr valign="top">
<td> <td>
<td> <td>
@@ -107,27 +107,84 @@
Currency Currency
</td> </td>
<td> <td>
<input type="text" id="standbyCurrencyField" size="40" value="USD"></input> <input type="text" id="standbyCurrencyField" size="40"></input>
<br>
</td> </td>
</tr> </tr>
</table> </table>
<p align="left"> <p align="left">
<textarea id="standbyResultField" cols="80" rows="20" ></textarea> <textarea id="standbyResultField" cols="60" rows="20" style="resize: none;"></textarea>
</p> </p>
<table>
<tr valign="top">
<td align="right">
Asset 1 Currency
</td>
<td>
<input type="text" id="asset1CurrencyField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 1 Issuer
</td>
<td>
<input type="text" id="asset1IssuerField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 1 Amount
</td>
<td>
<input type="text" id="asset1AmountField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 2 Currency
</td>
<td>
<input type="text" id="asset2CurrencyField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 2 Issuer
</td>
<td>
<input type="text" id="asset2IssuerField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 2 Amount
</td>
<td>
<input type="text" id="asset2AmountField" size="40"></input>
<br>
</td>
</tr>
</table>
</td> </td>
</td> </td>
<td> <td>
<table> <table>
<tr valign="top"> <tr valign="top">
<td align="center" valign="top"> <td align="center" valign="top" style="padding-top: 165px;">
<br><br><br><br> <br>
<button type="button" onClick="sendXRP()">Send XRP&#62;</button> <button type="button" onClick="sendXRP()">Send XRP&#62;</button>
<br/><br/> <br/><br/>
<button type="button" onClick="createTrustline()">Create TrustLine</button> <button type="button" onClick="createTrustline()">Create TrustLine</button>
<br/> <br/>
<button type="button" onClick="sendCurrency()">Send Currency</button> <button type="button" onClick="sendCurrency()">Send Currency</button>
<br/> <br/>
<button type="button" onClick="getBalances()">Get Balances</button> <button type="button" onClick="getBalances()" style="margin-bottom: 160px;">Get Balances</button>
<br/> <br/>
<button type="button" onClick="checkAMM()">Check AMM</button> <button type="button" onClick="checkAMM()">Check AMM</button>
<br/> <br/>
@@ -142,13 +199,13 @@
</table> </table>
</td> </td>
<td> <td>
<table> <table style="padding-bottom: 350px;">
<tr> <tr>
<td> <td>
<td> <td>
<table> <table>
<tr> <tr>
<td align="center" valign="top"> <td align="center" valign="top" style="padding-bottom: 100px;">
<button type="button" onClick="oPsendXRP()">&#60; Send XRP</button> <button type="button" onClick="oPsendXRP()">&#60; Send XRP</button>
<br/><br/> <br/><br/>
<button type="button" onClick="oPcreateTrustline()">Create TrustLine</button> <button type="button" onClick="oPcreateTrustline()">Create TrustLine</button>
@@ -219,12 +276,14 @@
Currency Currency
</td> </td>
<td> <td>
<input type="text" id="operationalCurrencyField" size="40" value="USD"></input> <input type="text" id="operationalCurrencyField" size="40"></input>
</td> </td>
</tr> </tr>
</table> </table>
<p align="right"> <p align="right">
<textarea id="operationalResultField" cols="80" rows="20" ></textarea> <textarea id="operationalResultField" cols="60" rows="20" style="resize: none;"></textarea>
<br><br>
<textarea id="ammInfoField" cols="60" rows="20" style="resize: none;"></textarea>
</p> </p>
</td> </td>
</td> </td>

View File

@@ -1,6 +1,6 @@
<html> <html>
<head> <head>
<title>Add Assets to AMM Test Harness</title> <title>Add to AMM Test Harness</title>
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'> <link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
<style> <style>
body{font-family: "Work Sans", sans-serif;padding: 20px;background: #fafafa;} body{font-family: "Work Sans", sans-serif;padding: 20px;background: #fafafa;}
@@ -26,7 +26,7 @@
<!-- ************************************************************** --> <!-- ************************************************************** -->
<body> <body>
<h1>Add Assets to AMM Test Harness</h1> <h1>Add to AMM Test Harness</h1>
<form id="theForm"> <form id="theForm">
Choose your ledger instance: Choose your ledger instance:
&nbsp;&nbsp; &nbsp;&nbsp;
@@ -45,7 +45,7 @@
<table> <table>
<tr valign="top"> <tr valign="top">
<td> <td>
<table> <table style="padding-bottom: 400px;">
<tr valign="top"> <tr valign="top">
<td> <td>
<td> <td>
@@ -108,15 +108,66 @@
Currency Currency
</td> </td>
<td> <td>
<input type="text" id="standbyCurrencyField" size="40" value="USD"></input> <input type="text" id="standbyCurrencyField" size="40"></input>
<br>
</td>
</tr>
</table>
<p align="left">
<textarea id="standbyResultField" cols="60" rows="20" style="resize: none;"></textarea>
</p>
<table>
<tr valign="top">
<td align="right">
Asset 1 Currency
</td>
<td>
<input type="text" id="asset1CurrencyField" size="40"></input>
<br>
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="right"> <td align="right">
LP Tokens Asset 1 Issuer
</td> </td>
<td> <td>
<input type="text" id="standbyLPField" size="40"></input> <input type="text" id="asset1IssuerField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 1 Amount
</td>
<td>
<input type="text" id="asset1AmountField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 2 Currency
</td>
<td>
<input type="text" id="asset2CurrencyField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 2 Issuer
</td>
<td>
<input type="text" id="asset2IssuerField" size="40"></input>
<br>
</td>
</tr>
<tr>
<td align="right">
Asset 2 Amount
</td>
<td>
<input type="text" id="asset2AmountField" size="40"></input>
<br> <br>
</td> </td>
</tr> </tr>
@@ -129,16 +180,22 @@
<br> <br>
</td> </td>
</tr> </tr>
<tr>
<td align="right">
LP Tokens
</td>
<td>
<input type="text" id="standbyLPField" size="40"></input>
<br>
</td>
</tr>
</table> </table>
<p align="left">
<textarea id="standbyResultField" cols="80" rows="20" ></textarea>
</p>
</td> </td>
</td> </td>
<td> <td>
<table> <table>
<tr valign="top"> <tr valign="top">
<td align="center" valign="top" style="padding-top: 270px;"> <td align="center" valign="top" style="padding-top: 240px;">
<br> <br>
<button type="button" onClick="sendXRP()">Send XRP&#62;</button> <button type="button" onClick="sendXRP()">Send XRP&#62;</button>
<br/><br/> <br/><br/>
@@ -146,8 +203,8 @@
<br/> <br/>
<button type="button" onClick="sendCurrency()">Send Currency</button> <button type="button" onClick="sendCurrency()">Send Currency</button>
<br/> <br/>
<button type="button" onClick="getBalances()">Get Balances</button> <button type="button" onClick="getBalances()" style="margin-bottom: 160px;">Get Balances</button>
<br/><br/> <br/>
<button type="button" onClick="checkAMM()">Check AMM</button> <button type="button" onClick="checkAMM()">Check AMM</button>
<br/> <br/>
<button type="button" onClick="createAMM()">Create AMM</button> <button type="button" onClick="createAMM()">Create AMM</button>
@@ -169,14 +226,13 @@
</table> </table>
</td> </td>
<td> <td>
<table> <table style="padding-bottom: 430px;">
<tr> <tr>
<td> <td>
<td> <td>
<table> <table>
<tr> <tr>
<td align="center" valign="top" style="padding-top: 15px;"> <td align="center" valign="top" style="padding-bottom: 100px;">
<br/>
<button type="button" onClick="oPsendXRP()">&#60; Send XRP</button> <button type="button" onClick="oPsendXRP()">&#60; Send XRP</button>
<br/><br/> <br/><br/>
<button type="button" onClick="oPcreateTrustline()">Create TrustLine</button> <button type="button" onClick="oPcreateTrustline()">Create TrustLine</button>
@@ -184,7 +240,6 @@
<button type="button" onClick="oPsendCurrency()">Send Currency</button> <button type="button" onClick="oPsendCurrency()">Send Currency</button>
<br/> <br/>
<button type="button" onClick="getBalances()">Get Balances</button> <button type="button" onClick="getBalances()">Get Balances</button>
<br>
</td> </td>
<td valign="top" align="right"> <td valign="top" align="right">
<button type="button" onClick="getAccount('operational')">Get New Operational Account</button> <button type="button" onClick="getAccount('operational')">Get New Operational Account</button>
@@ -244,16 +299,18 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="right" style="padding-bottom: 60px;"> <td align="right">
Currency Currency
</td> </td>
<td> <td>
<input type="text" id="operationalCurrencyField" size="40" value="USD"></input> <input type="text" id="operationalCurrencyField" size="40"></input>
</td> </td>
</tr> </tr>
</table><br><br> </table>
<p align="right"> <p align="right">
<textarea id="operationalResultField" cols="80" rows="20" ></textarea> <textarea id="operationalResultField" cols="60" rows="20" style="resize: none;"></textarea>
<br><br>
<textarea id="ammInfoField" cols="60" rows="20" style="resize: none;"></textarea>
</p> </p>
</td> </td>
</td> </td>

View File

@@ -13,10 +13,16 @@ async function createAMM() {
standbyResultField.value = results standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value) const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const xrp_value = standbyBalanceField.value const asset1_currency = asset1CurrencyField.value
const currency_code = standbyCurrencyField.value const asset1_issuer = asset1IssuerField.value
const currency_value = standbyAmountField.value const asset1_amount = asset1AmountField.value
const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
const asset2_amount = asset2AmountField.value
let ammCreate = null
results += '\n\nCreating AMM ...' results += '\n\nCreating AMM ...'
standbyResultField.value = results standbyResultField.value = results
@@ -26,18 +32,83 @@ async function createAMM() {
const ss = await client.request({"command": "server_state"}) const ss = await client.request({"command": "server_state"})
const amm_fee_drops = ss.result.state.validated_ledger.reserve_inc.toString() const amm_fee_drops = ss.result.state.validated_ledger.reserve_inc.toString()
const ammcreate_result = await client.submitAndWait({ 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", "TransactionType": "AMMCreate",
"Account": standby_wallet.address, "Account": standby_wallet.address,
"Amount": { "Amount": {
"currency": currency_code, "currency": asset1_currency,
"issuer": operational_wallet.address, "issuer": asset1_issuer,
"value": currency_value "value": asset1_amount
}, },
"Amount2": JSON.stringify(xrp_value * 1000000), // convert XRP to drops "Amount2": JSON.stringify(asset2_amount * 1000000), // convert XRP to drops
"TradingFee": 500, // 500 = 0.5% "TradingFee": 500, // 500 = 0.5%
"Fee": amm_fee_drops, "Fee": amm_fee_drops
}, {autofill: true, wallet: standby_wallet, fail_hard: true}) // Use fail_hard so you don't waste the tx cost if you mess up }
} 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
}
}
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
const signed_create = standby_wallet.sign(prepared_create)
results += `\n\nSending AMMCreate transaction ...`
standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight
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}`
}
standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight
checkAMM() checkAMM()
@@ -50,46 +121,73 @@ async function createAMM() {
async function checkAMM() { async function checkAMM() {
let net = getNet() let net = getNet()
const client = new xrpl.Client(net) const client = new xrpl.Client(net)
results = `\n\nConnecting to ${getNet()} ...`
standbyResultField.value = results
await client.connect() await client.connect()
results += '\n\nConnected.'
standbyResultField.value = results
// Gets the issuer and currency code // Gets the issuer and currency code
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value) const asset1_currency = asset1CurrencyField.value
const currency_code = standbyCurrencyField.value const asset1_issuer = asset1IssuerField.value
results += '\n\nChecking AMM ...' const asset2_currency = asset2CurrencyField.value
standbyResultField.value = results const asset2_issuer = asset2IssuerField.value
let amm_info_request = null
// Get AMM info transaction // Get AMM info transaction
const amm_info_request = {
if (asset1_currency == 'XRP') {
amm_info_request = {
"command": "amm_info", "command": "amm_info",
"asset": { "asset": {
"currency": "XRP" "currency": "XRP"
}, },
"asset2": { "asset2": {
"currency": currency_code, "currency": asset2_currency,
"issuer": operational_wallet.address "issuer": asset2_issuer
}, },
"ledger_index": "validated" "ledger_index": "validated"
} }
try {
const amm_info_result = await client.request(amm_info_request) } else if (asset2_currency =='XRP') {
results += `\n\nAMM Info:\n${JSON.stringify(amm_info_result.result.amm, null, 2)}`
} catch(err) { amm_info_request = {
if (err.data.error === 'actNotFound') { "command": "amm_info",
results += `\n\nNo AMM exists for the pair ${currency_code} / XRP.` "asset": {
} else { "currency": asset1_currency,
results += `\n\n${err}` "issuer": asset1_issuer
} },
"asset2": {
"currency": "XRP"
},
"ledger_index": "validated"
} }
standbyResultField.value = results } else {
amm_info_request = {
"command": "amm_info",
"asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"asset2": {
"currency": asset2_currency,
"issuer": asset2_issuer
},
"ledger_index": "validated"
}
}
try {
const amm_info_result = await client.request(amm_info_request)
ammInfo = `${JSON.stringify(amm_info_result.result.amm, null, 2)}`
} catch(error) {
ammInfo = `${error}`
}
ammInfoField.value = ammInfo
client.disconnect() client.disconnect()

View File

@@ -13,14 +13,19 @@ async function addAssets() {
standbyResultField.value = results standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value) const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const addXRP = standbyBalanceField.value
const currency_code = standbyCurrencyField.value
const addCurrency = standbyAmountField.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
// Check for all combinations of asset deposits.
let ammdeposit = null let ammdeposit = null
if (addXRP && addCurrency) { if (asset1_currency == "XRP" && asset2_currency && asset1_amount && asset2_amount ) {
ammdeposit = { ammdeposit = {
"TransactionType": "AMMDeposit", "TransactionType": "AMMDeposit",
@@ -28,51 +33,160 @@ async function addAssets() {
currency: "XRP" currency: "XRP"
}, },
"Asset2": { "Asset2": {
currency: currency_code, currency: asset2_currency,
issuer: operational_wallet.address issuer: asset2_issuer
}, },
"Account": standby_wallet.address, "Account": standby_wallet.address,
"Amount": xrpl.xrpToDrops(addXRP), "Amount": xrpl.xrpToDrops(asset1_amount),
"Amount2": { "Amount2": {
currency: currency_code, currency: asset2_currency,
issuer: operational_wallet.address, issuer: asset2_issuer,
value: addCurrency value: asset2_amount
}, },
"Flags": 0x00100000 "Flags": 0x00100000
} }
} else if ( addXRP ) { } else if ( asset1_currency && asset2_currency == "XRP" && asset1_amount && asset2_amount ) {
ammdeposit = { ammdeposit = {
"TransactionType": "AMMDeposit", "TransactionType": "AMMDeposit",
"Asset": { "Asset": {
currency: "XRP" currency: asset1_currency,
issuer: asset1_issuer
}, },
"Asset2": { "Asset2": {
currency: currency_code,
issuer: operational_wallet.address
},
"Account": standby_wallet.address,
"Amount": xrpl.xrpToDrops(addXRP),
"Flags": 0x00080000
}
} else if ( addCurrency ) {
ammdeposit = {
"TransactionType": "AMMDeposit",
"Asset": {
currency: "XRP" currency: "XRP"
}, },
"Asset2": {
currency: currency_code,
issuer: operational_wallet.address
},
"Account": standby_wallet.address, "Account": standby_wallet.address,
"Amount": { "Amount": {
currency: currency_code, currency: asset1_currency,
issuer: operational_wallet.address, issuer: asset1_issuer,
value: addCurrency value: asset1_amount
},
"Amount2": xrpl.xrpToDrops(asset2_amount),
"Flags": 0x00100000
}
} else if ( asset1_currency && asset2_currency && asset1_amount && asset2_amount ) {
ammdeposit = {
"TransactionType": "AMMDeposit",
"Asset": {
currency: asset1_currency,
issuer: asset1_issuer
},
"Asset2": {
currency: asset2_currency,
issuer: asset2_issuer
},
"Account": standby_wallet.address,
"Amount": {
currency: asset1_currency,
issuer: asset1_issuer,
value: asset1_amount
},
"Amount2": {
currency: asset2_currency,
issuer: asset2_issuer,
value: asset2_amount
},
"Flags": 0x00100000
}
} else if ( asset1_currency == "XRP" && asset2_currency && asset1_amount ) {
ammdeposit = {
"TransactionType": "AMMDeposit",
"Asset": {
currency: "XRP"
},
"Asset2": {
currency: asset2_currency,
issuer: asset2_issuer
},
"Account": standby_wallet.address,
"Amount": xrpl.xrpToDrops(asset1_amount),
"Flags": 0x00080000
}
} else if ( asset1_currency && asset2_currency == "XRP" && asset1_amount ) {
ammdeposit = {
"TransactionType": "AMMDeposit",
"Asset": {
currency: asset1_currency,
issuer: asset1_issuer
},
"Asset2": {
currency: "XRP"
},
"Account": standby_wallet.address,
"Amount": {
currency: asset1_currency,
issuer: asset1_issuer,
value: asset1_amount
},
"Flags": 0x00080000
}
} else if ( asset1_currency == "XRP" && asset2_currency && asset2_amount ) {
ammdeposit = {
"TransactionType": "AMMDeposit",
"Asset": {
currency: "XRP"
},
"Asset2": {
currency: asset2_currency,
issuer: asset2_issuer
},
"Account": standby_wallet.address,
"Amount": {
currency: asset2_currency,
issuer: asset2_issuer,
value: asset2_amount
},
"Flags": 0x00080000
}
} else if ( asset1_currency && asset2_currency && asset1_amount ) {
ammdeposit = {
"TransactionType": "AMMDeposit",
"Asset": {
currency: asset1_currency,
issuer: asset1_issuer
},
"Asset2": {
currency: asset2_currency,
issuer: asset2_issuer
},
"Account": standby_wallet.address,
"Amount": {
currency: asset1_currency,
issuer: asset1_issuer,
value: asset1_amount
},
"Flags": 0x00080000
}
} else if ( asset1_currency && asset2_currency && asset2_amount ) {
ammdeposit = {
"TransactionType": "AMMDeposit",
"Asset": {
currency: asset1_currency,
issuer: asset1_issuer
},
"Asset2": {
currency: asset2_currency,
issuer: asset2_issuer
},
"Account": standby_wallet.address,
"Amount": {
currency: asset2_currency,
issuer: asset2_issuer,
value: asset2_amount
}, },
"Flags": 0x00080000 "Flags": 0x00080000
} }
@@ -82,9 +196,12 @@ async function addAssets() {
results += `\n\nNo assets selected to add ...` results += `\n\nNo assets selected to add ...`
standbyResultField.value = results standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight standbyResultField.scrollTop = standbyResultField.scrollHeight
return
} }
try {
const prepared_deposit = await client.autofill(ammdeposit) const prepared_deposit = await client.autofill(ammdeposit)
results += `\n\nPrepared transaction:\n${JSON.stringify(prepared_deposit, null, 2)}` results += `\n\nPrepared transaction:\n${JSON.stringify(prepared_deposit, null, 2)}`
standbyResultField.value = results standbyResultField.value = results
@@ -99,39 +216,18 @@ async function addAssets() {
if (lp_deposit.result.meta.TransactionResult == "tesSUCCESS") { if (lp_deposit.result.meta.TransactionResult == "tesSUCCESS") {
results += `\n\nTransaction succeeded.` results += `\n\nTransaction succeeded.`
checkAMM()
} else { } else {
results += `\n\nError sending transaction: ${lp_deposit}` results += `\n\nError sending transaction: ${JSON.stringify(lp_deposit.result.meta.TransactionResult, null, 2)}`
}
} catch (error) {
results += `\n\n${error.message}`
} }
standbyResultField.value = results standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight standbyResultField.scrollTop = standbyResultField.scrollHeight
// Update LP token balance.
standbyWalletBalances = (await client.getBalances(standby_wallet.address))
const amm_info_request = {
"command": "amm_info",
"asset": {
"currency": "XRP"
},
"asset2": {
"currency": currency_code,
"issuer": operational_wallet.address
},
"ledger_index": "validated"
}
const amm_info_result = await client.request(amm_info_request)
// Get the AMM account address that issues LP tokens to depositors
ammAccount = amm_info_result.result.amm.account
const lpCurrency = standbyWalletBalances.find(item => item.issuer === ammAccount);
const lpValue = lpCurrency ? lpCurrency.value : 'Currency not found';
standbyLPField.value = lpValue
client.disconnect() client.disconnect()
} }
@@ -150,23 +246,65 @@ async function voteFees() {
standbyResultField.value = results standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value) const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const currency_code = standbyCurrencyField.value
const voteFee = standbyFeeField.value const voteFee = standbyFeeField.value
const ammvote = { const asset1_currency = asset1CurrencyField.value
const asset1_issuer = asset1IssuerField.value
const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
let ammvote = null
if ( asset1_currency == "XRP" ) {
ammvote = {
"TransactionType": "AMMVote", "TransactionType": "AMMVote",
"Asset": { "Asset": {
"currency": "XRP" "currency": "XRP"
}, },
"Asset2": { "Asset2": {
"currency": currency_code, "currency": asset2_currency,
"issuer": operational_wallet.address "issuer": asset2_issuer
}, },
"Account": standby_wallet.address, "Account": standby_wallet.address,
"TradingFee": Number(voteFee) "TradingFee": Number(voteFee)
} }
} else if ( asset2_currency == "XRP" ) {
ammvote = {
"TransactionType": "AMMVote",
"Asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"Asset2": {
"currency": "XRP"
},
"Account": standby_wallet.address,
"TradingFee": Number(voteFee)
}
} else {
ammvote = {
"TransactionType": "AMMVote",
"Asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"Asset2": {
"currency": asset2_currency,
"issuer": asset2_issuer
},
"Account": standby_wallet.address,
"TradingFee": Number(voteFee)
}
}
try {
const prepared_vote = await client.autofill(ammvote) const prepared_vote = await client.autofill(ammvote)
results += `\n\nPrepared transaction:\n${JSON.stringify(prepared_vote, null, 2)}` results += `\n\nPrepared transaction:\n${JSON.stringify(prepared_vote, null, 2)}`
standbyResultField.value = results standbyResultField.value = results
@@ -180,8 +318,13 @@ async function voteFees() {
const response_vote = await client.submitAndWait(signed_vote.tx_blob) const response_vote = await client.submitAndWait(signed_vote.tx_blob)
if (response_vote.result.meta.TransactionResult == "tesSUCCESS") { if (response_vote.result.meta.TransactionResult == "tesSUCCESS") {
results += `\n\nTransaction succeeded.` results += `\n\nTransaction succeeded.`
checkAMM()
} else { } else {
results += `\n\nError sending transaction: ${response_vote}` results += `\n\nError sending transaction: ${JSON.stringify(response_vote.result.meta.TransactionResult, null, 2)}`
}
} catch (error) {
results += `\n\n${error.message}`
} }
standbyResultField.value = results standbyResultField.value = results
@@ -204,30 +347,109 @@ async function calculateLP() {
results += '\n\nConnected.' results += '\n\nConnected.'
standbyResultField.value = results standbyResultField.value = results
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value) const standby_wallet = standbyAccountField.value
const currency_code = standbyCurrencyField.value
const LPTokens = standbyLPField.value const asset1_currency = asset1CurrencyField.value
const asset1_issuer = asset1IssuerField.value
const amm_info = (await client.request({ const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
let amm_info = null
if ( asset1_currency == "XRP" ) {
amm_info = {
"command": "amm_info", "command": "amm_info",
"asset": { "asset": {
"currency": "XRP" "currency": "XRP"
}, },
"asset2": { "asset2": {
"currency": currency_code, "currency": asset2_currency,
"issuer": operational_wallet.address "issuer": asset2_issuer
}
} }
}))
const my_share = LPTokens / amm_info.result.amm.lp_token.value } else if ( asset2_currency == "XRP" ) {
const my_asset1 = (amm_info.result.amm.amount * my_share) / 1000000 amm_info = {
const my_asset2 = amm_info.result.amm.amount2.value * my_share "command": "amm_info",
"asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"asset2": {
"currency": "XRP"
}
}
results += `\n\nMy ${LPTokens} LP tokens are worth:\n } else {
amm_info = {
"command": "amm_info",
"asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"asset2": {
"currency": asset2_currency,
"issuer": asset2_issuer
}
}
}
try {
// Get LP token balance.
standbyWalletBalances = await client.getBalances(standby_wallet)
const amm_info_result = await client.request(amm_info)
// Get the AMM account address that issues LP tokens to depositors
ammAccount = amm_info_result.result.amm.account
const lpCurrency = standbyWalletBalances.find(item => item.issuer === ammAccount);
const lpBalance = lpCurrency ? lpCurrency.value : 'Currency not found';
const my_share = lpBalance / amm_info_result.result.amm.lp_token.value
let my_asset1 = null
let my_asset2 = null
if ( amm_info_result.result.amm.amount.value && amm_info_result.result.amm.amount2.value ) {
my_asset1 = amm_info_result.result.amm.amount.value * my_share
my_asset2 = amm_info_result.result.amm.amount2.value * my_share
results += `\n\nI have a total of ${lpBalance} LP tokens that are worth:\n
${amm_info_result.result.amm.amount.currency}: ${my_asset1}
${amm_info_result.result.amm.amount2.currency}: ${my_asset2}`
} else if ( amm_info_result.result.amm.amount.value == undefined ) {
my_asset1 = (amm_info_result.result.amm.amount * my_share) / 1000000
my_asset2 = amm_info_result.result.amm.amount2.value * my_share
results += `\n\nI have a total of ${lpBalance} LP tokens that are worth:\n
XRP: ${my_asset1} XRP: ${my_asset1}
${amm_info.result.amm.amount2.currency}: ${my_asset2}` ${amm_info_result.result.amm.amount2.currency}: ${my_asset2}`
} else {
my_asset1 = amm_info_result.result.amm.amount.value * my_share
my_asset2 = (amm_info_result.result.amm.amount2 * my_share) / 1000000
results += `\n\nI have a total of ${lpBalance} LP tokens that are worth:\n
${amm_info_result.result.amm.amount.currency}: ${my_asset1}
XRP: ${my_asset2}`
}
} catch (error) {
results += `\n\n${error.message}`
}
standbyResultField.value = results standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight standbyResultField.scrollTop = standbyResultField.scrollHeight
@@ -236,7 +458,7 @@ async function calculateLP() {
} }
// Withdraw by redeeming LP tokens. // Redeem LP tokens.
async function redeemLP() { async function redeemLP() {
let net = getNet() let net = getNet()
@@ -250,35 +472,88 @@ async function redeemLP() {
standbyResultField.value = results standbyResultField.value = results
const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value) const standby_wallet = xrpl.Wallet.fromSeed(standbySeedField.value)
const operational_wallet = xrpl.Wallet.fromSeed(operationalSeedField.value)
const currency_code = standbyCurrencyField.value
const LPTokens = standbyLPField.value
// Get LP token info. const asset1_currency = asset1CurrencyField.value
const amm_info_request = { const asset1_issuer = asset1IssuerField.value
const asset2_currency = asset2CurrencyField.value
const asset2_issuer = asset2IssuerField.value
// Structure "amm_info" command based on asset combo.
let amm_info = null
if ( asset1_currency == "XRP" ) {
amm_info = {
"command": "amm_info", "command": "amm_info",
"asset": { "asset": {
"currency": "XRP" "currency": "XRP"
}, },
"asset2": { "asset2": {
"currency": currency_code, "currency": asset2_currency,
"issuer": operational_wallet.address "issuer": asset2_issuer
}, }
"ledger_index": "validated"
} }
const amm_info_result = await client.request(amm_info_request) } else if ( asset2_currency == "XRP" ) {
const ammIssuer = amm_info_result.result.amm.lp_token.issuer
const ammCurrency = amm_info_result.result.amm.lp_token.currency
const ammwithdraw = { amm_info = {
"command": "amm_info",
"asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"asset2": {
"currency": "XRP"
}
}
} else {
amm_info = {
"command": "amm_info",
"asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"asset2": {
"currency": asset2_currency,
"issuer": asset2_issuer
}
}
}
// Get LP token info.
let ammIssuer = null
let ammCurrency = null
const LPTokens = standbyLPField.value
try {
const amm_info_result = await client.request(amm_info)
ammIssuer = amm_info_result.result.amm.lp_token.issuer
ammCurrency = amm_info_result.result.amm.lp_token.currency
} catch (error) {
results += `\n\n${error.message}`
standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight
return
}
// Structure ammwithdraw transaction based on asset combo.
let ammwithdraw = null
if ( asset1_currency == "XRP" ) {
ammwithdraw = {
"TransactionType": "AMMWithdraw", "TransactionType": "AMMWithdraw",
"Asset": { "Asset": {
"currency": "XRP" "currency": "XRP"
}, },
"Asset2": { "Asset2": {
"currency": currency_code, "currency": asset2_currency,
"issuer": operational_wallet.address "issuer": asset2_issuer
}, },
"Account": standby_wallet.address, "Account": standby_wallet.address,
"LPTokenIn": { "LPTokenIn": {
@@ -289,6 +564,51 @@ async function redeemLP() {
"Flags": 0x00010000 "Flags": 0x00010000
} }
} else if ( asset2_currency == "XRP" ) {
ammwithdraw = {
"TransactionType": "AMMWithdraw",
"Asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"Asset2": {
"currency": "XRP"
},
"Account": standby_wallet.address,
"LPTokenIn": {
currency: ammCurrency,
issuer: ammIssuer,
value: LPTokens
},
"Flags": 0x00010000
}
} else {
ammwithdraw = {
"TransactionType": "AMMWithdraw",
"Asset": {
"currency": asset1_currency,
"issuer": asset1_issuer
},
"Asset2": {
"currency": asset2_currency,
"issuer": asset2_issuer
},
"Account": standby_wallet.address,
"LPTokenIn": {
currency: ammCurrency,
issuer: ammIssuer,
value: LPTokens
},
"Flags": 0x00010000
}
}
try {
const prepared_withdraw = await client.autofill(ammwithdraw) const prepared_withdraw = await client.autofill(ammwithdraw)
results += `\n\nPrepared transaction:\n${JSON.stringify(prepared_withdraw, null, 2)}` results += `\n\nPrepared transaction:\n${JSON.stringify(prepared_withdraw, null, 2)}`
standbyResultField.value = results standbyResultField.value = results
@@ -302,30 +622,20 @@ async function redeemLP() {
const response_withdraw = await client.submitAndWait(signed_withdraw.tx_blob) const response_withdraw = await client.submitAndWait(signed_withdraw.tx_blob)
if (response_withdraw.result.meta.TransactionResult == "tesSUCCESS") { if (response_withdraw.result.meta.TransactionResult == "tesSUCCESS") {
results += `\n\nTransaction succeeded. Updating balances ...` results += `\n\nTransaction succeeded.`
checkAMM()
getBalances()
} else { } else {
results += `\n\nError sending transaction: ${response_withdraw}` results += `\n\nError sending transaction: ${JSON.stringify(response_withdraw.result.meta.TransactionResult, null, 2)}`
}
} catch (error) {
results += `\n\n${error.message}`
} }
standbyResultField.value = results standbyResultField.value = results
standbyResultField.scrollTop = standbyResultField.scrollHeight standbyResultField.scrollTop = standbyResultField.scrollHeight
// Update standby wallet XRP, token, and LP balances.
standbyBalanceField.value = (await client.getXrpBalance(standby_wallet.address))
walletBalances = (await client.getBalances(standby_wallet.address))
const currencyAmount = walletBalances.find(item => item.currency === currency_code);
const currencyValue = currencyAmount ? currencyAmount.value : 'Currency not found';
standbyAmountField.value = currencyValue
ammAccount = amm_info_result.result.amm.account
const lpCurrency = walletBalances.find(item => item.issuer === ammAccount);
const lpValue = lpCurrency ? lpCurrency.value : 'Currency not found';
standbyLPField.value = lpValue
client.disconnect() client.disconnect()
} }

View File

@@ -126,8 +126,7 @@ async function sendCurrency() {
const pay_prepared = await client.autofill(send_token_tx) const pay_prepared = await client.autofill(send_token_tx)
const pay_signed = standby_wallet.sign(pay_prepared) const pay_signed = standby_wallet.sign(pay_prepared)
results += 'Sending ${issue_quantity} ${currency_code} to ' + results += `\n\nSending ${issue_quantity} ${currency_code} to ${standbyDestinationField.value} ...`
standbyDestinationField.value + '...'
standbyResultField.value = results standbyResultField.value = results
const pay_result = await client.submitAndWait(pay_signed.tx_blob) const pay_result = await client.submitAndWait(pay_signed.tx_blob)
if (pay_result.result.meta.TransactionResult == "tesSUCCESS") { if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
@@ -260,8 +259,7 @@ async function oPsendCurrency() {
const pay_prepared = await client.autofill(send_token_tx) const pay_prepared = await client.autofill(send_token_tx)
const pay_signed = operational_wallet.sign(pay_prepared) const pay_signed = operational_wallet.sign(pay_prepared)
results += 'Sending ${issue_quantity} ${currency_code} to ' + results += `\n\nSending ${issue_quantity} ${currency_code} to ${operationalDestinationField.value} ...`
operationalDestinationField.value + '...'
operationalResultField.value = results operationalResultField.value = results
const pay_result = await client.submitAndWait(pay_signed.tx_blob) const pay_result = await client.submitAndWait(pay_signed.tx_blob)
if (pay_result.result.meta.TransactionResult == "tesSUCCESS") { if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 164 KiB

View File

@@ -10,10 +10,10 @@ labels:
This example shows how to: This example shows how to:
1. Deposit `XRP` and issued tokens to an AMM and receive LP tokens. 1. Deposit assets to an existing AMM and receive LP tokens.
2. Vote on AMM trading fees. 2. Vote on AMM trading fees.
3. Check the value of your LP tokens. 3. Check the value of your LP tokens.
4. Redeem LP Tokens for assets. 4. Redeem LP tokens for assets in the AMM pair.
[![Add assets to AMM test harness](/docs/img/quickstart-add-to-amm1.png)](/docs/img/quickstart-add-to-amm1.png) [![Add assets to AMM test harness](/docs/img/quickstart-add-to-amm1.png)](/docs/img/quickstart-add-to-amm1.png)
@@ -41,13 +41,31 @@ Without the Quickstart Samples, you will not be able to try the examples that fo
[![Get account results](/docs/img/quickstart-add-to-amm2.png)](/docs/img/quickstart-add-to-amm2.png) [![Get account results](/docs/img/quickstart-add-to-amm2.png)](/docs/img/quickstart-add-to-amm2.png)
### Add Assets to an Existing AMM ### Get the AMM
Choose the amount of assets to add to the AMM. You can deposit either one or both assets, but deposting only one asset reduces the amount of LP tokens you receive. In the standby account fields: 1. Enter a [currency code](/docs/references/protocol/data-types/currency-formats.md#currency-codes) in the **Asset 1 Currency** field. For example, `TST`.
2. (Optional) If you entered a currency code other than `XRP`, also enter the token issuer in the **Asset 1 Issuer** field.
3. Enter a second currency code in the **Asset 2 Currency** field.
4. (Optional) If you entered a second currency code other than `XRP`, also enter the token issuer in the **Asset 2 Issuer** field.
5. Click **Check AMM**.
1. Enter how much XRP to add in the **XRP Balance** field. [![Add assets to AMM results](/docs/img/quickstart-add-to-amm3.png)](/docs/img/quickstart-add-to-amm3.png)
2. Enter how many issued tokens to add in the **Amount** field.
3. Enter the token issuer address in the **Destination** field.
### (Optional) Acquire More Assets
If you need more assets, you can:
- Fund a new wallet with `XRP` by clicking **Get New Standby Account**.
- Get more tokens from the token issuer in the AMM pair. See: [Create an AMM](/docs/tutorials/javascript/amm/create-an-amm)
### Add Assets to the AMM
Choose the amount of assets to add to the AMM. You can deposit either one or both assets, but deposting only one reduces the amount of LP tokens you receive.
1. Click **Get Balances** to verify how many tokens you have.
2. Enter a value in the **Asset 1 Amount** field.
3. (Optional) Enter a value in the **Asset 2 Amount** field.
4. Click **Add to AMM**. 4. Click **Add to AMM**.
[![Add assets to AMM results](/docs/img/quickstart-add-to-amm3.png)](/docs/img/quickstart-add-to-amm3.png) [![Add assets to AMM results](/docs/img/quickstart-add-to-amm3.png)](/docs/img/quickstart-add-to-amm3.png)
@@ -61,20 +79,13 @@ Choose the amount of assets to add to the AMM. You can deposit either one or bot
[![Vote on trading fees results](/docs/img/quickstart-add-to-amm4.png)](/docs/img/quickstart-add-to-amm4.png) [![Vote on trading fees results](/docs/img/quickstart-add-to-amm4.png)](/docs/img/quickstart-add-to-amm4.png)
### Check LP Token Value
1. Enter a value in the **LP Tokens** field.
2. Click **Get LP Value**.
[![Get LP token value results](/docs/img/quickstart-add-to-amm5.png)](/docs/img/quickstart-add-to-amm5.png)
### Redeem Your LP Tokens ### Redeem Your LP Tokens
1. Enter a value in the **LP Tokens** field. 1. Click **Get LP Value**.
2. Click **Redeem LP**. 2. Enter a value in the **LP Tokens** field.
3. Click **Redeem LP**.
[![Get LP token value results](/docs/img/quickstart-add-to-amm6.png)](/docs/img/quickstart-add-to-amm6.png) [![Get LP token value results](/docs/img/quickstart-add-to-amm5.png)](/docs/img/quickstart-add-to-amm5.png)
## Code Walkthrough ## Code Walkthrough
@@ -86,27 +97,20 @@ You can open `ripplex12-add-to-amm.js` from the [Quickstart Samples](https://git
This code checks if you're trying to add one or both assets, and then modifies the `AMMDeposit` transaction to be either a single or double-asset deposit. This code checks if you're trying to add one or both assets, and then modifies the `AMMDeposit` transaction to be either a single or double-asset deposit.
The function to update LP balance checks the AMM to get the unique AMM account, which acts as its own issuer of LP tokens. It then checks your wallet balance and gets the LP token value by matching it with the AMM issuer.
{% code-snippet file="/_code-samples/quickstart/js/ripplex12-add-to-amm.js" from="// Deposit assets to existing AMM." before="// Vote on AMM trading fees" language="js" /%} {% code-snippet file="/_code-samples/quickstart/js/ripplex12-add-to-amm.js" from="// Deposit assets to existing AMM." before="// Vote on AMM trading fees" language="js" /%}
### Vote on Trading Fees ### Vote on Trading Fees
Trading fees are applied to any transaction that interacts with the AMM. The act of voting is straightforward and only requires you to hold the AMM LP tokens before submitting a vote. Trading fees are applied to any transaction that interacts with the AMM. As with the `addAssets()` function, this one checks the combination of assets provided to modifty the `ammVote` transaction.
{% code-snippet file="/_code-samples/quickstart/js/ripplex12-add-to-amm.js" from="// Vote on AMM trading fees" before="// Calculate the value of your LP tokens." language="js" /%} {% code-snippet file="/_code-samples/quickstart/js/ripplex12-add-to-amm.js" from="// Vote on AMM trading fees" before="// Calculate the value of your LP tokens." language="js" /%}
### Calculate Value of LP Tokens
There isn't a dedicated method to calculate how much you can redeem your LP tokens for, but the math isn't too complicated. The percentage of the total LP tokens in circulation that you own qualifies you for the same percentage of the total assets in the AMM.
{% code-snippet file="/_code-samples/quickstart/js/ripplex12-add-to-amm.js" from="// Calculate the value of your LP tokens." before="// Withdraw by redeeming LP tokens." language="js" /%}
### Redeem Your LP Tokens ### Redeem Your LP Tokens
Redeeming your LP tokens requires you to get the LP token issuer and currency code, both of which you can check using the `amm_info` method. The `calculateLP()` function gets the AMM account, which acts as its own issuer of LP tokens. It then checks your wallet balance and gets your LP token balance by matching it with the AMM issuer. Although there isn't a dedicated method to calculate what you can redeem your LP tokens for, the math to do so is simple. The function checks the percentage of LP tokens in circulation that you own, and then applies that same percentage to the total assets in the AMM to give you their redemption value.
{% code-snippet file="/_code-samples/quickstart/js/ripplex12-add-to-amm.js" from="// Withdraw by redeeming LP tokens." language="js" /%} The code to redeem the LP tokens checks how many tokens you want to redeem, as well as the combination of assets to format `amm_info` and `AMMWithdraw`.
{% code-snippet file="/_code-samples/quickstart/js/ripplex12-add-to-amm.js" from="// Calculate the value of your LP tokens." language="js" /%}

View File

@@ -34,11 +34,13 @@ Without the Quickstart Samples, you will not be able to try the examples that fo
### Check AMM ### Check AMM
In the standby account fields: 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).
1. Enter a [currency code](/docs/references/protocol/data-types/currency-formats.md#currency-codes) in the **Currency** field. 1. Enter a [currency code](/docs/references/protocol/data-types/currency-formats.md#currency-codes) in the **Asset 1 Currency** field. For example, `TST`.
2. Enter a token issuer in the **Destination** field. 2. (Optional) If you entered a currency code other than `XRP`, also enter the token issuer in the **Asset 1 Issuer** field.
3. Click **Check AMM**. 3. Enter a second currency code in the **Asset 2 Currency** field.
4. (Optional) If you entered a second currency code other than `XRP`, also enter the token issuer in the **Asset 2 Issuer** field.
5. Click **Check AMM**.
[![Check AMM results](/docs/img/quickstart-create-amm3.png)](/docs/img/quickstart-create-amm3.png) [![Check AMM results](/docs/img/quickstart-create-amm3.png)](/docs/img/quickstart-create-amm3.png)
@@ -47,9 +49,9 @@ In the standby account fields:
Create a trustline from the operational account to the standby account. In the standby account fields: Create a trustline from the operational account to the standby account. In the standby account fields:
1. Enter a currency code in the **Currency** field. 1. Enter the maximum transfer limit in the **Amount** field.
2. Enter the maximum transfer limit in the **Amount** field. 2. Enter the operational account address in the **Destination** field.
3. Enter the operational account address in the **Destination** field. 3. Enter a currency code in the **Currency** field.
4. Click **Create Trustline**. 4. Click **Create Trustline**.
[![Create trustline results](/docs/img/quickstart-create-amm4.png)](/docs/img/quickstart-create-amm4.png) [![Create trustline results](/docs/img/quickstart-create-amm4.png)](/docs/img/quickstart-create-amm4.png)
@@ -67,17 +69,18 @@ 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) [![Issue token results](/docs/img/quickstart-create-amm5.png)](/docs/img/quickstart-create-amm5.png)
{% admonition type="note" name="Note" %}
If you want to create an AMM with two test tokens, repeat the _Create Trustline_ and _Issue Tokens_ steps, using a different currency code.
{% /admonition %}
### Create an AMM ### Create an AMM
In the standby account fields: Create a new AMM pool.
1. Click **Get Balances** to verify how many tokens you have. 1. Click **Get Balances** to verify how many tokens you have.
2. Enter how much XRP to add in the **XRP Balance** field. 2. Enter a value in the **Asset 1 Amount** field.
3. Enter the operational account address in the **Destination** field. 3. Enter a value in the **Asset 2 Amount** field.
4. Enter the currency code in the **Currency** field. 4. Click **Create AMM**.
5. Enter how many issued tokens to add in the **Amount** field.
6. Click **Create AMM**.
[![Create AMM results](/docs/img/quickstart-create-amm6.png)](/docs/img/quickstart-create-amm6.png) [![Create AMM results](/docs/img/quickstart-create-amm6.png)](/docs/img/quickstart-create-amm6.png)
@@ -96,6 +99,6 @@ This checks if an AMM already exists. While multiple tokens can share the same c
### Create AMM ### Create AMM
This sends the `AMMCreate` transaction and creates a new AMM, using the initial assets provided. This sends the `AMMCreate` transaction and creates a new AMM, using the initial assets provided. The code checks the token currency fields and formats the `AMMCreate` transaction based on the combination of `XRP` and custom tokens.
{% code-snippet file="/_code-samples/quickstart/js/ripplex11-create-amm.js" from="// Create AMM function" before="// Check AMM function" language="js" /%} {% code-snippet file="/_code-samples/quickstart/js/ripplex11-create-amm.js" from="// Create AMM function" before="// Check AMM function" language="js" /%}