diff --git a/web/cashtab/src/utils/__mocks__/chronikTxHistory.js b/web/cashtab/src/utils/__mocks__/chronikTxHistory.js --- a/web/cashtab/src/utils/__mocks__/chronikTxHistory.js +++ b/web/cashtab/src/utils/__mocks__/chronikTxHistory.js @@ -7386,3 +7386,89 @@ isCoinbase: false, network: 'XEC', }; + +export const mockReceivedEtokenTx = { + txid: 'b808f6a831dcdfda2bd4c5f857f94e1a746a4effeda6a5ad742be6137884a4fb', + version: 2, + inputs: [ + { + prevOut: { + txid: 'c638754cb7707edd4faad89bdfee899aa7acbbc61f66e21f8faf60bdbb34fd65', + outIdx: 3, + }, + inputScript: + '4830450221009d649476ad963306a5210d9df2dfd7e2bb604be43d6cdfe359638d96239973eb02200ac6e71575f0f111dad2fbbeb2712490cc709ffe03eda7de33acc8614b2c0979412103318d0e1109f32debc66952d0e3ec21b1cf96575ea4c2a97a6535628f7f8b10e6', + outputScript: '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac', + value: '3503', + sequenceNo: 4294967295, + slpBurn: { + token: { + amount: '0', + isMintBaton: false, + }, + tokenId: + '98183238638ecb4ddc365056e22de0e8a05448c1e6084bae247fae5a74ad4f48', + }, + }, + { + prevOut: { + txid: '82d8dc652779f8d6c8453d2ba5aefec91f5247489246e5672cf3c5986fa3d235', + outIdx: 2, + }, + inputScript: + '483045022100b7bec6d09e71bc4c124886e5953f6e7a7845c920f66feac2e9e5d16fc58a649a0220689d617c11ef0bd63dbb7ea0fa5c0d3419d6500535bda8f7a7fc3e27f27c3de6412103318d0e1109f32debc66952d0e3ec21b1cf96575ea4c2a97a6535628f7f8b10e6', + outputScript: '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac', + value: '546', + sequenceNo: 4294967295, + slpToken: { + amount: '9876543156', + isMintBaton: false, + }, + }, + ], + outputs: [ + { + value: '0', + outputScript: + '6a04534c500001010453454e4420acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f550800000000075bcd1508000000024554499f', + }, + { + value: '546', + outputScript: '76a91495e79f51d4260bc0dc3ba7fb77c7be92d0fbdd1d88ac', + slpToken: { + amount: '123456789', + isMintBaton: false, + }, + }, + { + value: '546', + outputScript: '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac', + slpToken: { + amount: '9753086367', + isMintBaton: false, + }, + }, + { + value: '1685', + outputScript: '76a9144e532257c01b310b3b5c1fd947c79a72addf852388ac', + }, + ], + lockTime: 0, + slpTxData: { + slpMeta: { + tokenType: 'FUNGIBLE', + txType: 'SEND', + tokenId: + 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55', + }, + }, + block: { + height: 760076, + hash: '00000000000000000bf1ee10a21cc4b784ea48840fa00237e41f69a027c6a86c', + timestamp: '1664840266', + }, + timeFirstSeen: '1664837660', + size: 481, + isCoinbase: false, + network: 'XEC', +}; diff --git a/web/cashtab/src/utils/__tests__/chronik.test.js b/web/cashtab/src/utils/__tests__/chronik.test.js --- a/web/cashtab/src/utils/__tests__/chronik.test.js +++ b/web/cashtab/src/utils/__tests__/chronik.test.js @@ -52,6 +52,7 @@ mockReceivedEncryptedTx, mockTokenBurnTx, mockTokenBurnWithDecimalsTx, + mockReceivedEtokenTx, } from '../__mocks__/chronikTxHistory'; import { ChronikClient } from 'chronik-client'; import { when } from 'jest-when'; @@ -683,3 +684,52 @@ replyAddress: 'ecash:qz2708636snqhsxu8wnlka78h6fdp77ar59jrf5035', }); }); +it(`Correctly parses received quantity for a received eToken address`, () => { + const BCH = new BCHJS({ + restURL: 'https://FakeBchApiUrlToEnsureMocksOnly.com', + }); + // This function needs to be mocked as bch-js functions that require Buffer types do not work in jest environment + BCH.Address.hash160ToCash = jest + .fn() + .mockReturnValue( + 'bitcoincash:qp89xgjhcqdnzzemts0aj378nfe2mhu9yvll3cvjwd', + ); + expect( + parseChronikTx( + BCH, + mockReceivedEtokenTx, + anotherMockParseTxWallet, + txHistoryTokenInfoById, + ), + ).toStrictEqual({ + incoming: true, + xecAmount: '5.46', + originatingHash160: '4e532257c01b310b3b5c1fd947c79a72addf8523', + isEtokenTx: true, + etokenAmount: '0.123456789', + isTokenBurn: false, + slpMeta: { + tokenType: 'FUNGIBLE', + txType: 'SEND', + tokenId: + 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55', + }, + genesisInfo: { + tokenTicker: 'CTB', + tokenName: 'CashTabBits', + tokenDocumentUrl: 'https://cashtabapp.com/', + tokenDocumentHash: '', + decimals: 9, + tokenId: + 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55', + success: true, + }, + airdropFlag: false, + airdropTokenId: '', + opReturnMessage: '', + isCashtabMessage: false, + isEncryptedMessage: false, + decryptionSuccess: false, + replyAddress: 'ecash:qp89xgjhcqdnzzemts0aj378nfe2mhu9yvxj9nhgg6', + }); +}); diff --git a/web/cashtab/src/utils/chronik.js b/web/cashtab/src/utils/chronik.js --- a/web/cashtab/src/utils/chronik.js +++ b/web/cashtab/src/utils/chronik.js @@ -458,7 +458,13 @@ const thisInput = inputs[i]; const thisInputSendingHash160 = thisInput.outputScript; // If this is an etoken tx, check for token burn - if (isEtokenTx && typeof thisInput.slpBurn !== 'undefined') { + if ( + isEtokenTx && + typeof thisInput.slpBurn !== 'undefined' && + thisInput.slpBurn.token && + thisInput.slpBurn.token.amount && + thisInput.slpBurn.token.amount !== '0' + ) { console.log(`Token burn at ${tx.txid}`); // Assume that any eToken tx with a burn is a burn tx isTokenBurn = true;