diff --git a/cashtab/package-lock.json b/cashtab/package-lock.json
--- a/cashtab/package-lock.json
+++ b/cashtab/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cashtab",
- "version": "2.36.2",
+ "version": "2.36.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cashtab",
- "version": "2.36.2",
+ "version": "2.36.3",
"dependencies": {
"@bitgo/utxo-lib": "^9.33.0",
"@zxing/browser": "^0.1.4",
diff --git a/cashtab/package.json b/cashtab/package.json
--- a/cashtab/package.json
+++ b/cashtab/package.json
@@ -1,6 +1,6 @@
{
"name": "cashtab",
- "version": "2.36.2",
+ "version": "2.36.3",
"private": true,
"scripts": {
"start": "node scripts/start.js",
diff --git a/cashtab/src/chronik/fixtures/mocks.js b/cashtab/src/chronik/fixtures/mocks.js
--- a/cashtab/src/chronik/fixtures/mocks.js
+++ b/cashtab/src/chronik/fixtures/mocks.js
@@ -10903,6 +10903,68 @@
],
};
+export const oneOutputReceivedTx = {
+ tx: {
+ txid: '0edd96775cc1dbc4c36dbf5f1773f937de3bdadd572265ad78bae931fec3f431',
+ version: 2,
+ inputs: [
+ {
+ prevOut: {
+ txid: 'cd5731b4f5ec4ff2e12fe3187e37ce3dc544f5419df8f6c36f649e1236d7dcee',
+ outIdx: 0,
+ },
+ inputScript:
+ '41246058dcfab4114536db638d064612e12e0cfff613b568535c278e544ec68ec3e02ffc94d09a0ffe0f4e6fd9ff9608b01aad46cad3765059c3fe45ea09898abe4121029bd5d9d9565b734188493dfd3b0fe985ccd55bb6bc1544cf6ed25a46076f045f',
+ value: 45553900000,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a914bb3f3669824acaf67902cbc8477f75ae5b139a0f88ac',
+ },
+ {
+ prevOut: {
+ txid: '3719ef3aa2739da328a1a2916a422931fb7b0fa897183f3fd8f3c26864285e34',
+ outIdx: 0,
+ },
+ inputScript:
+ '415d1ee0074f11a0adf5c35039167a731d008656eb0a33b5eec9144dd8614419e88866779cce3da0de8c9f839ddbb8d8ee8d24c82526a8900730ea8af8ef102c6d4121020b5c467c0276678df5f50cc932e81abf259f40477f815ed11f4d0fecab39f2d6',
+ value: 100000000,
+ sequenceNo: 4294967294,
+ outputScript:
+ '76a91409c388abff6922c7e97ef8ea58e9697b6637910c88ac',
+ },
+ ],
+ outputs: [
+ {
+ value: 45653899320,
+ outputScript:
+ '76a914601efc2aa406fe9eaedd41d2b5d95d1f4db9041d88ac',
+ spentBy: {
+ txid: 'b9aab1e26381457b390ad689c7577962cef1ec48de3a83d87db68968afb7e4cf',
+ outIdx: 54,
+ },
+ },
+ ],
+ lockTime: 0,
+ timeFirstSeen: 1714138690,
+ size: 326,
+ isCoinbase: false,
+ tokenEntries: [],
+ tokenFailedParsings: [],
+ tokenStatus: 'TOKEN_STATUS_NON_TOKEN',
+ block: {
+ height: 842022,
+ hash: '00000000000000000c331ba563d903d20ff670b18afd0d6cd4aadca854d294a6',
+ timestamp: 1714139968,
+ },
+ },
+ parsed: {
+ recipients: [],
+ satoshisSent: 45653899320,
+ stackArray: [],
+ xecTxType: 'Received',
+ },
+};
+
/**
* Mock chronik.token(tokenId) and chronik.tx(tokenId) for
* several slpv1 tokens
diff --git a/cashtab/src/chronik/fixtures/vectors.js b/cashtab/src/chronik/fixtures/vectors.js
--- a/cashtab/src/chronik/fixtures/vectors.js
+++ b/cashtab/src/chronik/fixtures/vectors.js
@@ -42,6 +42,7 @@
SlpNftParentFanTx,
SlpNftMint,
SlpParentGenesisTxMock,
+ oneOutputReceivedTx,
} from './mocks';
import { mockChronikUtxos, mockOrganizedUtxosByType } from './chronikUtxos';
import { getHashes } from 'wallet';
@@ -221,6 +222,12 @@
hashes: ['95e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d'],
parsed: SlpV1Mint.parsed,
},
+ {
+ description: 'received xec tx with no change',
+ tx: oneOutputReceivedTx.tx,
+ hashes: ['601efc2aa406fe9eaedd41d2b5d95d1f4db9041d'],
+ parsed: oneOutputReceivedTx.parsed,
+ },
],
},
sortAndTrimChronikTxHistory: {
diff --git a/cashtab/src/components/Home/Tx/__tests__/index.test.js b/cashtab/src/components/Home/Tx/__tests__/index.test.js
--- a/cashtab/src/components/Home/Tx/__tests__/index.test.js
+++ b/cashtab/src/components/Home/Tx/__tests__/index.test.js
@@ -46,6 +46,7 @@
SlpNftParentFanTx,
SlpNftMint,
SlpParentGenesisTxMock,
+ oneOutputReceivedTx,
} from 'chronik/fixtures/mocks';
import CashtabState from 'config/CashtabState';
import { MemoryRouter } from 'react-router-dom';
@@ -163,6 +164,49 @@
// We see the 'Confirming' text
expect(screen.getByText('Confirming')).toBeInTheDocument();
});
+ it('Incoming XEC no change', async () => {
+ render(
+
+
+
+ ,
+
+ ,
+ );
+
+ // We see the tx received icon
+ expect(screen.getByTitle('tx-received')).toBeInTheDocument();
+
+ // We see the tx received label
+ expect(screen.getByText(/Received from/)).toBeInTheDocument();
+
+ // For a tx with timeFirstSeen of 0, we render the block timestamp
+ expect(screen.getByText('Apr 26, 2024, 13:38:10')).toBeInTheDocument();
+
+ // We see the formatted XEC amount
+ expect(screen.getByText('456.54M XEC')).toBeInTheDocument();
+
+ // We see the formatted fiat amount
+ expect(screen.getByText('$13,696.17')).toBeInTheDocument();
+
+ // We do not see the avalanche finalized check
+ expect(
+ screen.queryByTitle('Finalized by Avalanche'),
+ ).not.toBeInTheDocument();
+
+ // We see two inline-loader elements
+ expect(screen.getAllByTitle('Loading')[1]).toBeInTheDocument();
+
+ // We see the 'Confirming' text
+ expect(screen.getByText('Confirming')).toBeInTheDocument();
+ });
it('Outgoing XEC-only', async () => {
render(
diff --git a/cashtab/src/components/Home/Tx/index.js b/cashtab/src/components/Home/Tx/index.js
--- a/cashtab/src/components/Home/Tx/index.js
+++ b/cashtab/src/components/Home/Tx/index.js
@@ -783,7 +783,8 @@
typeof knownRecipient === 'undefined' &&
typeof recipients[0] !== 'undefined');
- const isSelfSendTx = typeof recipients[0] === 'undefined';
+ const isSelfSendTx =
+ typeof recipients[0] === 'undefined' && xecTxType !== 'Received';
return (
<>