diff --git a/assets/js/interactive-tutorial.js b/assets/js/interactive-tutorial.js
index b3e676b677..f280101c95 100644
--- a/assets/js/interactive-tutorial.js
+++ b/assets/js/interactive-tutorial.js
@@ -114,6 +114,7 @@ function complete_step_by_id(step_id) {
".interactive-block").eq(0).find(".previous-steps-required")
next_ui.prop("title", "")
next_ui.prop("disabled", false)
+ next_ui.removeClass("disabled")
}
/**
@@ -360,7 +361,6 @@ function setup_wait_steps() {
min_ledger,
max_ledger
})
- console.log(tx_result)
if (tx_result.validated) {
status_box.html(
diff --git a/assets/js/tutorials/issue-a-token.js b/assets/js/tutorials/issue-a-token.js
index 1b1914d3ee..8729572913 100644
--- a/assets/js/tutorials/issue-a-token.js
+++ b/assets/js/tutorials/issue-a-token.js
@@ -174,7 +174,7 @@ $(document).ready(() => {
"Flags": flags
}
- generic_full_send(event, cold_settings_tx, cold_secret)
+ await generic_full_send(event, cold_settings_tx, cold_secret)
complete_step("Configure Issuer")
} catch(err) {
@@ -212,7 +212,7 @@ $(document).ready(() => {
"Flags": flags
}
- generic_full_send(event, hot_settings_tx, hot_secret)
+ await generic_full_send(event, hot_settings_tx, hot_secret)
complete_step("Configure Hot Address")
} catch(err) {
@@ -256,7 +256,7 @@ $(document).ready(() => {
"value": limit
}
}
- generic_full_send(event, trust_set_tx, hot_secret)
+ await generic_full_send(event, trust_set_tx, hot_secret)
complete_step("Make Trust Line")
} catch(err) {
@@ -301,7 +301,7 @@ $(document).ready(() => {
if (use_dest_tag) {
send_token_tx["DestinationTag"] = dest_tag
}
- generic_full_send(event, send_token_tx, cold_secret)
+ await generic_full_send(event, send_token_tx, cold_secret)
complete_step("Send Token")
} catch(err) {
diff --git a/assets/js/tutorials/require-destination-tags.js b/assets/js/tutorials/require-destination-tags.js
index 15199b8ba1..40ac243793 100644
--- a/assets/js/tutorials/require-destination-tags.js
+++ b/assets/js/tutorials/require-destination-tags.js
@@ -4,16 +4,21 @@
$(document).ready(() => {
// 3. Send AccountSet --------------------------------------------------------
- $("#send-accountset").click( (event) => {
+ $("#send-accountset").click( async (event) => {
const address = get_address(event)
if (!address) {return}
- generic_full_send(event, {
- "TransactionType": "AccountSet",
- "Account": address,
- "SetFlag": 1 // RequireDest
- })
- complete_step("Send AccountSet")
+ try {
+ await generic_full_send(event, {
+ "TransactionType": "AccountSet",
+ "Account": address,
+ "SetFlag": 1 // RequireDest
+ })
+ complete_step("Send AccountSet")
+ } catch(err) {
+ block.find(".loader").hide()
+ show_error(block, err)
+ }
})
// 4. Wait for Validation: handled by interactive-tutorial.js and by the
diff --git a/content/_code-samples/issue-a-token/demo.html b/content/_code-samples/issue-a-token/js/demo.html
similarity index 100%
rename from content/_code-samples/issue-a-token/demo.html
rename to content/_code-samples/issue-a-token/js/demo.html
diff --git a/content/_code-samples/issue-a-token/issue-a-token.js b/content/_code-samples/issue-a-token/js/issue-a-token.js
similarity index 100%
rename from content/_code-samples/issue-a-token/issue-a-token.js
rename to content/_code-samples/issue-a-token/js/issue-a-token.js
diff --git a/content/_code-samples/issue-a-token/package.json b/content/_code-samples/issue-a-token/js/package.json
similarity index 100%
rename from content/_code-samples/issue-a-token/package.json
rename to content/_code-samples/issue-a-token/js/package.json
diff --git a/content/_code-samples/issue-a-token/yarn.lock b/content/_code-samples/issue-a-token/js/yarn.lock
similarity index 100%
rename from content/_code-samples/issue-a-token/yarn.lock
rename to content/_code-samples/issue-a-token/js/yarn.lock
diff --git a/content/_code-samples/issue-a-token/py/issue-a-token.py b/content/_code-samples/issue-a-token/py/issue-a-token.py
new file mode 100644
index 0000000000..2bfe9767ba
--- /dev/null
+++ b/content/_code-samples/issue-a-token/py/issue-a-token.py
@@ -0,0 +1,108 @@
+# Stand-alone code sample for the "issue a token" tutorial:
+# https://xrpl.org/issue-a-fungible-token.html
+# License: https://github.com/XRPLF/xrpl-dev-portal/blob/master/LICENSE
+
+# Connect ----------------------------------------------------------------------
+import xrpl
+testnet_url = "https://s.altnet.rippletest.net:51234"
+client = xrpl.clients.JsonRpcClient(testnet_url)
+
+
+# Get credentials from the Testnet Faucet --------------------------------------
+# For production, instead create a Wallet instance
+faucet_url = "https://faucet.altnet.rippletest.net/accounts"
+print("Getting 2 new accounts from the Testnet faucet...")
+from xrpl.wallet import generate_faucet_wallet
+cold_wallet = generate_faucet_wallet(client, debug=True)
+hot_wallet = generate_faucet_wallet(client, debug=True)
+
+
+# Configure issuer (cold address) settings -------------------------------------
+cold_settings_tx = xrpl.models.transactions.AccountSet(
+ account=cold_wallet.classic_address,
+ transfer_rate=0,
+ tick_size=5,
+ domain=bytes.hex("example.com".encode("ASCII")),
+ set_flag=xrpl.models.transactions.AccountSetFlag.ASF_DEFAULT_RIPPLE,
+)
+cst_prepared = xrpl.transaction.safe_sign_and_autofill_transaction(
+ transaction=cold_settings_tx,
+ wallet=cold_wallet,
+ client=client,
+)
+print("Sending cold address AccountSet transaction...")
+response = xrpl.transaction.send_reliable_submission(cst_prepared, client)
+print(response)
+
+
+# Configure hot address settings -----------------------------------------------
+hot_settings_tx = xrpl.models.transactions.AccountSet(
+ account=hot_wallet.classic_address,
+ set_flag=xrpl.models.transactions.AccountSetFlag.ASF_REQUIRE_AUTH,
+)
+hst_prepared = xrpl.transaction.safe_sign_and_autofill_transaction(
+ transaction=hot_settings_tx,
+ wallet=hot_wallet,
+ client=client,
+)
+print("Sending hot address AccountSet transaction...")
+response = xrpl.transaction.send_reliable_submission(hst_prepared, client)
+print(response)
+
+
+# Create trust line from hot to cold address -----------------------------------
+currency_code = "FOO"
+trust_set_tx = xrpl.models.transactions.TrustSet(
+ account=hot_wallet.classic_address,
+ limit_amount=xrpl.models.amounts.issued_currency_amount.IssuedCurrencyAmount(
+ currency=currency_code,
+ issuer=cold_wallet.classic_address,
+ value="10000000000", # Large limit, arbitrarily chosen
+ )
+)
+ts_prepared = xrpl.transaction.safe_sign_and_autofill_transaction(
+ transaction=trust_set_tx,
+ wallet=hot_wallet,
+ client=client,
+)
+print("Creating trust line from hot address to issuer...")
+response = xrpl.transaction.send_reliable_submission(ts_prepared, client)
+print(response)
+
+
+# Send token -------------------------------------------------------------------
+issue_quantity = "3840"
+send_token_tx = xrpl.models.transactions.Payment(
+ account=cold_wallet.classic_address,
+ destination=hot_wallet.classic_address,
+ amount=xrpl.models.amounts.issued_currency_amount.IssuedCurrencyAmount(
+ currency=currency_code,
+ issuer=cold_wallet.classic_address,
+ value=issue_quantity
+ )
+)
+pay_prepared = xrpl.transaction.safe_sign_and_autofill_transaction(
+ transaction=send_token_tx,
+ wallet=cold_wallet,
+ client=client,
+)
+print(f"Sending {issue_quantity} {currency_code} to {hot_wallet.classic_address}...")
+response = xrpl.transaction.send_reliable_submission(pay_prepared, client)
+print(response)
+
+
+# Check balances ---------------------------------------------------------------
+print("Getting hot address balances...")
+response = client.request(xrpl.models.requests.AccountLines(
+ account=hot_wallet.classic_address,
+ ledger_index="validated",
+))
+print(response)
+
+print("Getting cold address balances...")
+response = client.request(xrpl.models.requests.GatewayBalances(
+ account=cold_wallet.classic_address,
+ ledger_index="validated",
+ hotwallet=[hot_wallet.classic_address]
+))
+print(response)
diff --git a/content/tutorials/use-tokens/issue-a-fungible-token.md b/content/tutorials/use-tokens/issue-a-fungible-token.md
index 1dc3cbe52f..a96656e034 100644
--- a/content/tutorials/use-tokens/issue-a-fungible-token.md
+++ b/content/tutorials/use-tokens/issue-a-fungible-token.md
@@ -17,9 +17,9 @@ Anyone can issue various types of tokens in the XRP Ledger, ranging from informa
- You need two funded XRP Ledger accounts, each with an address, secret key, and some XRP. For this tutorial, you can generate new test credentials as needed.
- Each address needs enough XRP to satisfy the [reserve requirement](reserves.html) including the additional reserve for a trust line.
-- You need a connection to the XRP Ledger network.
+- You need a connection to the XRP Ledger network. As shown in this tutorial, you can use public servers for testing.
-This page provides examples that use [ripple-lib for JavaScript](get-started-with-rippleapi-for-javascript.html). Since JavaScript works in the web browser, you can read along and use the interactive steps without any setup.
+This page provides examples that use [ripple-lib for JavaScript](get-started-with-rippleapi-for-javascript.html) or [xrpl-py for Python](get-started-using-python.html). You can also read along and use the interactive steps in your browser without any setup.
@@ -59,7 +59,11 @@ When you're [building actual production-ready software](production-readiness.htm
You must be connected to the network to submit transactions to it.
-The following code uses a [ripple-lib for JavaScript](rippleapi-reference.html) instance to connect to a public XRP Ledger Testnet server:
+The following code shows how to connect to a public XRP Ledger Testnet server a supported [client library](client-libraries.html):
+
+
+
+_JavaScript_
```js
ripple = require('ripple-lib') // Node.js only. Use a