Skip to content

Commit 9394d79

Browse files
relativisticelectronmoneymanolisk9ert
authored
Bugfix: Missing values in tx details (#1862)
* fix missing values in tx details * cypress test * remove spaces after Address * better handling of non-wallet txids in inputs * Update zblack.yml Co-authored-by: moneymanolis <[email protected]> Co-authored-by: k9ert <[email protected]>
1 parent e3d09f1 commit 9394d79

File tree

7 files changed

+168
-78
lines changed

7 files changed

+168
-78
lines changed

.github/workflows/zblack.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,4 @@ jobs:
88
steps:
99
- uses: actions/checkout@v2
1010
- uses: actions/setup-python@v2
11-
- uses: psf/[email protected] # the default is equivalent to `black . --diff --check`.
12-
with:
13-
args: ". --diff --check"
11+
- uses: psf/black@stable # https://black.readthedocs.io/en/stable/integrations/github_actions.html

cypress/integration/spec_wallet_send.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,38 @@ describe('Test sending transactions', () => {
3030
expect(n).to.be.equals(0)
3131
})
3232
})
33-
33+
34+
// Skipped for now, will only work reliably once the the Cypress tests run without mining loop
35+
it('Open up transaction details', () => {
36+
cy.selectWallet("Test Hot Wallet 1")
37+
cy.get('#btn_transactions').click()
38+
// Click on the txid in the first row
39+
cy.get('tbody.tx-tbody').find('tr').eq(0).find('#column-txid').find('.explorer-link').click()
40+
cy.get('.tx-data-info').contains('Input #0')
41+
cy.get('.tx-data-info').contains('Transaction id:')
42+
cy.get('.tx-data-info').contains('Output index:') // Not sure whether it is always 1 - output ordering is random in Core ...
43+
cy.get('.tx-data-info').contains('Address #0')
44+
cy.get('.tx-data-info').contains('Value: 20 tBTC')
45+
cy.get('.tx-data-info').contains('Output #0')
46+
cy.get('.tx-data-info').contains('Burn address')
47+
cy.get('.tx-data-info').contains('Value: 19.9999989 tBTC') // Fees should always be the same
48+
cy.get('#page_overlay_popup_cancel_button').click()
49+
// Change to sats and check amounts and units
50+
cy.get('[href="/settings/"]').click()
51+
cy.get('[name="unit"]').select('sats')
52+
cy.contains('Save').click()
53+
cy.selectWallet("Test Hot Wallet 1")
54+
cy.get('#btn_transactions').click()
55+
cy.get('tbody.tx-tbody').find('tr').eq(0).find('#column-txid').find('.explorer-link').click()
56+
cy.get('.tx-data-info').contains('Value: 2,000,000,000 tsat')
57+
cy.get('.tx-data-info').contains('Value: 1,999,999,890 tsat')
58+
cy.get('#page_overlay_popup_cancel_button').click()
59+
// Change back to btc
60+
cy.get('[href="/settings/"]').click()
61+
cy.get('[name="unit"]').select('BTC')
62+
cy.contains('Save').click()
63+
})
64+
3465
it('Adding and deleting recipients', () => {
3566
// We need new sats but mine2wallet only works if a wallet is selected
3667
cy.selectWallet("Test Hot Wallet 1")

src/cryptoadvance/specter/server_endpoints/wallets_api.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,24 @@ def decoderawtx(wallet_alias):
256256
wallet: Wallet = app.specter.wallet_manager.get_by_alias(wallet_alias)
257257
txid = request.form.get("txid", "")
258258
if txid:
259-
tx = wallet.rpc.gettransaction(txid)
259+
try:
260+
tx = wallet.rpc.gettransaction(txid)
261+
except RpcError as e:
262+
if "Invalid or non-wallet transaction id" in str(e):
263+
# Expected failure when looking up a txid that didn't originate from the
264+
# user's Wallet.
265+
logger.info(
266+
"Looking up a txid that didn't originate from the user's wallet. Can't return any tx data."
267+
)
268+
return jsonify(
269+
success=False,
270+
nonWalletTxId=True,
271+
)
272+
else:
273+
logger.warning(
274+
"Failed to fetch transaction data. Exception: {}".format(e)
275+
)
276+
return jsonify(success=False)
260277
# This is a fix for Bitcoin Core versions < v0.20
261278
# These do not return the blockheight as part of the `gettransaction` command
262279
# So here we check if this property is lacking and if so
@@ -310,15 +327,6 @@ def decoderawtx(wallet_alias):
310327
rawtx=rawtx,
311328
walletName=wallet.name,
312329
)
313-
except RpcError as e:
314-
if "Invalid or non-wallet transaction id" in str(e):
315-
# Expected failure when looking up a txid that didn't originate from the
316-
# user's Wallet.
317-
pass
318-
else:
319-
app.logger.warning(
320-
"Failed to fetch transaction data. Exception: {}".format(e)
321-
)
322330
except Exception as e:
323331
app.logger.warning("Failed to fetch transaction data. Exception: {}".format(e))
324332

src/cryptoadvance/specter/templates/base.jinja

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
}
4141
</style>
4242
<script type="text/javascript" src="{{ url_for('static', filename='helpers.js') }}"></script>
43+
{% include "includes/helpers.jinja" %}
4344
{% include "services/inject_in_basejinja_head.jinja" %}
4445
{% block head %}
4546
{% endblock %}

src/cryptoadvance/specter/templates/includes/address-label.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
}
66
.service-icon {
77
margin-top: -5px;
8-
margin-right: 0.25em;
98
height:24px;
109
vertical-align: middle;
1110
}
@@ -65,9 +64,7 @@
6564
}
6665
</style>
6766
<form class="address-label-form">
68-
<input type="hidden" class="csrf-token" name="csrf_token" value="{{ csrf_token() }}"/>
69-
<img class="service-icon"/>
70-
<a target="_blank" class="explorer-link"><span class="label" autocomplete="off" spellcheck="false">{{ _("Fetching address label...") }}</span></a>
67+
<input type="hidden" class="csrf-token" name="csrf_token" value="{{ csrf_token() }}"/><img class="service-icon"><a target="_blank" class="explorer-link"><span class="label" autocomplete="off" spellcheck="false">{{ _("Fetching address label...") }}</span></a>
7168
<button type="button" class="btn edit" title="Edit label"><img src="{{ url_for('static', filename='img/edit.svg') }}" style="width: 22px; margin-bottom:-5px;" class="svg-white"/></button>
7269
<button type="button" class="btn update hidden">{{ _("Update") }}</button>
7370
<button type="button" class="btn cancel hidden">{{ _("Cancel") }}</button>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<!-- This file contains javascript helper functions that also can use jinja -->
2+
<script type="text/javascript">
3+
4+
// Formats an unitLabel (e.g. from a tx output) to a useful unit label
5+
function formatUnitLabel(unitLabel, convertToSat){
6+
var newLabel = unitLabel;
7+
if (newLabel == "" || !newLabel){
8+
newLabel = {% if specter.is_liquid %}"LBTC"{%else%}"BTC"{%endif%}
9+
}
10+
if (convertToSat) {
11+
if(newLabel == "LBTC"){
12+
newLabel = "Lsat";
13+
}
14+
// Liquid JSON response on testnet is already tLBTC
15+
else if (newLabel == "tLBTC") {
16+
newLabel = "tLsat";
17+
}
18+
if(newLabel == "BTC"){
19+
newLabel = "sat";
20+
}
21+
}
22+
23+
{% if specter.is_testnet %}
24+
if (!newLabel.startsWith("t")){
25+
newLabel = "t" + newLabel;
26+
}
27+
{%endif%}
28+
29+
return newLabel;
30+
}
31+
32+
// Formats the valueInBTC (e.g. from a tx output) to "formattedValue formattedUnitLabel"
33+
// e.g. 0.22569496 tBTC
34+
function formatBtcAmount(valueInBTC, unitLabel, convertToSat){
35+
var formattedUnitLabel = formatUnitLabel(unitLabel, convertToSat);
36+
var formattedValue = valueInBTC;
37+
if (valueInBTC) {
38+
value = parseFloat(valueInBTC.toFixed(8));
39+
// The second condition in the if clause if True if formattedUnitLabel is equal to any element of the array
40+
if (convertToSat && (["Lsat", "sat", "tLsat", "tsat"].indexOf(formattedUnitLabel) > -1)) {
41+
formattedValue = parseInt(value * 1e8)
42+
}
43+
formattedValue = `${numberWithCommas(formattedValue)}`;
44+
}
45+
else {
46+
formattedValue = '{{ _("Confidential") }}';
47+
formattedUnitLabel = '';
48+
}
49+
return `${formattedValue} ${formattedUnitLabel}`;
50+
}
51+
52+
// Determines if an unitLabel (e.g. from a tx output) is "BTC", "LBTC", "tBTC", "tLBTC"
53+
function unitLabelIsBitcoin(unitLabel){
54+
if (!unitLabel){
55+
return true
56+
}
57+
return ([null, "", "LBTC", "BTC", "tBTC", "tLBTC"].indexOf(unitLabel) > -1)
58+
}
59+
60+
// Calculates and formats the price as a span class="note"
61+
function formatPrice(valueInBTC, unitLabel, symbol, price){
62+
var formattedPrice = "";
63+
if (valueInBTC) {
64+
if(unitLabelIsBitcoin(unitLabel)){
65+
if (price && symbol) {
66+
formattedPrice = `<span class="note">(${symbol}${numberWithCommas((parseFloat(price) * valueInBTC).toFixed(2))})</span>`;
67+
}
68+
}
69+
}
70+
return formattedPrice
71+
}
72+
73+
74+
75+
</script>

src/cryptoadvance/specter/templates/includes/tx-data.html

Lines changed: 40 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -153,29 +153,6 @@ <h2>{{ _("Transaction details") }}</h2><br>
153153
if (isMine) {
154154
bgColor = '#925d07';
155155
}
156-
157-
158-
let value = "Confidential";
159-
let price = '';
160-
let assetlabel = "";
161-
if("assetlabel" in spentOutput){
162-
assetlabel = spentOutput.assetlabel;
163-
}
164-
if (spentOutput.value) {
165-
value = parseFloat(spentOutput.value.toFixed(8));
166-
if(assetlabel == "LBTC" || assetlabel == ""){
167-
if (this.price && this.symbol) {
168-
price = `<span class="note">(${this.symbol}${numberWithCommas((parseFloat(this.price) * value).toFixed(2))})</span>`;
169-
}
170-
171-
if (this.btcUnit == 'sat') {
172-
assetlabel = "sat";
173-
value = parseInt(value * 1e8);
174-
}
175-
}
176-
value = `${numberWithCommas(value.toString())}`;
177-
}
178-
179156
let labelAttr = "";
180157
if ("label" in spentOutput) {
181158
labelAttr = `data-label="${spentOutput.label}"`;
@@ -184,16 +161,21 @@ <h2>{{ _("Transaction details") }}</h2><br>
184161
if ("service_id" in spentOutput) {
185162
serviceIdAttr = `data-service-id="${spentOutput.service_id}"`;
186163
}
164+
// assetlabel only exists for Liquid, for BTC it is just null
165+
var amountAndUnit = formatBtcAmount(spentOutput.value, spentOutput.assetlabel, this.btcUnit == 'sat');
166+
var price = formatPrice(spentOutput.value, spentOutput.assetlabel, this.symbol, this.price);
187167

188-
addressAndValue = `<br>
189-
{{ _("Address:") }} <address-label
168+
addressAndValue = `
169+
{{ _("Address:") }}
170+
<address-label
190171
data-copy-hidden="true"
191172
data-address="${address}"
192173
data-wallet="${this.wallet}"
193174
${labelAttr}
194-
${serviceIdAttr}
195-
/><br>
196-
{{ _("Value:") }} ${value} ${assetlabel} ${price}`;
175+
${serviceIdAttr}>
176+
</address-label><br>
177+
{{ _("Value:") }} ${amountAndUnit} ${price}
178+
`;
197179
}
198180

199181
if ('coinbase' in rawtx.vin[i]) {
@@ -206,14 +188,28 @@ <h2>{{ _("Transaction details") }}</h2><br>
206188
`;
207189
continue;
208190
}
209-
rawtxHTML += `
210-
<p class="tx_info" style="text-align: left; background-color: ${bgColor};">
211-
<b>{{ _("Input #") }}${i}</b><br><br>
212-
{{ _("Transaction id") }}: <explorer-link style="word-break: break-all;" data-type="tx" data-value="${rawtx.vin[i].txid}"></explorer-link><br>
213-
{{ _("Output #") }}" ${rawtx.vin[i].vout}
214-
${addressAndValue}
215-
</p>
216-
`;
191+
if (jsonResponse.nonWalletTxId) {
192+
let nonWalletTxId = jsonResponse.nonWalletTxId ? `<span>Not known, this is a non-wallet txid.</span>` : null
193+
rawtxHTML += `
194+
<p class="tx_info" style="text-align: left; background-color: ${bgColor};">
195+
<b>{{ _("Input #") }}${i}</b><br><br>
196+
{{ _("Transaction id") }}: <explorer-link style="word-break: break-all;" data-type="tx" data-value="${rawtx.vin[i].txid}"></explorer-link><br>
197+
{{ _("Output index: ") }}${rawtx.vin[i].vout}<br>
198+
{{ _("Address & value:") }} ${nonWalletTxId}
199+
</p>
200+
`;
201+
}
202+
else {
203+
rawtxHTML += `
204+
<p class="tx_info" style="text-align: left; background-color: ${bgColor};">
205+
<b>{{ _("Input #") }}${i}</b><br><br>
206+
{{ _("Transaction id") }}: <explorer-link style="word-break: break-all;" data-type="tx" data-value="${rawtx.vin[i].txid}"></explorer-link><br>
207+
{{ _("Output index: ") }}${rawtx.vin[i].vout}<br>
208+
${addressAndValue}
209+
</p>
210+
`;
211+
212+
}
217213
}
218214

219215
rawtxHTML += `<h3>{{ _("Outputs") }}</h3>`;
@@ -229,26 +225,6 @@ <h2>{{ _("Transaction details") }}</h2><br>
229225
if (address == 'Unknown') {
230226
address = rawtx.vout[i].address ? rawtx.vout[i].address : 'Unknown';
231227
}
232-
let value = "Confidential";
233-
let price = '';
234-
let assetlabel = "";
235-
if("assetlabel" in rawtx.vout[i]){
236-
assetlabel = rawtx.vout[i].assetlabel;
237-
}
238-
if (rawtx.vout[i].value) {
239-
value = parseFloat(rawtx.vout[i].value.toFixed(8));
240-
if(assetlabel == "LBTC" || assetlabel == ""){
241-
if (this.price && this.symbol) {
242-
price = `<span class="note">(${this.symbol}${numberWithCommas((parseFloat(this.price) * value).toFixed(2))})</span>`;
243-
}
244-
245-
if (this.btcUnit == 'sat') {
246-
assetlabel = "sat";
247-
value = parseInt(value * 1e8)
248-
}
249-
}
250-
value = `${numberWithCommas(value.toString())}`;
251-
}
252228

253229
let bgColor = '#131a24';
254230
if ("index" in rawtx.vout[i]) {
@@ -266,18 +242,22 @@ <h2>{{ _("Transaction details") }}</h2><br>
266242
if ("service_id" in rawtx.vout[i]) {
267243
serviceIdAttr = `data-service-id="${rawtx.vout[i].service_id}"`;
268244
}
245+
// assetlabel only exists for Liquid, for BTC it is just null
246+
var amountAndUnit = formatBtcAmount(rawtx.vout[i].value, rawtx.vout[i].assetlabel, this.btcUnit == 'sat');
247+
var price = formatPrice(rawtx.vout[i].value, rawtx.vout[i].assetlabel, this.symbol, this.price);
269248

270249
rawtxHTML += `
271250
<p class="tx_info" style="text-align: left; background-color: ${bgColor};">
272251
<b>{{ _("Output #${i}") }}</b><br><br>
273-
{{ _("Address:") }} <address-label
252+
{{ _("Address:") }}
253+
<address-label
274254
data-copy-hidden="true"
275255
data-address="${address}"
276256
data-wallet="${this.wallet}"
277257
${labelAttr}
278-
${serviceIdAttr}
279-
/><br/>
280-
{{ _("Value:") }} ${value} ${assetlabel} ${price}
258+
${serviceIdAttr}>
259+
</address-label><br>
260+
{{ _("Value:") }} ${amountAndUnit} ${price}
281261
</p>
282262
`;
283263
}

0 commit comments

Comments
 (0)