diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py
index 2367f04..149c942 100644
--- a/basicswap/basicswap.py
+++ b/basicswap/basicswap.py
@@ -1329,39 +1329,57 @@ class BasicSwap(BaseApp):
             self.closeDB(cursor)
 
     def updateIdentityBidState(self, cursor, address: str, bid) -> None:
-        identity_stats = self.queryOne(KnownIdentity, cursor, {"address": address})
-        if not identity_stats:
-            identity_stats = KnownIdentity(
-                active_ind=1, address=address, created_at=self.getTime()
-            )
-
-        if bid.state == BidStates.SWAP_COMPLETED:
-            if bid.was_sent:
-                identity_stats.num_sent_bids_successful = (
-                    zeroIfNone(identity_stats.num_sent_bids_successful) + 1
+        # self.log.debug(f"Starting updateIdentityBidState for address {address}, bid {bid.bid_id.hex()}")
+        offer = self.getOffer(bid.offer_id, cursor)
+        # self.log.debug(f"Offer from: {offer.addr_from}, Bid from: {bid.bid_addr}, Reverse bid: {reverse_bid}")
+        addresses_to_update = [offer.addr_from, bid.bid_addr]
+        for addr in addresses_to_update:
+            # self.log.debug(f"Processing address: {addr}")
+            identity_stats = self.queryOne(KnownIdentity, cursor, {"address": addr})
+            if not identity_stats:
+                # self.log.debug(f"Creating new identity record for {addr}")
+                identity_stats = KnownIdentity(
+                    active_ind=1,
+                    address=addr,
+                    created_at=self.getTime()
                 )
-            else:
-                identity_stats.num_recv_bids_successful = (
-                    zeroIfNone(identity_stats.num_recv_bids_successful) + 1
-                )
-        elif bid.state in (
-            BidStates.BID_ERROR,
-            BidStates.XMR_SWAP_FAILED_REFUNDED,
-            BidStates.XMR_SWAP_FAILED_SWIPED,
-            BidStates.XMR_SWAP_FAILED,
-            BidStates.SWAP_TIMEDOUT,
-        ):
-            if bid.was_sent:
-                identity_stats.num_sent_bids_failed = (
-                    zeroIfNone(identity_stats.num_sent_bids_failed) + 1
-                )
-            else:
-                identity_stats.num_recv_bids_failed = (
-                    zeroIfNone(identity_stats.num_recv_bids_failed) + 1
-                )
-
-        identity_stats.updated_at = self.getTime()
-        self.add(identity_stats, cursor, upsert=True)
+            is_offer_creator = addr == offer.addr_from
+            # self.log.debug(f"Is offer creator: {is_offer_creator}, Current state: {bid.state}")
+            if bid.state == BidStates.SWAP_COMPLETED:
+                # self.log.debug("Processing successful swap")
+                if is_offer_creator:
+                    old_value = zeroIfNone(identity_stats.num_recv_bids_successful)
+                    identity_stats.num_recv_bids_successful = old_value + 1
+                    # self.log.debug(f"Updated received successful: {old_value} -> {identity_stats.num_recv_bids_successful}")
+                else:
+                    old_value = zeroIfNone(identity_stats.num_sent_bids_successful)
+                    identity_stats.num_sent_bids_successful = old_value + 1
+                    # self.log.debug(f"Updated sent successful: {old_value} -> {identity_stats.num_sent_bids_successful}")
+            elif bid.state in (BidStates.BID_ERROR,
+                               BidStates.XMR_SWAP_FAILED_REFUNDED,
+                               BidStates.XMR_SWAP_FAILED_SWIPED,
+                               BidStates.XMR_SWAP_FAILED,
+                               BidStates.SWAP_TIMEDOUT):
+                # self.log.debug(f"Processing failed swap: {bid.state}")
+                if is_offer_creator:
+                    old_value = zeroIfNone(identity_stats.num_recv_bids_failed)
+                    identity_stats.num_recv_bids_failed = old_value + 1
+                    # self.log.debug(f"Updated received failed: {old_value} -> {identity_stats.num_recv_bids_failed}")
+                else:
+                    old_value = zeroIfNone(identity_stats.num_sent_bids_failed)
+                    identity_stats.num_sent_bids_failed = old_value + 1
+                    # self.log.debug(f"Updated sent failed: {old_value} -> {identity_stats.num_sent_bids_failed}")
+            elif bid.state == BidStates.BID_REJECTED:
+                # self.log.debug("Processing rejected bid")
+                if is_offer_creator:
+                    old_value = zeroIfNone(identity_stats.num_recv_bids_rejected)
+                    identity_stats.num_recv_bids_rejected = old_value + 1
+                    # self.log.debug(f"Updated received rejected: {old_value} -> {identity_stats.num_recv_bids_rejected}")
+                else:
+                    old_value = zeroIfNone(identity_stats.num_sent_bids_rejected)
+                    identity_stats.num_sent_bids_rejected = old_value + 1
+                    # self.log.debug(f"Updated sent rejected: {old_value} -> {identity_stats.num_sent_bids_rejected}")
+            self.add(identity_stats, cursor, upsert=True)
 
     def getPreFundedTx(
         self, linked_type: int, linked_id: bytes, tx_type: int, cursor=None
diff --git a/basicswap/js_server.py b/basicswap/js_server.py
index 16a1a4e..f9a887e 100644
--- a/basicswap/js_server.py
+++ b/basicswap/js_server.py
@@ -250,6 +250,7 @@ def js_offers(self, url_split, post_string, is_json, sent=False) -> bytes:
             "is_expired": o.expire_at <= swap_client.getTime(),
             "is_own_offer": o.was_sent,
             "is_revoked": True if o.active_ind == 2 else False,
+            "is_public": o.addr_to == swap_client.network_addr or o.addr_to.strip() == "",
         }
         if with_extra_info:
             offer_data["amount_negotiable"] = o.amount_negotiable
@@ -655,6 +656,23 @@ def js_identities(self, url_split, post_string: str, is_json: bool) -> bytes:
     swap_client = self.server.swap_client
     swap_client.checkSystemStatus()
 
+    if len(url_split) > 3:
+        address = url_split[3]
+        identity = swap_client.getIdentity(address)
+        if identity:
+            return bytes(json.dumps({
+                "label": identity.label if identity.label is not None else "",
+                "note": identity.note if identity.note is not None else "",
+                "automation_override": identity.automation_override if identity.automation_override is not None else 0,
+                "num_sent_bids_successful": identity.num_sent_bids_successful if identity.num_sent_bids_successful is not None else 0,
+                "num_recv_bids_successful": identity.num_recv_bids_successful if identity.num_recv_bids_successful is not None else 0,
+                "num_sent_bids_rejected": identity.num_sent_bids_rejected if identity.num_sent_bids_rejected is not None else 0,
+                "num_recv_bids_rejected": identity.num_recv_bids_rejected if identity.num_recv_bids_rejected is not None else 0,
+                "num_sent_bids_failed": identity.num_sent_bids_failed if identity.num_sent_bids_failed is not None else 0,
+                "num_recv_bids_failed": identity.num_recv_bids_failed if identity.num_recv_bids_failed is not None else 0
+            }), "UTF-8")
+        return bytes(json.dumps({}), "UTF-8")
+
     filters = {
         "page_no": 1,
         "limit": PAGE_LIMIT,
@@ -662,10 +680,6 @@ def js_identities(self, url_split, post_string: str, is_json: bool) -> bytes:
         "sort_dir": "desc",
     }
 
-    if len(url_split) > 3:
-        address = url_split[3]
-        filters["address"] = address
-
     if post_string != "":
         post_data = getFormData(post_string, is_json)
 
diff --git a/basicswap/static/css/style.css b/basicswap/static/css/style.css
index 96bfb70..fd764b2 100644
--- a/basicswap/static/css/style.css
+++ b/basicswap/static/css/style.css
@@ -356,4 +356,14 @@ select.disabled-select-enabled {
   #toggle-auto-refresh[data-enabled="true"] {
     @apply bg-green-500 hover:bg-green-600 focus:ring-green-300;
   }
+  
+  [data-popper-placement] {
+    will-change: transform;
+    transform: translateZ(0);
+}
+
+.tooltip {
+    backface-visibility: hidden;
+    -webkit-backface-visibility: hidden;
+}
 
diff --git a/basicswap/static/js/offerstable.js b/basicswap/static/js/offerstable.js
index fce0a20..cec0722 100644
--- a/basicswap/static/js/offerstable.js
+++ b/basicswap/static/js/offerstable.js
@@ -102,7 +102,7 @@ const WebSocketManager = {
     },
 
     initialize() {
-        console.log('πŸš€ Initializing WebSocket Manager');
+        console.log('Initializing WebSocket Manager');
         this.setupPageVisibilityHandler();
         this.connect();
         this.startHealthCheck();
@@ -152,7 +152,7 @@ const WebSocketManager = {
 
     performHealthCheck() {
         if (!this.isConnected()) {
-            console.warn('πŸ₯ Health check: Connection lost, attempting reconnect');
+            console.warn('Health check: Connection lost, attempting reconnect');
             this.handleReconnect();
             return;
         }
@@ -160,13 +160,13 @@ const WebSocketManager = {
         const now = Date.now();
         const lastCheck = this.connectionState.lastHealthCheck;
         if (lastCheck && (now - lastCheck) > 60000) {
-            console.warn('πŸ₯ Health check: Connection stale, refreshing');
+            console.warn('Health check: Connection stale, refreshing');
             this.handleReconnect();
             return;
         }
 
         this.connectionState.lastHealthCheck = now;
-        console.log('βœ… Health check passed');
+        console.log('Health check passed');
     },
 
     connect() {
@@ -183,7 +183,7 @@ const WebSocketManager = {
             const wsPort = config.port || window.ws_port || '11700';
 
             if (!wsPort) {
-                console.error('❌ WebSocket port not configured');
+                console.error('WebSocket port not configured');
                 this.connectionState.isConnecting = false;
                 return false;
             }
@@ -201,7 +201,7 @@ const WebSocketManager = {
 
             return true;
         } catch (error) {
-            console.error('❌ Error creating WebSocket:', error);
+            console.error('Error creating WebSocket:', error);
             this.connectionState.isConnecting = false;
             this.handleReconnect();
             return false;
@@ -226,13 +226,13 @@ const WebSocketManager = {
             const message = JSON.parse(event.data);
             this.handleMessage(message);
         } catch (error) {
-            console.error('❌ Error processing WebSocket message:', error);
+            console.error('Error processing WebSocket message:', error);
             updateConnectionStatus('error');
         }
     };
 
     this.ws.onerror = (error) => {
-        console.error('❌ WebSocket error:', error);
+        console.error('WebSocket error:', error);
         updateConnectionStatus('error');
     };
 
@@ -250,7 +250,7 @@ const WebSocketManager = {
 
     handleMessage(message) {
         if (this.messageQueue.length >= this.maxQueueSize) {
-            console.warn('⚠️ Message queue full, dropping oldest message');
+            console.warn('⚠Message queue full, dropping oldest message');
             this.messageQueue.shift();
         }
 
@@ -286,7 +286,7 @@ const WebSocketManager = {
 
             this.messageQueue = [];
         } catch (error) {
-            console.error('❌ Error processing message queue:', error);
+            console.error('Error processing message queue:', error);
         } finally {
             this.processingQueue = false;
         }
@@ -299,7 +299,7 @@ const WebSocketManager = {
 
         this.reconnectAttempts++;
         if (this.reconnectAttempts <= this.maxReconnectAttempts) {
-            console.log(`πŸ”„ Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
+            console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
             
             const delay = Math.min(
                 this.reconnectDelay * Math.pow(1.5, this.reconnectAttempts - 1),
@@ -312,7 +312,7 @@ const WebSocketManager = {
                 }
             }, delay);
         } else {
-            console.error('❌ Max reconnection attempts reached');
+            console.error('Max reconnection attempts reached');
             updateConnectionStatus('error');
 
             setTimeout(() => {
@@ -323,7 +323,7 @@ const WebSocketManager = {
     },
 
     cleanup() {
-        console.log('🧹 Cleaning up WebSocket resources');
+        console.log('Cleaning up WebSocket resources');
         
         clearTimeout(this.debounceTimeout);
         clearTimeout(this.reconnectTimeout);
@@ -723,7 +723,7 @@ function checkOfferAgainstFilters(offer, filters) {
 
 function initializeFlowbiteTooltips() {
     if (typeof Tooltip === 'undefined') {
-        //console.warn('Tooltip is not defined. Make sure the required library is loaded.');
+        console.warn('Tooltip is not defined. Make sure the required library is loaded.');
         return;
     }
     
@@ -824,6 +824,17 @@ function filterAndSortData() {
 
     let filteredData = [...originalJsonData];
 
+    const sentFromFilter = filters.sent_from || 'any';
+    
+    filteredData = filteredData.filter(offer => {
+        if (sentFromFilter === 'public') {
+            return offer.is_public;
+        } else if (sentFromFilter === 'private') {
+            return !offer.is_public;
+        }
+        return true;
+    });
+
     filteredData = filteredData.filter(offer => {
         if (!isSentOffers && isOfferExpired(offer)) {
             return false;
@@ -1032,7 +1043,7 @@ async function fetchLatestPrices() {
         }
         
         if (data && Object.keys(data).length > 0) {
-            console.log('βœ… Fresh price data received');
+            console.log('Fresh price data received');
 
             latestPrices = data;
 
@@ -1047,7 +1058,7 @@ async function fetchLatestPrices() {
             //console.warn('Received empty price data');
         }
     } catch (error) {
-        //console.error('❌ Error fetching prices:', error);
+        //console.error('Error fetching prices:', error);
         throw error;
     }
 
@@ -1055,36 +1066,33 @@ async function fetchLatestPrices() {
 }
 
 async function fetchOffers(manualRefresh = false) {
-  const refreshButton = document.getElementById('refreshOffers');
-  const refreshIcon = document.getElementById('refreshIcon');
-  const refreshText = document.getElementById('refreshText');
+    const refreshButton = document.getElementById('refreshOffers');
+    const refreshIcon = document.getElementById('refreshIcon');
+    const refreshText = document.getElementById('refreshText');
 
-  refreshButton.disabled = true;
-  refreshIcon.classList.add('animate-spin');
-  refreshText.textContent = 'Refreshing...';
-  refreshButton.classList.add('opacity-75', 'cursor-wait');
-  
-  try {
-    const endpoint = isSentOffers ? '/json/sentoffers' : '/json/offers';
-    const response = await fetch(endpoint);
-    const data = await response.json();
-    
-    jsonData = formatInitialData(data);
-    originalJsonData = [...jsonData];
+    try {
+        refreshButton.disabled = true;
+        refreshIcon.classList.add('animate-spin');
+        refreshText.textContent = 'Refreshing...';
+        refreshButton.classList.add('opacity-75', 'cursor-wait');
+        
+        const endpoint = isSentOffers ? '/json/sentoffers' : '/json/offers';
+        const response = await fetch(endpoint);
+        const data = await response.json();
+        
+        jsonData = formatInitialData(data);
+        originalJsonData = [...jsonData];
 
-    await updateOffersTable();
-    updateJsonView();
-    updatePaginationInfo();
-    
-  } catch (error) {
-    //console.error('[Debug] Error fetching offers:', error);
-    ui.displayErrorMessage('Failed to fetch offers. Please try again later.');
-  } finally {
-    refreshButton.disabled = false;
-    refreshIcon.classList.remove('animate-spin');
-    refreshText.textContent = 'Refresh';
-    refreshButton.classList.remove('opacity-75', 'cursor-wait');
-  }
+        await updateOffersTable();
+        updateJsonView();
+        updatePaginationInfo();
+        
+    } catch (error) {
+        console.error('[Debug] Error fetching offers:', error);
+        ui.displayErrorMessage('Failed to fetch offers. Please try again later.');
+    } finally {
+        stopRefreshAnimation();
+    }
 }
 
 function formatInitialData(data) {
@@ -1092,6 +1100,7 @@ function formatInitialData(data) {
         offer_id: String(offer.offer_id || ''),
         swap_type: String(offer.swap_type || 'N/A'),
         addr_from: String(offer.addr_from || ''),
+        addr_to: String(offer.addr_to || ''),
         coin_from: String(offer.coin_from || ''),
         coin_to: String(offer.coin_to || ''),
         amount_from: String(offer.amount_from || '0'),
@@ -1102,6 +1111,7 @@ function formatInitialData(data) {
         is_own_offer: Boolean(offer.is_own_offer),
         amount_negotiable: Boolean(offer.amount_negotiable),
         is_revoked: Boolean(offer.is_revoked),
+        is_public: offer.is_public !== undefined ? Boolean(offer.is_public) : false,
         unique_id: `${offer.offer_id}_${offer.created_at}_${offer.coin_from}_${offer.coin_to}`
     }));
 }
@@ -1173,6 +1183,23 @@ function updateLastRefreshTime() {
     }
 }
 
+function stopRefreshAnimation() {
+    const refreshButton = document.getElementById('refreshOffers');
+    const refreshIcon = document.getElementById('refreshIcon');
+    const refreshText = document.getElementById('refreshText');
+
+    if (refreshButton) {
+        refreshButton.disabled = false;
+        refreshButton.classList.remove('opacity-75', 'cursor-wait');
+    }
+    if (refreshIcon) {
+        refreshIcon.classList.remove('animate-spin');
+    }
+    if (refreshText) {
+        refreshText.textContent = 'Refresh';
+    }
+}
+
 function updatePaginationInfo() {
     const validOffers = getValidOffers();
     const totalItems = validOffers.length;
@@ -1280,8 +1307,18 @@ function updateCoinFilterImages() {
 function updateClearFiltersButton() {
     const clearButton = document.getElementById('clearFilters');
     if (clearButton) {
-        clearButton.classList.toggle('opacity-50', !hasActiveFilters());
-        clearButton.disabled = !hasActiveFilters();
+        const hasFilters = hasActiveFilters();
+        clearButton.classList.toggle('opacity-50', !hasFilters);
+        clearButton.disabled = !hasFilters;
+        
+        // Update button styles based on state
+        if (hasFilters) {
+            clearButton.classList.add('hover:bg-green-600', 'hover:text-white');
+            clearButton.classList.remove('cursor-not-allowed');
+        } else {
+            clearButton.classList.remove('hover:bg-green-600', 'hover:text-white');
+            clearButton.classList.add('cursor-not-allowed');
+        }
     }
 }
 
@@ -1292,30 +1329,31 @@ function handleNoOffersScenario() {
                             filters.coin_from !== 'any' ||
                             (filters.status && filters.status !== 'any');
     
+    stopRefreshAnimation();
+
     if (hasActiveFilters) {
         offersBody.innerHTML = `
             <tr>
-                <td colspan="8" class="text-center py-4 text-gray-500 dark:text-white">
-                    No offers match the selected filters. Try different filter options or 
-                    <button onclick="clearFilters()" class="text-blue-500 hover:text-blue-700 bold">clear filters</button>
+                <td colspan="9" class="text-center py-8">
+                    <div class="flex items-center justify-center text-gray-500 dark:text-white">
+                        No offers match the selected filters. Try different filter options or 
+                        <button onclick="clearFilters()" class="ml-1 text-blue-500 hover:text-blue-700 font-semibold">
+                            clear filters
+                        </button>
+                    </div>
                 </td>
             </tr>`;
     } else {
         offersBody.innerHTML = `
             <tr>
-                <td colspan="8" class="text-center py-4 text-gray-500 dark:text-white">
-                    No active offers available. ${!isSentOffers ? 'Refreshing data...' : ''}
+                <td colspan="9" class="text-center py-8 text-gray-500 dark:text-white">
+                    No active offers available.
                 </td>
             </tr>`;
-        if (!isSentOffers) {
-            setTimeout(() => fetchOffers(true), 2000);
-        }
     }
 }
 
 async function updateOffersTable() {
-    //console.log('[Debug] Starting updateOffersTable function');
-    
     try {
         const PRICES_CACHE_KEY = 'prices_coingecko';
         const cachedPrices = CacheManager.get(PRICES_CACHE_KEY);
@@ -1323,27 +1361,25 @@ async function updateOffersTable() {
         if (!cachedPrices || !cachedPrices.remainingTime || cachedPrices.remainingTime < 60000) {
             console.log('Fetching fresh price data...');
             const priceData = await fetchLatestPrices();
-            if (!priceData) {
-                //console.error('Failed to fetch latest prices');
-            } else {
-                console.log('Latest prices fetched successfully');
+            if (priceData) {
                 latestPrices = priceData;
             }
         } else {
-            console.log('Using cached price data (still valid)');
             latestPrices = cachedPrices.value;
         }
 
-        const totalOffers = originalJsonData.filter(offer => !isOfferExpired(offer));
+        const validOffers = getValidOffers();
 
-        const networkOffersCount = document.getElementById('network-offers-count');
-        if (networkOffersCount && !isSentOffers) {
-            networkOffersCount.textContent = totalOffers.length;
-        }
-
-        let validOffers = getValidOffers();
-        console.log('[Debug] Valid offers:', validOffers.length);
+        const startIndex = (currentPage - 1) * itemsPerPage;
+        const endIndex = Math.min(startIndex + itemsPerPage, validOffers.length);
+        const itemsToDisplay = validOffers.slice(startIndex, endIndex);
 
+        const identityPromises = itemsToDisplay.map(offer => 
+            offer.addr_from ? getIdentityData(offer.addr_from) : Promise.resolve(null)
+        );
+        
+        const identities = await Promise.all(identityPromises);
+        
         if (validOffers.length === 0) {
             handleNoOffersScenario();
             return;
@@ -1351,15 +1387,12 @@ async function updateOffersTable() {
 
         const totalPages = Math.max(1, Math.ceil(validOffers.length / itemsPerPage));
         currentPage = Math.min(currentPage, totalPages);
-        const startIndex = (currentPage - 1) * itemsPerPage;
-        const endIndex = Math.min(startIndex + itemsPerPage, validOffers.length);
-        const itemsToDisplay = validOffers.slice(startIndex, endIndex);
 
         const fragment = document.createDocumentFragment();
 
-        const currentOffers = new Set();
-        itemsToDisplay.forEach(offer => {
-            const row = createTableRow(offer, isSentOffers);
+        itemsToDisplay.forEach((offer, index) => {
+            const identity = identities[index];
+            const row = createTableRow(offer, identity);
             if (row) {
                 fragment.appendChild(row);
             }
@@ -1380,22 +1413,14 @@ async function updateOffersTable() {
 
         lastRefreshTime = Date.now();
         if (newEntriesCountSpan) {
-            const displayCount = isSentOffers ? jsonData.length : validOffers.length;
-            newEntriesCountSpan.textContent = displayCount;
+            newEntriesCountSpan.textContent = validOffers.length;
         }
         if (lastRefreshTimeSpan) {
             lastRefreshTimeSpan.textContent = new Date(lastRefreshTime).toLocaleTimeString();
         }
 
-        if (!isSentOffers) {
-            const nextUpdateTime = getTimeUntilNextExpiration() * 1000;
-            setTimeout(() => {
-                updateRowTimes();
-            }, nextUpdateTime);
-        }
-
     } catch (error) {
-        //console.error('[Debug] Error in updateOffersTable:', error);
+        console.error('[Debug] Error in updateOffersTable:', error);
         offersBody.innerHTML = `
             <tr>
                 <td colspan="8" class="text-center py-4 text-red-500">
@@ -1405,46 +1430,124 @@ async function updateOffersTable() {
     }
 }
 
-function createTableRow(offer, isSentOffers) {
+async function getIdentityData(address) {
+    try {
+        const response = await fetch(`/json/identities/${address}`);
+        if (!response.ok) {
+            return null;
+        }
+        return await response.json();
+    } catch (error) {
+        console.error('Error fetching identity:', error);
+        return null;
+    }
+}
+
+function getIdentityInfo(address, identity) {
+    if (!identity) {
+        return {
+            displayAddr: address ? `${address.substring(0, 10)}...` : 'Unspecified',
+            fullAddress: address || '',
+            label: '',
+            note: '',
+            automationOverride: 0,
+            stats: {
+                sentBidsSuccessful: 0,
+                recvBidsSuccessful: 0,
+                sentBidsRejected: 0,
+                recvBidsRejected: 0,
+                sentBidsFailed: 0,
+                recvBidsFailed: 0
+            }
+        };
+    }
+
+    return {
+        displayAddr: address ? `${address.substring(0, 10)}...` : 'Unspecified',
+        fullAddress: address || '',
+        label: identity.label || '',
+        note: identity.note || '',
+        automationOverride: identity.automation_override || 0,
+        stats: {
+            sentBidsSuccessful: identity.num_sent_bids_successful || 0,
+            recvBidsSuccessful: identity.num_recv_bids_successful || 0,
+            sentBidsRejected: identity.num_sent_bids_rejected || 0,
+            recvBidsRejected: identity.num_recv_bids_rejected || 0,
+            sentBidsFailed: identity.num_sent_bids_failed || 0,
+            recvBidsFailed: identity.num_recv_bids_failed || 0
+        }
+    };
+}
+
+function createTableRow(offer, identity = null) {
     const row = document.createElement('tr');
     const uniqueId = `${offer.offer_id}_${offer.created_at}`;
-    row.className = `opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600`;
+    
+    row.className = 'relative opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600';
     row.setAttribute('data-offer-id', uniqueId);
 
-    const coinFrom = offer.coin_from;
-    const coinTo = offer.coin_to;
+    const {
+        coin_from: coinFrom,
+        coin_to: coinTo,
+        created_at: createdAt,
+        expire_at: expireAt,
+        amount_from: amountFrom,
+        amount_to: amountTo,
+        is_own_offer: isOwnOffer,
+        is_revoked: isRevoked,
+        is_public: isPublic
+    } = offer;
+
     const coinFromSymbol = coinNameToSymbol[coinFrom] || coinFrom.toLowerCase();
     const coinToSymbol = coinNameToSymbol[coinTo] || coinTo.toLowerCase();
     const coinFromDisplay = getDisplayName(coinFrom);
     const coinToDisplay = getDisplayName(coinTo);
-
-    const postedTime = formatTime(offer.created_at, true);
-    const expiresIn = formatTime(offer.expire_at);
+    const postedTime = formatTime(createdAt, true);
+    const expiresIn = formatTime(expireAt);
     
     const currentTime = Math.floor(Date.now() / 1000);
-    const isActuallyExpired = currentTime > offer.expire_at;
-
-    const fromAmount = parseFloat(offer.amount_from) || 0;
-    const toAmount = parseFloat(offer.amount_to) || 0;
+    const isActuallyExpired = currentTime > expireAt;
+    const fromAmount = parseFloat(amountFrom) || 0;
+    const toAmount = parseFloat(amountTo) || 0;
 
+    // Build row content
     row.innerHTML = `
+        ${!isPublic ? createPrivateIndicator() : '<td class="w-0 p-0 m-0"></td>'}
         ${createTimeColumn(offer, postedTime, expiresIn)}
-        ${createDetailsColumn(offer)}
+        ${createDetailsColumn(offer, identity)}
         ${createTakerAmountColumn(offer, coinTo, coinFrom)}
         ${createSwapColumn(offer, coinFromDisplay, coinToDisplay, coinFromSymbol, coinToSymbol)}
         ${createOrderbookColumn(offer, coinFrom, coinTo)}
         ${createRateColumn(offer, coinFrom, coinTo)}
         ${createPercentageColumn(offer)}
         ${createActionColumn(offer, isActuallyExpired)}
-        ${createTooltips(offer, offer.is_own_offer, coinFrom, coinTo, fromAmount, toAmount, postedTime, expiresIn, isActuallyExpired, Boolean(offer.is_revoked))}
+        ${createTooltips(
+            offer,
+            isOwnOffer,
+            coinFrom,
+            coinTo,
+            fromAmount,
+            toAmount,
+            postedTime,
+            expiresIn,
+            isActuallyExpired,
+            Boolean(isRevoked),
+            identity
+        )}
     `;
 
     updateTooltipTargets(row, uniqueId);
-    updateProfitLoss(row, coinFrom, coinTo, fromAmount, toAmount, offer.is_own_offer);
+    updateProfitLoss(row, coinFrom, coinTo, fromAmount, toAmount, isOwnOffer);
 
     return row;
 }
 
+function createPrivateIndicator() {
+    return `<td class="relative w-0 p-0 m-0">
+        <div class="absolute top-0 bottom-0 left-0 w-1 bg-red-700" style="min-height: 100%;"></div>
+    </td>`;
+}
+
 function createTimeColumn(offer, postedTime, expiresIn) {
     const now = Math.floor(Date.now() / 1000);
     const timeLeft = offer.expire_at - now;
@@ -1457,10 +1560,10 @@ function createTimeColumn(offer, postedTime, expiresIn) {
     }
 
     return `
-        <td class="py-3 pl-6 text-xs">
+        <td class="py-3 pl-1 pr-2 text-xs whitespace-nowrap">
             <div class="flex items-center">
                 <div class="relative" data-tooltip-target="tooltip-active${escapeHtml(offer.offer_id)}">
-                    <svg alt="" class="w-5 h-5 rounded-full mr-3 cursor-pointer" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
+                    <svg alt="" class="w-5 h-5 rounded-full mr-4 cursor-pointer" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24">
                         <g stroke-linecap="round" stroke-width="2" fill="none" stroke="${strokeColor}" stroke-linejoin="round">
                             <circle cx="12" cy="12" r="11"></circle>
                             <polyline points="12,6 12,12 18,12" stroke="${strokeColor}"></polyline>
@@ -1468,21 +1571,59 @@ function createTimeColumn(offer, postedTime, expiresIn) {
                     </svg>
                 </div>
                 <div class="flex flex-col hidden xl:block">
-                    <div class="text-xs"><span class="bold">Posted:</span> ${escapeHtml(postedTime)}</div>
-                    <div class="text-xs"><span class="bold">Expires in:</span> ${escapeHtml(expiresIn)}</div>
+                    <div class="text-xs whitespace-nowrap"><span class="bold">Posted:</span> ${escapeHtml(postedTime)}</div>
+                    <div class="text-xs whitespace-nowrap"><span class="bold">Expires in:</span> ${escapeHtml(expiresIn)}</div>
                 </div>
             </div>
         </td>
     `;
 }
 
-function createDetailsColumn(offer) {
+function shouldShowPublicTag(offers) {
+    return offers.some(offer => !offer.is_public);
+}
+
+function truncateText(text, maxLength = 15) {
+    if (typeof text !== 'string') return '';
+    return text.length > maxLength 
+        ? text.slice(0, maxLength) + '...' 
+        : text;
+}
+
+function createDetailsColumn(offer, identity = null) {
     const addrFrom = offer.addr_from || '';
+    const identityInfo = getIdentityInfo(addrFrom, identity);
+    
+    const showPublicPrivateTags = originalJsonData.some(o => o.is_public !== offer.is_public);
+
+    const tagClass = offer.is_public 
+        ? 'bg-green-600 dark:bg-green-600' 
+        : 'bg-red-500 dark:bg-red-500';
+    const tagText = offer.is_public ? 'Public' : 'Private';
+
+    const displayIdentifier = truncateText(
+        identityInfo.label || addrFrom || 'Unspecified'
+    );
+
+    const identifierTextClass = identityInfo.label 
+        ? 'text-white dark:text-white' 
+        : 'monospace';
+    
     return `
         <td class="py-8 px-4 text-xs text-left hidden xl:block">
-            <a data-tooltip-target="tooltip-recipient${escapeHtml(offer.offer_id)}" href="/identity/${escapeHtml(addrFrom)}">
-                <span class="bold">Recipient:</span> ${escapeHtml(addrFrom.substring(0, 10))}...
-            </a>
+            <div class="flex flex-col gap-2 relative">
+                ${showPublicPrivateTags ? `<span class="inline-flex pl-6 pr-6 py-1 justify-center text-[10px] w-1/4 font-medium text-gray-100 rounded-md ${tagClass}">${tagText}</span>
+                ` : ''}
+                
+                <a data-tooltip-target="tooltip-recipient-${escapeHtml(offer.offer_id)}" href="/identity/${escapeHtml(addrFrom)}" class="flex items-center">
+                    <svg class="w-4 h-4 mr-2 text-gray-400 dark:text-white" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
+                     <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path>
+                    </svg>
+                    <span class="${identifierTextClass} font-semibold">
+                        ${escapeHtml(displayIdentifier)}
+                    </span>
+                </a>
+            </div>
         </td>
     `;
 }
@@ -1635,12 +1776,28 @@ function createActionColumn(offer, isActuallyExpired = false) {
 }
 
 // TOOLTIP FUNCTIONS
-function createTooltips(offer, treatAsSentOffer, coinFrom, coinTo, fromAmount, toAmount, postedTime, expiresIn, isActuallyExpired, isRevoked) {
+function createTooltips(offer, treatAsSentOffer, coinFrom, coinTo, fromAmount, toAmount, postedTime, expiresIn, isActuallyExpired, isRevoked, identity = null) {
     const rate = parseFloat(offer.rate);
     const fromSymbol = getCoinSymbolLowercase(coinFrom);
     const toSymbol = getCoinSymbolLowercase(coinTo);
     const uniqueId = `${offer.offer_id}_${offer.created_at}`;
+
+    const addrFrom = offer.addr_from || '';
+    const identityInfo = getIdentityInfo(addrFrom, identity);
+
+    const totalBids = identity ? (
+        identityInfo.stats.sentBidsSuccessful + 
+        identityInfo.stats.recvBidsSuccessful + 
+        identityInfo.stats.sentBidsFailed + 
+        identityInfo.stats.recvBidsFailed + 
+        identityInfo.stats.sentBidsRejected + 
+        identityInfo.stats.recvBidsRejected
+    ) : 0;
     
+    const successRate = totalBids ? (
+        ((identityInfo.stats.sentBidsSuccessful + identityInfo.stats.recvBidsSuccessful) / totalBids) * 100
+    ).toFixed(1) : 0;
+
     const fromPriceUSD = latestPrices[fromSymbol]?.usd || 0;
     const toPriceUSD = latestPrices[toSymbol]?.usd || 0;
     const rateInUSD = rate * toPriceUSD;
@@ -1689,13 +1846,8 @@ function createTooltips(offer, treatAsSentOffer, coinFrom, coinTo, fromAmount, t
             </div>
             <div class="tooltip-arrow" data-popper-arrow></div>
         </div>
-        
-        <div id="tooltip-recipient-${uniqueId}" role="tooltip" class="inline-block absolute invisible z-50 py-2 px-3 text-sm font-medium text-white bg-gray-400 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
-            <div class="active-revoked-expired"><span class="bold monospace">${offer.addr_from}</span></div>
-            <div class="tooltip-arrow" data-popper-arrow></div>
-        </div>
        
-        <div id="tooltip-wallet-${uniqueId}" role="tooltip" class="inline-block absolute invisible z-50 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
+        <div id="tooltip-wallet-${uniqueId}" role="tooltip" class="inline-block absolute invisible z-50 py-2 px-3 text-sm font-medium text-white bg-gray-400 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
             <div class="active-revoked-expired">
                 <span class="bold">${treatAsSentOffer ? 'My' : ''} ${coinTo} Wallet</span>
             </div>
@@ -1711,7 +1863,7 @@ function createTooltips(offer, treatAsSentOffer, coinFrom, coinTo, fromAmount, t
             <div class="tooltip-arrow pr-6" data-popper-arrow></div>
         </div>
         
-        <div id="tooltip-wallet-maker-${uniqueId}" role="tooltip" class="inline-block absolute invisible z-50 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
+        <div id="tooltip-wallet-maker-${uniqueId}" role="tooltip" class="inline-block absolute invisible z-50 py-2 px-3 text-sm font-medium text-white bg-gray-400 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
             <div class="active-revoked-expired">
                 <span class="bold">${treatAsSentOffer ? 'My' : ''} ${coinFrom} Wallet</span>
             </div>
@@ -1731,9 +1883,92 @@ function createTooltips(offer, treatAsSentOffer, coinFrom, coinTo, fromAmount, t
             </div>
             <div class="tooltip-arrow" data-popper-arrow></div>
         </div>
+
+        ${createRecipientTooltip(uniqueId, identityInfo, identity, successRate, totalBids)}
     `;
 }
 
+function createRecipientTooltip(uniqueId, identityInfo, identity, successRate, totalBids) {
+
+    const getSuccessRateColor = (rate) => {
+        if (rate >= 80) return 'text-green-600';
+        if (rate >= 60) return 'text-yellow-600';
+        return 'text-red-600';
+    };
+
+
+    const truncateText = (text, maxLength) => {
+        if (text.length <= maxLength) return text;
+        return text.substring(0, maxLength) + '...';
+    };
+
+    return `
+        <div id="tooltip-recipient-${uniqueId}" role="tooltip" 
+            class="fixed z-50 py-3 px-4 text-sm font-medium text-white bg-gray-400 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip max-w-sm pointer-events-none">
+            <div class="identity-info space-y-2">
+                ${identityInfo.label ? `
+                    <div class="border-b border-gray-400 pb-2">
+                        <div class="text-white text-xs tracking-wide font-semibold">Label:</div>
+                        <div class="text-white">${escapeHtml(identityInfo.label)}</div>
+                    </div>
+                ` : ''}
+                
+                <div class="space-y-1">
+                    <div class="text-white text-xs tracking-wide font-semibold">Recipient Address:</div>
+                    <div class="monospace text-xs break-all bg-gray-500 p-2 rounded-md text-white">
+                        ${escapeHtml(identityInfo.fullAddress)}
+                    </div>
+                </div>
+
+                ${identityInfo.note ? `
+                    <div class="space-y-1 hidden">
+                        <div class="text-white text-xs tracking-wide font-semibold">Note:</div>
+                        <div class="text-white text-sm italic" title="${escapeHtml(identityInfo.note)}">
+                            ${escapeHtml(truncateText(identityInfo.note, 150))}
+                        </div>
+                    </div>
+                ` : ''}
+
+                ${identity ? `
+                    <div class="border-t border-gray-400 pt-2 mt-2">
+                        <div class="text-white text-xs tracking-wide font-semibold mb-2">Swap History:</div>
+                        <div class="grid grid-cols-2 gap-2">
+                            <div class="text-center p-2 bg-gray-500 rounded-md">
+                                <div class="text-lg font-bold ${getSuccessRateColor(successRate)}">${successRate}%</div>
+                                <div class="text-xs text-white">Success Rate</div>
+                            </div>
+                            <div class="text-center p-2 bg-gray-500 rounded-md">
+                                <div class="text-lg font-bold text-blue-500">${totalBids}</div>
+                                <div class="text-xs text-white">Total Trades</div>
+                            </div>
+                        </div>
+                        <div class="grid grid-cols-3 gap-2 mt-2 text-center text-xs">
+                            <div>
+                                <div class="text-green-600 font-semibold">
+                                    ${identityInfo.stats.sentBidsSuccessful + identityInfo.stats.recvBidsSuccessful}
+                                </div>
+                                <div class="text-white">Successful</div>
+                            </div>
+                            <div>
+                                <div class="text-yellow-600 font-semibold">
+                                    ${identityInfo.stats.sentBidsRejected + identityInfo.stats.recvBidsRejected}
+                                </div>
+                                <div class="text-white">Rejected</div>
+                            </div>
+                            <div>
+                                <div class="text-red-600 font-semibold">
+                                    ${identityInfo.stats.sentBidsFailed + identityInfo.stats.recvBidsFailed}
+                                </div>
+                                <div class="text-white">Failed</div>
+                            </div>
+                        </div>
+                    </div>
+                ` : ''}
+            </div>
+            <div class="tooltip-arrow" data-popper-arrow></div>
+        </div>`;
+}
+
 function createTooltipContent(isSentOffers, coinFrom, coinTo, fromAmount, toAmount, isOwnOffer) {
     if (!coinFrom || !coinTo) {
         //console.error(`Invalid coin names: coinFrom=${coinFrom}, coinTo=${coinTo}`);
@@ -1890,19 +2125,31 @@ function applyFilters() {
             filterTimeout = null;
         }, 250);
     } catch (error) {
-        //console.error('Error in filter timeout:', error);
+        console.error('Error in filter timeout:', error);
         filterTimeout = null;
     }
 }
 
 function clearFilters() {
+
     filterForm.reset();
+
+    const selectElements = filterForm.querySelectorAll('select');
+    selectElements.forEach(select => {
+        select.value = 'any';
+        // Trigger change event
+        const event = new Event('change', { bubbles: true });
+        select.dispatchEvent(event);
+    });
+
     const statusSelect = document.getElementById('status');
     if (statusSelect) {
         statusSelect.value = 'any';
     }
+
     jsonData = [...originalJsonData];
     currentPage = 1;
+
     updateOffersTable();
     updateJsonView();
     updateCoinFilterImages();
@@ -1916,26 +2163,18 @@ function hasActiveFilters() {
         coin_from: formData.get('coin_from'),
         status: formData.get('status')
     };
-    
-    //console.log('Current filters:', filters);
-    const hasFilters = 
-        filters.coin_to !== 'any' || 
-        filters.coin_from !== 'any' || 
-        (filters.status && filters.status !== 'any');                     
-    //console.log('Has active filters:', hasFilters);
-    
-    return hasFilters;
-}
 
-function getActiveFilters() {
-    const formData = new FormData(filterForm);
-    return {
-        coin_to: formData.get('coin_to'),
-        coin_from: formData.get('coin_from'),
-        status: formData.get('status')
-    };
-}
+    const selectElements = filterForm.querySelectorAll('select');
+    let hasChangedFilters = false;
+    
+    selectElements.forEach(select => {
+        if (select.value !== 'any') {
+            hasChangedFilters = true;
+        }
+    });
 
+    return hasChangedFilters;
+}
 // UTILITY FUNCTIONS
 function formatTimeLeft(timestamp) {
     const now = Math.floor(Date.now() / 1000);
@@ -2075,7 +2314,6 @@ function getCoinSymbol(fullName) {
 }
 
 // EVENT LISTENERS
-
 document.querySelectorAll('th[data-sortable="true"]').forEach(header => {
     header.addEventListener('click', () => {
         const columnIndex = parseInt(header.getAttribute('data-column-index'));
@@ -2192,12 +2430,24 @@ const timerManager = {
 };
 
 // INITIALIZATION AND EVENT BINDING
-
 document.addEventListener('DOMContentLoaded', () => {
     //console.log('DOM content loaded, initializing...');
     console.log('View type:', isSentOffers ? 'sent offers' : 'received offers');
 
     updateClearFiltersButton();
+    
+    // Add event listeners for filter controls
+    const selectElements = filterForm.querySelectorAll('select');
+    selectElements.forEach(select => {
+        select.addEventListener('change', () => {
+            updateClearFiltersButton();
+        });
+    });
+    
+    filterForm.addEventListener('change', () => {
+        applyFilters();
+        updateClearFiltersButton();
+    });
 
     setTimeout(() => {
         console.log('Starting WebSocket initialization...');
@@ -2215,7 +2465,7 @@ document.addEventListener('DOMContentLoaded', () => {
                 clearInterval(retryInterval);
                 continueInitialization();
             } else if (retryCount >= maxRetries) {
-                //console.error('❌ Failed to load tableRateModule after multiple attempts');
+                //console.error('Failed to load tableRateModule after multiple attempts');
                 clearInterval(retryInterval);
                 continueInitialization();
             }
@@ -2255,47 +2505,47 @@ document.addEventListener('DOMContentLoaded', () => {
     });
 
     eventListeners.add(document.getElementById('refreshOffers'), 'click', async () => {
-    console.log('Manual refresh initiated');
-    
-    const refreshButton = document.getElementById('refreshOffers');
-    const refreshIcon = document.getElementById('refreshIcon');
-    const refreshText = document.getElementById('refreshText');
+        console.log('Manual refresh initiated');
+        
+        const refreshButton = document.getElementById('refreshOffers');
+        const refreshIcon = document.getElementById('refreshIcon');
+        const refreshText = document.getElementById('refreshText');
 
-    refreshButton.disabled = true;
-    refreshIcon.classList.add('animate-spin');
-    refreshText.textContent = 'Refreshing...';
-    refreshButton.classList.add('opacity-75', 'cursor-wait');
+        refreshButton.disabled = true;
+        refreshIcon.classList.add('animate-spin');
+        refreshText.textContent = 'Refreshing...';
+        refreshButton.classList.add('opacity-75', 'cursor-wait');
 
-    try {
-        const endpoint = isSentOffers ? '/json/sentoffers' : '/json/offers';
-        const response = await fetch(endpoint);
-        if (!response.ok) {
-            throw new Error(`HTTP error! status: ${response.status}`);
+        try {
+            const endpoint = isSentOffers ? '/json/sentoffers' : '/json/offers';
+            const response = await fetch(endpoint);
+            if (!response.ok) {
+                throw new Error(`HTTP error! status: ${response.status}`);
+            }
+            const newData = await response.json();
+
+            const processedNewData = Array.isArray(newData) ? newData : Object.values(newData);
+            console.log('Fetched offers:', processedNewData.length);
+
+            jsonData = formatInitialData(processedNewData);
+            originalJsonData = [...jsonData];
+            
+            await updateOffersTable();
+            updateJsonView();
+            updatePaginationInfo();
+            
+            console.log(' Manual refresh completed successfully');
+            
+        } catch (error) {
+            console.error('Error during manual refresh:', error);
+            ui.displayErrorMessage('Failed to refresh offers. Please try again later.');
+        } finally {
+            refreshButton.disabled = false;
+            refreshIcon.classList.remove('animate-spin');
+            refreshText.textContent = 'Refresh';
+            refreshButton.classList.remove('opacity-75', 'cursor-wait');
         }
-        const newData = await response.json();
-
-        const processedNewData = Array.isArray(newData) ? newData : Object.values(newData);
-        console.log('Fetched offers:', processedNewData.length);
-
-        jsonData = formatInitialData(processedNewData);
-        originalJsonData = [...jsonData];
-        
-        await updateOffersTable();
-        updateJsonView();
-        updatePaginationInfo();
-        
-        console.log('βœ… Manual refresh completed successfully');
-        
-    } catch (error) {
-        console.error('❌ Error during manual refresh:', error);
-        ui.displayErrorMessage('Failed to refresh offers. Please try again later.');
-    } finally {
-        refreshButton.disabled = false;
-        refreshIcon.classList.remove('animate-spin');
-        refreshText.textContent = 'Refresh';
-        refreshButton.classList.remove('opacity-75', 'cursor-wait');
-    }
-});
+    });
 
     eventListeners.add(prevPageButton, 'click', () => {
         if (currentPage > 1) {
@@ -2332,7 +2582,7 @@ document.addEventListener('DOMContentLoaded', () => {
         //console.log('Initial offers fetched');
         applyFilters();
     }).catch(error => {
-        console.error('❌ Error fetching initial offers:', error);
+        console.error('Error fetching initial offers:', error);
     });
 
     const listingLabel = document.querySelector('span[data-listing-label]');
@@ -2351,7 +2601,7 @@ document.addEventListener('DOMContentLoaded', () => {
         }
     });
 
-    console.log('βœ… Initialization completed');
+    console.log('Initialization completed');
 });
 
 console.log('Offers Table Module fully initialized');
diff --git a/basicswap/templates/offer_new_1.html b/basicswap/templates/offer_new_1.html
index 00a5464..e85d32c 100644
--- a/basicswap/templates/offer_new_1.html
+++ b/basicswap/templates/offer_new_1.html
@@ -86,7 +86,7 @@
                     <select class="pl-10 hover:border-blue-500 pl-10 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="addr_to">
                       <option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">Public Network</option>
                         {% for a in addrs_to %}
-                        <option{% if data.addr_to==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option>
+                        <option{% if data.addr_to==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} ({{ a[1] }})</option>
                         {% endfor %}
                     </select>
                   </div>
@@ -471,7 +471,7 @@ if (document.readyState === 'loading') {
     }
 
     function getRateInferred(event) {
-        event.preventDefault(); // Prevent default form submission behavior
+        event.preventDefault();
 
         const coin_from = document.getElementById('coin_from').value;
         const coin_to = document.getElementById('coin_to').value;
@@ -558,7 +558,7 @@ if (document.readyState === 'loading') {
                 return;
             } else
             if (amt_from == '' && amt_to != '') {
-                if (value_changed == 'amt_from') {  // Don't try and set a value just cleared
+                if (value_changed == 'amt_from') {
                     return;
                 }
                 params += '&rate=' + rate + '&amt_to=' + amt_to;
diff --git a/basicswap/templates/offers.html b/basicswap/templates/offers.html
index 9153180..48bbbb7 100644
--- a/basicswap/templates/offers.html
+++ b/basicswap/templates/offers.html
@@ -290,6 +290,18 @@ function getWebSocketConfig() {
                         {% endif %}
                       </div>
                     </div>
+                    <div class="pt-3 px-3 md:w-auto hover-container">
+                    <div class="flex">
+                     <div class="relative">
+                       {{ input_arrow_down_svg | safe }}
+                       <select name="sent_from" id="sent_from" class="bg-gray-50 text-gray-900 appearance-none pr-10 pl-5 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-50 text-sm rounded-lg outline-none block w-full p-2.5 focus:ring-0">
+                        <option value="any" {% if not filters.sent_from %} selected{% endif %}>All Offers</option>
+                        <option value="public" {% if filters.sent_from == 'public' %} selected{% endif %}>Public</option>
+                        <option value="private" {% if filters.sent_from == 'private' %} selected{% endif %}>Private</option>
+                       </select>
+                        </div>
+                      </div>
+                     </div>
                     <div class="w-full md:w-auto pt-3 px-3">
                       <div class="relative">
                         <button type="button" id="clearFilters" class="transition-opacity duration-200 flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm hover:text-white dark:text-white dark:bg-gray-500 bg-coolGray-200 hover:bg-green-600 hover:border-green-600 rounded-lg transition duration-200 border border-coolGray-200 dark:border-gray-400 rounded-md shadow-button focus:ring-0 focus:outline-none" disabled>
@@ -322,15 +334,20 @@ function getWebSocketConfig() {
   <div id="jsonView" class="hidden mb-4">
     <pre id="jsonContent" class="bg-gray-100 p-4 rounded overflow-auto" style="max-height: 300px;"></pre>
   </div>
-  <div class="container mt-5 mx-auto">
+  <div class="container mt-5 mx-auto px-4">
     <div class="pt-0 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
       <div class="px-0">
-        <div class="w-auto mt-6 pb-6 overflow-x-auto">
+        <div class="w-auto mt-6 overflow-x-auto">
           <table class="w-full min-w-max">
             <thead class="uppercase">
               <tr>
                 <th class="p-0" data-sortable="true" data-column-index="0">
                   <div class="py-3 pl-4 justify-center rounded-tl-xl bg-coolGray-200 dark:bg-gray-600">
+                    <span class="text-sm mr-1 text-gray-600 dark:text-gray-300 font-semibold"></span>
+                  </div>
+                </th>
+                <th class="p-0" data-sortable="true" data-column-index="0">
+                  <div class="py-3 pl-4 justify-center bg-coolGray-200 dark:bg-gray-600">
                     <span class="text-sm mr-1 text-gray-600 dark:text-gray-300 font-semibold">Time</span>
                      <span class="sort-icon ml-1 text-gray-600 dark:text-gray-400" id="sort-icon-0">↓</span>
                   </div>
@@ -399,19 +416,19 @@ function getWebSocketConfig() {
       <div class="rounded-b-md">
         <div class="w-full">
           <div class="flex flex-wrap justify-between items-center pl-6 pt-6 pr-6 border-t border-gray-100 dark:border-gray-400">
-<div class="flex items-center">
-    <div class="flex items-center mr-4">
-        <span id="status-dot" class="w-2.5 h-2.5 rounded-full bg-gray-500 mr-2"></span>
-        <span id="status-text" class="text-sm text-gray-500">Connecting...</span>
-    </div>
-    <p class="text-sm font-heading dark:text-gray-400 mr-4">
-        Last refreshed: <span id="lastRefreshTime">Never</span>
-    </p>
-    <p class="text-sm font-heading dark:text-gray-400 mr-4">
-        <span data-listing-label>Network Listings: </span>
-        <span id="newEntriesCount"></span>
-    </p>
-</div>
+          <div class="flex items-center">
+           <div class="flex items-center mr-4">
+            <span id="status-dot" class="w-2.5 h-2.5 rounded-full bg-gray-500 mr-2"></span>
+            <span id="status-text" class="text-sm text-gray-500">Connecting...</span>
+           </div>
+             <p class="text-sm font-heading dark:text-gray-400 mr-4">
+              Last refreshed: <span id="lastRefreshTime">Never</span>
+             </p>
+             <p class="text-sm font-heading dark:text-gray-400 mr-4">
+             <span data-listing-label>Network Listings: </span>
+             <span id="newEntriesCount"></span>
+             </p>
+           </div>
             <div class="flex items-center space-x-2">
               <button type="button" id="prevPage" class="inline-flex items-center h-9 py-1 px-4 text-xs text-blue-50 font-semibold bg-blue-500 hover:bg-green-600 rounded-lg transition duration-200 focus:ring-0 focus:outline-none">
                 {{ page_back_svg | safe }}
diff --git a/basicswap/ui/page_offers.py b/basicswap/ui/page_offers.py
index f89f4d6..9f76e41 100644
--- a/basicswap/ui/page_offers.py
+++ b/basicswap/ui/page_offers.py
@@ -528,6 +528,15 @@ def page_newoffer(self, url_split, post_string):
 
     coins_from, coins_to = listAvailableCoins(swap_client, split_from=True)
 
+    addrs_from_raw = swap_client.listSMSGAddresses("offer_send_from")
+    addrs_to_raw = swap_client.listSMSGAddresses("offer_send_to")
+
+    all_addresses = swap_client.listAllSMSGAddresses({})
+    addr_notes = {addr["addr"]: addr["note"] for addr in all_addresses}
+
+    addrs_from = [(addr[0], addr_notes.get(addr[0], "")) for addr in addrs_from_raw]
+    addrs_to = [(addr[0], addr_notes.get(addr[0], "")) for addr in addrs_to_raw]
+
     automation_filters = {"type_ind": Concepts.OFFER, "sort_by": "label"}
     automation_strategies = swap_client.listAutomationStrategies(automation_filters)
 
@@ -556,8 +565,8 @@ def page_newoffer(self, url_split, post_string):
             "err_messages": err_messages,
             "coins_from": coins_from,
             "coins": coins_to,
-            "addrs": swap_client.listSMSGAddresses("offer_send_from"),
-            "addrs_to": swap_client.listSMSGAddresses("offer_send_to"),
+            "addrs": addrs_from,
+            "addrs_to": addrs_to,
             "data": page_data,
             "automation_strategies": automation_strategies,
             "summary": summary,
@@ -581,7 +590,7 @@ def page_offer(self, url_split, post_string):
     offer, xmr_offer = swap_client.getXmrOffer(offer_id)
     ensure(offer, "Unknown offer ID")
 
-    extend_data = {  # Defaults
+    extend_data = {
         "nb_validmins": 10,
     }
     messages = []
@@ -598,7 +607,6 @@ def page_offer(self, url_split, post_string):
 
     reverse_bid: bool = True if offer.bid_reversed else False
 
-    # Set defaults
     debugind = -1
     bid_amount = ci_from.format_amount(offer.amount_from)
     bid_rate = ci_to.format_amount(offer.rate)
@@ -617,7 +625,6 @@ def page_offer(self, url_split, post_string):
             except Exception as ex:
                 err_messages.append("Revoke offer failed: " + str(ex))
         elif b"repeat_offer" in form_data:
-            # Can't set the post data here as browsers will always resend the original post data when responding to redirects
             self.send_response(302)
             self.send_header("Location", "/newoffer?offer_from=" + offer_id.hex())
             self.end_headers()