{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Issue An RWA As An MPT","siteUrl":"https://opensource.ripple.com/","meta":[{"name":"google-site-verification","content":"bLwyBi1imklcIuQxZ7JeI_kRF5Mg7yfr6arpEQV2nsE"}],"llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]},"description":"Issue a Real-World Asset as a Multi-Purpose Token (MPT) through Ripple Custody, with XLS-89 metadata validated before submission."},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"issue-an-rwa-as-an-mpt","__idx":0},"children":["Issue An RWA As An MPT"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Real-World Assets are issued as Multi-Purpose Tokens (MPTs) via the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["token"]}," vertical. Here the issuer is a Ripple Custody account, so Custody signs and submits the issuance as one governed action, with XLS-89 metadata validated before submission. The XRP Ledger supports to token standards (MPT and trust line tokens). MPTs have been designed for greater efficiency and ease of use based on lessons learned from trust line tokens, however there are some cases where you may prefer trust line tokens. See: ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://xrpl.org/docs/concepts/tokens/fungible-tokens#which-fungible-token-type-to-use"},"children":["Which Fungible Token Type to Use"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"/**\n * Issue a Real-World Asset (RWA) through Ripple Custody.\n *\n * RWAs are issued as Multi-Purpose Tokens (MPTs) via the `token` vertical.\n * Metadata follows the XLS-89 standard and is validated before submission\n * (`asset_class: 'rwa'` requires an `asset_subclass`). Here the issuer is a\n * Ripple Custody account: Custody signs and submits the issuance as one\n * governed action, subject to the domain's approval policy. `MPTokenIssuanceCreate`\n * is native to Ripple Custody, so it flows through the governed native path.\n */\nimport { RippleCustody, SimpleXRPL } from 'simplexrpl'\n\n// The Custody-held issuer account; Custody governs every write it signs.\nconst ISSUER_ADDRESS = process.env.RIPPLE_CUSTODY_PRIMARY_ADDRESS ?? ''\n\n// Config (gateway, token endpoint, domain, intent-author key) comes from\n// `RIPPLE_CUSTODY_*` environment variables via `fromEnv`.\nconst custody = await RippleCustody.fromEnv({ primary: ISSUER_ADDRESS })\n\nconst client = await SimpleXRPL.init({\n  xrpldUrl: 'wss://s.altnet.rippletest.net:51233', // XRPL Testnet\n  signers: [custody],\n})\n\n// Metadata is the only required input, the SDK sets everything else.\n// The issuer is the primary signer (the Custody account).\nconst result = await client.token.issue({\n  metadata: {\n    ticker: 'TBILL',\n    name: 'Acme 3-Month T-Bill',\n    icon: 'https://acme.example/tbill.png',\n    asset_class: 'rwa',\n    asset_subclass: 'treasury',\n    issuer_name: 'Acme Capital',\n  },\n})\nconsole.log('issued MPT:', result.intent.mptIssuanceId)\n\n// Read the issuance back (no signer required): flags are decoded to booleans,\n// and XLS-89 metadata is parsed.\nconst token = await client.token.retrieve({\n  mptIssuanceId: result.intent.mptIssuanceId,\n})\nconsole.log('can claw back:', token.data?.flags.canClawback)\nconsole.log('metadata:', token.data?.metadata?.name)\n\nawait client.disconnect()\n","lang":"ts"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"see-also","__idx":1},"children":["See Also"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/simplexrpl/references/verticals/token/issue"},"children":["token.issue()"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/simplexrpl/references/verticals/token/retrieve"},"children":["token.retrieve()"]}]}]}]},"headings":[{"value":"Issue An RWA As An MPT","id":"issue-an-rwa-as-an-mpt","depth":1},{"value":"See Also","id":"see-also","depth":2}],"frontmatter":{"seo":{"description":"Issue a Real-World Asset as a Multi-Purpose Token (MPT) through Ripple Custody, with XLS-89 metadata validated before submission.","title":"Issue An RWA As An MPT"},"labels":["simpleXRPL","SDK"]},"editPage":{"to":"https://github.com/ripple/opensource.ripple.com/tree/main/docs/simpleXRPL/tutorials/issue-rwa-as-mpt.md"},"lastModified":"2026-08-26T19:04:06.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/simplexrpl/tutorials/issue-rwa-as-mpt","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}