update screenshots and sample code
139
_code-samples/mpt-generator/mpt-generator.css
Normal file
@@ -0,0 +1,139 @@
|
||||
body {
|
||||
font-family: "Inter", sans-serif;
|
||||
padding: 20px;
|
||||
background: #abe2ff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td {
|
||||
padding-left: 25px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
padding: 6px;
|
||||
margin-bottom: 8px;
|
||||
border: none
|
||||
}
|
||||
|
||||
button {
|
||||
font-weight: bold;
|
||||
font-family: "Work Sans", sans-serif;
|
||||
background-color: #006aff;
|
||||
-webkit-text-fill-color: white;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked+.slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus+.slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked+.slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.tooltip {
|
||||
position: relative;
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
|
||||
.tooltip:before {
|
||||
content: attr(tooltip-data);
|
||||
position: absolute;
|
||||
width: 250px;
|
||||
background-color: #006aff;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
line-height: 1.1;
|
||||
border-radius: 5px;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
transition: opacity .5s;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -60px;
|
||||
font-size: 0.70em;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tooltip:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 75%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
opacity: 0;
|
||||
transition: opacity .5s;
|
||||
border-color: #000 transparent transparent transparent;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tooltip:hover:before,
|
||||
.tooltip:hover:after {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
219
_code-samples/mpt-generator/mpt-generator.htm
Normal file
@@ -0,0 +1,219 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>MPT Generator</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="mpt-generator.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
|
||||
<script src='mpt-generator.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require("xrpl")
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>MPT Generator</h1>
|
||||
<form>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td colspan="3">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="tn" name="server"
|
||||
value="wss://s.altnet.rippletest.net:51233" >
|
||||
<label for="testnet">Testnet</label>
|
||||
|
||||
<input type="radio" id="dn" name="server"
|
||||
value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="devnet">Devnet</label><br />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<div class="container">
|
||||
<span class="tooltip" tooltip-data="The issuing account address.">Account
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<input type="text" id="accountField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccount()">Get New
|
||||
Account</button>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="The issuing account seed.">Seed
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<input type="text" id="seedField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed()">Get Account
|
||||
From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="An asset scale is the difference, in orders of magnitude, between a standard unit and a corresponding fractional unit.">
|
||||
Asset Scale
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" size="10" id="assetScaleField" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="The maximum number of tokens to be issued.">
|
||||
Maximum Tokens
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" size="10" id="maximumAmountField" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Fee collected when MPT is transferred.">
|
||||
Transfer Fee
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" size="5" id="transferFeeField" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Issuer can claw back value from holders.">
|
||||
Clawback
|
||||
</span>
|
||||
</td>
|
||||
<td align="middle">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="clawbackSlider">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="MPT can be locked individually and globally.">
|
||||
Lock
|
||||
</span>
|
||||
</td>
|
||||
<td align="middle">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="lockSlider" name="lockSlider">
|
||||
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Individual holders must be authorized.">
|
||||
Require Authorization
|
||||
</span>
|
||||
</td>
|
||||
<td align="middle">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="authTokensSlider">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="MPTs can be transferred to other accounts.">
|
||||
Can Transfer
|
||||
</span>
|
||||
</td>
|
||||
<td align="middle">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="txrSlider">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="MPT can be traded.">
|
||||
Can Trade
|
||||
</span>
|
||||
</td>
|
||||
<td align="middle">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="tradeSlider">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="MPT can be used in an escrow.">
|
||||
Can Escrow
|
||||
</span>
|
||||
</td>
|
||||
<td align="middle">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="escrowSlider">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Token Metadata</b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<textarea id="metadataTextArea" rows="25" cols="75"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<h2>MPToken Create Transaction</h2>
|
||||
<p><button type="button" onclick="generateCode()">Generate Transaction</button>
|
||||
<button type = "button" onclick="sendTransaction()">Send Transaction</button></p>
|
||||
<span class="tooltip" tooltip-data="Follow this link to see the MPT Issuance entry on the Explorer.">
|
||||
Link to Explorer entry for MPT Issuance.
|
||||
</span>
|
||||
<p><input type="text" id="urlField" size="50"></p>
|
||||
<textarea id="codeTextArea" rows="25" cols="75"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
112
_code-samples/mpt-generator/mpt-generator.js
Normal file
@@ -0,0 +1,112 @@
|
||||
function generateCode() {
|
||||
let v_flags = 0
|
||||
if (clawbackSlider.checked) {v_flags+=64}
|
||||
if (lockSlider.checked) {v_flags+=2}
|
||||
if (authTokensSlider.checked) {v_flags +=4}
|
||||
if (txrSlider.checked) {v_flags += 32}
|
||||
if (tradeSlider.checked) {v_flags += 16}
|
||||
if (escrowSlider.checked) {v_flags+=8}
|
||||
const mptHexString = xrpl.convertStringToHex(metadataTextArea.value)
|
||||
let v_codeBlock = "{\n \"TransactionType\": \"MPTokenIssuanceCreate\",\n \"Account\": \"" + accountField.value +
|
||||
"\",\n \"AssetScale\": 2, \n \"MaximumAmount\": \"" + maximumAmountField.value +
|
||||
"\",\n \"TransferFee\": " + transferFeeField.value +
|
||||
",\n \"Flags\": " + v_flags + ",\n \"MPTokenMetadata\": \"" + mptHexString + "\"\n}"
|
||||
|
||||
codeTextArea.value = v_codeBlock
|
||||
}
|
||||
// ******************************************************
|
||||
// ************* 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() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + net + '....'
|
||||
|
||||
//-------------------------------This uses the default faucet for Testnet/Devnet.
|
||||
let faucetHost = null
|
||||
codeTextArea.value = results
|
||||
await client.connect()
|
||||
results += '\nConnected, funding wallet.'
|
||||
// ----------------------------------------Create and fund a test account wallet.
|
||||
const my_wallet = (await client.fundWallet(null, { faucetHost })).wallet
|
||||
results += '\nGot a wallet.'
|
||||
|
||||
// ------------------------------------------------------Get the current balance.
|
||||
const my_balance = (await client.getXrpBalance(my_wallet.address))
|
||||
accountField.value = my_wallet.address
|
||||
seedField.value = my_wallet.seed
|
||||
results += '\nAccount created.'
|
||||
codeTextArea.value = results
|
||||
client.disconnect()
|
||||
} // End of getAccount()
|
||||
|
||||
// *******************************************************
|
||||
// ************ Get Account from Seed ********************
|
||||
// *******************************************************
|
||||
|
||||
async function getAccountFromSeed() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
await client.connect()
|
||||
results += '\nConnected, finding wallets.\n'
|
||||
codeTextArea.value = results
|
||||
// --------------------------------------------------Find the test account wallet.
|
||||
const my_wallet = xrpl.Wallet.fromSeed(seedField.value)
|
||||
|
||||
// -------------------------------------------------------Get the current balance.
|
||||
accountField.value = my_wallet.address
|
||||
seedField.value = my_wallet.seed
|
||||
client.disconnect()
|
||||
} // End of getAccountFromSeed()
|
||||
|
||||
// *******************************************************
|
||||
// *************** Send Transaction **********************
|
||||
// *******************************************************
|
||||
|
||||
async function sendTransaction() {
|
||||
let v_flags = 0
|
||||
if (clawbackSlider.checked) {v_flags+=64}
|
||||
if (lockSlider.checked) {v_flags+=2}
|
||||
if (authTokensSlider.checked) {v_flags +=4}
|
||||
if (txrSlider.checked) {v_flags += 32}
|
||||
if (tradeSlider.checked) {v_flags += 16}
|
||||
if (escrowSlider.checked) {v_flags+=8}
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
console.log(results)
|
||||
let net = getNet()
|
||||
const my_wallet = xrpl.Wallet.fromSeed(seedField.value)
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
|
||||
const metadataHexString = xrpl.convertStringToHex(metadataTextArea.value)
|
||||
|
||||
const transactionJson = {
|
||||
"TransactionType": "MPTokenIssuanceCreate",
|
||||
"Account": accountField.value,
|
||||
"AssetScale": parseInt(assetScaleField.value),
|
||||
"MaximumAmount": maximumAmountField.value,
|
||||
"TransferFee": parseInt(transferFeeField.value),
|
||||
"Flags": v_flags,
|
||||
"MPTokenMetadata": metadataHexString
|
||||
}
|
||||
const tx = await client.submitAndWait(transactionJson, { wallet: my_wallet} )
|
||||
if (document.getElementById("tn").checked) {
|
||||
codeTextArea.value += "\n Success! Ledger Index: " + tx.result.ledger_index + "\nSee https://testnet.xrpl.org/ledgers/" + tx.result.ledger_index
|
||||
} else {
|
||||
codeTextArea.value += "\n Success! Ledger Index: " + tx.result.ledger_index + "\nSee https://devnet.xrpl.org/ledgers/" + tx.result.ledger_index
|
||||
}
|
||||
urlField.value = "https://devnet.xrpl.org/ledgers/" + tx.result.ledger_index
|
||||
}
|
||||
BIN
_code-samples/mpt-generator/mpt-generator.zip
Normal file
BIN
docs/img/uc-mpt1-mpt-generator-empty-form.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 451 KiB After Width: | Height: | Size: 528 KiB |
|
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 435 KiB After Width: | Height: | Size: 523 KiB |
|
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 324 KiB |
@@ -23,6 +23,10 @@ To learn more, see [Multi-purpose Tokens](../../concepts/tokens/fungible-tokens/
|
||||
|
||||
The MPT Generator utility embedded on the page below lets you experiment with an MPT configuration in a sandbox environment. When you are satisfied with the settings, you can generate the transaction code required to create your MPT on Mainnet.
|
||||
|
||||

|
||||
|
||||
You can download a [standalone version of the MPT Generator](../../../_code-samples/mpt-generator/mpt-generator.zip) as sample code, or use the embedded form that follows.
|
||||
|
||||
In practice, you want to use an Issuer account configuration to issue an MPT, but you can try the form below with a new account and the transaction works fine. See [Creating a US Treasury Bill](#creating-a-us-treasury-bill) for a full description of the issuance process. The form is populated with sample values, but you can change the parameters for your own experiments. A T-bill is just one example of the many types of asset you can create and trade on the XRP Ledger.
|
||||
|
||||
<hr/>
|
||||
|
||||