> For the complete documentation index, see [llms.txt](https://docs.xrpl-commons.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xrpl-commons.org/xrpl-basics/writing-and-reading-memos.md).

# Writing and reading memos

### Writing a memo

This is how you would include a json object in the memo field of a transaction.

```javascript
// Create the JSON object you want to include in the memo
  const memoData = {
      invoice_id: '12345',
      description: 'Coffee and Milk',
      date: '2024-07-02'
  };

  // Convert JSON object to a string and then to hex
  const memoJson = JSON.stringify(memoData);
  const memoHex = Buffer.from(memoJson, 'utf8').toString('hex');

  // Create the Memo field
  const memo = {
      Memo: {
          MemoData: memoHex
      }
  };

  const tx = {
    TransactionType: "Payment",
    Account: wallet1.classicAddress,
    Destination: wallet2.classicAddress,
    Amount: "1234",
    Memos: [memo]
  };

  const result = await client.submitAndWait(tx, {
    autofill: true,
    wallet: wallet1,
  });
  console.log(result)
```

### Decoding memos

To decode memos from a transaction, we retrieve the memo components and decode the hexadecimal data to a string, and then parse them.

Create this file in your project and import it as needed, when you are processing the transaction data.

{% code title="parseMemo.ts" %}

```javascript
export const parseMemo = (memos) => {
  let report = {};
  if (memos && memos.length > 0) {
    for (const memo of memos) {
      if (memo.Memo.MemoData) {
        // Decode the hexadecimal memo data to a string
        const memoDataHex = memo.Memo.MemoData;
        const memoDataJson = Buffer.from(memoDataHex, "hex").toString("utf8");

        // Parse the JSON string into a JavaScript object
        const memoDataObject = JSON.parse(memoDataJson);

        // console.log('Decoded memo data:', memoDataObject)
        report = { ...report, ...memoDataObject };
      } else {
        console.log("No MemoData found.");
      }
    }
    return report;
  } else {
    console.log("No memos found in the transaction.");
  }
};

export default parseMemo
```

{% endcode %}

### Putting it all together

Here is an example of a fully fledged transaction listener that can parse the memos from the transaction we created above.

{% hint style="info" %}
replace the wallet address with the destination of the original transaction
{% endhint %}

{% code title="index.ts" %}

```javascript
import xrpl from "xrpl";
import { parseMemo } from "./parseMemo";

const serverURL = "wss://s.altnet.rippletest.net:51233"; // For testnet
const walletAddress = "r...";

const main = async () => {
  const client = new xrpl.Client(serverURL);
  await client.connect();

  // do something useful
  const subscriptionRequest = {
    command: "subscribe",
    accounts: [walletAddress],
  };

  await client.request(subscriptionRequest);
  console.log(`Subscribed to transactions for account: ${walletAddress}`);

  // Event listener for incoming transactions
  client.on("transaction", (transaction) => {
    console.log("Transaction:", transaction);
    const parsedMemos = parseMemo(transaction.transaction.Memos);
    console.log("Parsed memo:", parsedMemos);
  });

  // Event listener for errors
  client.on("error", (error) => {
    console.error("Error:", error);
  });

  // end
  // keep open
  console.log("listening...");
};

main()
```

{% endcode %}
