Fix DOGE fee calculation bug and improve UI consistency
- Fix negative DOGE processing fees from estimatesmartfee RPC issues - Add abs() protection for both DOGE and Monero fee calculations - Reduce transaction size estimate from 0.25KB to 0.15KB (more realistic) - Change fee multiplier from 2x to 1.5x (less excessive) - Set reasonable fallback fee of 0.5 DOGE when RPC fails - Add negative feerate detection with proper error handling - Fix crypto payment status color mapping (case insensitive lookup) - Add missing status mappings for confirmed-overpay-complete and doublepay-refund-complete - Improve comment system UI with dark mode styling and better layout - Add CSS preloader to prevent trans-background image flashing - Enhance user settings page with better button organization - Remove "View Quote" button for cancelled crypto quotes - Fix comment form styling and authentication flow
This commit is contained in:
parent
c61811293e
commit
f5d68ba267
10 changed files with 240 additions and 55 deletions
BIN
docs/state-machine.png
Normal file
BIN
docs/state-machine.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 275 KiB |
|
|
@ -7,6 +7,22 @@
|
|||
*
|
||||
* * * * * */
|
||||
|
||||
/* Preload hover background images to prevent flash */
|
||||
body::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
z-index: -1;
|
||||
background-image:
|
||||
url("/static/img/trans-blue.png"),
|
||||
url("/static/img/trans-green.png"),
|
||||
url("/static/img/trans-red.png"),
|
||||
url("/static/img/trans-blue2.png"),
|
||||
url("/static/img/trans-green2.png"),
|
||||
url("/static/img/trans-red2.png");
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0px;
|
||||
|
|
@ -411,6 +427,28 @@ input.mps-button-red {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Red cancel button */
|
||||
.mps-cancel-button-red {
|
||||
background: var(--red-color);
|
||||
color: white;
|
||||
border-color: var(--red-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mps-cancel-button-red {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-red.png");
|
||||
border: 2px solid var(--red-color);
|
||||
color: var(--red-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mps-cancel-button-red:hover {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-red2.png");
|
||||
color: #ffffff;
|
||||
border: 2px solid var(--red-color);
|
||||
}
|
||||
|
||||
.comment-actions {
|
||||
margin-bottom: 42px;
|
||||
display: grid;
|
||||
|
|
@ -438,6 +476,92 @@ input.mps-button-red {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Light mode color styling */
|
||||
.reply-link {
|
||||
background: var(--green-color);
|
||||
color: white;
|
||||
border-color: var(--green-color);
|
||||
}
|
||||
|
||||
.delete-link {
|
||||
background: var(--red-color);
|
||||
color: white;
|
||||
border-color: var(--red-color);
|
||||
}
|
||||
|
||||
.mps-comment-form-button {
|
||||
background: var(--green-color);
|
||||
color: white;
|
||||
border-color: var(--green-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .reply-link,
|
||||
[data-theme="dark"] .edit-link,
|
||||
[data-theme="dark"] .moderate-link {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-blue.png");
|
||||
border: 2px solid var(--blue-color);
|
||||
color: var(--blue-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .reply-link:hover,
|
||||
[data-theme="dark"] .edit-link:hover,
|
||||
[data-theme="dark"] .moderate-link:hover {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-blue2.png");
|
||||
color: #ffffff;
|
||||
border: 2px solid var(--blue-color);
|
||||
}
|
||||
|
||||
/* Reply button - green */
|
||||
[data-theme="dark"] .reply-link {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-green.png");
|
||||
border: 2px solid var(--green-color);
|
||||
color: var(--green-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .reply-link:hover {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-green2.png");
|
||||
color: #ffffff;
|
||||
border: 2px solid var(--green-color);
|
||||
}
|
||||
|
||||
/* Delete button - red */
|
||||
[data-theme="dark"] .delete-link {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-red.png");
|
||||
border: 2px solid var(--red-color);
|
||||
color: var(--red-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .delete-link:hover {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-red2.png");
|
||||
color: #ffffff;
|
||||
border: 2px solid var(--red-color);
|
||||
}
|
||||
|
||||
/* Post comment button - green */
|
||||
[data-theme="dark"] .mps-comment-form-button {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-green.png");
|
||||
border: 2px solid var(--green-color);
|
||||
color: var(--green-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mps-comment-form-button:hover {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-green2.png");
|
||||
color: #ffffff;
|
||||
border: 2px solid var(--green-color);
|
||||
}
|
||||
|
||||
.payment-toggle-button {
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
|
|
@ -1339,27 +1463,31 @@ div.message-ribbon {
|
|||
/* Flash message styling for dark mode */
|
||||
[data-theme="dark"] .alert-danger,
|
||||
[data-theme="dark"] .alert-error {
|
||||
color: #ff6b6b;
|
||||
background-color: #2d1f20;
|
||||
border-color: #ff6b6b;
|
||||
color: var(--red-color);
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-red2.png");
|
||||
border-color: var(--red-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .alert-warning {
|
||||
color: #ffd93d;
|
||||
background-color: #2d2a1f;
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-red2.png");
|
||||
border-color: #ffd93d;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .alert-info,
|
||||
[data-theme="dark"] .alert-notice {
|
||||
color: var(--blue-color);
|
||||
background-color: #1f252d;
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-blue2.png");
|
||||
border-color: var(--blue-color);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .alert-success {
|
||||
color: var(--green-color);
|
||||
background-color: #1f2d1f;
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-green2.png");
|
||||
border-color: var(--green-color);
|
||||
}
|
||||
|
||||
|
|
@ -1715,6 +1843,25 @@ img.crypto-button-icon {
|
|||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .original-comment-box {
|
||||
background-color: #2d3748;
|
||||
background-image: url("/static/img/trans-blue.png");
|
||||
border-left: 4px solid var(--blue-color);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Comment reply styling */
|
||||
.comment-reply {
|
||||
margin-left: 0px;
|
||||
margin-bottom: 20px;
|
||||
border-left: 2px solid #ddd;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .comment-reply {
|
||||
border-left: 2px solid var(--blue-color);
|
||||
}
|
||||
|
||||
.start-button-icon {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
{% block title %}Edit Comment{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<section class="one-column">
|
||||
<h2>Edit Comment</h2>
|
||||
|
||||
<div class="original-comment original-comment-box">
|
||||
|
|
@ -18,14 +18,16 @@
|
|||
|
||||
<form method="post" action="/comments/{{ comment.id }}/edit">
|
||||
<div class="form-group">
|
||||
<label for="comment_data">Edit Your Comment:</label>
|
||||
<textarea name="data" id="comment_data" rows="6" cols="80" required placeholder="Edit your comment... (You can use Markdown formatting)">{{ comment.data }}</textarea>
|
||||
<label for="comment-data">Edit Your Comment:</label>
|
||||
<textarea name="data" id="comment-data" rows="6" style="width: 100%;" required placeholder="Edit your comment... (You can use Markdown formatting)">{{ comment.data }}</textarea>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ product.absolute_url(request) }}" class="mps-cancel-button">Cancel</a>
|
||||
<a href="{{ product.absolute_url(request) }}" class="mps-cancel-button mps-cancel-button-red">Cancel</a>
|
||||
<input type="submit" value="Update Comment" class="mps-comment-form-button" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
{% block title %}Reply to Comment{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<section class="one-column">
|
||||
<h2>Reply to Comment</h2>
|
||||
|
||||
<div class="original-comment original-comment-box">
|
||||
|
|
@ -18,14 +18,16 @@
|
|||
|
||||
<form method="post" action="{{ request.route_url('comment_reply', comment_id=parent_comment.id) }}">
|
||||
<div class="form-group">
|
||||
<label for="comment_data">Your Reply:</label>
|
||||
<textarea name="data" id="comment_data" rows="6" cols="80" required placeholder="Write your reply... (You can use Markdown formatting)"></textarea>
|
||||
<label for="comment-data">Your Reply:</label>
|
||||
<textarea name="data" id="comment-data" rows="6" style="width: 100%;" required placeholder="Write your reply... (You can use Markdown formatting)"></textarea>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ product.absolute_url(request) }}" class="mps-cancel-button">Cancel</a>
|
||||
<a href="{{ product.absolute_url(request) }}" class="mps-cancel-button mps-cancel-button-red">Cancel</a>
|
||||
<input type="submit" value="Post Reply" class="mps-comment-form-button" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
{% block content -%}
|
||||
|
||||
<section class="two-column">
|
||||
<section class="one-column">
|
||||
|
||||
<div class="product-images">
|
||||
{% if "thumbnail1" in product.extensions %}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
<a href="{{ request.route_url('crypto_quote', payment_id=payment.id) }}" class="mps-button mps-button-small mps-button-blue">
|
||||
View Quote
|
||||
</a>
|
||||
{% elif payment.status.endswith('-refunded') or payment.status.endswith('-refunded-complete') or payment.status == 'cancelled' %}
|
||||
{% elif payment.status.endswith('-refunded') or payment.status.endswith('-refunded-complete') %}
|
||||
<a href="{{ request.route_url('crypto_quote', payment_id=payment.id) }}" class="mps-button mps-button-small mps-button-blue">
|
||||
View Quote
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
</div>
|
||||
|
||||
<section class="product-right">
|
||||
|
||||
<br/>
|
||||
<div class="well">
|
||||
<h1>${{ '{:,.2f}'.format(product.price) }}</h1>
|
||||
|
||||
|
|
@ -59,8 +59,6 @@
|
|||
<a href="{{ signed_get_object_url }}" class="product-download-button mps-button" download>⭳ Download</a>
|
||||
<br/>
|
||||
<br/>
|
||||
<hr/>
|
||||
<br/>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{% macro render_comment(comment, shop, request, max_depth=5) %}
|
||||
{% if comment.depth <= max_depth and (comment.approved or (request.user.authenticated and (shop.is_owner(request.user) or shop.is_editor(request.user)))) %}
|
||||
<div id="comment-{{ comment.id }}" class="comment{% if comment.parent_id %} reply{% endif %}" style="margin-left: {{ comment.depth * 20 }}px; margin-bottom: 20px;{% if comment.parent_id %} border-left: 2px solid #ddd; padding-left: 10px;{% endif %}">
|
||||
<div id="comment-{{ comment.id }}" class="comment{% if comment.parent_id %} reply comment-reply{% endif %}" style="margin-left: {{ comment.depth * 20 }}px; margin-bottom: 20px;">
|
||||
<div class="comment-header">
|
||||
<strong>{{ comment.user.name if comment.user else "Anonymous" }}</strong>
|
||||
<span class="comment-date">{{ comment.ago_string }}</span>
|
||||
|
|
@ -16,13 +16,14 @@
|
|||
{{ comment.data_html | safe }}
|
||||
</div>
|
||||
|
||||
{% if request.user.authenticated %}
|
||||
<div class="comment-actions">
|
||||
{% if request.user.authenticated and (request.user.id == comment.user_id or comment.can_user_moderate(request.user, shop)) %}
|
||||
{% if request.user.id == comment.user_id or comment.can_user_moderate(request.user, shop) %}
|
||||
<input type="submit" value="Delete" class="delete-link" onclick="return confirm('Are you sure you want to delete this comment?')" form="delete-{{ comment.id }}" />
|
||||
<form id="delete-{{ comment.id }}" method="post" action="/comments/{{ comment.id }}/delete" class="hidden-form"></form>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user.authenticated and comment.can_user_moderate(request.user, shop) %}
|
||||
{% if comment.can_user_moderate(request.user, shop) %}
|
||||
{% if comment.approved %}
|
||||
<input type="submit" value="Unapprove" class="moderate-link" form="unapprove-{{ comment.id }}" />
|
||||
<form id="unapprove-{{ comment.id }}" method="post" action="/comments/{{ comment.id }}/unapprove" class="hidden-form"></form>
|
||||
|
|
@ -32,17 +33,18 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if request.user.authenticated and (request.user.id == comment.user_id or comment.can_user_moderate(request.user, shop)) %}
|
||||
{% if request.user.id == comment.user_id or comment.can_user_moderate(request.user, shop) %}
|
||||
<a href="/comments/{{ comment.id }}/edit" class="edit-link">Edit</a>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user.authenticated and not comment.is_locked %}
|
||||
{% if not comment.is_locked %}
|
||||
{% set can_comment, error_msg = comment.can_user_comment(request.user, shop) %}
|
||||
{% if can_comment %}
|
||||
<a href="/comments/{{ comment.id }}/reply" class="reply-link">Reply</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if comment.enabled_children %}
|
||||
{% for child in comment.enabled_children %}
|
||||
|
|
@ -57,7 +59,14 @@
|
|||
<div class="comments-section">
|
||||
{% if comments %}
|
||||
<h3>Comments & Reviews ({{ product.public_comment_count }})</h3>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<!-- Authentication prompt for non-authenticated users -->
|
||||
{% if not request.user.authenticated %}
|
||||
<p><a href="/join-or-log-in">Sign in</a> to leave a comment.</p>
|
||||
{% endif %}
|
||||
|
||||
{% if comments %}
|
||||
{% for comment in comments %}
|
||||
{{ render_comment(comment, shop, request) }}
|
||||
{% endfor %}
|
||||
|
|
@ -78,20 +87,20 @@
|
|||
<input type="hidden" name="parent_id" value="" />
|
||||
|
||||
<div>
|
||||
<label for="comment_data">Comment:</label>
|
||||
<textarea name="data" id="comment_data" rows="4" cols="50" required></textarea>
|
||||
<label for="comment-data">Comment:</label>
|
||||
<textarea name="data" id="comment-data" rows="4" style="width: 100%;" required></textarea>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div>
|
||||
<input type="submit" value="Post Comment" class="mps-comment-form-button" />
|
||||
<input type="submit" value="Send Comment" class="mps-comment-form-button" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="comment-error">{{ error_msg }}</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p><a href="/join-or-log-in">Sign in</a> to leave a comment.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
@ -114,6 +114,7 @@
|
|||
|
||||
<section class="one-column">
|
||||
<section class="well">
|
||||
<h3>Account Actions</h3>
|
||||
|
||||
{% if request.is_saas_domain %}
|
||||
<a href="/u/shops" class="product-edit-button mps-button">My Shops</a>
|
||||
|
|
@ -129,8 +130,11 @@
|
|||
<a href="/u/settings/crypto" class="product-edit-button mps-button">Crypto Payment Preferences</a>
|
||||
<br/>
|
||||
<a href="/u/addresses" class="product-edit-button mps-button">Shipping Addresses</a>
|
||||
<br/>
|
||||
{% endif %}
|
||||
|
||||
<a href="/" class="mps-button mps-button-blue">Back to Shop</a>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1142,11 +1142,13 @@ def estimate_monero_fee_for_quote(settings, shop_sweep_to_address, amount_picone
|
|||
# Double the fee to cover both inbound (customer) and outbound (sweep) transactions
|
||||
total_fee_piconero = estimated_fee_piconero * 2
|
||||
|
||||
return Decimal(total_fee_piconero) / Decimal("1000000000000") # Convert to XMR
|
||||
return abs(
|
||||
Decimal(total_fee_piconero) / Decimal("1000000000000")
|
||||
) # Convert to XMR
|
||||
except Exception as e:
|
||||
# Fallback to hardcoded fee if RPC call fails, doubled for inbound + outbound
|
||||
fallback_fee = float(settings.get("monero.fee_buffer", "0.0001")) * 2
|
||||
return Decimal(str(fallback_fee))
|
||||
return abs(Decimal(str(fallback_fee)))
|
||||
|
||||
|
||||
def estimate_dogecoin_fee_for_quote(settings):
|
||||
|
|
@ -1164,41 +1166,56 @@ def estimate_dogecoin_fee_for_quote(settings):
|
|||
logger.info(f"Dogecoin estimatesmartfee result: {fee_estimate_result}")
|
||||
|
||||
if fee_estimate_result and "feerate" in fee_estimate_result:
|
||||
# feerate is in DOGE per KB, estimate transaction size as ~0.25KB (more realistic)
|
||||
# Typical DOGE transaction is ~225 bytes, not 500 bytes
|
||||
# feerate is in DOGE per KB, estimate transaction size as ~0.15KB (realistic)
|
||||
# Typical DOGE transaction is ~150 bytes for simple transfers
|
||||
network_feerate = float(fee_estimate_result["feerate"])
|
||||
|
||||
# Cap fee rate at reasonable maximum (0.1 DOGE/KB = ~$0.025/KB)
|
||||
# Dogecoin fees should never exceed this under normal conditions
|
||||
max_reasonable_feerate = 0.1
|
||||
# Ensure positive feerate - negative values indicate RPC issues
|
||||
if network_feerate <= 0:
|
||||
logger.warning(
|
||||
f"Invalid negative/zero feerate {network_feerate} from estimatesmartfee, using fallback"
|
||||
)
|
||||
raise ValueError(f"Invalid feerate: {network_feerate}")
|
||||
|
||||
# Cap fee rate at reasonable maximum (100 DOGE/KB = ~$26/KB)
|
||||
# This is very generous - normal DOGE fees are much lower
|
||||
max_reasonable_feerate = 100.0
|
||||
if network_feerate > max_reasonable_feerate:
|
||||
logger.warning(
|
||||
f"Network fee rate {network_feerate} DOGE/KB is excessive, capping at {max_reasonable_feerate} DOGE/KB"
|
||||
)
|
||||
network_feerate = max_reasonable_feerate
|
||||
|
||||
estimated_fee_doge = network_feerate * 0.25
|
||||
# Double the fee to cover both inbound (customer) and outbound (sweep) transactions
|
||||
total_fee_doge = estimated_fee_doge * 2
|
||||
estimated_fee_doge = network_feerate * 0.15
|
||||
# Add reasonable buffer for sweep transaction (not doubling)
|
||||
total_fee_doge = estimated_fee_doge * 1.5
|
||||
|
||||
# Cap the total fee at a reasonable maximum (0.5 DOGE = ~$0.13)
|
||||
# This should rarely be hit if RPC is working properly
|
||||
max_reasonable_total_fee = 0.5
|
||||
if total_fee_doge > max_reasonable_total_fee:
|
||||
logger.warning(
|
||||
f"Calculated DOGE fee {total_fee_doge} is excessive, capping at {max_reasonable_total_fee} DOGE"
|
||||
)
|
||||
total_fee_doge = max_reasonable_total_fee
|
||||
logger.info(
|
||||
f"Using dynamic DOGE fee: {network_feerate} DOGE/KB * 0.25KB * 2 = {total_fee_doge} DOGE"
|
||||
f"Using dynamic DOGE fee: {network_feerate} DOGE/KB * 0.15KB * 1.5 = {total_fee_doge} DOGE"
|
||||
)
|
||||
return Decimal(str(total_fee_doge))
|
||||
return abs(Decimal(str(total_fee_doge)))
|
||||
else:
|
||||
# Fallback to hardcoded fee if estimatesmartfee fails, doubled for inbound + outbound
|
||||
# Reduce fallback from 0.01 to 0.002 DOGE (~$0.0006 vs $0.003)
|
||||
fallback_fee = float(settings.get("dogecoin.fee_buffer", "0.002")) * 2
|
||||
# Fallback to reasonable fee if estimatesmartfee fails - RPC should be working!
|
||||
fallback_fee = float(settings.get("dogecoin.fee_buffer", "0.5"))
|
||||
logger.warning(
|
||||
f"Dogecoin estimatesmartfee failed, using fallback fee: {fallback_fee} DOGE"
|
||||
f"Dogecoin estimatesmartfee failed (RPC issue?), using fallback fee: {fallback_fee} DOGE"
|
||||
)
|
||||
return Decimal(str(fallback_fee))
|
||||
return abs(Decimal(str(fallback_fee)))
|
||||
except Exception as e:
|
||||
# Fallback to hardcoded fee if RPC call fails, doubled for inbound + outbound
|
||||
fallback_fee = float(settings.get("dogecoin.fee_buffer", "0.002")) * 2
|
||||
# Fallback to reasonable fee if RPC call fails - RPC should be working!
|
||||
fallback_fee = float(settings.get("dogecoin.fee_buffer", "0.5"))
|
||||
logger.error(
|
||||
f"Dogecoin fee estimation error: {e}, using fallback fee: {fallback_fee} DOGE"
|
||||
f"Dogecoin fee estimation error: {e} (RPC issue?), using fallback fee: {fallback_fee} DOGE"
|
||||
)
|
||||
return Decimal(str(fallback_fee))
|
||||
return abs(Decimal(str(fallback_fee)))
|
||||
|
||||
|
||||
def get_payment_status_info(status):
|
||||
|
|
@ -1209,6 +1226,10 @@ def get_payment_status_info(status):
|
|||
"confirmed": {"label": "✓ Confirmed", "color": "#28a745"},
|
||||
"confirmed-complete": {"label": "✓ Confirmed (Complete)", "color": "#28a745"},
|
||||
"confirmed-overpay": {"label": "✓ Confirmed (Overpaid)", "color": "#28a745"},
|
||||
"confirmed-overpay-complete": {
|
||||
"label": "✓ Confirmed (Overpaid)",
|
||||
"color": "#28a745",
|
||||
},
|
||||
"expired": {"label": "Expired", "color": "#6c757d"},
|
||||
"expired": {"label": "Expired", "color": "#6c757d"},
|
||||
"latepay-refunded": {"label": "Late Payment - Refunded", "color": "#fd7e14"},
|
||||
|
|
@ -1242,7 +1263,7 @@ def get_payment_status_info(status):
|
|||
"label": "Duplicate Payment - Refunding",
|
||||
"color": "#fd7e14",
|
||||
},
|
||||
"doublepay-refunded-complete": {
|
||||
"doublepay-refund-complete": {
|
||||
"label": "✓ Duplicate Payment - Refunded",
|
||||
"color": "#fd7e14",
|
||||
},
|
||||
|
|
@ -1267,7 +1288,9 @@ def get_payment_status_info(status):
|
|||
"color": "#dc3545",
|
||||
},
|
||||
}
|
||||
return status_mapping.get(status, {"label": status.title(), "color": "#6c757d"})
|
||||
return status_mapping.get(
|
||||
status.lower(), {"label": status.title(), "color": "#6c757d"}
|
||||
)
|
||||
|
||||
|
||||
# TODO: COMMENT OUT WHEN DEBUGGING COMPLETE - TEMPORARY PRODUCTION DEBUG ROUTE
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue