diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py
index 4b3c3b4..6cb1a69 100644
--- a/basicswap/basicswap.py
+++ b/basicswap/basicswap.py
@@ -3949,6 +3949,9 @@ class BasicSwap(BaseApp):
                     xmr_swap.a_lock_spend_tx = bytes.fromhex(spend_txn_hex)
                     bid.setState(BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED)  # TODO: Wait for confirmation?
 
+                    if bid.xmr_a_lock_tx:
+                        bid.xmr_a_lock_tx.setState(TxStates.TX_REDEEMED)
+
                     if not was_received:
                         bid.setState(BidStates.SWAP_COMPLETED)
                 else:
@@ -3996,6 +3999,8 @@ class BasicSwap(BaseApp):
             if spending_txid == xmr_swap.a_lock_refund_spend_tx_id:
                 self.log.info('Found coin a lock refund spend tx, bid {}'.format(bid_id.hex()))
                 self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_A_REFUND_SPEND_TX_SEEN, '', session)
+                if bid.xmr_a_lock_tx:
+                    bid.xmr_a_lock_tx.setState(TxStates.TX_REFUNDED)
 
                 if was_sent:
                     xmr_swap.a_lock_refund_spend_tx = bytes.fromhex(spend_txn['hex'])  # Replace with fully signed tx
@@ -4846,7 +4851,9 @@ class BasicSwap(BaseApp):
 
         bid.setState(BidStates.BID_ACCEPTED)  # ADS
         self.saveBidInSession(bid.bid_id, bid, session, xmr_swap)
-        self.notify(NT.BID_ACCEPTED, {'bid_id': bid.bid_id.hex()}, session)
+
+        if reverse_bid is False:
+            self.notify(NT.BID_ACCEPTED, {'bid_id': bid.bid_id.hex()}, session)
 
         delay = random.randrange(self.min_delay_event, self.max_delay_event)
         self.log.info('Responding to adaptor-sig bid accept %s in %d seconds', bid.bid_id.hex(), delay)
@@ -5412,6 +5419,9 @@ class BasicSwap(BaseApp):
 
         bid.xmr_b_lock_tx.spend_txid = txid
         bid.setState(BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED)
+        if bid.xmr_b_lock_tx:
+            bid.xmr_b_lock_tx.setState(TxStates.TX_REDEEMED)
+
         # TODO: Why does using bid.txns error here?
         self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
 
@@ -5477,6 +5487,8 @@ class BasicSwap(BaseApp):
         bid.xmr_b_lock_tx.spend_txid = txid
 
         bid.setState(BidStates.XMR_SWAP_NOSCRIPT_TX_RECOVERED)
+        if bid.xmr_b_lock_tx:
+            bid.xmr_b_lock_tx.setState(TxStates.TX_REFUNDED)
         self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
 
     def sendXmrBidCoinALockSpendTxMsg(self, bid_id: bytes, session) -> None:
@@ -5858,12 +5870,13 @@ class BasicSwap(BaseApp):
         self.log.info('Receiving reverse adaptor-sig bid %s for offer %s', bid_id.hex(), bid.offer_id.hex())
         self.saveBid(bid_id, bid, xmr_swap=xmr_swap)
 
-        if ci_to.curve_type() != Curves.ed25519:
-            try:
-                session = self.openSession()
+        try:
+            session = self.openSession()
+            self.notify(NT.BID_ACCEPTED, {'bid_id': bid_id.hex()}, session)
+            if ci_to.curve_type() != Curves.ed25519:
                 self.receiveXmrBid(bid, session)
-            finally:
-                self.closeSession(session)
+        finally:
+            self.closeSession(session)
 
     def processMsg(self, msg) -> None:
         self.mxDB.acquire()
@@ -6560,8 +6573,8 @@ class BasicSwap(BaseApp):
                         'tx1.state, tx2.state, offers.coin_from, bids.rate, bids.bid_addr, offers.bid_reversed, bids.amount_to, offers.coin_to ' + \
                         'FROM bids ' + \
                         'LEFT JOIN offers ON offers.offer_id = bids.offer_id ' + \
-                        'LEFT JOIN transactions AS tx1 ON tx1.bid_id = bids.bid_id AND tx1.tx_type = {} '.format(TxTypes.ITX) + \
-                        'LEFT JOIN transactions AS tx2 ON tx2.bid_id = bids.bid_id AND tx2.tx_type = {} '.format(TxTypes.PTX)
+                        'LEFT JOIN transactions AS tx1 ON tx1.bid_id = bids.bid_id AND tx1.tx_type = CASE WHEN offers.swap_type = :ads_swap THEN :al_type ELSE :itx_type END ' + \
+                        'LEFT JOIN transactions AS tx2 ON tx2.bid_id = bids.bid_id AND tx2.tx_type = CASE WHEN offers.swap_type = :ads_swap THEN :bl_type ELSE :ptx_type END '
 
             query_str += 'WHERE bids.active_ind = 1 '
             filter_bid_id = filters.get('bid_id', None)
@@ -6597,7 +6610,7 @@ class BasicSwap(BaseApp):
             if offset is not None:
                 query_str += f' OFFSET {offset}'
 
-            q = session.execute(query_str)
+            q = session.execute(query_str, {'ads_swap': SwapTypes.XMR_SWAP, 'itx_type': TxTypes.ITX, 'ptx_type': TxTypes.PTX, 'al_type': TxTypes.XMR_SWAP_A_LOCK, 'bl_type': TxTypes.XMR_SWAP_B_LOCK})
             for row in q:
                 result = [x for x in row]
                 if result[12]:  # Reversed
@@ -6618,7 +6631,18 @@ class BasicSwap(BaseApp):
         try:
             rv = []
             for k, v in self.swaps_in_progress.items():
-                rv.append((k, v[0].offer_id.hex(), v[0].state, v[0].getITxState(), v[0].getPTxState()))
+                bid, offer = v
+                itx_state = None
+                ptx_state = None
+
+                if offer.swap_type == SwapTypes.XMR_SWAP:
+                    itx_state = bid.xmr_a_lock_tx.state if bid.xmr_a_lock_tx else None
+                    ptx_state = bid.xmr_b_lock_tx.state if bid.xmr_b_lock_tx else None
+                else:
+                    itx_state = bid.getITxState()
+                    ptx_state = bid.getPTxState()
+
+                rv.append((k, bid.offer_id.hex(), bid.state, itx_state, ptx_state))
             return rv
         finally:
             self.mxDB.release()
diff --git a/basicswap/db.py b/basicswap/db.py
index 6f5be06..0f610f4 100644
--- a/basicswap/db.py
+++ b/basicswap/db.py
@@ -217,6 +217,8 @@ class SwapTx(Base):
     states = sa.Column(sa.LargeBinary)  # Packed states and times
 
     def setState(self, new_state):
+        if self.state == new_state:
+            return
         self.state = new_state
         self.states = (self.states if self.states is not None else bytes()) + struct.pack('<iq', new_state, int(time.time()))
 
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 43ce99f..0156fb3 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -10,6 +10,9 @@
 - Added option to remove Offers and bids from the database automatically one week
   after they expire if they have no active bids.
   - Controlled by new settings: expire_db_records and expire_db_records_after
+- Raised adaptor signature swap protocol version
+  - Not backwards compatible with previous versions.
+- ui: Show ITX and PTX status for adaptor sig type swaps.
 
 
 0.0.63
diff --git a/tests/basicswap/selenium/test_offer.py b/tests/basicswap/selenium/test_offer.py
new file mode 100644
index 0000000..c2ca7f5
--- /dev/null
+++ b/tests/basicswap/selenium/test_offer.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 tecnovert
+# Distributed under the MIT software license, see the accompanying
+# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
+
+"""
+cd /tmp
+wget -4 https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_linux64.zip
+7z x chromedriver_linux64.zip
+sudo mv chromedriver /opt/chromedriver114
+
+python tests/basicswap/extended/test_xmr_persistent.py
+python tests/basicswap/selenium/test_offer.py
+
+"""
+
+import time
+
+from selenium import webdriver
+from selenium.webdriver.chrome.service import Service
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import Select
+from selenium.webdriver.support.wait import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+
+def test_html():
+    node1_url = 'http://localhost:12701'
+    node2_url = 'http://localhost:12702'
+
+    driver = webdriver.Chrome(service=Service('/opt/chromedriver114'))
+
+    driver.get(node1_url + '/newoffer')
+    time.sleep(1)
+
+    select = Select(driver.find_element(By.ID, 'coin_from'))
+    select.select_by_visible_text('Bitcoin')
+    select = Select(driver.find_element(By.ID, 'coin_to'))
+    select.select_by_visible_text('Monero')
+
+    driver.find_element(By.NAME, 'amt_from').send_keys('1')
+    driver.find_element(By.NAME, 'amt_to').send_keys('1')
+
+    driver.find_element(By.NAME, 'continue').click()
+    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click()
+    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click()
+
+    driver.close()
+
+    print('Done.')
+
+
+if __name__ == '__main__':
+    test_html()
diff --git a/tests/basicswap/selenium/test_wallets.py b/tests/basicswap/selenium/test_wallets.py
index 8e674ca..934ae79 100644
--- a/tests/basicswap/selenium/test_wallets.py
+++ b/tests/basicswap/selenium/test_wallets.py
@@ -1,19 +1,17 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
-# Copyright (c) 2022 tecnovert
+# Copyright (c) 2022-2023 tecnovert
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
 """
 cd /tmp
-wget -4 https://chromedriver.storage.googleapis.com/107.0.5304.62/chromedriver_linux64.zip
+wget -4 https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_linux64.zip
 7z x chromedriver_linux64.zip
-sudo mv chromedriver /opt/chromedriver96
-
+sudo mv chromedriver /opt/chromedriver114
 
 python tests/basicswap/extended/test_xmr_persistent.py
-
 python tests/basicswap/selenium/test_wallets.py
 
 """
@@ -31,7 +29,7 @@ def test_html():
     base_url = 'http://localhost:12701'
     node2_url = 'http://localhost:12702'
 
-    driver = webdriver.Chrome(service=Service('/opt/chromedriver96'))
+    driver = webdriver.Chrome(service=Service('/opt/chromedriver114'))
 
     # Check json coins data
     coins = json.loads(urlopen(base_url + '/json/coins').read())