Page MenuHomePhabricator

[Cashtab] Upgrade tx history to recognize eToken burn transactions
AbandonedPublic

Authored by emack on Feb 8 2022, 13:35.

Details

Reviewers
bytesofman
Group Reviewers
Restricted Project
Summary

burnedtx.PNG (214×492 px, 25 KB)

  • Follow up enhancement to D10912 which upgrades Tx History to recognize and uniquely render eToken burn transactions.
  • useBCH.parseTokenInfoForTxHistory() has been updated to an asyc function as it needs to call bch-api to retrieve eToken decimals and call async parseTokenTxForBurnData() to retrieve the token burn data via Chronik-client (which is failing the unit tests but I'll ping you on telegram on how best to refactor the eToken tests)
  • new parseTokenTxForBurnData() function added to useBCH.js which uses Chronik-client to retrieve the corresponding eToken burn data
  • new formatLongValueTokenByDecimal() function added to useBCH.js which uses the eToken's decimal point to format the eToken's burn amount
  • Since eTokens can have decimal points between 0 - 9, there is an additional bch-api call to retrieve the decimal point of the eToken via BCH.SLP.Utils.tokenStats() since Chronik only returns the eToken's decimal point as part of the genesis tx only. In non-genesis txs, the 'SlpGenesisInfo' attribute in the Chronik tx response object is undefined.

Dependencies:

Manifest: T2208

Test Plan
  • use D10912 to create a few new eTokens with 0, 2 and 9 decimal points
  • burn a few of the newly created eTokens from above, incl. sending and receiving txs
  • switch to this diff and load up the same wallet with the burn transactions above
  • force refresh tx history by sending a dust XEC to this wallet
  • For the burn tx, verify the Tx Icon shows a Fire icon, Tx Label is showing a red 'Burned' Label, eToken Icon, name and ticker are displayed correctly, and the burned amount is displayed correctly based on the token's decimal points.
  • For non burn txs, such as send/receive XEC, send/receive eToken, create eToken genesis tx, verify no regression issues with their rendering in Tx History.
  • Test with a Max Burn transaction
  • Test with an eToken that was created before this diff
  • Test with a newly created wallet

Diff Detail

Repository
rABC Bitcoin ABC
Branch
parseBurnTx
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 18194
Build 36196: Build Diffcashtab-tests
Build 36195: arc lint + arc unit

Event Timeline

emack requested review of this revision.Feb 8 2022, 13:35

Failed tests logs:

====== CashTab Unit Tests: useBCH hook Correctly parses a "send eToken" transaction with token details ======
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 8
+ Received  + 1

- Object {
-   "qtyReceived": "0",
-   "qtySent": "222",
-   "tokenId": "7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d",
-   "tokenName": "Test Token With Exceptionally Long Name For CSS And Style Revisions",
-   "tokenTicker": "WDT",
-   "transactionType": "SEND",
- }
+ Promise {}
    at Object.<anonymous> (/work/web/cashtab/src/hooks/__tests__/useBCH.test.js:522:11)
    at Object.asyncJestTest (/work/web/cashtab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:45:12
    at new Promise (<anonymous>)
    at mapper (/work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:75:41
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
====== CashTab Unit Tests: useBCH hook Correctly parses a "receive eToken" transaction with token details and 9 decimals of precision ======
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 8
+ Received  + 1

- Object {
-   "qtyReceived": "1.123456789",
-   "qtySent": "0",
-   "tokenId": "bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1",
-   "tokenName": "Cash Tab Points",
-   "tokenTicker": "CTP",
-   "transactionType": "SEND",
- }
+ Promise {}
    at Object.<anonymous> (/work/web/cashtab/src/hooks/__tests__/useBCH.test.js:534:11)
    at Object.asyncJestTest (/work/web/cashtab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:45:12
    at new Promise (<anonymous>)
    at mapper (/work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:75:41
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
====== CashTab Unit Tests: useBCH hook Correctly parses a "receive eToken" transaction from an HD wallet (change address different from sending address) ======
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 8
+ Received  + 1

- Object {
-   "qtyReceived": "5",
-   "qtySent": "0",
-   "tokenId": "ccf5fe5a387559c8ab9efdeb0c0ef1b444e677298cfddf07671245ce3cb3c79f",
-   "tokenName": "Garmonbozia",
-   "tokenTicker": "XGB",
-   "transactionType": "SEND",
- }
+ Promise {}
    at Object.<anonymous> (/work/web/cashtab/src/hooks/__tests__/useBCH.test.js:546:11)
    at Object.asyncJestTest (/work/web/cashtab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:45:12
    at new Promise (<anonymous>)
    at mapper (/work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:75:41
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
====== CashTab Unit Tests: useBCH hook Correctly parses a "GENESIS eToken" transaction with token details ======
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 8
+ Received  + 1

- Object {
-   "qtyReceived": "55.55555",
-   "qtySent": "0",
-   "tokenId": "45f0ff5cae7e89da6b96c26c8c48a959214c5f0e983e78d0925f8956ca8848c6",
-   "tokenName": "CashtabMintAlpha",
-   "tokenTicker": "CMA",
-   "transactionType": "GENESIS",
- }
+ Promise {}
    at Object.<anonymous> (/work/web/cashtab/src/hooks/__tests__/useBCH.test.js:558:11)
    at Object.asyncJestTest (/work/web/cashtab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:45:12
    at new Promise (<anonymous>)
    at mapper (/work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
    at /work/web/cashtab/node_modules/jest-jasmine2/build/queueRunner.js:75:41
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
====== CashTab Unit Tests: useBCH hook handleEncryptedOpReturn() correctly throws error when attempting to encrypt a message based on an invalid cash address ======
ReferenceError: TextDecoder is not defined
    at convertToSlpGenesisInfo (/work/web/cashtab/node_modules/chronik-client/index.ts:553:19)
    at convertToSlpTxData (/work/web/cashtab/node_modules/chronik-client/index.ts:501:11)
    at convertToTx (/work/web/cashtab/node_modules/chronik-client/index.ts:422:31)
    at ChronikClient.<anonymous> (/work/web/cashtab/node_modules/chronik-client/index.ts:100:12)
    at Generator.next (<anonymous>)
    at fulfilled (/work/web/cashtab/node_modules/chronik-client/dist/index.js:24:58)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)

Each failure log is accessible here:
CashTab Unit Tests: useBCH hook Correctly parses a "send eToken" transaction with token details
CashTab Unit Tests: useBCH hook Correctly parses a "receive eToken" transaction with token details and 9 decimals of precision
CashTab Unit Tests: useBCH hook Correctly parses a "receive eToken" transaction from an HD wallet (change address different from sending address)
CashTab Unit Tests: useBCH hook Correctly parses a "GENESIS eToken" transaction with token details
CashTab Unit Tests: useBCH hook handleEncryptedOpReturn() correctly throws error when attempting to encrypt a message based on an invalid cash address

emack edited the summary of this revision. (Show Details)

While this "works," I think it's overcomplicated. For example, parsing every token to see if it may or not be a burn is extreme, in all probability > 99% of eToken txs will not be burn txs. It would be better to just parse all the txs in one go, with that function classifying them as burned or not.

Ultimately the solution is to more broadly implement chronik into the app in place of bch-api. For example, since chronik tracks a "first seen" time for txs, getting all the tx history with chronik would also take care of T1775.

For now:

  1. It's okay to land the burn token diff even if these txs are not correctly parsed in tx history. I think the feature gain is worth the bug.
  2. tx history parsing is a pretty big mess due to incremental features and imperfect endpoints from bch-api. Please create a task to parse tx history using only chronik.
  3. Note: it is possible to get token info from chronik by getting tx data from the tokenId, as the tokenId is the txid of that token's genesis transaction.

e.g. txDetails = await chronik.tx(eTokenTxid); gives an object including this genesisInfo key

genesisInfo: {
      tokenTicker: 'CTB',
      tokenName: 'CashTabBits',
      tokenDocumentUrl: 'https://cashtabapp.com/',
      tokenDocumentHash: '',
      decimals: 9
    }
This revision now requires changes to proceed.Feb 11 2022, 20:09
emack planned changes to this revision.Feb 12 2022, 05:52

Putting this on hold until T2248 lands to integrate Chronik for tx history retrieval

Please abandon. This diff is a proof of concept and the underlying app has changed too much for it to be relevant.