mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-20 11:45:50 +00:00
Fix interactive tutorial faucet interface on Devnet; migrate AMM tutorial to Devnet
This commit is contained in:
@@ -186,29 +186,36 @@ function setup_generate_step() {
|
|||||||
const faucet_url = $("#generate-creds-button").data("fauceturl")
|
const faucet_url = $("#generate-creds-button").data("fauceturl")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// destination not defined - API will create account.
|
const wallet = xrpl.Wallet.generate("ed25519")
|
||||||
const data = await call_faucet(faucet_url, undefined, event)
|
const data = await call_faucet(faucet_url, wallet.address, event)
|
||||||
|
|
||||||
block.find(".loader").hide()
|
block.find(".loader").hide()
|
||||||
block.find(".output-area").html(`<div><strong>${tl("Address:")}</strong>
|
block.find(".output-area").html(`<div><strong>${tl("Address:")}</strong>
|
||||||
<span id="use-address">${data.account.address}</span></div>
|
<span id="use-address">${data.account.address}</span></div>
|
||||||
<div><strong>${tl("Secret:")}</strong>
|
<div><strong>${tl("Secret:")}</strong>
|
||||||
<span id="use-secret">${data.account.secret}</span></div>
|
<span id="use-secret">${wallet.seed}</span></div>`)
|
||||||
<strong>${tl("Balance:")}</strong>
|
if (data.balance) {
|
||||||
${Number(data.balance).toLocaleString(current_locale)} XRP`)
|
block.find(".output-area").append(`<div><strong>${tl("Balance:")}</strong>
|
||||||
|
${Number(data.balance).toLocaleString(current_locale)} XRP</div>`)
|
||||||
|
}
|
||||||
|
|
||||||
// Automatically populate all examples in the page with the
|
// Automatically populate all examples in the page with the
|
||||||
// generated credentials...
|
// generated credentials...
|
||||||
|
let creds_updated = false;
|
||||||
$("code span:contains('"+EXAMPLE_ADDR+"')").each( function() {
|
$("code span:contains('"+EXAMPLE_ADDR+"')").each( function() {
|
||||||
|
creds_updated = true
|
||||||
let eltext = $(this).text()
|
let eltext = $(this).text()
|
||||||
$(this).text( eltext.replace(EXAMPLE_ADDR, data.account.address) )
|
$(this).text( eltext.replace(EXAMPLE_ADDR, data.account.address) )
|
||||||
})
|
})
|
||||||
$("code span:contains('"+EXAMPLE_SECRET+"')").each( function() {
|
$("code span:contains('"+EXAMPLE_SECRET+"')").each( function() {
|
||||||
|
creds_updated = true
|
||||||
let eltext = $(this).text()
|
let eltext = $(this).text()
|
||||||
$(this).text( eltext.replace(EXAMPLE_SECRET, data.account.secret) )
|
$(this).text( eltext.replace(EXAMPLE_SECRET, data.account.secret) )
|
||||||
})
|
})
|
||||||
|
|
||||||
block.find(".output-area").append(`<p>${tl("Populated this page's examples with these credentials.")}</p>`)
|
if (creds_updated) {
|
||||||
|
block.find(".output-area").append(`<p>${tl("Populated this page's examples with these credentials.")}</p>`)
|
||||||
|
}
|
||||||
|
|
||||||
complete_step("Generate")
|
complete_step("Generate")
|
||||||
|
|
||||||
@@ -278,7 +285,7 @@ async function call_faucet(faucet_url, destination, event) {
|
|||||||
step: block.data("stepnumber"),
|
step: block.data("stepnumber"),
|
||||||
totalsteps: block.data("totalsteps"),
|
totalsteps: block.data("totalsteps"),
|
||||||
};
|
};
|
||||||
//pass in plain text instead of HEX- the API will encode.
|
//pass in plain text instead of HEX- the API will encode.
|
||||||
const memo = {
|
const memo = {
|
||||||
data: JSON.stringify(tutorial_info, null, 0),
|
data: JSON.stringify(tutorial_info, null, 0),
|
||||||
format: "application/json", // application/json
|
format: "application/json", // application/json
|
||||||
@@ -288,9 +295,7 @@ async function call_faucet(faucet_url, destination, event) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const body = {};
|
const body = {};
|
||||||
if (typeof destination != "undefined") {
|
body["destination"] = destination;
|
||||||
body["destination"] = destination;
|
|
||||||
}
|
|
||||||
body["memos"] = [memo];
|
body["memos"] = [memo];
|
||||||
|
|
||||||
const response = await fetch(faucet_url, {
|
const response = await fetch(faucet_url, {
|
||||||
|
|||||||
269
assets/js/tutorials/create-amm.js
Normal file
269
assets/js/tutorials/create-amm.js
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
// 1. Generate
|
||||||
|
// 2. Connect
|
||||||
|
// The code for these steps is handled by interactive-tutorial.js
|
||||||
|
$(document).ready(() => {
|
||||||
|
|
||||||
|
const EXPLORER = $("#connect-button").data("explorer")
|
||||||
|
|
||||||
|
$("#get-foo").click( async (event) => {
|
||||||
|
const block = $(event.target).closest(".interactive-block")
|
||||||
|
const wallet = get_wallet(event)
|
||||||
|
if (!wallet) {return}
|
||||||
|
|
||||||
|
const currency_code = "FOO"
|
||||||
|
const issue_quantity = "1000"
|
||||||
|
|
||||||
|
block.find(".loader").show()
|
||||||
|
show_log(block, "<p>Funding an issuer address with the faucet...</p>")
|
||||||
|
const issuer = (await api.fundWallet()).wallet
|
||||||
|
show_log(block, `<p>Got issuer <span id="issuer-address" data-seed="${issuer.seed}">${issuer.address}</span>.</p>`)
|
||||||
|
$(".foo-issuer").text(issuer.address) // Update display in the "Create AMM" step
|
||||||
|
|
||||||
|
// Enable issuer DefaultRipple ----------------------------------------------
|
||||||
|
const issuer_setup_tx = {
|
||||||
|
"TransactionType": "AccountSet",
|
||||||
|
"Account": issuer.address,
|
||||||
|
"SetFlag": xrpl.AccountSetAsfFlags.asfDefaultRipple
|
||||||
|
}
|
||||||
|
add_memo(event, issuer_setup_tx)
|
||||||
|
const issuer_setup_result = await api.submitAndWait(issuer_setup_tx, {autofill: true, wallet: issuer} )
|
||||||
|
if (issuer_setup_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||||
|
show_log(block, `<p><a href="${EXPLORER}/transactions/${issuer_setup_result.result.hash}">✅ Issuer DefaultRipple enabled</a></p>`)
|
||||||
|
} else {
|
||||||
|
show_error(block, `Error sending transaction: <pre><code>${pretty_print(issuer_setup_result)}</code></pre>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create trust line to issuer ----------------------------------------------
|
||||||
|
const trust_tx = {
|
||||||
|
"TransactionType": "TrustSet",
|
||||||
|
"Account": wallet.address,
|
||||||
|
"LimitAmount": {
|
||||||
|
"currency": currency_code,
|
||||||
|
"issuer": issuer.address,
|
||||||
|
"value": "10000000000" // Large limit, arbitrarily chosen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_memo(event, trust_tx)
|
||||||
|
const trust_result = await api.submitAndWait(trust_tx, {autofill: true, wallet: wallet})
|
||||||
|
if (trust_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||||
|
show_log(block, `<p><a href="${EXPLORER}/transactions/${trust_result.result.hash}">✅ Trust line created</a></p>`)
|
||||||
|
} else {
|
||||||
|
show_error(block, `Error sending transaction: <pre><code>${pretty_print(trust_result)}</code></pre>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue tokens -------------------------------------------------------------
|
||||||
|
const issue_tx = {
|
||||||
|
"TransactionType": "Payment",
|
||||||
|
"Account": issuer.address,
|
||||||
|
"Amount": {
|
||||||
|
"currency": currency_code,
|
||||||
|
"value": issue_quantity,
|
||||||
|
"issuer": issuer.address
|
||||||
|
},
|
||||||
|
"Destination": wallet.address
|
||||||
|
}
|
||||||
|
add_memo(event, issue_tx)
|
||||||
|
const issue_result = await api.submitAndWait(issue_tx, {autofill: true, wallet: issuer})
|
||||||
|
if (issue_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||||
|
show_log(block, `<p><a href="${EXPLORER}/transactions/${issue_result.result.hash}">✅ Tokens issued</a></p>`)
|
||||||
|
$("#get-foo").data("foo-acquired", true).prop("disabled", true).addClass("disabled").addClass("done")
|
||||||
|
} else {
|
||||||
|
show_error(block, `Error sending transaction: <pre><code>${pretty_print(issue_result)}</code></pre>`)
|
||||||
|
}
|
||||||
|
block.find(".loader").hide()
|
||||||
|
|
||||||
|
if ($("#get-foo").data("foo-acquired") && $("#buy-tst").data("tst-acquired")) {
|
||||||
|
complete_step("Acquire tokens")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#buy-tst").click( async (event) => {
|
||||||
|
const block = $(event.target).closest(".interactive-block")
|
||||||
|
const wallet = get_wallet(event)
|
||||||
|
if (!wallet) {return}
|
||||||
|
block.find(".loader").show()
|
||||||
|
|
||||||
|
const tx_json = {
|
||||||
|
"TransactionType": "OfferCreate",
|
||||||
|
"Account": wallet.address,
|
||||||
|
"TakerPays": {
|
||||||
|
currency: "TST",
|
||||||
|
issuer: "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
|
||||||
|
value: "25"
|
||||||
|
},
|
||||||
|
"TakerGets": xrpl.xrpToDrops(25*10*1.16)
|
||||||
|
}
|
||||||
|
add_memo(event, tx_json)
|
||||||
|
|
||||||
|
const offer_result = await api.submitAndWait(tx_json, {autofill: true, wallet: wallet})
|
||||||
|
|
||||||
|
if (offer_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||||
|
show_log(block, `<p><a href="${EXPLORER}/transactions/${offer_result.result.hash}">✅ TST offer placed</a></p>`)
|
||||||
|
const balance_changes = xrpl.getBalanceChanges(offer_result.result.meta)
|
||||||
|
for (const bc of balance_changes) {
|
||||||
|
if (bc.account != wallet.address) {continue}
|
||||||
|
for (const bal of bc.balances) {
|
||||||
|
if (bal.currency == "TST") {
|
||||||
|
show_log(block, `<p>Got <strong>${bal.value}</strong> ${bal.currency}.${bal.issuer}.</p>`)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
$("#buy-tst").data("tst-acquired", true).prop("disabled", true).addClass("disabled").addClass("done")
|
||||||
|
} else {
|
||||||
|
show_error(block, `<p>Transaction failed:</p><pre><code>${pretty_print(offer_result)}</code></pre>`)
|
||||||
|
}
|
||||||
|
block.find(".loader").hide()
|
||||||
|
|
||||||
|
if ($("#get-foo").data("foo-acquired") && $("#buy-tst").data("tst-acquired")) {
|
||||||
|
complete_step("Acquire tokens")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#check-for-amm").click( async (event) => {
|
||||||
|
const block = $(event.target).closest(".interactive-block")
|
||||||
|
const foo_issuer_address = $("#issuer-address").text()
|
||||||
|
|
||||||
|
block.find(".output-area").html("")
|
||||||
|
block.find(".loader").show()
|
||||||
|
try {
|
||||||
|
const amm_info = await api.request({
|
||||||
|
"command": "amm_info",
|
||||||
|
"asset": {
|
||||||
|
"currency": "TST",
|
||||||
|
"issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
|
||||||
|
},
|
||||||
|
"asset2": {
|
||||||
|
"currency": "FOO",
|
||||||
|
"issuer": foo_issuer_address
|
||||||
|
},
|
||||||
|
"ledger_index": "validated"
|
||||||
|
})
|
||||||
|
show_log(block, `<pre><code>${pretty_print}amm_info</code></pre>`)
|
||||||
|
} catch(err) {
|
||||||
|
if (err.data.error === 'actNotFound') {
|
||||||
|
show_log(block, `<p>✅ No AMM exists yet for the pair
|
||||||
|
FOO.${foo_issuer_address} /
|
||||||
|
TST.rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd.`)
|
||||||
|
complete_step("Check for AMM")
|
||||||
|
} else {
|
||||||
|
show_error(block, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block.find(".loader").hide()
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#look-up-ammcreate-cost").click( async (event) => {
|
||||||
|
const block = $(event.target).closest(".interactive-block")
|
||||||
|
block.find(".loader").show()
|
||||||
|
let amm_fee_drops = "5000000"
|
||||||
|
try {
|
||||||
|
const ss = await api.request({"command": "server_state"})
|
||||||
|
amm_fee_drops = ss.result.state.validated_ledger.reserve_inc.toString()
|
||||||
|
show_log(block, `<p>Current AMMCreate transaction cost: ${xrpl.dropsToXrp(amm_fee_drops)} XRP (<span id="ammcreate-cost-drops">${amm_fee_drops}</span> drops)</p>`)
|
||||||
|
complete_step("Look up AMMCreate cost")
|
||||||
|
} catch(err) {
|
||||||
|
show_error(block, `Error looking up AMMCreate tx cost: ${err}`)
|
||||||
|
}
|
||||||
|
block.find(".loader").hide()
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#create-amm").click( async (event) => {
|
||||||
|
const block = $(event.target).closest(".interactive-block")
|
||||||
|
const wallet = get_wallet(event)
|
||||||
|
if (!wallet) {return}
|
||||||
|
|
||||||
|
amm_fee_drops = $("#ammcreate-cost-drops").text()
|
||||||
|
if (!amm_fee_drops) {return}
|
||||||
|
|
||||||
|
const asset_amount = $("#asset-amount").val()
|
||||||
|
const asset2_amount = $("#asset2-amount").val()
|
||||||
|
const asset2_issuer_address = $("#issuer-address").text()
|
||||||
|
const trading_fee = Math.floor($("#trading-fee").val()*1000) // Convert from %
|
||||||
|
|
||||||
|
const ammcreate_tx = {
|
||||||
|
"TransactionType": "AMMCreate",
|
||||||
|
"Account": wallet.address,
|
||||||
|
"Amount": {
|
||||||
|
currency: "TST",
|
||||||
|
issuer: "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
|
||||||
|
value: asset_amount
|
||||||
|
},
|
||||||
|
"Amount2": {
|
||||||
|
"currency": "FOO",
|
||||||
|
"issuer": asset2_issuer_address,
|
||||||
|
"value": asset2_amount
|
||||||
|
},
|
||||||
|
"TradingFee": 500, // 0.5%
|
||||||
|
"Fee": amm_fee_drops
|
||||||
|
}
|
||||||
|
add_memo(event, ammcreate_tx)
|
||||||
|
const ammcreate_result = await api.submitAndWait(ammcreate_tx, {autofill: true, wallet: wallet, fail_hard: true})
|
||||||
|
if (ammcreate_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||||
|
show_log(block, `<p><a href="${EXPLORER}/transactions/${ammcreate_result.result.hash}">AMM created</a>:</p>
|
||||||
|
<pre><code>${pretty_print(ammcreate_result)}</code></pre>`)
|
||||||
|
complete_step("Create AMM")
|
||||||
|
} else {
|
||||||
|
throw `Error sending transaction: ${ammcreate_result}`
|
||||||
|
}
|
||||||
|
block.find(".loader").hide()
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#check-amm-info").click( async (event) => {
|
||||||
|
const block = $(event.target).closest(".interactive-block")
|
||||||
|
const foo_issuer_address = $("#issuer-address").text()
|
||||||
|
|
||||||
|
block.find(".output-area").html("")
|
||||||
|
block.find(".loader").show()
|
||||||
|
try {
|
||||||
|
const amm_info = await api.request({
|
||||||
|
"command": "amm_info",
|
||||||
|
"asset": {
|
||||||
|
"currency": "TST",
|
||||||
|
"issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
|
||||||
|
},
|
||||||
|
"asset2": {
|
||||||
|
"currency": "FOO",
|
||||||
|
"issuer": foo_issuer_address
|
||||||
|
},
|
||||||
|
"ledger_index": "validated"
|
||||||
|
})
|
||||||
|
show_log(block, `<p><strong>AMM Info:</strong><pre><code>${pretty_print(amm_info)}</code></pre>`)
|
||||||
|
const lp_token = amm_info.result.amm.lp_token
|
||||||
|
show_log(block, `<p>The AMM account <strong>${lp_token.issuer}</strong> has <strong>${lp_token.value}</strong> total
|
||||||
|
LP tokens outstanding, and uses the currency code <code>${lp_token.currency}</code>.</p>`)
|
||||||
|
const amount = amm_info.result.amm.amount
|
||||||
|
const amount2 = amm_info.result.amm.amount2
|
||||||
|
show_log(block, `<p>In its pool, the AMM holds <strong>${amount.value} ${amount.currency}.${amount.issuer}</strong>
|
||||||
|
and <strong>${amount2.value} ${amount2.currency}.${amount2.issuer}</strong></p>`)
|
||||||
|
complete_step("Check AMM info")
|
||||||
|
} catch(err) {
|
||||||
|
show_error(block, err)
|
||||||
|
}
|
||||||
|
block.find(".loader").hide()
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#check-trust-lines").click( async (event) => {
|
||||||
|
const block = $(event.target).closest(".interactive-block")
|
||||||
|
const address = get_address()
|
||||||
|
if (!address) {return}
|
||||||
|
|
||||||
|
block.find(".output-area").html("")
|
||||||
|
block.find(".loader").show()
|
||||||
|
try {
|
||||||
|
const account_lines = await api.request({
|
||||||
|
"command": "account_lines",
|
||||||
|
"account": address,
|
||||||
|
"ledger_index": "validated"
|
||||||
|
})
|
||||||
|
show_log(block, `<p><strong>Trust lines:</strong><pre><code>${pretty_print(account_lines)}</code></pre>`)
|
||||||
|
complete_step("Check trust lines")
|
||||||
|
} catch(err) {
|
||||||
|
show_error(block, err)
|
||||||
|
}
|
||||||
|
block.find(".loader").hide()
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
// In browsers, use a <script> tag. In Node.js, uncomment the following line:
|
// In browsers, use a <script> tag. In Node.js, uncomment the following line:
|
||||||
// const xrpl = require('xrpl')
|
// const xrpl = require('xrpl')
|
||||||
|
|
||||||
const WS_URL = 'wss://amm.devnet.rippletest.net:51233/'
|
const WS_URL = 'wss://s.devnet.rippletest.net:51233/'
|
||||||
const EXPLORER = 'amm-devnet.xrpl.org' // Optional, for linking
|
const EXPLORER = 'devnet.xrpl.org' // Optional, for linking
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
// Define the network client
|
// Define the network client
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
// Code to set up an AMM instance between
|
// Code to set up an AMM instance between
|
||||||
// "TST.rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd" and novel "FOO" tokens.
|
// "TST.rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd" and novel "FOO" tokens.
|
||||||
|
|
||||||
// Dependencies for Node.js; this if statement lets the code run unmodified
|
// Dependencies for Node.js; this if statement lets the code run unmodified
|
||||||
@@ -14,8 +14,8 @@ if (typeof module !== "undefined") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect to the network -----------------------------------------------------
|
// Connect to the network -----------------------------------------------------
|
||||||
const WS_URL = 'wss://amm.devnet.rippletest.net:51233'
|
const WS_URL = 'wss://s.devnet.rippletest.net:51233'
|
||||||
const EXPLORER = 'https://amm-devnet.xrpl.org'
|
const EXPLORER = 'https://devnet.xrpl.org'
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const client = new xrpl.Client(WS_URL);
|
const client = new xrpl.Client(WS_URL);
|
||||||
@@ -24,7 +24,7 @@ async function main() {
|
|||||||
// Get credentials from the Faucet -------------------------------------------
|
// Get credentials from the Faucet -------------------------------------------
|
||||||
console.log("Requesting address from the faucet...")
|
console.log("Requesting address from the faucet...")
|
||||||
const wallet = (await client.fundWallet()).wallet
|
const wallet = (await client.fundWallet()).wallet
|
||||||
|
|
||||||
// To use an existing account, use code such as the following:
|
// To use an existing account, use code such as the following:
|
||||||
// const wallet = xrpl.Wallet.fromSeed(process.env['USE_SEED'])
|
// const wallet = xrpl.Wallet.fromSeed(process.env['USE_SEED'])
|
||||||
|
|
||||||
@@ -58,14 +58,14 @@ async function main() {
|
|||||||
}
|
}
|
||||||
// Successfully placing the offer doesn't necessarily mean that you have TST,
|
// Successfully placing the offer doesn't necessarily mean that you have TST,
|
||||||
// but for now, let's assume it matched existing Offers on ledger so you do.
|
// but for now, let's assume it matched existing Offers on ledger so you do.
|
||||||
|
|
||||||
// Call helper function to set up a new "FOO" issuer, create a trust line
|
// Call helper function to set up a new "FOO" issuer, create a trust line
|
||||||
// to them, and receive 1000 FOO from them.
|
// to them, and receive 1000 FOO from them.
|
||||||
const foo_amount = await get_new_token(client, wallet, "FOO", "1000")
|
const foo_amount = await get_new_token(client, wallet, "FOO", "1000")
|
||||||
|
|
||||||
// Check if AMM already exists ----------------------------------------------
|
// Check if AMM already exists ----------------------------------------------
|
||||||
const amm_info_request = {
|
const amm_info_request = {
|
||||||
"command": "amm_info",
|
"command": "amm_info",
|
||||||
"asset": {
|
"asset": {
|
||||||
"currency": "TST",
|
"currency": "TST",
|
||||||
"issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
|
"issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
|
||||||
@@ -81,8 +81,8 @@ async function main() {
|
|||||||
console.log(amm_info_result)
|
console.log(amm_info_result)
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
if (err.data.error === 'actNotFound') {
|
if (err.data.error === 'actNotFound') {
|
||||||
console.log(`No AMM exists yet for the pair
|
console.log(`No AMM exists yet for the pair
|
||||||
${foo_amount.currency}.${foo_amount.issuer} /
|
${foo_amount.currency}.${foo_amount.issuer} /
|
||||||
TST.rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd.
|
TST.rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd.
|
||||||
(This is probably as expected.)`)
|
(This is probably as expected.)`)
|
||||||
} else {
|
} else {
|
||||||
@@ -153,9 +153,9 @@ main()
|
|||||||
|
|
||||||
|
|
||||||
/* Issue tokens ---------------------------------------------------------------
|
/* Issue tokens ---------------------------------------------------------------
|
||||||
* Fund a new issuer using the faucet, and issue some fungible tokens
|
* Fund a new issuer using the faucet, and issue some fungible tokens
|
||||||
* to the specified address. In production, you would not do this; instead,
|
* to the specified address. In production, you would not do this; instead,
|
||||||
* you would acquire tokens from an existing issuer (for example, you might
|
* you would acquire tokens from an existing issuer (for example, you might
|
||||||
* buy them in the DEX, or make an off-ledger deposit at a stablecoin issuer).
|
* buy them in the DEX, or make an off-ledger deposit at a stablecoin issuer).
|
||||||
* For a more thorough explanation of this process, see
|
* For a more thorough explanation of this process, see
|
||||||
* "Issue a Fungible Token": https://xrpl.org/issue-a-fungible-token.html
|
* "Issue a Fungible Token": https://xrpl.org/issue-a-fungible-token.html
|
||||||
@@ -163,7 +163,7 @@ main()
|
|||||||
* client: an xrpl.Client instance that is already connected to the network
|
* client: an xrpl.Client instance that is already connected to the network
|
||||||
* wallet: an xrpl.Wallet instance that should hold the new tokens
|
* wallet: an xrpl.Wallet instance that should hold the new tokens
|
||||||
* currency_code: string currency code (3-char ISO-like or hex code)
|
* currency_code: string currency code (3-char ISO-like or hex code)
|
||||||
* issue_quantity: string number of tokens to issue. Arbitrarily capped
|
* issue_quantity: string number of tokens to issue. Arbitrarily capped
|
||||||
* at "10000000000"
|
* at "10000000000"
|
||||||
* Resolves to: an "Amount"-type JSON object, such as:
|
* Resolves to: an "Amount"-type JSON object, such as:
|
||||||
* {
|
* {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Complete sample code for all of the steps of these tutorials is available under
|
|||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
{% set n = cycler(* range(1,99)) %}
|
{% set n = cycler(* range(1,99)) %}
|
||||||
{% set use_network = "AMM-Devnet" %}
|
{% set use_network = "Devnet" %}
|
||||||
|
|
||||||
### {{n.next()}}. Connect to the network
|
### {{n.next()}}. Connect to the network
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ If the AMM does already exist, you should double-check that you specified the ri
|
|||||||
|
|
||||||
Creating an AMM has a special [transaction cost][] to prevent spam: since it creates objects in the ledger that no one owns, you must burn at least one [owner reserve increment](reserves.html) of XRP to send the AMMCreate transaction. The exact value can change due to [fee voting](https://xrpl.org/fee-voting.html), so you should look up the current incremental reserve value using the [server_state method][].
|
Creating an AMM has a special [transaction cost][] to prevent spam: since it creates objects in the ledger that no one owns, you must burn at least one [owner reserve increment](reserves.html) of XRP to send the AMMCreate transaction. The exact value can change due to [fee voting](https://xrpl.org/fee-voting.html), so you should look up the current incremental reserve value using the [server_state method][].
|
||||||
|
|
||||||
It is also a good practice to display this value and give a human operator a chance to stop before you send the transaction. Burning an owner reserve is typically a much higher cost than sending a normal transaction, so you don't want it to be a surprise. (Currently, on both Mainnet and AMM-Devnet, the cost of sending a typical transaction is 0.000010 XRP but the cost of AMMCreate is 2 XRP.)
|
It is also a good practice to display this value and give a human operator a chance to stop before you send the transaction. Burning an owner reserve is typically a much higher cost than sending a normal transaction, so you don't want it to be a surprise. (Currently, on both Mainnet and Devnet, the cost of sending a typical transaction is 0.000010 XRP but the cost of AMMCreate is 2 XRP.)
|
||||||
|
|
||||||
<!-- MULTICODE_BLOCK_START -->
|
<!-- MULTICODE_BLOCK_START -->
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user