{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-@l10n/es-ES/sidebars.yaml","index-page-items":"/es-es/docs/tutorials/payments/send-an-mpt_index-page-items"},"props":{"metadata":{"markdoc":{"tagList":["amendment-disclaimer","repo-link","tabs","tab","code-snippet","admonition"]},"type":"markdown","indexPage":true},"seo":{"title":"Send a Multi-Purpose Token (MPT)","siteUrl":"https://xrpl.org/","llmstxt":{"hide":false,"title":"XRPL Developer Portal & Documentation","description":"Explore XRP Ledger documentation, blogs, and other blockchain developer resources needed to start building and integrating with the ledger.","details":{"content":"XRP Ledger concepts, use cases, tutorials, references, and other blockchain developer resources. Also, stay up to date with release announcements and more through the XRPL Blog."},"sections":[{"title":"Introduction","description":"A high-level introduction to the XRP Ledger.","includeFiles":["docs/introduction/**/*.*","about/faq.md"],"excludeFiles":["docs/introduction/index.md"]},{"title":"Use Cases","description":"Real-world applications and business scenarios for the XRP Ledger.","includeFiles":["docs/use-cases/**/*.*"],"excludeFiles":["docs/use-cases/index.md","docs/use-cases/defi/index.md"]},{"title":"Agentic Transactions","description":"XRPL AI Starter Kit to help autonomous agents discover, set up, and execute agentic transactions on the XRP Ledger.","includeFiles":["docs/agents/**/*.*"],"excludeFiles":[]},{"title":"Concepts","description":"Core concepts including accounts, tokens, transactions, consensus, and more.","includeFiles":["docs/concepts/**/*.*"],"excludeFiles":["docs/concepts/index.md","docs/concepts/decentralized-storage/index.md","docs/concepts/payment-types/index.md"]},{"title":"Tutorials","description":"Step-by-step guides for building on the XRP Ledger in JavaScript, Python, Go, and more.","includeFiles":["docs/tutorials/**/*.*"],"excludeFiles":[]},{"title":"References","description":"Protocol specification, transaction types, ledger entries, and API methods.","includeFiles":["docs/references/**/*.*"],"excludeFiles":["docs/references/xrp-api.md","docs/references/data-api.md","docs/references/protocol/index.md","docs/references/protocol/ledger-data/ledger-entry-types/index.md","docs/references/protocol/transactions/index.md","docs/references/protocol/transactions/types/index.md","docs/references/http-websocket-apis/api-conventions/index.md","docs/references/http-websocket-apis/public-api-methods/*/index.md","docs/references/http-websocket-apis/admin-api-methods/*/index.md"]},{"title":"Infrastructure","description":"Install, configure, and troubleshoot rippled and Clio servers.","includeFiles":["docs/infrastructure/**/*.*"],"excludeFiles":["docs/infrastructure/index.md","docs/infrastructure/*/index.md","docs/infrastructure/installation/build-run-rippled-in-reporting-mode.md","docs/infrastructure/configuration/data-retention/index.md","docs/infrastructure/configuration/server-modes/index.md"]},{"title":"Blog (2023+)","description":"Recent XRPL Blog posts (showing 2023 and newer).","includeFiles":["blog/2023/**/*.*","blog/2024/**/*.*","blog/2025/**/*.*","blog/2026/**/*.*"],"excludeFiles":[]},{"title":"Resources","description":"Developer resources and contribution guidelines.","includeFiles":["resources/**/*.*"],"excludeFiles":["resources/index.md"]}],"excludeFiles":[]},"description":"Send a direct payment of a Multi-Purpose Token (MPT) on the XRP Ledger."},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"send-a-multi-purpose-token-mpt","__idx":0},"children":["Send a Multi-Purpose Token (MPT)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This tutorial shows you how to send a direct ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/es-es/docs/concepts/tokens/fungible-tokens/multi-purpose-tokens"},"children":["Multi-Purpose Token (MPT)"]}," payment on the XRP Ledger."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each account must authorize the MPT before it can hold the token. This is to prevent malicious users from spamming accounts with unwanted tokens that could negatively impact storage and XRP reserves. Holders can send the MPT to each other only if the issuance has the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Can Transfer"]}," flag enabled, and both parties are authorized."]},{"$$mdtype":"Tag","name":"AmendmentDisclaimer","attributes":{"name":"MPTokensV1","compact":false,"mode":""},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"goals","__idx":1},"children":["Goals"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["By the end of this tutorial, you will be able to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Authorize an account to hold a specific MPT."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Send a payment of an MPT between two accounts."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify the payment was successful."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prerequisites","__idx":2},"children":["Prerequisites"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To complete this tutorial, you should:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Have a basic understanding of the XRP Ledger."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["JavaScript"]}," with the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/XRPLF/xrpl.js"},"children":["xrpl.js library"]},". See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/tutorials/get-started/get-started-javascript"},"children":["Get Started Using JavaScript"]}," for setup steps."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Python"]}," with the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/XRPLF/xrpl-py"},"children":["xrpl-py library"]},". See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/tutorials/get-started/get-started-python"},"children":["Get Started Using Python"]}," for setup steps."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Go"]}," with the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/XRPLF/xrpl-go"},"children":["xrpl-go library"]},". See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/tutorials/get-started/get-started-go"},"children":["Get Started Using Go"]}," for setup steps."]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"source-code","__idx":3},"children":["Source Code"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can find the complete source code for this tutorial's examples in the ",{"$$mdtype":"Tag","name":"RepoLink","attributes":{"path":"_code-samples/send-an-mpt/","github_fork":"https://github.com/XRPLF/xrpl-dev-portal","github_branch":"master"},"children":["code samples section of this website's repository"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"steps","__idx":4},"children":["Steps"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"1-install-dependencies","__idx":5},"children":["1. Install dependencies"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["From the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["js/"]}," folder, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["npm"]}," to install dependencies."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sh","header":{"controls":{"copy":{}}},"source":"npm install\n","lang":"sh"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["From the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["py/"]}," folder, set up a virtual environment and use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pip"]}," to install dependencies."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sh","header":{"controls":{"copy":{}}},"source":"python3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n","lang":"sh"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["From the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["go/"]}," folder, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["go"]}," to install dependencies."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sh","header":{"controls":{"copy":{}}},"source":"go mod tidy\n","lang":"sh"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"2-set-up-client-and-accounts","__idx":6},"children":["2. Set up client and accounts"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["xrpl"]},": Used for XRPL client connection, transaction submission, and wallet handling."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fs"]},": Used to check for and load the tutorial setup data."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["./sendMPTSetup.js"]},": The tutorial set up script, imported and called directly."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/js/sendMPT.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"import xrpl from 'xrpl'\nimport fs from 'fs'\nimport { setup } from './sendMPTSetup.js'\n\n// Connect to the network ----------------------\nconst client = new xrpl.Client('wss://s.altnet.rippletest.net:51233')\nawait client.connect()"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["xrpl"]},": Used for XRPL client connection, transaction submission, and wallet handling."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["json"]},": Used for loading and formatting JSON data."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["os"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sys"]},": Used to check for setup data and exit on transaction failures."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["asyncio"]},": Used to run the async tutorial set up function."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["send_mpt_setup"]},": The tutorial set up script, imported and called directly."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/py/send_mpt.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"import asyncio\nimport json\nimport os\nimport sys\n\nfrom xrpl.clients import JsonRpcClient, XRPLRequestFailureException\nfrom xrpl.models import LedgerEntry, MPTokenAuthorize, Payment\nfrom xrpl.models.amounts import MPTAmount\nfrom xrpl.models.requests.ledger_entry import MPToken\nfrom xrpl.transaction import submit_and_wait\nfrom xrpl.wallet import Wallet, generate_faucet_wallet\n\nfrom send_mpt_setup import main as run_setup\n\n# Set up client ----------------------\nclient = JsonRpcClient(\"https://s.altnet.rippletest.net:51234\")"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["xrpl-go"]},": Used for XRPL client connection, transaction submission, and wallet handling."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["encoding/json"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fmt"]},": Used for formatting and printing results to the console."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["os"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["os/exec"]},": Used to run the tutorial set up script."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/go/send-mpt/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\n\t\"github.com/Peersyst/xrpl-go/pkg/crypto\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/faucet\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/queries/common\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/queries/version\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/transaction\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/transaction/types\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/wallet\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/websocket\"\n\twstypes \"github.com/Peersyst/xrpl-go/xrpl/websocket/types\"\n)\n\n// mptokenFilter targets an MPToken ledger entry by issuance ID and holder.\ntype mptokenFilter struct {\n\tMPTIssuanceID string `json:\"mpt_issuance_id\"`\n\tAccount       string `json:\"account\"`\n}\n\n// ledgerEntryMPTRequest is a minimal ledger_entry request that looks up an\n// MPToken entry directly. The xrpl-go SDK doesn't ship a typed wrapper for\n// this lookup, so this implements the websocket Request interface inline.\ntype ledgerEntryMPTRequest struct {\n\tcommon.BaseRequest\n\tLedgerIndex common.LedgerSpecifier `json:\"ledger_index,omitempty\"`\n\tMPToken     mptokenFilter          `json:\"mptoken\"`\n}\n\nfunc (*ledgerEntryMPTRequest) Method() string  { return \"ledger_entry\" }\nfunc (*ledgerEntryMPTRequest) Validate() error { return nil }\nfunc (*ledgerEntryMPTRequest) APIVersion() int { return version.RippledAPIV2 }\n\nfunc main() {\n\t// Connect to the network ----------------------\n\tclient := websocket.NewClient(\n\t\twebsocket.NewClientConfig().\n\t\t\tWithHost(\"wss://s.altnet.rippletest.net:51233\").\n\t\t\tWithFaucetProvider(faucet.NewTestnetFaucetProvider()),\n\t)\n\tdefer client.Disconnect()\n\n\tif err := client.Connect(); err != nil {\n\t\tpanic(err)\n\t}\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Next, provide the sender and receiver wallets, and the MPT issuance ID."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/js/sendMPT.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Load setup data ----------------------\n// This step checks for the necessary setup data to run the tutorial.\n// If missing, sendMPTSetup.js will generate it.\nif (!fs.existsSync('sendMPTSetup.json')) {\n  console.log(`\\n=== Setup data doesn't exist. Running setup script... ===\\n`)\n  await setup()\n}\n\n// Load preconfigured sender wallet and MPT issuance ID.\nconst setupData = JSON.parse(fs.readFileSync('sendMPTSetup.json', 'utf8'))\nconst sender = xrpl.Wallet.fromSeed(setupData.sender.seed)\nconst mptIssuanceID = setupData.mptIssuanceID\n\nconsole.log(`Sender address:   ${sender.address}`)\nconsole.log(`MPT issuance ID:  ${mptIssuanceID}`)\n\n// Fund a fresh receiver wallet from the faucet.\nconsole.log(`\\nCreating and funding receiver wallet...`)\nconst { wallet: receiver } = await client.fundWallet()\nconsole.log(`Receiver address: ${receiver.address}`)"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example uses a preconfigured sender and MPT issuance from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sendMPTSetup.js"]}," script, but you can replace ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mptIssuanceID"]}," with your own values."]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/py/send_mpt.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Load setup data ----------------------\n# This step checks for the necessary setup data to run the tutorial.\n# If missing, send_mpt_setup.py will generate it.\nif not os.path.exists(\"send_mpt_setup.json\"):\n    print(\"\\n=== Setup data doesn't exist. Running setup script... ===\\n\")\n    asyncio.run(run_setup())\n\n# Load sender wallet and MPT issuance ID.\nwith open(\"send_mpt_setup.json\") as f:\n    setup_data = json.load(f)\n\nsender = Wallet.from_seed(setup_data[\"sender\"][\"seed\"])\nmpt_issuance_id = setup_data[\"mpt_issuance_id\"]\n\nprint(f\"Sender address:   {sender.address}\")\nprint(f\"MPT issuance ID:  {mpt_issuance_id}\")\n\n# Fund a fresh receiver wallet from the faucet.\nprint(f\"\\nCreating and funding receiver wallet...\")\nreceiver = generate_faucet_wallet(client)\nprint(f\"Receiver address: {receiver.address}\")"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example uses a preconfigured sender and MPT issuance from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["send_mpt_setup.py"]}," script, but you can replace ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mpt_issuance_id"]}," with your own values."]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/go/send-mpt/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Load setup data ----------------------\n\t// Check for setup data; run send-mpt-setup if missing\n\tif _, err := os.Stat(\"send-mpt-setup.json\"); os.IsNotExist(err) {\n\t\tfmt.Printf(\"\\n=== Setup data doesn't exist. Running setup script... ===\\n\\n\")\n\t\tcmd := exec.Command(\"go\", \"run\", \"./send-mpt-setup\")\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\tif err := cmd.Run(); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n\n\t// Load preconfigured sender wallet and MPT issuance ID.\n\tdata, err := os.ReadFile(\"send-mpt-setup.json\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tvar setup map[string]any\n\tif err := json.Unmarshal(data, &setup); err != nil {\n\t\tpanic(err)\n\t}\n\n\tsenderSeed := setup[\"sender\"].(map[string]any)[\"seed\"].(string)\n\tsender, err := wallet.FromSecret(senderSeed)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tmptIssuanceID := setup[\"mptIssuanceID\"].(string)\n\n\tfmt.Printf(\"Sender address:   %s\\n\", sender.ClassicAddress)\n\tfmt.Printf(\"MPT issuance ID:  %s\\n\", mptIssuanceID)\n\n\t// Fund a fresh receiver wallet from the faucet.\n\tfmt.Printf(\"\\nCreating and funding receiver wallet...\\n\")\n\treceiver, err := wallet.New(crypto.ED25519())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif err := client.FundWallet(&receiver); err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Receiver address: %s\\n\", receiver.ClassicAddress)\n\n\t"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example uses a preconfigured sender and MPT issuance from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["send-mpt-setup/main.go"]}," script, but you can replace ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mptIssuanceID"]}," with your own values."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"3-authorize-the-receiving-account","__idx":7},"children":["3. Authorize the receiving account"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Any account that wants to hold an MPT, whether sending or receiving, must opt in first. Submit an ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/transactions/types/mptokenauthorize"},"children":["MPTokenAuthorize transaction"]},", signed by the holder, to create an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MPToken"]}," ledger entry on their account. In this tutorial, the setup script authorizes the sender before transferring it any tokens, so this step only runs for the receiver."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/js/sendMPT.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Authorize receiver to hold the MPT ----------------------\nconsole.log(`\\n=== Authorizing receiver to hold the MPT... ===\\n`)\nconst authorizeTx = {\n  TransactionType: 'MPTokenAuthorize',\n  Account: receiver.address,\n  MPTokenIssuanceID: mptIssuanceID\n}\nxrpl.validate(authorizeTx)\nconsole.log(JSON.stringify(authorizeTx, null, 2))\n\nconst authorizeResponse = await client.submitAndWait(authorizeTx, {\n  wallet: receiver,\n  autofill: true\n})\nif (authorizeResponse.result.meta.TransactionResult !== 'tesSUCCESS') {\n  const code = authorizeResponse.result.meta.TransactionResult\n  console.error('Error: MPTokenAuthorize failed:', code)\n  await client.disconnect()\n  process.exit(1)\n}\nconsole.log('Receiver authorized to hold the MPT!')\nconsole.log(`Explorer link: https://testnet.xrpl.org/transactions/${authorizeResponse.result.hash}`)"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/py/send_mpt.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Authorize receiver to hold the MPT ----------------------\nprint(\"\\n=== Authorizing receiver to hold the MPT... ===\\n\")\nauthorize_tx = MPTokenAuthorize(\n    account=receiver.address,\n    mptoken_issuance_id=mpt_issuance_id,\n)\nprint(json.dumps(authorize_tx.to_xrpl(), indent=2))\n\nauthorize_response = submit_and_wait(authorize_tx, client, receiver)\nif authorize_response.result[\"meta\"][\"TransactionResult\"] != \"tesSUCCESS\":\n    code = authorize_response.result[\"meta\"][\"TransactionResult\"]\n    print(f\"Error: MPTokenAuthorize failed: {code}\")\n    sys.exit(1)\nprint(\"Receiver authorized to hold the MPT!\")\nprint(f\"Explorer link: https://testnet.xrpl.org/transactions/{authorize_response.result['hash']}\")"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/go/send-mpt/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Authorize receiver to hold the MPT ----------------------\n\tfmt.Printf(\"\\n=== Authorizing receiver to hold the MPT... ===\\n\\n\")\n\tauthorizeTx := transaction.MPTokenAuthorize{\n\t\tBaseTx: transaction.BaseTx{\n\t\t\tAccount: receiver.ClassicAddress,\n\t\t},\n\t\tMPTokenIssuanceID: mptIssuanceID,\n\t}\n\n\tflatAuthorize := authorizeTx.Flatten()\n\tauthorizeJSON, _ := json.MarshalIndent(flatAuthorize, \"\", \"  \")\n\tfmt.Printf(\"%s\\n\", string(authorizeJSON))\n\n\tauthorizeResponse, err := client.SubmitTxAndWait(flatAuthorize, &wstypes.SubmitOptions{\n\t\tAutofill: true,\n\t\tWallet:   &receiver,\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif authorizeResponse.Meta.TransactionResult != \"tesSUCCESS\" {\n\t\tfmt.Printf(\"Error: MPTokenAuthorize failed: %s\\n\", authorizeResponse.Meta.TransactionResult)\n\t\tos.Exit(1)\n\t}\n\tfmt.Printf(\"Receiver authorized to hold the MPT!\\n\")\n\tfmt.Printf(\"Explorer link: https://testnet.xrpl.org/transactions/%s\\n\", authorizeResponse.Hash.String())\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tesSUCCESS"]}," result confirms the receiver is now authorized to hold the MPT, and should have an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MPToken"]}," ledger entry with a balance of zero."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Note"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the issuance uses allow-listing (the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Require Auth"]}," flag), this step isn't enough on its own. After the holder opts in, the issuer typically must also approve the holder—usually by submitting its own ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/transactions/types/mptokenauthorize"},"children":["MPTokenAuthorize transaction"]}," with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Holder"]}," field set to the holder's address. ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["The token used in this tutorial doesn't use allow-listing, so no issuer approval is needed."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"4-check-initial-balances","__idx":8},"children":["4. Check initial balances"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before sending the payment, check each account's MPT holdings using the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/http-websocket-apis/public-api-methods/ledger-methods/ledger_entry"},"children":["ledger_entry method"]},". Pass the holder's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account"]}," and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mpt_issuance_id"]}," in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mptoken"]}," parameter to look up the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MPToken"]}," entry directly. This avoids paginating through the account's owner directory and works reliably for accounts that own many ledger entries."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/js/sendMPT.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Check initial balances ----------------------\n/**\n * Return the MPTAmount for the given MPT issuance held by an account.\n *\n * Looks up the holder's MPToken ledger entry directly via ledger_entry. \n * Returns \"0\" if the entry doesn't exist or has no\n * MPTAmount.\n *\n * @param {string} address - Classic address of the account to query.\n * @param {string} mptIssuanceID - MPT issuance ID to look up.\n * @returns {Promise<string>} The MPT amount as a string, or \"0\".\n */\nasync function getMPTBalance(address, mptIssuanceID) {\n  try {\n    const response = await client.request({\n      command: 'ledger_entry',\n      ledger_index: 'validated',\n      mptoken: {\n        mpt_issuance_id: mptIssuanceID,\n        account: address\n      }\n    })\n    return response.result.node?.MPTAmount ?? '0'\n  } catch (e) {\n    if (e.data?.error === 'entryNotFound') {\n      return '0'\n    }\n    throw e\n  }\n}\n\nconsole.log(`\\n=== Checking initial MPT balances for issuance ${mptIssuanceID}... ===\\n`)\nconst senderBalanceBefore = await getMPTBalance(sender.address, mptIssuanceID)\nconst receiverBalanceBefore = await getMPTBalance(receiver.address, mptIssuanceID)\nconsole.log(`Sender balance:   ${senderBalanceBefore}`)\nconsole.log(`Receiver balance: ${receiverBalanceBefore}`)"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/py/send_mpt.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Check initial balances ----------------------\ndef get_mpt_balance(address, issuance_id):\n    \"\"\"Return the MPTAmount for the given MPT issuance held by an account.\n\n    Looks up the holder's MPToken ledger entry directly via ledger_entry.\n    Returns \"0\" if the entry doesn't exist or has no MPTAmount.\n    \"\"\"\n    response = client.request(LedgerEntry(\n        ledger_index=\"validated\",\n        mptoken=MPToken(mpt_issuance_id=issuance_id, account=address),\n    ))\n    if not response.is_successful():\n        if response.result.get(\"error\") == \"entryNotFound\":\n            return \"0\"\n        raise XRPLRequestFailureException(response.result)\n    return response.result.get(\"node\", {}).get(\"MPTAmount\", \"0\")\n\nprint(f\"\\n=== Checking initial MPT balances for issuance {mpt_issuance_id}... ===\\n\")\nsender_balance_before = get_mpt_balance(sender.address, mpt_issuance_id)\nreceiver_balance_before = get_mpt_balance(receiver.address, mpt_issuance_id)\nprint(f\"Sender balance:   {sender_balance_before}\")\nprint(f\"Receiver balance: {receiver_balance_before}\")"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/go/send-mpt/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Check initial balances ----------------------\n\t// getMPTBalance returns the MPTAmount for the given MPT issuance held by\n\t// address. It looks up the holder's MPToken ledger entry directly via ledger_entry.\n\t// Returns \"0\" if the entry doesn't exist or has no MPTAmount.\n\tgetMPTBalance := func(address types.Address, mptIssuanceID string) (string, error) {\n\t\tresp, err := client.Request(&ledgerEntryMPTRequest{\n\t\t\tLedgerIndex: common.Validated,\n\t\t\tMPToken: mptokenFilter{\n\t\t\t\tMPTIssuanceID: mptIssuanceID,\n\t\t\t\tAccount:       string(address),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\tif err.Error() == \"entryNotFound\" {\n\t\t\t\treturn \"0\", nil\n\t\t\t}\n\t\t\treturn \"\", err\n\t\t}\n\n\t\tnode, ok := resp.Result[\"node\"].(map[string]any)\n\t\tif !ok {\n\t\t\treturn \"0\", nil\n\t\t}\n\t\tif amt, ok := node[\"MPTAmount\"].(string); ok {\n\t\t\treturn amt, nil\n\t\t}\n\t\treturn \"0\", nil\n\t}\n\n\tfmt.Printf(\"\\n=== Checking initial MPT balances for issuance %s... ===\\n\\n\", mptIssuanceID)\n\tsenderBalanceBefore, err := getMPTBalance(sender.ClassicAddress, mptIssuanceID)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treceiverBalanceBefore, err := getMPTBalance(receiver.ClassicAddress, mptIssuanceID)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Sender balance:   %s\\n\", senderBalanceBefore)\n\tfmt.Printf(\"Receiver balance: %s\\n\", receiverBalanceBefore)\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"5-send-the-token-payment","__idx":9},"children":["5. Send the token payment"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Specify an ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/es-es/docs/references/protocol/data-types/currency-formats#mpt-amounts"},"children":["MPT amount"]}," to send to the receiver, then submit the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/transactions/types/payment"},"children":["Payment transaction"]},"."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/js/sendMPT.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Send MPT from sender to receiver ----------------------\nconsole.log(`\\n=== Sending MPT payment... ===\\n`)\nconst paymentTx = {\n  TransactionType: 'Payment',\n  Account: sender.address,\n  Destination: receiver.address,\n  Amount: {\n    mpt_issuance_id: mptIssuanceID,\n    value: '100'\n  }\n}\nxrpl.validate(paymentTx)\nconsole.log(JSON.stringify(paymentTx, null, 2))\n\nconst paymentResponse = await client.submitAndWait(paymentTx, {\n  wallet: sender,\n  autofill: true\n})\nif (paymentResponse.result.meta.TransactionResult !== 'tesSUCCESS') {\n  const code = paymentResponse.result.meta.TransactionResult\n  console.error('Error: Payment failed:', code)\n  await client.disconnect()\n  process.exit(1)\n}\nconsole.log('Payment successful!')\nconsole.log(`Explorer link: https://testnet.xrpl.org/transactions/${paymentResponse.result.hash}`)"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/py/send_mpt.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Send MPT from sender to receiver ----------------------\nprint(\"\\n=== Sending MPT payment... ===\\n\")\npayment_tx = Payment(\n    account=sender.address,\n    destination=receiver.address,\n    amount=MPTAmount(\n        mpt_issuance_id=mpt_issuance_id,\n        value=\"100\",\n    ),\n)\nprint(json.dumps(payment_tx.to_xrpl(), indent=2))\n\npayment_response = submit_and_wait(payment_tx, client, sender)\nif payment_response.result[\"meta\"][\"TransactionResult\"] != \"tesSUCCESS\":\n    code = payment_response.result[\"meta\"][\"TransactionResult\"]\n    print(f\"Error: Payment failed: {code}\")\n    sys.exit(1)\nprint(\"Payment successful!\")\nprint(f\"Explorer link: https://testnet.xrpl.org/transactions/{payment_response.result['hash']}\")"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/go/send-mpt/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Send MPT from sender to receiver ----------------------\n\tfmt.Printf(\"\\n=== Sending MPT payment... ===\\n\\n\")\n\tpaymentTx := transaction.Payment{\n\t\tBaseTx: transaction.BaseTx{\n\t\t\tAccount: sender.ClassicAddress,\n\t\t},\n\t\tDestination: receiver.ClassicAddress,\n\t\tAmount: &types.MPTCurrencyAmount{\n\t\t\tMPTIssuanceID: mptIssuanceID,\n\t\t\tValue:         \"100\",\n\t\t},\n\t}\n\tflatPayment := paymentTx.Flatten()\n\tpaymentJSON, _ := json.MarshalIndent(flatPayment, \"\", \"  \")\n\tfmt.Printf(\"%s\\n\", string(paymentJSON))\n\n\tpaymentResponse, err := client.SubmitTxAndWait(flatPayment, &wstypes.SubmitOptions{\n\t\tAutofill: true,\n\t\tWallet:   &sender,\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif paymentResponse.Meta.TransactionResult != \"tesSUCCESS\" {\n\t\tfmt.Printf(\"Error: Payment failed: %s\\n\", paymentResponse.Meta.TransactionResult)\n\t\tos.Exit(1)\n\t}\n\tfmt.Printf(\"Payment successful!\\n\")\n\tfmt.Printf(\"Explorer link: https://testnet.xrpl.org/transactions/%s\\n\", paymentResponse.Hash.String())\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The MPT issuance in this example uses an ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/es-es/docs/references/protocol/data-types/currency-formats#mpt-precision"},"children":["asset scale"]}," of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["2"]},", so applications shift the displayed amount two decimal places. A ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["value"]}," of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"100\""]}," therefore shows as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["1.00"]}," units of the token."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The example MPT has a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransferFee"]}," of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["0"]},", which means the sender's debit matches the payment value exactly. With a non-zero ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransferFee"]},", the sender would have to pay extra so the receiver gets the full value."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Caution"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the payment fails, it could be for one of the following reasons:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tecNO_AUTH"]},": the issuance does not have ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Can Transfer"]}," enabled, or (with allow-listing) the issuer hasn't approved the holder."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tecPATH_PARTIAL"]},": the sender doesn't have enough of the MPT to cover the payment. This can also occur if the issuance has a non-zero ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransferFee"]}," and the sender doesn't have enough to cover it."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tecLOCKED"]},": the issuance, the sender, or the receiver is locked by the issuer (only possible if the issuance has the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Can Lock"]}," flag enabled)."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"6-verify-updated-balances","__idx":10},"children":["6. Verify updated balances"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Check both accounts' MPT holdings again to confirm the transfer."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/js/sendMPT.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Verify balances ----------------------\nconsole.log(`\\n=== Checking final MPT balances for issuance ${mptIssuanceID}... ===\\n`)\nconst senderBalanceAfter = await getMPTBalance(sender.address, mptIssuanceID)\nconst receiverBalanceAfter = await getMPTBalance(receiver.address, mptIssuanceID)\nconsole.log(`Sender balance:   ${senderBalanceAfter}`)\nconsole.log(`Receiver balance: ${receiverBalanceAfter}`)\n\nawait client.disconnect()\n"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/py/send_mpt.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Verify balances ----------------------\nprint(f\"\\n=== Checking final MPT balances for issuance {mpt_issuance_id}... ===\\n\")\nsender_balance_after = get_mpt_balance(sender.address, mpt_issuance_id)\nreceiver_balance_after = get_mpt_balance(receiver.address, mpt_issuance_id)\nprint(f\"Sender balance:   {sender_balance_after}\")\nprint(f\"Receiver balance: {receiver_balance_after}\")\n"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-an-mpt/go/send-mpt/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Verify balances ----------------------\n\tfmt.Printf(\"\\n=== Checking final MPT balances for issuance %s... ===\\n\\n\", mptIssuanceID)\n\tsenderBalanceAfter, err := getMPTBalance(sender.ClassicAddress, mptIssuanceID)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treceiverBalanceAfter, err := getMPTBalance(receiver.ClassicAddress, mptIssuanceID)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Sender balance:   %s\\n\", senderBalanceAfter)\n\tfmt.Printf(\"Receiver balance: %s\\n\", receiverBalanceAfter)\n}\n"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The sender's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MPTAmount"]}," should have decreased by the value you sent, and the receiver's should match it."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"see-also","__idx":11},"children":["See Also"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Concepts"]},":"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/es-es/docs/concepts/tokens/fungible-tokens/multi-purpose-tokens"},"children":["Multi-Purpose Tokens (MPT)"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Tutorials"]},":"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/es-es/docs/tutorials/tokens/mpts/issue-a-multi-purpose-token"},"children":["Issue a Multi-Purpose Token (MPT)"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["References"]},":"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/transactions/types/mptokenauthorize"},"children":["MPTokenAuthorize transaction"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/transactions/types/payment"},"children":["Payment transaction"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/http-websocket-apis/public-api-methods/ledger-methods/ledger_entry"},"children":["ledger_entry method"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/ledger-data/ledger-entry-types/mptoken"},"children":["MPToken entry"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/ledger-data/ledger-entry-types/mptokenissuance"},"children":["MPTokenIssuance entry"]}]}]}]},"headings":[{"value":"Send a Multi-Purpose Token (MPT)","id":"send-a-multi-purpose-token-mpt","depth":1},{"value":"Goals","id":"goals","depth":2},{"value":"Prerequisites","id":"prerequisites","depth":2},{"value":"Source Code","id":"source-code","depth":2},{"value":"Steps","id":"steps","depth":2},{"value":"1. Install dependencies","id":"1-install-dependencies","depth":3},{"value":"2. Set up client and accounts","id":"2-set-up-client-and-accounts","depth":3},{"value":"3. Authorize the receiving account","id":"3-authorize-the-receiving-account","depth":3},{"value":"4. Check initial balances","id":"4-check-initial-balances","depth":3},{"value":"5. Send the token payment","id":"5-send-the-token-payment","depth":3},{"value":"6. Verify updated balances","id":"6-verify-updated-balances","depth":3},{"value":"See Also","id":"see-also","depth":2}],"frontmatter":{"seo":{"description":"Send a direct payment of a Multi-Purpose Token (MPT) on the XRP Ledger.","title":"Send a Multi-Purpose Token (MPT)"},"metadata":{"indexPage":true},"labels":["Multi-Purpose Token","MPT","Payments"]},"editPage":{"to":"https://github.com/XRPLF/xrpl-dev-portal/tree/master/docs/tutorials/payments/send-an-mpt.md"},"lastModified":"2026-06-12T17:57:27.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/es-es/docs/tutorials/payments/send-an-mpt","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}