ui: Add option to remove expired offers and bids.

2024-05-20_merge
tecnovert 2 years ago
parent 1dcd750fea
commit cbb3d0ac02
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
  1. 9
      basicswap/basicswap.py
  2. 3
      basicswap/basicswap_util.py
  3. 54
      basicswap/db_util.py
  4. 29
      basicswap/http_server.py
  5. 14
      basicswap/templates/debug.html
  6. 10
      basicswap/templates/wallets.html
  7. 54
      basicswap/ui/page_debug.py
  8. 1
      doc/release-notes.md

@ -145,6 +145,7 @@ from .basicswap_util import (
NotificationTypes as NT, NotificationTypes as NT,
AutomationOverrideOptions, AutomationOverrideOptions,
VisibilityOverrideOptions, VisibilityOverrideOptions,
inactive_states,
) )
@ -6109,6 +6110,12 @@ class BasicSwap(BaseApp):
session.remove() session.remove()
self.mxDB.release() self.mxDB.release()
def activeBidsQueryStr(self, now: int, offer_table: str = 'offers', bids_table: str = 'bids'):
offers_inset = f' AND {offer_table}.expire_at > {now}' if offer_table != '' else ''
inactive_states_str = ', '.join([str(int(s)) for s in inactive_states])
return f' ({bids_table}.state NOT IN ({inactive_states_str}) AND ({bids_table}.state > {BidStates.BID_RECEIVED} OR ({bids_table}.expire_at > {now}{offers_inset}))) '
def listBids(self, sent=False, offer_id=None, for_html=False, filters={}): def listBids(self, sent=False, offer_id=None, for_html=False, filters={}):
self.mxDB.acquire() self.mxDB.acquire()
try: try:
@ -6139,7 +6146,7 @@ class BasicSwap(BaseApp):
with_available_or_active = filters.get('with_available_or_active', False) with_available_or_active = filters.get('with_available_or_active', False)
with_expired = filters.get('with_expired', True) with_expired = filters.get('with_expired', True)
if with_available_or_active: if with_available_or_active:
query_str += 'AND (bids.state NOT IN ({}, {}, {}, {}, {}) AND (bids.state > {} OR (bids.expire_at > {} AND offers.expire_at > {}))) '.format(BidStates.SWAP_COMPLETED, BidStates.BID_ERROR, BidStates.BID_REJECTED, BidStates.SWAP_TIMEDOUT, BidStates.BID_ABANDONED, BidStates.BID_RECEIVED, now, now) query_str += ' AND ' + self.activeBidsQueryStr(now)
else: else:
if with_expired is not True: if with_expired is not True:
query_str += 'AND bids.expire_at > {} AND offers.expire_at > {} '.format(now, now) query_str += 'AND bids.expire_at > {} AND offers.expire_at > {} '.format(now, now)

@ -506,3 +506,6 @@ def strSwapDesc(swap_type):
if swap_type == SwapTypes.XMR_SWAP: if swap_type == SwapTypes.XMR_SWAP:
return 'Adaptor Sig' return 'Adaptor Sig'
return None return None
inactive_states = [BidStates.SWAP_COMPLETED, BidStates.BID_ERROR, BidStates.BID_REJECTED, BidStates.SWAP_TIMEDOUT, BidStates.BID_ABANDONED]

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2023 The BSX Developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from .db import (
Concepts,
)
def remove_expired_data(self):
self.log.warning('Removing expired data')
now: int = self.getTime()
try:
session = self.openSession()
active_bids_insert = self.activeBidsQueryStr(now, '', 'b2')
query_str = f'''
SELECT o.offer_id FROM offers o
WHERE o.expire_at <= :now AND 0 = (SELECT COUNT(*) FROM bids b2 WHERE b2.offer_id = o.offer_id AND {active_bids_insert})
'''
num_offers = 0
num_bids = 0
offer_rows = session.execute(query_str, {'now': now})
for offer_row in offer_rows:
num_offers += 1
bid_rows = session.execute('SELECT bids.bid_id FROM bids WHERE bids.offer_id = :offer_id', {'offer_id': offer_row[0]})
for bid_row in bid_rows:
num_bids += 1
session.execute('DELETE FROM transactions WHERE transactions.bid_id = :bid_id', {'bid_id': bid_row[0]})
session.execute('DELETE FROM eventlog WHERE eventlog.linked_type = :type_ind AND eventlog.linked_id = :bid_id', {'type_ind': int(Concepts.BID), 'bid_id': bid_row[0]})
session.execute('DELETE FROM automationlinks WHERE automationlinks.linked_type = :type_ind AND automationlinks.linked_id = :bid_id', {'type_ind': int(Concepts.BID), 'bid_id': bid_row[0]})
session.execute('DELETE FROM prefunded_transactions WHERE prefunded_transactions.linked_type = :type_ind AND prefunded_transactions.linked_id = :bid_id', {'type_ind': int(Concepts.BID), 'bid_id': bid_row[0]})
session.execute('DELETE FROM history WHERE history.concept_type = :type_ind AND history.concept_id = :bid_id', {'type_ind': int(Concepts.BID), 'bid_id': bid_row[0]})
session.execute('DELETE FROM xmr_swaps WHERE xmr_swaps.bid_id = :bid_id', {'bid_id': bid_row[0]})
session.execute('DELETE FROM actions WHERE actions.linked_id = :bid_id', {'bid_id': bid_row[0]})
session.execute('DELETE FROM addresspool WHERE addresspool.bid_id = :bid_id', {'bid_id': bid_row[0]})
session.execute('DELETE FROM xmr_split_data WHERE xmr_split_data.bid_id = :bid_id', {'bid_id': bid_row[0]})
session.execute('DELETE FROM bids WHERE bids.bid_id = :bid_id', {'bid_id': bid_row[0]})
session.execute('DELETE FROM eventlog WHERE eventlog.linked_type = :type_ind AND eventlog.linked_id = :offer_id', {'type_ind': int(Concepts.OFFER), 'offer_id': offer_row[0]})
session.execute('DELETE FROM automationlinks WHERE automationlinks.linked_type = :type_ind AND automationlinks.linked_id = :offer_id', {'type_ind': int(Concepts.OFFER), 'offer_id': offer_row[0]})
session.execute('DELETE FROM prefunded_transactions WHERE prefunded_transactions.linked_type = :type_ind AND prefunded_transactions.linked_id = :offer_id', {'type_ind': int(Concepts.OFFER), 'offer_id': offer_row[0]})
session.execute('DELETE FROM history WHERE history.concept_type = :type_ind AND history.concept_id = :offer_id', {'type_ind': int(Concepts.OFFER), 'offer_id': offer_row[0]})
session.execute('DELETE FROM xmr_offers WHERE xmr_offers.offer_id = :offer_id', {'offer_id': offer_row[0]})
session.execute('DELETE FROM sentoffers WHERE sentoffers.offer_id = :offer_id', {'offer_id': offer_row[0]})
session.execute('DELETE FROM actions WHERE actions.linked_id = :offer_id', {'offer_id': offer_row[0]})
session.execute('DELETE FROM offers WHERE offers.offer_id = :offer_id', {'offer_id': offer_row[0]})
self.log.warning(f'Removed data for {num_offers} expired offers and {num_bids} bids.')
finally:
self.closeSession(session)

@ -38,7 +38,6 @@ from .ui.util import (
getCoinName, getCoinName,
get_data_entry, get_data_entry,
get_data_entry_or, get_data_entry_or,
have_data_entry,
listAvailableCoins, listAvailableCoins,
) )
from .ui.page_automation import ( from .ui.page_automation import (
@ -55,6 +54,7 @@ from .ui.page_settings import page_settings
from .ui.page_encryption import page_changepassword, page_unlock, page_lock from .ui.page_encryption import page_changepassword, page_unlock, page_lock
from .ui.page_identity import page_identity from .ui.page_identity import page_identity
from .ui.page_smsgaddresses import page_smsgaddresses from .ui.page_smsgaddresses import page_smsgaddresses
from .ui.page_debug import page_debug
env = Environment(loader=PackageLoader('basicswap', 'templates')) env = Environment(loader=PackageLoader('basicswap', 'templates'))
env.filters['formatts'] = format_timestamp env.filters['formatts'] = format_timestamp
@ -333,31 +333,6 @@ class HttpHandler(BaseHTTPRequestHandler):
'summary': summary, 'summary': summary,
}) })
def page_debug(self, url_split, post_string):
swap_client = self.server.swap_client
swap_client.checkSystemStatus()
summary = swap_client.getSummary()
result = None
messages = []
err_messages = []
form_data = self.checkForm(post_string, 'wallets', err_messages)
if form_data:
if have_data_entry(form_data, 'reinit_xmr'):
try:
swap_client.initialiseWallet(Coins.XMR)
messages.append('Done.')
except Exception as a:
err_messages.append('Failed.')
template = env.get_template('debug.html')
return self.render_template(template, {
'messages': messages,
'err_messages': err_messages,
'result': result,
'summary': summary,
})
def page_active(self, url_split, post_string): def page_active(self, url_split, post_string):
swap_client = self.server.swap_client swap_client = self.server.swap_client
swap_client.checkSystemStatus() swap_client.checkSystemStatus()
@ -502,7 +477,7 @@ class HttpHandler(BaseHTTPRequestHandler):
if page == 'rpc': if page == 'rpc':
return self.page_rpc(url_split, post_string) return self.page_rpc(url_split, post_string)
if page == 'debug': if page == 'debug':
return self.page_debug(url_split, post_string) return page_debug(self, url_split, post_string)
if page == 'explorers': if page == 'explorers':
return self.page_explorers(url_split, post_string) return self.page_explorers(url_split, post_string)
if page == 'offer': if page == 'offer':

@ -67,6 +67,13 @@
</tr> </tr>
</thead> </thead>
<form method="post"> <form method="post">
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Remove expired offers and bids</td>
<td td class="py-3 px-6 ">
<button name="remove_expired" type="submit" value="Yes" class="flex flex-wrap justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" onclick="return confirmRemoveExpired();">
Yes - Remove Data</button>
</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100"> <tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Reinitialise XMR wallet</td> <td class="py-3 px-6 bold">Reinitialise XMR wallet</td>
<td td class="py-3 px-6 "> <td td class="py-3 px-6 ">
@ -82,8 +89,8 @@
</g> </g>
</svg>Yes - Start Process</button> </svg>Yes - Start Process</button>
</td> </td>
<input type="hidden" name="formid" value="{{ form_id }}">
</tr> </tr>
<input type="hidden" name="formid" value="{{ form_id }}">
</form> </form>
</table> </table>
</div> </div>
@ -121,4 +128,9 @@
{% include 'footer.html' %} {% include 'footer.html' %}
</div> </div>
</body> </body>
<script>
function confirmRemoveExpired() {
return confirm("This will remove all expired offers and bids from the database - Are you sure?");
}
</script>
</html> </html>

@ -142,15 +142,7 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
<!-- havedata --> <!-- havedata -->
</div> {% endfor %} <script> </div> {% endfor %}
function confirmReseed() {
return confirm("Are you sure?\nBackup your wallet before and after.\nWon't detect used keys.\nShould only be used for new wallets.");
}
function confirmWithdrawal() {
return confirm("Are you sure?");
}
</script>
</div> </div>
</section> </section>
</div> </div>

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2023 The BSX Developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import traceback
from .util import (
have_data_entry,
)
from basicswap.chainparams import (
Coins,
)
from basicswap.db_util import (
remove_expired_data,
)
def page_debug(self, url_split, post_string):
server = self.server
swap_client = server.swap_client
swap_client.checkSystemStatus()
summary = swap_client.getSummary()
result = None
messages = []
err_messages = []
form_data = self.checkForm(post_string, 'wallets', err_messages)
if form_data:
if have_data_entry(form_data, 'reinit_xmr'):
try:
swap_client.initialiseWallet(Coins.XMR)
messages.append('Done.')
except Exception as e:
err_messages.append('Failed.')
if have_data_entry(form_data, 'remove_expired'):
try:
remove_expired_data(swap_client)
messages.append('Done.')
except Exception as e:
if swap_client.debug is True:
swap_client.log.error(traceback.format_exc())
else:
swap_client.log.error(f'remove_expired_data: {e}')
err_messages.append('Failed.')
template = server.env.get_template('debug.html')
return self.render_template(template, {
'messages': messages,
'err_messages': err_messages,
'result': result,
'summary': summary,
})

@ -3,6 +3,7 @@
============== ==============
- cores: Raised Particl and Monero daemon version. - cores: Raised Particl and Monero daemon version.
- ui: Add debug option to remove expired offers, bids and transactions.
0.0.62 0.0.62

Loading…
Cancel
Save