diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 15f7f95cd0c29ac6fc2f116830135a316c305f7c..21b0e19ebb1f50b646783b19435bb822ee78e1fe 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -360,6 +360,7 @@ set(viewer_SOURCE_FILES
     llfloatertopobjects.cpp
     llfloatertos.cpp
     llfloatertoybox.cpp
+    llfloatertransactionlog.cpp
     llfloatertranslationsettings.cpp
     llfloateruipreview.cpp
     llfloaterurlentry.cpp
@@ -1092,6 +1093,7 @@ set(viewer_HEADER_FILES
     llfloatertopobjects.h
     llfloatertos.h
     llfloatertoybox.h
+    llfloatertransactionlog.h
     llfloatertranslationsettings.h
     llfloateruipreview.h
     llfloaterurlentry.h
diff --git a/indra/newview/llfloatertransactionlog.cpp b/indra/newview/llfloatertransactionlog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..161f6bc4f6a32c3853b88c781429f7c93c05b444
--- /dev/null
+++ b/indra/newview/llfloatertransactionlog.cpp
@@ -0,0 +1,128 @@
+/*
+ * @file llfloatertransactionlog.h
+ * @brief Transaction log floater
+ *
+ * (C) 2014 Cinder Roxley @ Second Life <cinder@sdf.org>
+ * (C) 2024 Improvements by Fallen Kiyori Shadow
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloatertransactionlog.h"
+
+#include "llavataractions.h"
+#include "llavatarnamecache.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "lltextbase.h"
+
+LLFloaterTransactionLog::LLFloaterTransactionLog(const LLSD& key) :
+    LLFloater(key),
+    mList(nullptr),
+    mTotalReceivedText(nullptr),
+    mTotalSpentText(nullptr),
+    mReceivedTotal(0),
+    mSpentTotal(0),
+    mAvatarNameCacheConnection()
+{
+    mCommitCallbackRegistrar.add("TL.Reset", boost::bind(&LLFloaterTransactionLog::reset, this));
+}
+
+LLFloaterTransactionLog::~LLFloaterTransactionLog()
+{
+    if (mAvatarNameCacheConnection.connected())
+        mAvatarNameCacheConnection.disconnect();
+}
+
+BOOL LLFloaterTransactionLog::postBuild()
+{
+    mList = getChild<LLScrollListCtrl>("transaction_list");
+    mList->setDoubleClickCallback(boost::bind(&LLFloaterTransactionLog::onDoubleClick, this));
+    mTotalReceivedText = getChild<LLTextBase>("total_received");
+    mTotalSpentText    = getChild<LLTextBase>("total_spent");
+    return TRUE;
+}
+
+void LLFloaterTransactionLog::addTransaction(const LLDate& date, const LLUUID& sender, S32 amount, bool incoming)
+{
+    // drop it
+    if (!getVisible())
+        return;
+
+    if (incoming)
+    {
+        mReceivedTotal += amount;
+    }
+    else
+    {
+        mSpentTotal += amount;
+    }
+
+    updateLabels();
+
+    LLSD row;
+    row["value"]               = sender;
+    row["column"][0]["column"] = "time";
+    row["column"][0]["value"]  = date.toHTTPDateString(LLStringExplicit("%H:%M:%S"));
+    row["column"][2]["column"] = "amount";
+    row["column"][2]["value"]  = llformat("L$%d", (incoming ? amount : -amount));
+    row["column"][2]["halign"] = LLFontGL::RIGHT;
+
+    mAvatarNameCacheConnection =
+        LLAvatarNameCache::get(sender, boost::bind(&LLFloaterTransactionLog::onAvatarNameCache, this, _1, _2, row));
+}
+
+void LLFloaterTransactionLog::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, LLSD& row)
+{
+    row["column"][1]["column"] = "name";
+    row["column"][1]["value"]  = av_name.getDisplayName();
+    mList->addElement(row);
+}
+
+void LLFloaterTransactionLog::onDoubleClick()
+{
+    const LLUUID& id = mList->getFirstSelected()->getValue().asUUID();
+    LLAvatarActions::showProfile(id);
+}
+
+void LLFloaterTransactionLog::reset()
+{
+    mList->deleteAllItems();
+    mReceivedTotal = 0;
+    mSpentTotal    = 0;
+
+    updateLabels();
+}
+
+void LLFloaterTransactionLog::updateLabels()
+{
+    LLStringUtil::format_map_t receivedArgs;
+    LLStringUtil::format_map_t spentArgs;
+
+    receivedArgs["TOTAL"] = std::to_string(mReceivedTotal);
+    spentArgs["TOTAL"]    = std::to_string(mSpentTotal);
+
+    mTotalReceivedText->setValue(getString("total_received_fmt", receivedArgs));
+    mTotalSpentText->setValue(getString("total_spent_fmt", spentArgs));
+}
diff --git a/indra/newview/llfloatertransactionlog.h b/indra/newview/llfloatertransactionlog.h
new file mode 100644
index 0000000000000000000000000000000000000000..a28ae9314354ec596aaa27d7582c327432fd1c00
--- /dev/null
+++ b/indra/newview/llfloatertransactionlog.h
@@ -0,0 +1,63 @@
+/*
+ * @file llfloatertransactionlog.h
+ * @brief Transaction log floater
+ *
+ * (C) 2014 Cinder Roxley @ Second Life <cinder@sdf.org>
+ * (C) 2024 Improvements by Fallen Kiyori Shadow
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LL_FLOATERTRANSACTIONLOG_H
+#define LL_FLOATERTRANSACTIONLOG_H
+
+#include "llfloater.h"
+
+class LLAvatarName;
+class LLScrollListCtrl;
+class LLTextBase;
+
+class LLFloaterTransactionLog : public LLFloater
+{
+  public:
+    LLFloaterTransactionLog(const LLSD& key);
+    BOOL postBuild();
+    void addTransaction(const LLDate& date, const LLUUID& sender, S32 amount, bool incoming);
+
+  private:
+    ~LLFloaterTransactionLog();
+    void reset();
+    void onDoubleClick();
+    void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, LLSD& row);
+    void updateLabels();
+
+    LLScrollListCtrl* mList;
+    LLTextBase*       mTotalReceivedText;
+    LLTextBase*       mTotalSpentText;
+    S32               mReceivedTotal;
+    S32               mSpentTotal;
+
+    boost::signals2::connection mAvatarNameCacheConnection;
+};
+
+#endif  // LL_FLOATERTRANSACTIONLOG_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index cb90770a5f80b189d76ac7be68cafff5f5821c34..a3d70aa4ffe01495ecf1c8a30b82e3cf2c9b46c0 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -172,6 +172,7 @@
 #include "llfloatertopobjects.h"
 #include "llfloatertos.h"
 #include "llfloatertoybox.h"
+#include "llfloatertransactionlog.h"
 #include "llfloatertranslationsettings.h"
 #include "llfloateruipreview.h"
 #include "llfloatervoiceeffect.h"
@@ -514,6 +515,7 @@ void LLViewerFloaterReg::registerFloaters()
     LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", &LLFloaterReg::build<LLFloater>);
     LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTopObjects>);
     LLFloaterReg::add("toybox", "floater_toybox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterToybox>);
+    LLFloaterReg::add("transaction_log", "floater_transaction_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTransactionLog>);
 
     LLFloaterReg::add("reporter", "floater_report_abuse.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterReporter>);
     LLFloaterReg::add("reset_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterResetQueue>);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 18f31b09062cebd62b15fe48d0fa4f85d5f160c1..1d0be72db65a3e948baf4c4cc97e2a14bce50777 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -67,6 +67,7 @@
 #include "llfloaterpreference.h"
 #include "llfloatersidepanelcontainer.h"
 #include "llfloatersnapshot.h"
+#include "llfloatertransactionlog.h"
 #include "llhudeffecttrail.h"
 #include "llhudmanager.h"
 #include "llimprocessing.h"
@@ -5304,6 +5305,13 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
         notification = "PaymentReceived";
     }
 
+    LLFloaterTransactionLog* floater = LLFloaterReg::findTypedInstance<LLFloaterTransactionLog>("transaction_log");
+    // only log the successful transactions --FLN
+    if (success && floater)
+    {
+        floater->addTransaction(LLDate::now(), source_id, amount, !you_paid_someone);
+    }
+
     // Despite using SLURLs, wait until the name is available before
     // showing the notification, otherwise the UI layout is strange and
     // the user sees a "Loading..." message
diff --git a/indra/newview/skins/default/xui/en/floater_transaction_log.xml b/indra/newview/skins/default/xui/en/floater_transaction_log.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e5a0ea3c868e49369b4589db977fd5511b6f5c05
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_transaction_log.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_close="true"
+ can_drag_on_left="false"
+ can_minimize="true"
+ can_resize="true"
+ height="500"
+ width="350"
+ min_width="450"
+ min_height="200"
+ name="floater_transaction_log"
+ title="Transaction Log"
+ single_instance="true"
+ save_rect="true">
+ <floater.string
+   name="total_received_fmt">
+    Received: L$ [TOTAL]
+  </floater.string>
+ <floater.string
+   name="total_spent_fmt">
+    Spent: L$ -[TOTAL]
+  </floater.string>
+  <scroll_list
+   draw_heading="true"
+   follows="left|top|bottom|right"
+   name="transaction_list"
+   background_visible="true"
+   fg_unselected_color="ScrollSelectedFGColor"
+   fg_selected_color="ScrollSelectedFGColor"
+   column_padding="0"
+   top="0"
+   left="4"
+   right="-4"
+   bottom="-50">
+    <column name="time" width="50" label="Time" />
+    <column name="name" dynamicwidth="true" label="Name" />
+    <column name="amount" width="70" label="Amount" />
+  </scroll_list>
+    <text
+   type="string"
+   length="1"
+   follows="left|bottom"
+   font="SansSerif"
+   height="20"
+   layout="topleft"
+   name="total_received"
+   left="15" 
+   value="Received: L$ 0"/>
+    <text
+   type="string"
+   length="1"
+   follows="left|bottom"
+   font="SansSerif"
+   height="20"
+   layout="topleft"
+   name="total_spent"
+   left="15" 
+   value="Spent: L$ -0"/>
+  <button
+    label="Reset"
+    top_pad="-35"
+    name="btn_reset"
+    font="SansSerif"
+    mouse_opaque="true"
+    height="20"
+    width="75"
+    left_pad="-80"
+    follows="right|bottom">
+     <button.commit_callback
+     function="TL.Reset" />
+   </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 4ca62fc7928472fe04cd4cf123ed7ac420550e9f..66920d6c4d00ec534c56e0058eab9fcd6d6561b8 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -123,6 +123,16 @@
             <menu_item_call.on_click
             function="Avatar.OpenMarketplace"  />
         </menu_item_call>
+        <menu_item_check
+         label="Transaction Log..."
+         name="transaction_log">
+            <menu_item_check.on_check
+             function="Floater.Visible"
+             parameter="transaction_log" />
+            <menu_item_check.on_click
+             function="Floater.Toggle"
+             parameter="transaction_log" />
+        </menu_item_check>
         <menu_item_call
             label="Marketplace listings..."
             name="MarketplaceListings">