// 1. Generate // 2. Connect // The code for these steps is handled by interactive-tutorial.js onCurrentRouteLoaded(() => { 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, '
Funding an issuer address with the faucet...
') const issuer = (await api.fundWallet()).wallet show_log(block, `Got issuer ${issuer.address}.
`) $('.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, `✅ Issuer DefaultRipple enabled
`) } else { show_error(block, `Error sending transaction:${pretty_print(issuer_setup_result)}`)
}
// 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, ``)
} else {
show_error(block, `Error sending transaction: ${pretty_print(trust_result)}`)
}
// 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, ``)
$('#get-foo').data('foo-acquired', true).prop('disabled', true).addClass('disabled').addClass('done')
} else {
show_error(block, `Error sending transaction: ${pretty_print(issue_result)}`)
}
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, ``)
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, `Got ${bal.value} ${bal.currency}.${bal.issuer}.
`) break } } break } $('#buy-tst').data('tst-acquired', true).prop('disabled', true).addClass('disabled').addClass('done') } else { show_error(block, `Transaction failed:
${pretty_print(offer_result)}`)
}
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, `${pretty_print}amm_info`)
} catch (err) {
if (err.data.error === 'actNotFound') {
show_log(
block,
`✅ 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, `
Current AMMCreate transaction cost: ${xrpl.dropsToXrp(amm_fee_drops)} XRP (${amm_fee_drops} drops)
`, ) 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 } block.find('.output-area').html('') block.find('.loader').show() 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, `${pretty_print(ammcreate_result)}`,
)
complete_step('Create AMM')
} else {
console.error(ammcreate_result)
show_error(block, `Error sending transaction: ${ammcreate_result.result.meta.TransactionResult}`)
}
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, `AMM Info:
${pretty_print(amm_info)}`)
const lp_token = amm_info.result.amm.lp_token
show_log(
block,
`The AMM account ${lp_token.issuer} has ${lp_token.value} total
LP tokens outstanding, and uses the currency code ${lp_token.currency}.
In its pool, the AMM holds ${amount.value} ${amount.currency}.${amount.issuer} and ${amount2.value} ${amount2.currency}.${amount2.issuer}
`, ) 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, `Trust lines:
${pretty_print(account_lines)}`)
complete_step('Check trust lines')
} catch (err) {
show_error(block, err)
}
block.find('.loader').hide()
})
})