Add tutorial for issuing an MPT (Javascript and Python).

This commit is contained in:
Maria Shodunke
2025-11-18 16:54:41 +00:00
parent 003927517f
commit a71a3fca10
8 changed files with 624 additions and 103 deletions

View File

@@ -9,8 +9,135 @@ npm i
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
MPToken created successfully with issuance ID 005073C721E14A7613BAAF5E0B1A253459832FF8D0D81278.
```sh
=== 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'
}
]
}
```

View File

@@ -1,85 +1,108 @@
import { stringToHex, hexToString } from '@xrplf/isomorphic/dist/utils/index.js'
import { MPTokenIssuanceCreateFlags, Client } from 'xrpl'
import {
MPTokenIssuanceCreateFlags,
Client,
encodeMPTokenMetadata,
decodeMPTokenMetadata,
} from "xrpl";
// Connect to network and get a wallet
const client = new Client('wss://s.devnet.rippletest.net:51233')
await client.connect()
const client = new Client("wss://s.devnet.rippletest.net:51233");
await client.connect();
console.log('Funding new wallet from faucet...')
const { wallet } = await client.fundWallet()
console.log("=== Funding new wallet from faucet...===");
const { wallet: issuer } = await client.fundWallet();
console.log(`Issuer address: ${issuer.address}`);
// Define metadata as JSON
const mpt_metadata = {
t: 'TBILL',
n: 'T-Bill Yield Token',
d: 'A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.',
i: 'https://example.org/tbill-icon.png',
ac: 'rwa',
as: 'treasury',
in: 'Example Yield Co.',
us: [
ticker: "TBILL",
name: "T-Bill Yield Token",
desc: "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
icon: "https://example.org/tbill-icon.png",
asset_class: "rwa",
asset_subclass: "treasury",
issuer_name: "Example Yield Co.",
uris: [
{
u: 'https://exampleyield.co/tbill',
c: 'website',
t: 'Product Page'
uri: "https://exampleyield.co/tbill",
category: "website",
title: "Product Page",
},
{
u: 'https://exampleyield.co/docs',
c: 'docs',
t: 'Yield Token Docs'
}
uri: "https://exampleyield.co/docs",
category: "docs",
title: "Yield Token Docs",
},
],
ai: {
interest_rate: '5.00%',
interest_type: 'variable',
yield_source: 'U.S. Treasury Bills',
maturity_date: '2045-06-30',
cusip: '912796RX0'
}
}
additional_info: {
interest_rate: "5.00%",
interest_type: "variable",
yield_source: "U.S. Treasury Bills",
maturity_date: "2045-06-30",
cusip: "912796RX0",
},
};
// Convert JSON to a string (without excess whitespace), then string to hex
const mpt_metadata_hex = stringToHex(JSON.stringify(mpt_metadata))
// Encode the 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
const mpt_issuance_create = {
TransactionType: 'MPTokenIssuanceCreate',
Account: wallet.address,
TransactionType: "MPTokenIssuanceCreate",
Account: issuer.address,
AssetScale: 4,
MaximumAmount: '50000000',
MaximumAmount: "50000000",
TransferFee: 0,
Flags: MPTokenIssuanceCreateFlags.tfMPTCanTransfer |
MPTokenIssuanceCreateFlags.tfMPTCanTrade,
MPTokenMetadata: mpt_metadata_hex
Flags:
MPTokenIssuanceCreateFlags.tfMPTCanTransfer |
MPTokenIssuanceCreateFlags.tfMPTCanTrade,
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
console.log('Sending MPTokenIssuanceCreate transaction...')
const submit_response = await client.submitAndWait(mpt_issuance_create, { wallet, autofill: true })
// Check transaction results and disconnect
console.log(JSON.stringify(submit_response, null, 2))
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}.`)
const issuance_id = submit_response.result.meta.mpt_issuance_id;
console.log(
`\n- MPToken created successfully with issuance ID: ${issuance_id}`
);
// View the MPT issuance on the XRPL Explorer
console.log(`- Explorer URL: https://devnet.xrpl.org/mpt/${issuance_id}`);
// 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({
"command": "ledger_entry",
"mpt_issuance": issuance_id,
"ledger_index": "validated"
})
command: "ledger_entry",
mpt_issuance: issuance_id,
ledger_index: "validated",
});
// Decode the metadata
const metadata_blob = ledger_entry_response.result.node.MPTokenMetadata
const decoded_metadata = JSON.parse(hexToString(metadata_blob))
console.log('Decoded metadata:', decoded_metadata)
// Decode the metadata.
// The decodeMPTokenMetadata 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.
const metadata_blob = ledger_entry_response.result.node.MPTokenMetadata;
const decoded_metadata = decodeMPTokenMetadata(metadata_blob);
console.log("Decoded MPT metadata:\n", decoded_metadata);
client.disconnect()
// Disconnect from the client
await client.disconnect();

View File

@@ -1,6 +1,6 @@
{
"dependencies": {
"xrpl": "^4.4.0"
"xrpl": "^4.4.3"
},
"type": "module"
}

View File

@@ -11,8 +11,137 @@ pip install -r requirements.txt
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
MPToken created successfully with issuance ID 0050773D6B8DF8C6BEA497016C8679728A217DE1C4D50AC5.
```sh
=== 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"
}
]
}
```

View File

@@ -1,5 +1,5 @@
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.wallet import generate_faucet_wallet
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
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
print("Funding new wallet from faucet...")
wallet = generate_faucet_wallet(client, debug=True)
print("=== Funding new wallet from faucet... ===")
issuer = generate_faucet_wallet(client, debug=True)
# Define metadata as JSON
# Define metadata as JSON
mpt_metadata = {
"t": "TBILL",
"n": "T-Bill Yield Token",
"d": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
"i": "example.org/tbill-icon.png",
"ac": "rwa",
"as": "treasury",
"in": "Example Yield Co.",
"us": [
"ticker": "TBILL",
"name": "T-Bill Yield Token",
"desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.",
"icon": "https://example.org/tbill-icon.png",
"asset_class": "rwa",
"asset_subclass": "treasury",
"issuer_name": "Example Yield Co.",
"uris": [
{
"u": "exampleyield.co/tbill",
"c": "website",
"t": "Product Page"
"uri": "https://exampleyield.co/tbill",
"category": "website",
"title": "Product Page"
},
{
"u": "exampleyield.co/docs",
"c": "docs",
"t": "Yield Token Docs"
"uri": "https://exampleyield.co/docs",
"category": "docs",
"title": "Yield Token Docs"
}
],
"ai": {
"additional_info": {
"interest_rate": "5.00%",
"interest_type": "variable",
"yield_source": "U.S. Treasury Bills",
@@ -40,13 +40,17 @@ mpt_metadata = {
}
}
# Convert JSON to a string (without excess whitespace), then string to hex
mpt_metadata_string = json.dumps(mpt_metadata, separators=(',', ':'))
mpt_metadata_hex = str_to_hex(mpt_metadata_string)
# Encode the metadata.
# The encode_mptoken_metadata 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
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
mpt_issuance_create = MPTokenIssuanceCreate(
account=wallet.address,
account=issuer.address,
asset_scale=4,
maximum_amount="50000000",
transfer_fee=0,
@@ -55,28 +59,33 @@ mpt_issuance_create = MPTokenIssuanceCreate(
mptoken_metadata=mpt_metadata_hex
)
# Prepare, sign, and submit the transaction
print("Sending MPTokenIssuanceCreate transaction...")
response = submit_and_wait(mpt_issuance_create, client, wallet, autofill=True)
print(json.dumps(response.result, indent=2))
# Sign and submit the transaction
print("\n=== Sending MPTokenIssuanceCreate transaction...===")
print(json.dumps(mpt_issuance_create.to_xrpl(), indent=2))
response = submit_and_wait(mpt_issuance_create, client, issuer, autofill=True)
# Check transaction results
print("\n=== Checking MPTokenIssuanceCreate results... ===")
print(json.dumps(response.result, indent=2))
result_code = response.result["meta"]["TransactionResult"]
if result_code != "tesSUCCESS":
print(f"Transaction failed with result code {result_code}")
print(f"Transaction failed with result code {result_code}.")
exit(1)
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
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(
mpt_issuance=issuance_id,
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"]
decoded_metadata = json.loads(hex_to_str(metadata_blob))
print("Decoded metadata:", decoded_metadata)
decoded_metadata = decode_mptoken_metadata(metadata_blob)
print("Decoded MPT metadata:\n", json.dumps(decoded_metadata, indent=2))

View File

@@ -1 +1 @@
xrpl-py==4.3.0
xrpl-py==4.3.1