mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-21 12:15:50 +00:00
Compare commits
1 Commits
master
...
issue-mpto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84e08700b7 |
@@ -9,8 +9,135 @@ npm i
|
|||||||
node issue-mpt-with-metadata.js
|
node issue-mpt-with-metadata.js
|
||||||
```
|
```
|
||||||
|
|
||||||
The script should output a validated transaction and end with a line such as the following:
|
The script should output a validated transaction and decoded metadata, similar to the following:
|
||||||
|
|
||||||
```text
|
```sh
|
||||||
MPToken created successfully with issuance ID 005073C721E14A7613BAAF5E0B1A253459832FF8D0D81278.
|
=== Funding new wallet from faucet...===
|
||||||
|
Issuer address: r9fhoyac7uUM9XZFDJV9wXQ4pcJb6UDpJM
|
||||||
|
|
||||||
|
=== Encoding metadata...===
|
||||||
|
Encoded mpt_metadata_hex: 7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D
|
||||||
|
|
||||||
|
=== Sending MPTokenIssuanceCreate transaction...===
|
||||||
|
{
|
||||||
|
"TransactionType": "MPTokenIssuanceCreate",
|
||||||
|
"Account": "r9fhoyac7uUM9XZFDJV9wXQ4pcJb6UDpJM",
|
||||||
|
"AssetScale": 4,
|
||||||
|
"MaximumAmount": "50000000",
|
||||||
|
"TransferFee": 0,
|
||||||
|
"Flags": 48,
|
||||||
|
"MPTokenMetadata": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D"
|
||||||
|
}
|
||||||
|
|
||||||
|
=== Checking MPTokenIssuanceCreate results... ===
|
||||||
|
{
|
||||||
|
"close_time_iso": "2025-11-20T18:13:30Z",
|
||||||
|
"ctid": "C0148E8700000002",
|
||||||
|
"hash": "555FAFDB99B239567FDF30DDF22BA3B30F8E70D8D06833B1270AC600E1575948",
|
||||||
|
"ledger_hash": "A7010A2025989778420280F7F96B10F5D3C879E049BE5DA12500FFBB90D162C5",
|
||||||
|
"ledger_index": 1347207,
|
||||||
|
"meta": {
|
||||||
|
"AffectedNodes": [
|
||||||
|
{
|
||||||
|
"CreatedNode": {
|
||||||
|
"LedgerEntryType": "DirectoryNode",
|
||||||
|
"LedgerIndex": "33468621DEF32177E84C1EBC2C457C908567E245622CBDE03185C4ABC83B7F9D",
|
||||||
|
"NewFields": {
|
||||||
|
"Owner": "r9fhoyac7uUM9XZFDJV9wXQ4pcJb6UDpJM",
|
||||||
|
"RootIndex": "33468621DEF32177E84C1EBC2C457C908567E245622CBDE03185C4ABC83B7F9D"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"CreatedNode": {
|
||||||
|
"LedgerEntryType": "MPTokenIssuance",
|
||||||
|
"LedgerIndex": "6567EE49937AADAB4FC4D5DDBD6A4A6E179E0E5A9DF2FC7ED8B41B807F0DDBF2",
|
||||||
|
"NewFields": {
|
||||||
|
"AssetScale": 4,
|
||||||
|
"Flags": 48,
|
||||||
|
"Issuer": "r9fhoyac7uUM9XZFDJV9wXQ4pcJb6UDpJM",
|
||||||
|
"MPTokenMetadata": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D",
|
||||||
|
"MaximumAmount": "50000000",
|
||||||
|
"Sequence": 1347205
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ModifiedNode": {
|
||||||
|
"FinalFields": {
|
||||||
|
"Account": "r9fhoyac7uUM9XZFDJV9wXQ4pcJb6UDpJM",
|
||||||
|
"Balance": "99999999",
|
||||||
|
"Flags": 0,
|
||||||
|
"OwnerCount": 1,
|
||||||
|
"Sequence": 1347206
|
||||||
|
},
|
||||||
|
"LedgerEntryType": "AccountRoot",
|
||||||
|
"LedgerIndex": "AB5FC35110CED5BFD2CEA3E37B41E43CC4BBAF89AE66BA85942E04CBC38550FB",
|
||||||
|
"PreviousFields": {
|
||||||
|
"Balance": "100000000",
|
||||||
|
"OwnerCount": 0,
|
||||||
|
"Sequence": 1347205
|
||||||
|
},
|
||||||
|
"PreviousTxnID": "1CDF420134492607EC54838F91FA06A655E07DD296ED69CC7172C1AC356BF22B",
|
||||||
|
"PreviousTxnLgrSeq": 1347205
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"TransactionIndex": 0,
|
||||||
|
"TransactionResult": "tesSUCCESS",
|
||||||
|
"mpt_issuance_id": "00148E8558E6AEAA301085FBFD01D615F059A7CCE6E38296"
|
||||||
|
},
|
||||||
|
"tx_json": {
|
||||||
|
"Account": "r9fhoyac7uUM9XZFDJV9wXQ4pcJb6UDpJM",
|
||||||
|
"AssetScale": 4,
|
||||||
|
"Fee": "1",
|
||||||
|
"Flags": 48,
|
||||||
|
"LastLedgerSequence": 1347225,
|
||||||
|
"MPTokenMetadata": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D",
|
||||||
|
"MaximumAmount": "50000000",
|
||||||
|
"Sequence": 1347205,
|
||||||
|
"SigningPubKey": "ED1EC65DB85E686A55F8FD9BC6E405E8F2F8EA5E1712AED64E28C97350EB4EF6E7",
|
||||||
|
"TransactionType": "MPTokenIssuanceCreate",
|
||||||
|
"TransferFee": 0,
|
||||||
|
"TxnSignature": "3A671905D57342F051E3BF057CCF65B0D94114C04D255D4AE3CEE01C2D0B368118E94011CEB27EC9BB447D3498B24B750F2691B4D7AB71F82626BC6F49465806",
|
||||||
|
"ctid": "C0148E8700000002",
|
||||||
|
"date": 816977610,
|
||||||
|
"ledger_index": 1347207
|
||||||
|
},
|
||||||
|
"validated": true
|
||||||
|
}
|
||||||
|
|
||||||
|
- MPToken created successfully with issuance ID: 00148E8558E6AEAA301085FBFD01D615F059A7CCE6E38296
|
||||||
|
- Explorer URL: https://devnet.xrpl.org/mpt/00148E8558E6AEAA301085FBFD01D615F059A7CCE6E38296
|
||||||
|
|
||||||
|
=== Confirming MPT Issuance metadata in the validated ledger... ===
|
||||||
|
Decoded MPT metadata:
|
||||||
|
{
|
||||||
|
asset_class: 'rwa',
|
||||||
|
additional_info: {
|
||||||
|
cusip: '912796RX0',
|
||||||
|
interest_rate: '5.00%',
|
||||||
|
interest_type: 'variable',
|
||||||
|
maturity_date: '2045-06-30',
|
||||||
|
yield_source: 'U.S. Treasury Bills'
|
||||||
|
},
|
||||||
|
asset_subclass: 'treasury',
|
||||||
|
desc: 'A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.',
|
||||||
|
icon: 'https://example.org/tbill-icon.png',
|
||||||
|
issuer_name: 'Example Yield Co.',
|
||||||
|
name: 'T-Bill Yield Token',
|
||||||
|
ticker: 'TBILL',
|
||||||
|
uris: [
|
||||||
|
{
|
||||||
|
category: 'website',
|
||||||
|
title: 'Product Page',
|
||||||
|
uri: 'https://exampleyield.co/tbill'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'docs',
|
||||||
|
title: 'Yield Token Docs',
|
||||||
|
uri: 'https://exampleyield.co/docs'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,85 +1,108 @@
|
|||||||
import { stringToHex, hexToString } from '@xrplf/isomorphic/dist/utils/index.js'
|
import {
|
||||||
import { MPTokenIssuanceCreateFlags, Client } from 'xrpl'
|
MPTokenIssuanceCreateFlags,
|
||||||
|
Client,
|
||||||
|
encodeMPTokenMetadata,
|
||||||
|
decodeMPTokenMetadata,
|
||||||
|
} from "xrpl";
|
||||||
|
|
||||||
// Connect to network and get a wallet
|
// Connect to network and get a wallet
|
||||||
const client = new Client('wss://s.devnet.rippletest.net:51233')
|
const client = new Client("wss://s.devnet.rippletest.net:51233");
|
||||||
await client.connect()
|
await client.connect();
|
||||||
|
|
||||||
console.log('Funding new wallet from faucet...')
|
console.log("=== Funding new wallet from faucet...===");
|
||||||
const { wallet } = await client.fundWallet()
|
const { wallet: issuer } = await client.fundWallet();
|
||||||
|
console.log(`Issuer address: ${issuer.address}`);
|
||||||
|
|
||||||
// Define metadata as JSON
|
// Define metadata as JSON
|
||||||
const mpt_metadata = {
|
const mpt_metadata = {
|
||||||
t: 'TBILL',
|
ticker: "TBILL",
|
||||||
n: 'T-Bill Yield Token',
|
name: "T-Bill Yield Token",
|
||||||
d: 'A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.',
|
desc: "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
|
||||||
i: 'https://example.org/tbill-icon.png',
|
icon: "https://example.org/tbill-icon.png",
|
||||||
ac: 'rwa',
|
asset_class: "rwa",
|
||||||
as: 'treasury',
|
asset_subclass: "treasury",
|
||||||
in: 'Example Yield Co.',
|
issuer_name: "Example Yield Co.",
|
||||||
us: [
|
uris: [
|
||||||
{
|
{
|
||||||
u: 'https://exampleyield.co/tbill',
|
uri: "https://exampleyield.co/tbill",
|
||||||
c: 'website',
|
category: "website",
|
||||||
t: 'Product Page'
|
title: "Product Page",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
u: 'https://exampleyield.co/docs',
|
uri: "https://exampleyield.co/docs",
|
||||||
c: 'docs',
|
category: "docs",
|
||||||
t: 'Yield Token Docs'
|
title: "Yield Token Docs",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
ai: {
|
additional_info: {
|
||||||
interest_rate: '5.00%',
|
interest_rate: "5.00%",
|
||||||
interest_type: 'variable',
|
interest_type: "variable",
|
||||||
yield_source: 'U.S. Treasury Bills',
|
yield_source: "U.S. Treasury Bills",
|
||||||
maturity_date: '2045-06-30',
|
maturity_date: "2045-06-30",
|
||||||
cusip: '912796RX0'
|
cusip: "912796RX0",
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// Convert JSON to a string (without excess whitespace), then string to hex
|
// Encode the metadata.
|
||||||
const mpt_metadata_hex = stringToHex(JSON.stringify(mpt_metadata))
|
// The encodeMPTokenMetadata function converts the JSON metadata object into
|
||||||
|
// a compact, hex-encoded string, following the XLS-89 standard.
|
||||||
|
// https://xls.xrpl.org/xls/XLS-0089-multi-purpose-token-metadata-schema.html
|
||||||
|
console.log("\n=== Encoding metadata...===");
|
||||||
|
const mpt_metadata_hex = encodeMPTokenMetadata(mpt_metadata);
|
||||||
|
console.log("Encoded mpt_metadata_hex: ", mpt_metadata_hex);
|
||||||
|
|
||||||
// Define the transaction, including other MPT parameters
|
// Define the transaction, including other MPT parameters
|
||||||
const mpt_issuance_create = {
|
const mpt_issuance_create = {
|
||||||
TransactionType: 'MPTokenIssuanceCreate',
|
TransactionType: "MPTokenIssuanceCreate",
|
||||||
Account: wallet.address,
|
Account: issuer.address,
|
||||||
AssetScale: 4,
|
AssetScale: 4,
|
||||||
MaximumAmount: '50000000',
|
MaximumAmount: "50000000",
|
||||||
TransferFee: 0,
|
TransferFee: 0,
|
||||||
Flags: MPTokenIssuanceCreateFlags.tfMPTCanTransfer |
|
Flags:
|
||||||
|
MPTokenIssuanceCreateFlags.tfMPTCanTransfer |
|
||||||
MPTokenIssuanceCreateFlags.tfMPTCanTrade,
|
MPTokenIssuanceCreateFlags.tfMPTCanTrade,
|
||||||
MPTokenMetadata: mpt_metadata_hex
|
MPTokenMetadata: mpt_metadata_hex,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sign and submit the transaction
|
||||||
|
console.log("\n=== Sending MPTokenIssuanceCreate transaction...===");
|
||||||
|
console.log(JSON.stringify(mpt_issuance_create, null, 2));
|
||||||
|
const submit_response = await client.submitAndWait(mpt_issuance_create, {
|
||||||
|
wallet: issuer,
|
||||||
|
autofill: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check transaction results
|
||||||
|
console.log("\n=== Checking MPTokenIssuanceCreate results... ===");
|
||||||
|
console.log(JSON.stringify(submit_response.result, null, 2));
|
||||||
|
if (submit_response.result.meta.TransactionResult !== "tesSUCCESS") {
|
||||||
|
const result_code = submit_response.result.meta.TransactionResult;
|
||||||
|
console.warn(`Transaction failed with result code ${result_code}.`);
|
||||||
|
await client.disconnect();
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare, sign, and submit the transaction
|
const issuance_id = submit_response.result.meta.mpt_issuance_id;
|
||||||
console.log('Sending MPTokenIssuanceCreate transaction...')
|
console.log(
|
||||||
const submit_response = await client.submitAndWait(mpt_issuance_create, { wallet, autofill: true })
|
`\n- MPToken created successfully with issuance ID: ${issuance_id}`
|
||||||
|
);
|
||||||
// Check transaction results and disconnect
|
// View the MPT issuance on the XRPL Explorer
|
||||||
console.log(JSON.stringify(submit_response, null, 2))
|
console.log(`- Explorer URL: https://devnet.xrpl.org/mpt/${issuance_id}`);
|
||||||
if (submit_response.result.meta.TransactionResult !== 'tesSUCCESS') {
|
|
||||||
const result_code = response.result.meta.TransactionResult
|
|
||||||
console.warn(`Transaction failed with result code ${result_code}.`)
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const issuance_id = submit_response.result.meta.mpt_issuance_id
|
|
||||||
console.log(`MPToken created successfully with issuance ID ${issuance_id}.`)
|
|
||||||
|
|
||||||
// Look up MPT Issuance entry in the validated ledger
|
// Look up MPT Issuance entry in the validated ledger
|
||||||
console.log('Confirming MPT Issuance metadata in the validated ledger.')
|
console.log("\n=== Confirming MPT Issuance metadata in the validated ledger... ===");
|
||||||
const ledger_entry_response = await client.request({
|
const ledger_entry_response = await client.request({
|
||||||
"command": "ledger_entry",
|
command: "ledger_entry",
|
||||||
"mpt_issuance": issuance_id,
|
mpt_issuance: issuance_id,
|
||||||
"ledger_index": "validated"
|
ledger_index: "validated",
|
||||||
})
|
});
|
||||||
|
|
||||||
// Decode the metadata
|
// Decode the metadata.
|
||||||
const metadata_blob = ledger_entry_response.result.node.MPTokenMetadata
|
// The decodeMPTokenMetadata function takes a hex-encoded string representing MPT metadata,
|
||||||
const decoded_metadata = JSON.parse(hexToString(metadata_blob))
|
// decodes it to a JSON object, and expands any compact field names to their full forms.
|
||||||
console.log('Decoded metadata:', decoded_metadata)
|
const metadata_blob = ledger_entry_response.result.node.MPTokenMetadata;
|
||||||
|
const decoded_metadata = decodeMPTokenMetadata(metadata_blob);
|
||||||
|
console.log("Decoded MPT metadata:\n", decoded_metadata);
|
||||||
|
|
||||||
|
// Disconnect from the client
|
||||||
client.disconnect()
|
await client.disconnect();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"xrpl": "^4.4.0"
|
"xrpl": "^4.4.3"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,137 @@ pip install -r requirements.txt
|
|||||||
python issue-mpt-with-metadata.py
|
python issue-mpt-with-metadata.py
|
||||||
```
|
```
|
||||||
|
|
||||||
The script should output a validated transaction and end with a line such as the following:
|
The script should output a validated transaction and decoded metadata, similar to the following:
|
||||||
|
|
||||||
```text
|
```sh
|
||||||
MPToken created successfully with issuance ID 0050773D6B8DF8C6BEA497016C8679728A217DE1C4D50AC5.
|
=== Funding new wallet from faucet... ===
|
||||||
|
Attempting to fund address rN1vQBHqgbfXjeAfYVUVpQXMyyZYjAnQkS
|
||||||
|
Faucet fund successful.
|
||||||
|
|
||||||
|
=== Encoding metadata...===
|
||||||
|
Encoded mpt_metadata_hex: 7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D
|
||||||
|
|
||||||
|
=== Sending MPTokenIssuanceCreate transaction...===
|
||||||
|
{
|
||||||
|
"Account": "rN1vQBHqgbfXjeAfYVUVpQXMyyZYjAnQkS",
|
||||||
|
"TransactionType": "MPTokenIssuanceCreate",
|
||||||
|
"Flags": 48,
|
||||||
|
"SigningPubKey": "",
|
||||||
|
"AssetScale": 4,
|
||||||
|
"MaximumAmount": "50000000",
|
||||||
|
"TransferFee": 0,
|
||||||
|
"MPTokenMetadata": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D"
|
||||||
|
}
|
||||||
|
|
||||||
|
=== Checking MPTokenIssuanceCreate results... ===
|
||||||
|
{
|
||||||
|
"close_time_iso": "2025-11-20T18:21:12Z",
|
||||||
|
"ctid": "C0148F2200000002",
|
||||||
|
"hash": "47D87C3C93C80F2158CE5A688C63386E939BC77CFF4F5B62F84775A97EF991AE",
|
||||||
|
"ledger_hash": "663C9D10B10586009F5C17B4A9A98220ECB00AF64A248A71ECF970D3E7D206F4",
|
||||||
|
"ledger_index": 1347362,
|
||||||
|
"meta": {
|
||||||
|
"AffectedNodes": [
|
||||||
|
{
|
||||||
|
"ModifiedNode": {
|
||||||
|
"FinalFields": {
|
||||||
|
"Account": "rN1vQBHqgbfXjeAfYVUVpQXMyyZYjAnQkS",
|
||||||
|
"Balance": "99999999",
|
||||||
|
"Flags": 0,
|
||||||
|
"OwnerCount": 1,
|
||||||
|
"Sequence": 1347360
|
||||||
|
},
|
||||||
|
"LedgerEntryType": "AccountRoot",
|
||||||
|
"LedgerIndex": "0B10E7C08910B27DE817A935972FBD91B57E6177627FDA78C9C75CD83D32D973",
|
||||||
|
"PreviousFields": {
|
||||||
|
"Balance": "100000000",
|
||||||
|
"OwnerCount": 0,
|
||||||
|
"Sequence": 1347359
|
||||||
|
},
|
||||||
|
"PreviousTxnID": "2166929BBF80BEAA631AB4FBE6864E03CD669D4AFEE6559BA6AB850602A9151A",
|
||||||
|
"PreviousTxnLgrSeq": 1347359
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"CreatedNode": {
|
||||||
|
"LedgerEntryType": "DirectoryNode",
|
||||||
|
"LedgerIndex": "5D2D7A2717A4ECF4C865A6F80E0C2C228409B27CE948307F3ED01213C9906AC4",
|
||||||
|
"NewFields": {
|
||||||
|
"Owner": "rN1vQBHqgbfXjeAfYVUVpQXMyyZYjAnQkS",
|
||||||
|
"RootIndex": "5D2D7A2717A4ECF4C865A6F80E0C2C228409B27CE948307F3ED01213C9906AC4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"CreatedNode": {
|
||||||
|
"LedgerEntryType": "MPTokenIssuance",
|
||||||
|
"LedgerIndex": "886355A55396B5511A96BCA43E73E3DEDC2875776EC307252157142B1D36B852",
|
||||||
|
"NewFields": {
|
||||||
|
"AssetScale": 4,
|
||||||
|
"Flags": 48,
|
||||||
|
"Issuer": "rN1vQBHqgbfXjeAfYVUVpQXMyyZYjAnQkS",
|
||||||
|
"MPTokenMetadata": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D",
|
||||||
|
"MaximumAmount": "50000000",
|
||||||
|
"Sequence": 1347359
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"TransactionIndex": 0,
|
||||||
|
"TransactionResult": "tesSUCCESS",
|
||||||
|
"mpt_issuance_id": "00148F1F983B024FB54CE16CBC7F788C2F71AC9728355EFC"
|
||||||
|
},
|
||||||
|
"tx_json": {
|
||||||
|
"Account": "rN1vQBHqgbfXjeAfYVUVpQXMyyZYjAnQkS",
|
||||||
|
"AssetScale": 4,
|
||||||
|
"Fee": "1",
|
||||||
|
"Flags": 48,
|
||||||
|
"LastLedgerSequence": 1347380,
|
||||||
|
"MPTokenMetadata": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D",
|
||||||
|
"MaximumAmount": "50000000",
|
||||||
|
"Sequence": 1347359,
|
||||||
|
"SigningPubKey": "ED0BFB56FB91211F7DCB245C3863958B8FF5A5BAC4B7293E598C7B4D34265EF0A9",
|
||||||
|
"TransactionType": "MPTokenIssuanceCreate",
|
||||||
|
"TransferFee": 0,
|
||||||
|
"TxnSignature": "4710CCD303902101E6A009E8D459774D1FA9C59E20816588B9248883FF6A37DD8670C1C6EEED1DE5B363A15C88FCA40C1E74319886F3DB8278A63CF0B88CDC0A",
|
||||||
|
"ctid": "C0148F2200000002",
|
||||||
|
"date": 816978072,
|
||||||
|
"ledger_index": 1347362
|
||||||
|
},
|
||||||
|
"validated": true
|
||||||
|
}
|
||||||
|
|
||||||
|
- MPToken created successfully with issuance ID: 00148F1F983B024FB54CE16CBC7F788C2F71AC9728355EFC
|
||||||
|
- Explorer URL: https://devnet.xrpl.org/mpt/00148F1F983B024FB54CE16CBC7F788C2F71AC9728355EFC
|
||||||
|
|
||||||
|
=== Confirming MPT Issuance metadata in the validated ledger... ===
|
||||||
|
Decoded MPT metadata:
|
||||||
|
{
|
||||||
|
"asset_class": "rwa",
|
||||||
|
"additional_info": {
|
||||||
|
"cusip": "912796RX0",
|
||||||
|
"interest_rate": "5.00%",
|
||||||
|
"interest_type": "variable",
|
||||||
|
"maturity_date": "2045-06-30",
|
||||||
|
"yield_source": "U.S. Treasury Bills"
|
||||||
|
},
|
||||||
|
"asset_subclass": "treasury",
|
||||||
|
"desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
|
||||||
|
"icon": "https://example.org/tbill-icon.png",
|
||||||
|
"issuer_name": "Example Yield Co.",
|
||||||
|
"name": "T-Bill Yield Token",
|
||||||
|
"ticker": "TBILL",
|
||||||
|
"uris": [
|
||||||
|
{
|
||||||
|
"category": "website",
|
||||||
|
"title": "Product Page",
|
||||||
|
"uri": "https://exampleyield.co/tbill"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "docs",
|
||||||
|
"title": "Yield Token Docs",
|
||||||
|
"uri": "https://exampleyield.co/docs"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
from xrpl.utils import str_to_hex, hex_to_str
|
from xrpl.utils import encode_mptoken_metadata, decode_mptoken_metadata
|
||||||
from xrpl.clients import JsonRpcClient
|
from xrpl.clients import JsonRpcClient
|
||||||
from xrpl.wallet import generate_faucet_wallet
|
from xrpl.wallet import generate_faucet_wallet
|
||||||
from xrpl.transaction import submit_and_wait
|
from xrpl.transaction import submit_and_wait
|
||||||
@@ -7,31 +7,31 @@ from xrpl.models import LedgerEntry, MPTokenIssuanceCreate, MPTokenIssuanceCreat
|
|||||||
|
|
||||||
# Set up client and get a wallet
|
# Set up client and get a wallet
|
||||||
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
||||||
print("Funding new wallet from faucet...")
|
print("=== Funding new wallet from faucet... ===")
|
||||||
wallet = generate_faucet_wallet(client, debug=True)
|
issuer = generate_faucet_wallet(client, debug=True)
|
||||||
|
|
||||||
# Define metadata as JSON
|
# Define metadata as JSON
|
||||||
mpt_metadata = {
|
mpt_metadata = {
|
||||||
"t": "TBILL",
|
"ticker": "TBILL",
|
||||||
"n": "T-Bill Yield Token",
|
"name": "T-Bill Yield Token",
|
||||||
"d": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
|
"desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
|
||||||
"i": "example.org/tbill-icon.png",
|
"icon": "https://example.org/tbill-icon.png",
|
||||||
"ac": "rwa",
|
"asset_class": "rwa",
|
||||||
"as": "treasury",
|
"asset_subclass": "treasury",
|
||||||
"in": "Example Yield Co.",
|
"issuer_name": "Example Yield Co.",
|
||||||
"us": [
|
"uris": [
|
||||||
{
|
{
|
||||||
"u": "exampleyield.co/tbill",
|
"uri": "https://exampleyield.co/tbill",
|
||||||
"c": "website",
|
"category": "website",
|
||||||
"t": "Product Page"
|
"title": "Product Page"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"u": "exampleyield.co/docs",
|
"uri": "https://exampleyield.co/docs",
|
||||||
"c": "docs",
|
"category": "docs",
|
||||||
"t": "Yield Token Docs"
|
"title": "Yield Token Docs"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ai": {
|
"additional_info": {
|
||||||
"interest_rate": "5.00%",
|
"interest_rate": "5.00%",
|
||||||
"interest_type": "variable",
|
"interest_type": "variable",
|
||||||
"yield_source": "U.S. Treasury Bills",
|
"yield_source": "U.S. Treasury Bills",
|
||||||
@@ -40,13 +40,17 @@ mpt_metadata = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Convert JSON to a string (without excess whitespace), then string to hex
|
# Encode the metadata.
|
||||||
mpt_metadata_string = json.dumps(mpt_metadata, separators=(',', ':'))
|
# The encode_mptoken_metadata function converts the JSON metadata object into
|
||||||
mpt_metadata_hex = str_to_hex(mpt_metadata_string)
|
# a compact, hex-encoded string, following the XLS-89 standard.
|
||||||
|
# https://xls.xrpl.org/xls/XLS-0089-multi-purpose-token-metadata-schema.html
|
||||||
|
print("\n=== Encoding metadata...===")
|
||||||
|
mpt_metadata_hex = encode_mptoken_metadata(mpt_metadata)
|
||||||
|
print("Encoded mpt_metadata_hex:", mpt_metadata_hex)
|
||||||
|
|
||||||
# Define the transaction, including other MPT parameters
|
# Define the transaction, including other MPT parameters
|
||||||
mpt_issuance_create = MPTokenIssuanceCreate(
|
mpt_issuance_create = MPTokenIssuanceCreate(
|
||||||
account=wallet.address,
|
account=issuer.address,
|
||||||
asset_scale=4,
|
asset_scale=4,
|
||||||
maximum_amount="50000000",
|
maximum_amount="50000000",
|
||||||
transfer_fee=0,
|
transfer_fee=0,
|
||||||
@@ -55,28 +59,33 @@ mpt_issuance_create = MPTokenIssuanceCreate(
|
|||||||
mptoken_metadata=mpt_metadata_hex
|
mptoken_metadata=mpt_metadata_hex
|
||||||
)
|
)
|
||||||
|
|
||||||
# Prepare, sign, and submit the transaction
|
# Sign and submit the transaction
|
||||||
print("Sending MPTokenIssuanceCreate transaction...")
|
print("\n=== Sending MPTokenIssuanceCreate transaction...===")
|
||||||
response = submit_and_wait(mpt_issuance_create, client, wallet, autofill=True)
|
print(json.dumps(mpt_issuance_create.to_xrpl(), indent=2))
|
||||||
print(json.dumps(response.result, indent=2))
|
response = submit_and_wait(mpt_issuance_create, client, issuer, autofill=True)
|
||||||
|
|
||||||
# Check transaction results
|
# Check transaction results
|
||||||
|
print("\n=== Checking MPTokenIssuanceCreate results... ===")
|
||||||
|
print(json.dumps(response.result, indent=2))
|
||||||
result_code = response.result["meta"]["TransactionResult"]
|
result_code = response.result["meta"]["TransactionResult"]
|
||||||
if result_code != "tesSUCCESS":
|
if result_code != "tesSUCCESS":
|
||||||
print(f"Transaction failed with result code {result_code}")
|
print(f"Transaction failed with result code {result_code}.")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
issuance_id = response.result["meta"]["mpt_issuance_id"]
|
issuance_id = response.result["meta"]["mpt_issuance_id"]
|
||||||
print(f"MPToken successfully created with issuance ID {issuance_id}")
|
print(f"\n- MPToken created successfully with issuance ID: {issuance_id}")
|
||||||
|
print(f"- Explorer URL: https://devnet.xrpl.org/mpt/{issuance_id}")
|
||||||
|
|
||||||
# Look up MPT Issuance entry in the validated ledger
|
# Look up MPT Issuance entry in the validated ledger
|
||||||
print("Confirming MPT Issuance metadata in the validated ledger.")
|
print("\n=== Confirming MPT Issuance metadata in the validated ledger... ===")
|
||||||
ledger_entry_response = client.request(LedgerEntry(
|
ledger_entry_response = client.request(LedgerEntry(
|
||||||
mpt_issuance=issuance_id,
|
mpt_issuance=issuance_id,
|
||||||
ledger_index="validated"
|
ledger_index="validated"
|
||||||
))
|
))
|
||||||
|
|
||||||
# Decode the metadata
|
# Decode the metadata.
|
||||||
|
# The decode_mptoken_metadata function takes a hex-encoded string representing MPT metadata,
|
||||||
|
# decodes it to a JSON object, and expands any compact field names to their full forms.
|
||||||
metadata_blob = ledger_entry_response.result["node"]["MPTokenMetadata"]
|
metadata_blob = ledger_entry_response.result["node"]["MPTokenMetadata"]
|
||||||
decoded_metadata = json.loads(hex_to_str(metadata_blob))
|
decoded_metadata = decode_mptoken_metadata(metadata_blob)
|
||||||
print("Decoded metadata:", decoded_metadata)
|
print("Decoded MPT metadata:\n", json.dumps(decoded_metadata, indent=2))
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
xrpl-py==4.3.0
|
xrpl-py==4.3.1
|
||||||
|
|||||||
221
docs/tutorials/how-tos/use-tokens/issue-a-multi-purpose-token.md
Normal file
221
docs/tutorials/how-tos/use-tokens/issue-a-multi-purpose-token.md
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
---
|
||||||
|
seo:
|
||||||
|
description: Issue a Multi-Purpose Token (MPT) with arbitrary metadata on the XRP Ledger.
|
||||||
|
metadata:
|
||||||
|
indexPage: true
|
||||||
|
labels:
|
||||||
|
- Multi-Purpose Token
|
||||||
|
- MPT
|
||||||
|
- Token Issuance
|
||||||
|
---
|
||||||
|
# Issue a Multi-Purpose Token (MPT)
|
||||||
|
|
||||||
|
A [Multi-Purpose Token (MPT)](../../../concepts/tokens/fungible-tokens/multi-purpose-tokens.md) lets you to quickly access powerful, built-in tokenization features on the XRP Ledger with minimal code.
|
||||||
|
|
||||||
|
This tutorial shows you how to issue an MPT with on-chain metadata such as the token's ticker, name, or description, encoded according to the MPT [metadata schema](../../../concepts/tokens/fungible-tokens/multi-purpose-tokens.md#metadata-schema) defined in [XLS-89](https://xls.xrpl.org/xls/XLS-0089-multi-purpose-token-metadata-schema.html).
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
By the end of this tutorial, you will be able to:
|
||||||
|
|
||||||
|
- Issue a new MPToken on the XRP Ledger.
|
||||||
|
- Encode or decode token metadata following MPT standards best practices.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
To complete this tutorial, you should:
|
||||||
|
|
||||||
|
- Have a basic understanding of the XRP Ledger.
|
||||||
|
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||||
|
- **JavaScript** with the [xrpl.js library](https://github.com/XRPLF/xrpl.js). See [Get Started Using JavaScript](../../javascript/build-apps/get-started.md) for setup steps.
|
||||||
|
- **Python** with the [xrpl-py library](https://github.com/XRPLF/xrpl-py). See [Get Started Using Python](../../python/build-apps/get-started.md) for setup steps.
|
||||||
|
|
||||||
|
## Source Code
|
||||||
|
|
||||||
|
You can find the complete source code for this tutorial's example in the [code samples section of this website's repository](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/issue-mpt-with-metadata).
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
The example in this tutorial demonstrates how to issue a sample [US Treasury bill (T-bill)](https://www.treasurydirect.gov/research-center/history-of-marketable-securities/bills/t-bills-indepth/) as an MPT on the XRP Ledger.
|
||||||
|
|
||||||
|
### 1. Install dependencies
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
From the code sample folder, use npm to install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install xrpl
|
||||||
|
```
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
From the code sample folder, install dependencies using pip:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
{% /tab %}
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
### 2. Set up client and fund issuer wallet
|
||||||
|
|
||||||
|
Import the client library, instantiate a client to connect to the XRPL, and fund a new wallet to act as the token issuer.
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js" language="js" before="// Define metadata as JSON" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py" language="py" before="# Define metadata as JSON" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
### 3. Define and encode MPT metadata
|
||||||
|
|
||||||
|
The metadata you provide is what distinguishes your token from other MPTs. Define the JSON metadata as shown in the following code snippet:
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js" language="js" from="// Define metadata as JSON" before="// Encode the metadata" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py" language="py" from="# Define metadata as JSON" before="# Encode the metadata" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
The metadata schema defined in XLS-89 supports both long field names (`ticker`, `name`, `desc`) and compact short keys (`t`, `n`, `d`). To save space on the ledger, it’s recommended to use short key names. The MPT metadata field has a 1024-byte limit, so using compact keys allows you to include more information.
|
||||||
|
|
||||||
|
The SDK libraries provide utility functions to encode or decode the metadata for you, so you don't have to. If long field names are provided in the JSON, the **encoding utility function** automatically shortens them to their compact key equivalents before encoding. Similarly, when decoding, the **decoding utility function** converts the short keys back to their respective long names.
|
||||||
|
|
||||||
|
To encode the metadata:
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js" language="js" from="// Encode the metadata" before="// Define the transaction" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py" language="py" from="# Encode the metadata" before="# Define the transaction" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
{% admonition type="warning" name="Warning" %}
|
||||||
|
The encoding function will raise an error if the input is not a valid JSON object.
|
||||||
|
{% /admonition %}
|
||||||
|
|
||||||
|
### 4. Prepare the MPTokenIssuanceCreate transaction
|
||||||
|
|
||||||
|
To issue the MPT, create an `MPTokenIssuanceCreate` transaction object. Specify the issuer, asset scale, maximum amount, flags, and the encoded metadata.
|
||||||
|
|
||||||
|
| Field | Description |
|
||||||
|
|:------------------- |:------ |
|
||||||
|
| `TransactionType` | The type of transaction, in this case `MPTokenIssuanceCreate`. |
|
||||||
|
| `Account` | The wallet address of the account that is issuing the MPT, in this case the `issuer`. |
|
||||||
|
| `AssetScale` | The number of decimal places for the token. |
|
||||||
|
| `MaximumAmount` | The maximum supply of the token to be issued. |
|
||||||
|
| `TransferFee` | The transfer fee (if any) to charge for token transfers. |
|
||||||
|
| `Flags` | Flags to set token permissions. For this example the **Can Transfer** and **Can Trade** flags are enabled. See [MPTokenIssuanceCreate Flags](../../../references/protocol/transactions/types/mptokenissuancecreate.md#mptokenissuancecreate-flags) for all available flags. |
|
||||||
|
| `MPTokenMetadata` | The hex-encoded metadata for the token. |
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js" language="js" from="// Define the transaction" before="// Sign and submit the transaction" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py" language="py" from="# Define the transaction" before="# Sign and submit the transaction" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
### 5. Submit MPTokenIssuanceCreate transaction
|
||||||
|
|
||||||
|
Sign and submit the `MPTokenIssuanceCreate` transaction to the ledger.
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js" language="js" from="// Sign and submit the transaction" before="// Check transaction results" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py" language="py" from="# Sign and submit the transaction" before="# Check transaction results" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
Some important considerations about token metadata when you submit the transaction:
|
||||||
|
|
||||||
|
- If you provide metadata that exceeds the 1024-byte limit, the transaction will fail with an error.
|
||||||
|
|
||||||
|
- If the metadata does not conform to the XLS-89 standards, the transaction still succeeds, but your token may not be compatible with wallets and applications that expect valid MPT metadata.
|
||||||
|
|
||||||
|
The SDK libraries provide a warning to help you diagnose why your metadata is not compliant. For example, you might see a warning like the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
MPTokenMetadata is not properly formatted as JSON as per the XLS-89d standard.
|
||||||
|
While adherence to this standard is not mandatory, such non-compliant MPToken's
|
||||||
|
might not be discoverable by Explorers and Indexers in the XRPL ecosystem.
|
||||||
|
- ticker/t: should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.
|
||||||
|
- name/n: should be a non-empty string.
|
||||||
|
- icon/i: should be a non-empty string.
|
||||||
|
- asset_class/ac: should be one of rwa, memes, wrapped, gaming, defi, other.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Check transaction result
|
||||||
|
|
||||||
|
Verify that the transaction succeeded and retrieve the MPT issuance ID.
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js" language="js" from="// Check transaction results" before="// Look up MPT Issuance entry" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py" language="py" from="# Check transaction results" before="# Look up MPT Issuance entry" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
A `tesSUCCESS` result indicates that the transaction is successful and the token has been created.
|
||||||
|
|
||||||
|
### 7. Confirm MPT issuance and decode metadata
|
||||||
|
|
||||||
|
Look up the MPT issuance entry in the validated ledger and decode the metadata to verify it matches your original input.
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
|
||||||
|
{% tab label="Javascript" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/js/issue-mpt-with-metadata.js" language="js" from="// Look up MPT Issuance entry" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% tab label="Python" %}
|
||||||
|
{% code-snippet file="/_code-samples/issue-mpt-with-metadata/py/issue-mpt-with-metadata.py" language="py" from="# Look up MPT Issuance entry" /%}
|
||||||
|
{% /tab %}
|
||||||
|
|
||||||
|
{% /tabs %}
|
||||||
|
|
||||||
|
The decoding utility function converts the metadata back to a JSON object and expands the compact key names back to their respective long names.
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- **Concepts**:
|
||||||
|
- [Multi-Purpose Tokens (MPT)](../../../concepts/tokens/fungible-tokens/multi-purpose-tokens.md)
|
||||||
|
- **References**:
|
||||||
|
- [MPTokenIssuance entry][]
|
||||||
|
- [MPTokenIssuanceCreate transaction][]
|
||||||
|
|
||||||
|
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||||
@@ -322,6 +322,7 @@
|
|||||||
expanded: false
|
expanded: false
|
||||||
items:
|
items:
|
||||||
- page: docs/tutorials/how-tos/use-tokens/issue-a-fungible-token.md
|
- page: docs/tutorials/how-tos/use-tokens/issue-a-fungible-token.md
|
||||||
|
- page: docs/tutorials/how-tos/use-tokens/issue-a-multi-purpose-token.md
|
||||||
- page: docs/tutorials/how-tos/use-tokens/trade-in-the-decentralized-exchange.md
|
- page: docs/tutorials/how-tos/use-tokens/trade-in-the-decentralized-exchange.md
|
||||||
- page: docs/tutorials/how-tos/use-tokens/enable-no-freeze.md
|
- page: docs/tutorials/how-tos/use-tokens/enable-no-freeze.md
|
||||||
- page: docs/tutorials/how-tos/use-tokens/enact-global-freeze.md
|
- page: docs/tutorials/how-tos/use-tokens/enact-global-freeze.md
|
||||||
|
|||||||
Reference in New Issue
Block a user