{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-@l10n/ja/sidebars.yaml","index-page-items":"/ja/docs/tutorials/payments/send-a-trust-line-token_index-page-items"},"props":{"metadata":{"markdoc":{"tagList":["repo-link","tabs","tab","code-snippet","admonition"]},"type":"markdown","indexPage":true},"seo":{"title":"Send a Trust Line Token","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/**/*.*"]},{"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/**/*.*"]},{"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 xrpld and Clio servers.","includeFiles":["docs/infrastructure/**/*.*"],"excludeFiles":["docs/infrastructure/index.md","docs/infrastructure/*/index.md","docs/infrastructure/installation/build-run-xrpld-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/**/*.*"]},{"title":"Resources","description":"Developer resources and contribution guidelines.","includeFiles":["resources/**/*.*"]}]},"description":"Send a trust line token from one holder to another on the XRP Ledger."},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"send-a-trust-line-token","__idx":0},"children":["Send a Trust Line Token"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This tutorial shows you how to send a ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/fungible-tokens/trust-line-tokens"},"children":["trust line token"]}," from one holder to another on the XRP Ledger."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each account must create a trust line to the issuer before it can hold the token. Holders can send the token to each other through the issuer only if the issuer allows rippling on both of their trust lines, either on all of its trust lines by enabling the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Default Ripple"]}," flag (recommended), or on individual trust lines. This indirect movement of funds is called ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/fungible-tokens/rippling"},"children":["rippling"]},"."]},{"$$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":["Check that a receiving account can accept a trust line token payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Send a trust line token payment 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-a-trust-line-token/","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":"TabItemFragment","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["From the code sample folder, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["npm"]}," to install dependencies."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"npm install\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["From the code sample 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":"bash","header":{"controls":{"copy":{}}},"source":"python3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["From the code sample folder, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["go"]}," to install dependencies."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"go mod tidy\n","lang":"bash"},"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":"TabItemFragment","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":["bignumber.js"]},": Used to compare token amounts without floating-point rounding."]},{"$$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":["./sendTrustLineTokenSetup.js"]},": The tutorial set up script, imported and called directly."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/js/sendTrustLineToken.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"import xrpl from 'xrpl'\nimport BigNumber from 'bignumber.js'\nimport fs from 'fs'\nimport { setup } from './sendTrustLineTokenSetup.js'\n\n// Set up client ----------------------\nconst client = new xrpl.Client('wss://s.altnet.rippletest.net:51233')\nawait client.connect()"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","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":["decimal"]},": Used to compare token amounts without floating-point rounding."]},{"$$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":["send_trust_line_token_setup"]},": The tutorial set up script, imported and called directly."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/py/send_trust_line_token.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"import json\nimport os\nimport sys\nfrom decimal import ROUND_UP, Context, Decimal\n\nfrom xrpl.clients import JsonRpcClient\nfrom xrpl.models import AccountInfo, AccountLines\nfrom xrpl.models.amounts import IssuedCurrencyAmount\nfrom xrpl.models.transactions import Payment\nfrom xrpl.transaction import submit_and_wait\nfrom xrpl.wallet import Wallet\n\nfrom send_trust_line_token_setup import setup\n\n# Set up client ----------------------\nclient = JsonRpcClient(\"https://s.altnet.rippletest.net:51234\")"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","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, wallet handling, and ledger entry flag constants."]},{"$$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":["math"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["math/big"]},": Used to compare token amounts without floating-point rounding."]},{"$$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 setup script."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/go/send-trust-line-token/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\"math/big\"\n\t\"os\"\n\t\"os/exec\"\n\n\tledger \"github.com/Peersyst/xrpl-go/xrpl/ledger-entry-types\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/queries/account\"\n\taccounttypes \"github.com/Peersyst/xrpl-go/xrpl/queries/account/types\"\n\t\"github.com/Peersyst/xrpl-go/xrpl/queries/common\"\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// decimal parses a token value string into a big.Rat, which is exact. Token\n// values can have up to 16 significant digits, so avoid float64.\nfunc decimal(value string) *big.Rat {\n\tr, ok := new(big.Rat).SetString(value)\n\tif !ok {\n\t\tpanic(\"invalid decimal value: \" + value)\n\t}\n\treturn r\n}\n\n// amountString formats a token amount with at most 16 significant digits, the\n// ledger's precision, rounding up so a SendMax never falls short.\nfunc amountString(x *big.Rat) string {\n\ts := new(big.Float).SetRat(x).Text('g', 16)\n\tif rounded := decimal(s); rounded.Cmp(x) < 0 {\n\t\tf, _ := x.Float64()\n\t\tunit := new(big.Rat).SetFloat64(math.Pow10(int(math.Floor(math.Log10(f))) - 15))\n\t\ts = new(big.Float).SetRat(rounded.Add(rounded, unit)).Text('g', 16)\n\t}\n\treturn s\n}\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)\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, load the sender wallet, and set the token to send and the receiver address. This example uses pre-configured data from the setup script, which funds the sender and buys TST for it on the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/decentralized-exchange"},"children":["Decentralized Exchange (DEX)"]},", but you can replace these with your own values."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/js/sendTrustLineToken.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// This step checks for the necessary setup data to run the tutorial.\n// If missing, sendTrustLineTokenSetup.js will generate it.\nif (!fs.existsSync('sendTrustLineTokenSetup.json')) {\n  console.log(`\\n=== Tutorial setup data doesn't exist. Running setup script... ===\\n`)\n  await setup()\n}\n\n// Load the preconfigured sender account.\nconst setupData = JSON.parse(fs.readFileSync('sendTrustLineTokenSetup.json', 'utf8'))\nconst sender = xrpl.Wallet.fromSeed(setupData.sender.seed)\n\n// The token to send and who to send it to. TST is a test token on Testnet,\n// and the receiver is a well-known account that already holds a TST trust\n// line. You can replace these values with your own.\nconst issuerAddress = 'rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd'\nconst currencyCode = 'TST'\nconst receiverAddress = 'rG6ZCtKCURU58DP2iiff4qziApBGSuvPqE'\nconst sendQuantity = '2'\n\n// The highest transfer fee this script is willing to pay, as a percentage of\n// the amount sent. Protects against approving a large fee by accident.\nconst maxTransferFeePercent = 10\n\nconsole.log(`Issuer address:   ${issuerAddress}`)\nconsole.log(`Sender address:   ${sender.address}`)\nconsole.log(`Receiver address: ${receiverAddress}`)\n\n// getTrustLine returns the trust line between `account` and `peer` for the\n// given currency, or undefined if no such trust line exists.\nasync function getTrustLine(account, currency, peer) {\n  const pages = await client.requestAll({\n    command: 'account_lines',\n    account,\n    peer,\n    ledger_index: 'validated'\n  })\n  return pages.flatMap(page => page.result.lines).find(line => line.currency === currency)\n}"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/py/send_trust_line_token.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# This step checks for the necessary setup data to run the tutorial.\n# If missing, send_trust_line_token_setup.py will generate it.\nif not os.path.exists(\"send_trust_line_token_setup.json\"):\n    print(\"\\n=== Tutorial setup data doesn't exist. Running setup script... ===\\n\")\n    setup()\n\n# Load the preconfigured sender account.\nwith open(\"send_trust_line_token_setup.json\") as f:\n    setup_data = json.load(f)\n\nsender = Wallet.from_seed(setup_data[\"sender\"][\"seed\"])\n\n# The token to send and who to send it to. TST is a test token on Testnet,\n# and the receiver is a well-known account that already holds a TST trust\n# line. You can replace these values with your own.\nissuer_address = \"rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd\"\ncurrency_code = \"TST\"\nreceiver_address = \"rG6ZCtKCURU58DP2iiff4qziApBGSuvPqE\"\nsend_quantity = \"2\"\n\n# The highest transfer fee this script is willing to pay, as a percentage of\n# the amount sent. Protects against approving a large fee by accident.\nmax_transfer_fee_percent = 10\n\n# AccountRoot flags. See https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/accountroot\nLSF_REQUIRE_AUTH = 0x00040000\nLSF_DEFAULT_RIPPLE = 0x00800000\n\nprint(f\"Issuer address:   {issuer_address}\")\nprint(f\"Sender address:   {sender.address}\")\nprint(f\"Receiver address: {receiver_address}\")\n\n\n# get_trust_line returns the trust line between `account` and `peer` for the\n# given currency, or None if no such trust line exists.\ndef get_trust_line(account, currency, peer):\n    marker = None\n    while True:\n        response = client.request(\n            AccountLines(\n                account=account,\n                peer=peer,\n                ledger_index=\"validated\",\n                marker=marker,\n            )\n        )\n        for line in response.result[\"lines\"]:\n            if line[\"currency\"] == currency:\n                return line\n        marker = response.result.get(\"marker\")\n        if marker is None:\n            return None"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/go/send-trust-line-token/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// This step checks for the necessary setup data to run the tutorial.\n\t// If missing, send-trust-line-token-setup will generate it.\n\tif _, err := os.Stat(\"send-trust-line-token-setup.json\"); os.IsNotExist(err) {\n\t\tfmt.Printf(\"\\n=== Tutorial setup data doesn't exist. Running setup script... ===\\n\\n\")\n\t\tcmd := exec.Command(\"go\", \"run\", \"./send-trust-line-token-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 the preconfigured sender account.\n\tdata, err := os.ReadFile(\"send-trust-line-token-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\tsender, err := wallet.FromSecret(setup[\"sender\"].(map[string]any)[\"seed\"].(string))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// The token to send and who to send it to. TST is a test token on Testnet,\n\t// and the receiver is a well-known account that already holds a TST trust\n\t// line. You can replace these values with your own.\n\tconst (\n\t\tissuerAddress   = \"rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd\"\n\t\tcurrencyCode    = \"TST\"\n\t\treceiverAddress = \"rG6ZCtKCURU58DP2iiff4qziApBGSuvPqE\"\n\t\tsendQuantity    = \"2\"\n\n\t\t// The highest transfer fee this command is willing to pay, as a percentage\n\t\t// of the amount sent. Protects against approving a large fee by accident.\n\t\tmaxTransferFeePercent = 10\n\n\t\t// TransferRate is in billionths; this value (or unset) means no fee.\n\t\tnoTransferFee = 1000000000\n\t)\n\n\tfmt.Printf(\"Issuer address:   %s\\n\", issuerAddress)\n\tfmt.Printf(\"Sender address:   %s\\n\", sender.ClassicAddress)\n\tfmt.Printf(\"Receiver address: %s\\n\", receiverAddress)\n\n\t// getTrustLine returns the trust line between `addr` and `peer` for the\n\t// given currency, or nil if no such trust line exists.\n\tgetTrustLine := func(addr, peer types.Address, currency string) *accounttypes.TrustLine {\n\t\treq := &account.LinesRequest{\n\t\t\tAccount:     addr,\n\t\t\tPeer:        peer,\n\t\t\tLedgerIndex: common.Validated,\n\t\t}\n\t\tfor {\n\t\t\tresp, err := client.GetAccountLines(req)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tfor _, line := range resp.Lines {\n\t\t\t\tif line.Currency == currency {\n\t\t\t\t\treturn &line\n\t\t\t\t}\n\t\t\t}\n\t\t\tif resp.Marker == nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treq.Marker = resp.Marker\n\t\t}\n\t}\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["TST is a test token available on Testnet, and the receiver is an account that already holds a TST trust line."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["getTrustLine"]}," helper uses the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines"},"children":["account_lines method"]}," to look up the trust line between an account and the issuer, and the remaining steps use it to read balances. The response is paginated, and an account that owns many ledger entries can return a first page with no matching lines and a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["marker"]},", so the helper follows the markers until it finds the line."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"3-check-the-senders-balance","__idx":7},"children":["3. Check the sender's balance"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before sending the payment, check the sender's balance using the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines"},"children":["account_lines method"]},". The sender should have an initial balance from the setup script, and at least enough to cover the payment plus any ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/fungible-tokens/transfer-fees"},"children":["transfer fee"]}," the issuer charges."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/js/sendTrustLineToken.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Check sender balance ----------------------\n// Confirm the sender holds enough of the token to make the payment, including\n// the issuer's transfer fee, which the sender pays on top of the amount sent.\nconsole.log(`\\n=== Checking sender's ${currencyCode} balance... ===\\n`)\nconst issuerInfo = await client.request({\n  command: 'account_info',\n  account: issuerAddress,\n  ledger_index: 'validated'\n})\n// parseAccountRootFlags turns the Flags bitmask into an object of booleans.\nconst issuerFlags = xrpl.parseAccountRootFlags(issuerInfo.result.account_data.Flags)\n\n// If the issuer charges a transfer fee, the sender pays more than the\n// receiver gets. Work out the SendMax needed and refuse unreasonable fees.\n// TransferRate is a multiplier in billionths, e.g. 1005000000 = 1.005 = 0.5% fee.\nconst transferRate = issuerInfo.result.account_data.TransferRate ?? 1000000000\nconst transferFee = new BigNumber(xrpl.transferRateToDecimal(transferRate))\nconst transferFeePercent = transferFee.times(100)\nif (transferFeePercent.gt(maxTransferFeePercent)) {\n  console.error(`Error: Transfer fee of ${transferFeePercent}% exceeds the ${maxTransferFeePercent}% limit.`)\n  await client.disconnect()\n  process.exit(1)\n}\nlet sendMax\nif (transferFeePercent.gt(0)) {\n  // Token amounts have at most 16 significant digits. Round up so SendMax\n  // never falls short of the exact cost.\n  sendMax = new BigNumber(sendQuantity).times(transferFee.plus(1)).precision(16, BigNumber.ROUND_UP).toString()\n  console.log(`✓ Transfer fee is ${transferFeePercent}%; sender will pay up to ${sendMax} ${currencyCode}`)\n} else {\n  console.log('✓ No transfer fee')\n}\n\nconst senderLine = await getTrustLine(sender.address, currencyCode, issuerAddress)\nif (!senderLine) {\n  console.error(`Error: Sender has no ${currencyCode} trust line with the issuer.`)\n  await client.disconnect()\n  process.exit(1)\n}\nconsole.log(`Sender's balance: ${senderLine.balance}`)\nif (new BigNumber(senderLine.balance).lt(sendMax ?? sendQuantity)) {\n  console.error(`Error: Sender's balance is less than the ${sendMax ?? sendQuantity} ${currencyCode} to send.`)\n  await client.disconnect()\n  process.exit(1)\n}"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/py/send_trust_line_token.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Check sender balance ----------------------\n# Confirm the sender holds enough of the token to make the payment, including\n# the issuer's transfer fee, which the sender pays on top of the amount sent.\nprint(f\"\\n=== Checking sender's {currency_code} balance... ===\\n\")\nissuer_info = client.request(\n    AccountInfo(account=issuer_address, ledger_index=\"validated\")\n)\nissuer_flags = issuer_info.result[\"account_data\"][\"Flags\"]\n\n# If the issuer charges a transfer fee, the sender pays more than the\n# receiver gets. Work out the SendMax needed and refuse unreasonable fees.\n# TransferRate is a multiplier in billionths, e.g. 1005000000 = 1.005 = 0.5% fee.\ntransfer_rate = issuer_info.result[\"account_data\"].get(\"TransferRate\", 1000000000)\ntransfer_fee_percent = Decimal(transfer_rate - 1000000000) / Decimal(10000000)\nif transfer_fee_percent > max_transfer_fee_percent:\n    print(f\"Error: Transfer fee of {transfer_fee_percent}% exceeds the {max_transfer_fee_percent}% limit.\")\n    sys.exit(1)\nsend_max = None\nif transfer_fee_percent > 0:\n    # Token amounts have at most 16 significant digits. Round up so SendMax\n    # never falls short of the exact cost.\n    send_max = str(Context(prec=16, rounding=ROUND_UP).divide(Decimal(send_quantity) * Decimal(transfer_rate), Decimal(1000000000)))\n    print(f\"✓ Transfer fee is {transfer_fee_percent}%; sender will pay up to {send_max} {currency_code}\")\nelse:\n    print(\"✓ No transfer fee\")\n\nsender_line = get_trust_line(sender.address, currency_code, issuer_address)\nif sender_line is None:\n    print(f\"Error: Sender has no {currency_code} trust line with the issuer.\")\n    sys.exit(1)\nprint(f\"Sender's balance: {sender_line['balance']}\")\nif Decimal(sender_line[\"balance\"]) < Decimal(send_max or send_quantity):\n    print(f\"Error: Sender's balance is less than the {send_max or send_quantity} {currency_code} to send.\")\n    sys.exit(1)"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/go/send-trust-line-token/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Check sender balance ----------------------\n\t// Confirm the sender holds enough of the token to make the payment, including\n\t// the issuer's transfer fee, which the sender pays on top of the amount sent.\n\tfmt.Printf(\"\\n=== Checking sender's %s balance... ===\\n\\n\", currencyCode)\n\tissuerInfo, err := client.GetAccountInfo(&account.InfoRequest{\n\t\tAccount:     issuerAddress,\n\t\tLedgerIndex: common.Validated,\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tissuerFlags := issuerInfo.AccountData.Flags\n\n\t// If the issuer charges a transfer fee, the sender pays more than the\n\t// receiver gets. Work out the SendMax needed and refuse unreasonable fees.\n\t// TransferRate is a multiplier in billionths, e.g. 1005000000 = 1.005 = 0.5% fee.\n\ttransferRate := issuerInfo.AccountData.TransferRate\n\tif transferRate == 0 {\n\t\ttransferRate = noTransferFee\n\t}\n\ttransferFeePercent := float64(transferRate-noTransferFee) / 10000000\n\tif transferFeePercent > maxTransferFeePercent {\n\t\tfmt.Printf(\"Error: Transfer fee of %g%% exceeds the %d%% limit.\\n\", transferFeePercent, maxTransferFeePercent)\n\t\tos.Exit(1)\n\t}\n\tsendMax := \"\"\n\tif transferFeePercent > 0 {\n\t\trate := new(big.Rat).SetFrac64(int64(transferRate), noTransferFee)\n\t\tsendMax = amountString(new(big.Rat).Mul(decimal(sendQuantity), rate))\n\t\tfmt.Printf(\"✓ Transfer fee is %g%%; sender will pay up to %s %s\\n\", transferFeePercent, sendMax, currencyCode)\n\t} else {\n\t\tfmt.Println(\"✓ No transfer fee\")\n\t}\n\tneeded := sendQuantity\n\tif sendMax != \"\" {\n\t\tneeded = sendMax\n\t}\n\n\tsenderLine := getTrustLine(sender.ClassicAddress, issuerAddress, currencyCode)\n\tif senderLine == nil {\n\t\tfmt.Printf(\"Error: Sender has no %s trust line with the issuer.\\n\", currencyCode)\n\t\tos.Exit(1)\n\t}\n\tfmt.Printf(\"Sender's balance: %s\\n\", senderLine.Balance)\n\tif decimal(senderLine.Balance).Cmp(decimal(needed)) < 0 {\n\t\tfmt.Printf(\"Error: Sender's balance is less than the %s %s to send.\\n\", needed, currencyCode)\n\t\tos.Exit(1)\n\t}\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A trust line is a bidirectional relationship with a single, shared balance that is positive from one account's perspective and negative from the other's. Querying ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account_lines"]}," on a holder with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["peer"]}," set to the issuer returns the positive value."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"4-check-that-the-receiver-can-receive-the-payment","__idx":8},"children":["4. Check that the receiver can receive the payment"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A payment between two holders can fail for reasons that have nothing to do with the sender. Check the receiver's trust line and the issuer's settings before submitting, so you can tell the user why a payment can't go through instead of letting it fail on the ledger."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["First, request the receiver's trust line with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account_lines"]},"."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/js/sendTrustLineToken.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Check receiver ----------------------\n// Confirm the receiver can accept the payment before sending it.\nconsole.log(`\\n=== Checking receiver can receive ${currencyCode}... ===\\n`)\nconst receiverLine = await getTrustLine(receiverAddress, currencyCode, issuerAddress)"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/py/send_trust_line_token.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Check receiver ----------------------\n# Confirm the receiver can accept the payment before sending it.\nprint(f\"\\n=== Checking receiver can receive {currency_code}... ===\\n\")\nreceiver_line = get_trust_line(receiver_address, currency_code, issuer_address)"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/go/send-trust-line-token/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Check receiver ----------------------\n\t// Confirm the receiver can accept the payment before sending it.\n\tfmt.Printf(\"\\n=== Checking receiver can receive %s... ===\\n\\n\", currencyCode)\n\treceiverLine := getTrustLine(receiverAddress, issuerAddress, currencyCode)\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Then, run the following checks:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/js/sendTrustLineToken.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// 1. The receiver must have a trust line to the issuer for this currency.\nif (!receiverLine) {\n  console.error(`Error: Receiver has no ${currencyCode} trust line with the issuer.`)\n  await client.disconnect()\n  process.exit(1)\n}\nconsole.log('✓ Receiver has a trust line to the issuer')\n\n// 2. The issuer must allow rippling on at least one of the two trust lines, since\n//    a payment between holders moves through the issuer. Default Ripple on the\n//    issuer is the usual way to allow this, but check the lines themselves.\nif (senderLine.no_ripple_peer && receiverLine.no_ripple_peer) {\n  console.error('Error: The issuer has disabled rippling on both the sender and receiver trust lines.')\n  await client.disconnect()\n  process.exit(1)\n}\nconst defaultRipple = issuerFlags.lsfDefaultRipple === true\nconsole.log(`✓ Rippling is allowed (issuer Default Ripple: ${defaultRipple})`)\n\n// 3. The receiver's limit must cover their current balance plus the payment.\nif (new BigNumber(receiverLine.balance).plus(sendQuantity).gt(receiverLine.limit)) {\n  console.error(`Error: Payment would exceed the receiver's limit of ${receiverLine.limit} ${currencyCode}.`)\n  await client.disconnect()\n  process.exit(1)\n}\nconsole.log(`✓ Receiver's limit covers the payment`)\n\n// 4. If the issuer requires authorization, the receiver's line must be authorized.\nconst requireAuth = issuerFlags.lsfRequireAuth === true\nif (requireAuth && !receiverLine.peer_authorized) {\n  console.error('Error: The issuer requires authorization and has not authorized the receiver.')\n  await client.disconnect()\n  process.exit(1)\n}\nconsole.log(`✓ Authorization OK (issuer Require Auth: ${requireAuth})`)\n\nconsole.log(`\\nBalances before payment:`)\nconsole.log(`  Sender:   ${senderLine.balance} ${currencyCode}`)\nconsole.log(`  Receiver: ${receiverLine.balance} ${currencyCode}`)"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/py/send_trust_line_token.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# 1. The receiver must have a trust line to the issuer for this currency.\nif receiver_line is None:\n    print(f\"Error: Receiver has no {currency_code} trust line with the issuer.\")\n    sys.exit(1)\nprint(\"✓ Receiver has a trust line to the issuer\")\n\n# 2. The issuer must allow rippling on at least one of the two trust lines, since\n#    a payment between holders moves through the issuer. Default Ripple on the\n#    issuer is the usual way to allow this, but check the lines themselves.\nif sender_line.get(\"no_ripple_peer\") and receiver_line.get(\"no_ripple_peer\"):\n    print(\"Error: The issuer has disabled rippling on both the sender and receiver trust lines.\")\n    sys.exit(1)\ndefault_ripple = bool(issuer_flags & LSF_DEFAULT_RIPPLE)\nprint(f\"✓ Rippling is allowed (issuer Default Ripple: {default_ripple})\")\n\n# 3. The receiver's limit must cover their current balance plus the payment.\nif Decimal(receiver_line[\"balance\"]) + Decimal(send_quantity) > Decimal(receiver_line[\"limit\"]):\n    print(f\"Error: Payment would exceed the receiver's limit of {receiver_line['limit']} {currency_code}.\")\n    sys.exit(1)\nprint(\"✓ Receiver's limit covers the payment\")\n\n# 4. If the issuer requires authorization, the receiver's line must be authorized.\nrequire_auth = bool(issuer_flags & LSF_REQUIRE_AUTH)\nif require_auth and not receiver_line.get(\"peer_authorized\"):\n    print(\"Error: The issuer requires authorization and has not authorized the receiver.\")\n    sys.exit(1)\nprint(f\"✓ Authorization OK (issuer Require Auth: {require_auth})\")\n\nprint(\"\\nBalances before payment:\")\nprint(f\"  Sender:   {sender_line['balance']} {currency_code}\")\nprint(f\"  Receiver: {receiver_line['balance']} {currency_code}\")"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/go/send-trust-line-token/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// 1. The receiver must have a trust line to the issuer for this currency.\n\tif receiverLine == nil {\n\t\tfmt.Printf(\"Error: Receiver has no %s trust line with the issuer.\\n\", currencyCode)\n\t\tos.Exit(1)\n\t}\n\tfmt.Println(\"✓ Receiver has a trust line to the issuer\")\n\n\t// 2. The issuer must allow rippling on at least one of the two trust lines, since\n\t//    a payment between holders moves through the issuer. Default Ripple on the\n\t//    issuer is the usual way to allow this, but check the lines themselves.\n\tif senderLine.NoRipplePeer && receiverLine.NoRipplePeer {\n\t\tfmt.Println(\"Error: The issuer has disabled rippling on both the sender and receiver trust lines.\")\n\t\tos.Exit(1)\n\t}\n\tdefaultRipple := issuerFlags&ledger.LsfDefaultRipple != 0\n\tfmt.Printf(\"✓ Rippling is allowed (issuer Default Ripple: %t)\\n\", defaultRipple)\n\n\t// 3. The receiver's limit must cover their current balance plus the payment.\n\tnewBalance := new(big.Rat).Add(decimal(receiverLine.Balance), decimal(sendQuantity))\n\tif newBalance.Cmp(decimal(receiverLine.Limit)) > 0 {\n\t\tfmt.Printf(\"Error: Payment would exceed the receiver's limit of %s %s.\\n\", receiverLine.Limit, currencyCode)\n\t\tos.Exit(1)\n\t}\n\tfmt.Println(\"✓ Receiver's limit covers the payment\")\n\n\t// 4. If the issuer requires authorization, the receiver's line must be authorized.\n\trequireAuth := issuerFlags&ledger.LsfRequireAuth != 0\n\tif requireAuth && !receiverLine.PeerAuthorized {\n\t\tfmt.Println(\"Error: The issuer requires authorization and has not authorized the receiver.\")\n\t\tos.Exit(1)\n\t}\n\tfmt.Printf(\"✓ Authorization OK (issuer Require Auth: %t)\\n\", requireAuth)\n\n\tfmt.Println(\"\\nBalances before payment:\")\n\tfmt.Printf(\"  Sender:   %s %s\\n\", senderLine.Balance, currencyCode)\n\tfmt.Printf(\"  Receiver: %s %s\\n\", receiverLine.Balance, currencyCode)\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Trust line exists"]},": The receiver has a trust line to the issuer for this currency."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Rippling is allowed"]},": The issuer hasn't set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["no_ripple_peer"]}," on ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["both"]}," the sender's and receiver's lines."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Limit covers the payment"]},": The receiver's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["limit"]}," is at least their ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["balance"]}," plus the amount."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Authorization"]},": If the issuer requires auth, the receiver's line has ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["peer_authorized"]}," set."]}]},{"$$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":["Once the checks pass, the sender can send the token to the receiver with a ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/transactions/types/payment"},"children":["Payment transaction"]},". Provide the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/references/protocol/data-types/currency-formats#token-amounts"},"children":["issued currency amount"]}," object that specifies the currency code, the issuer's address, and the value to send."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/js/sendTrustLineToken.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Send payment ----------------------\n// The sender pays the receiver with the token. Amount is what the receiver\n// gets; SendMax (if set) is the most the sender is willing to spend.\nconsole.log(`\\n=== Sending ${sendQuantity} ${currencyCode} to receiver... ===\\n`)\nconst paymentTx = {\n  TransactionType: 'Payment',\n  Account: sender.address,\n  Destination: receiverAddress,\n  Amount: {\n    currency: currencyCode,\n    issuer: issuerAddress,\n    value: sendQuantity\n  }\n}\nif (sendMax) {\n  paymentTx.SendMax = {\n    currency: currencyCode,\n    issuer: issuerAddress,\n    value: sendMax\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 resultCode = paymentResponse.result.meta?.TransactionResult\n  console.error('Error: Unable to send token:', resultCode)\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":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/py/send_trust_line_token.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Send payment ----------------------\n# The sender pays the receiver with the token. Amount is what the receiver\n# gets; SendMax (if set) is the most the sender is willing to spend.\nprint(f\"\\n=== Sending {send_quantity} {currency_code} to receiver... ===\\n\")\npayment_tx = Payment(\n    account=sender.address,\n    destination=receiver_address,\n    amount=IssuedCurrencyAmount(\n        currency=currency_code,\n        issuer=issuer_address,\n        value=send_quantity,\n    ),\n    send_max=(\n        IssuedCurrencyAmount(\n            currency=currency_code,\n            issuer=issuer_address,\n            value=send_max,\n        )\n        if send_max\n        else None\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    result_code = payment_response.result[\"meta\"][\"TransactionResult\"]\n    print(f\"Error: Unable to send token: {result_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":"TabItemFragment","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/go/send-trust-line-token/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Send payment ----------------------\n\t// The sender pays the receiver with the token. Amount is what the receiver\n\t// gets; SendMax (if set) is the most the sender is willing to spend.\n\tfmt.Printf(\"\\n=== Sending %s %s to receiver... ===\\n\\n\", sendQuantity, currencyCode)\n\tpaymentTx := transaction.Payment{\n\t\tBaseTx:      transaction.BaseTx{Account: sender.ClassicAddress},\n\t\tDestination: receiverAddress,\n\t\tAmount: types.IssuedCurrencyAmount{\n\t\t\tCurrency: currencyCode,\n\t\t\tIssuer:   issuerAddress,\n\t\t\tValue:    sendQuantity,\n\t\t},\n\t}\n\tif sendMax != \"\" {\n\t\tpaymentTx.SendMax = types.IssuedCurrencyAmount{\n\t\t\tCurrency: currencyCode,\n\t\t\tIssuer:   issuerAddress,\n\t\t\tValue:    sendMax,\n\t\t}\n\t}\n\n\t// Flatten() converts the struct to a map and adds the TransactionType field\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: Unable to send token: %s\\n\", paymentResponse.Meta.TransactionResult)\n\t\tos.Exit(1)\n\t}\n\tfmt.Println(\"Payment successful!\")\n\tfmt.Printf(\"Explorer link: https://testnet.xrpl.org/transactions/%s\\n\", paymentResponse.Hash)\n\n\t"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The TST issuer doesn't charge a transfer fee, so the sender's balance decreases by the same amount the receiver gains. If you replace the issuer with one that has a non-zero ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransferRate"]},", the sender's balance decreases by more than the receiver gains. The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SendMax"]}," field set in step 3 covers the difference."]},{"$$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":["tecPATH_PARTIAL"]},": the sender doesn't have enough balance to cover the payment. This can also occur if the issuer has configured a non-zero ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransferRate"]}," and the sender doesn't have enough to cover the payment plus the transfer fee."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tecPATH_DRY"]},": no path could deliver any amount at all. This commonly happens when the receiver has no trust line for the token, the issuer doesn't allow rippling, or the receiver's trust line isn't authorized."]}]}]},{"$$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 the account balances again to confirm the transfer."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"JavaScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/js/sendTrustLineToken.js","language":"js","header":{"controls":{"copy":{}}},"lang":"js","source":"// Verify balances ----------------------\n// Check both balances again to confirm the transfer.\nconsole.log(`\\n=== Checking final ${currencyCode} balances... ===\\n`)\n\n// The metadata's delivered_amount is the amount the receiver actually got.\n// Always read this field rather than the transaction's Amount, because a\n// partial payment can succeed while delivering less than Amount.\nconst deliveredAmount = paymentResponse.result.meta.delivered_amount\nconsole.log(`  Delivered amount: ${deliveredAmount.value} ${deliveredAmount.currency}`)\n\nconst senderLineAfter = await getTrustLine(sender.address, currencyCode, issuerAddress)\nconst receiverLineAfter = await getTrustLine(receiverAddress, currencyCode, issuerAddress)\nconsole.log(`  Sender:   ${senderLineAfter.balance} ${currencyCode}`)\nconsole.log(`  Receiver: ${receiverLineAfter.balance} ${currencyCode}`)\n\nawait client.disconnect()\n"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/py/send_trust_line_token.py","language":"py","header":{"controls":{"copy":{}}},"lang":"py","source":"# Verify balances ----------------------\n# Check both balances again to confirm the transfer.\nprint(f\"\\n=== Checking final {currency_code} balances... ===\\n\")\n\n# The metadata's delivered_amount is the amount the receiver actually got.\n# Always read this field rather than the transaction's Amount, because a\n# partial payment can succeed while delivering less than Amount.\ndelivered_amount = payment_response.result[\"meta\"][\"delivered_amount\"]\nprint(f\"  Delivered amount: {delivered_amount['value']} {delivered_amount['currency']}\")\n\nsender_line_after = get_trust_line(sender.address, currency_code, issuer_address)\nreceiver_line_after = get_trust_line(receiver_address, currency_code, issuer_address)\nprint(f\"  Sender:   {sender_line_after['balance']} {currency_code}\")\nprint(f\"  Receiver: {receiver_line_after['balance']} {currency_code}\")\n"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Go","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"file":"/_code-samples/send-a-trust-line-token/go/send-trust-line-token/main.go","language":"go","header":{"controls":{"copy":{}}},"lang":"go","source":"\t// Verify balances ----------------------\n\t// Check both balances again to confirm the transfer.\n\tfmt.Printf(\"\\n=== Checking final %s balances... ===\\n\\n\", currencyCode)\n\n\t// The metadata's delivered_amount is the amount the receiver actually got.\n\t// Always read this field rather than the transaction's Amount, because a\n\t// partial payment can succeed while delivering less than Amount.\n\tdeliveredAmount := paymentResponse.Meta.DeliveredAmount.(map[string]any)\n\tfmt.Printf(\"  Delivered amount: %s %s\\n\", deliveredAmount[\"value\"], deliveredAmount[\"currency\"])\n\n\tsenderLineAfter := getTrustLine(sender.ClassicAddress, issuerAddress, currencyCode)\n\treceiverLineAfter := getTrustLine(receiverAddress, issuerAddress, currencyCode)\n\tfmt.Printf(\"  Sender:   %s %s\\n\", senderLineAfter.Balance, currencyCode)\n\tfmt.Printf(\"  Receiver: %s %s\\n\", receiverLineAfter.Balance, currencyCode)\n}\n"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The code first prints the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["delivered amount"]}," from the transaction metadata, which is the amount the receiver actually got. Always read this field when processing incoming payments, because a ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/payment-types/partial-payments"},"children":["partial payment"]}," can return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tesSUCCESS"]}," while delivering less than ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Amount"]},"."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Note"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If either trust line has a non-default ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/fungible-tokens/trust-line-tokens#trust-line-settings"},"children":["Quality setting"]},", that can also affect the amounts each side sees."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The sender's balance should have decreased by the amount sent plus the transfer fee, while the receiver's balance should have increased by only the delivered amount."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"see-also","__idx":11},"children":["See Also"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","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":"/ja/docs/concepts/tokens/fungible-tokens/trust-line-tokens"},"children":["Trust Line Tokens"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/fungible-tokens/rippling"},"children":["Rippling"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/fungible-tokens/authorized-trust-lines"},"children":["Authorized Trust Lines"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/concepts/tokens/fungible-tokens/transfer-fees"},"children":["Transfer Fees"]}]}]}]},{"$$mdtype":"Tag","name":"li","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":"/ja/docs/tutorials/tokens/fungible-tokens/issue-a-fungible-token"},"children":["Issue a Fungible Token"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/ja/docs/tutorials/defi/dex/trade-in-the-decentralized-exchange"},"children":["Trade in the Decentralized Exchange"]}]}]}]},{"$$mdtype":"Tag","name":"li","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/payment"},"children":["Payment transaction"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/transactions/types/trustset"},"children":["TrustSet transaction"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines"},"children":["account_lines method"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/http-websocket-apis/public-api-methods/account-methods/account_info"},"children":["account_info method"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/ledger-data/ledger-entry-types/ripplestate"},"children":["RippleState entry"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/references/protocol/ledger-data/ledger-entry-types/accountroot"},"children":["AccountRoot entry"]}]}]}]}]}]},"headings":[{"value":"Send a Trust Line Token","id":"send-a-trust-line-token","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. Check the sender's balance","id":"3-check-the-senders-balance","depth":3},{"value":"4. Check that the receiver can receive the payment","id":"4-check-that-the-receiver-can-receive-the-payment","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 trust line token from one holder to another on the XRP Ledger.","title":"Send a Trust Line Token"},"metadata":{"indexPage":true},"labels":["Tokens","Payments"]},"editPage":{"to":"https://github.com/XRPLF/xrpl-dev-portal/tree/master/docs/tutorials/payments/send-a-trust-line-token.md"},"lastModified":"2026-10-22T10:21:54.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/ja/docs/tutorials/payments/send-a-trust-line-token","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}