Page MenuHomePhabricator

[Cashtab] Support ALP tokens
ClosedPublic

Authored by bytesofman on Nov 23 2024, 15:12.

Details

Reviewers
emack
tobias_ruck
Group Reviewers
Restricted Project
Commits
rABC94529eb3cc96: [Cashtab] Support ALP tokens
Summary

Add support for ALP tokens (genesis, send, burn, mint)

Will handle listing and agora in a separate diff

Some other changes needed in this diff for things to work:

  • Update validation functions as ALP has different max qty per output
  • Improve handling of cached token info on Token screen (needed for integration test of how screen handles loading an ALP token)
  • new 'alp' dir for function to return alp decimalized max qty; includes first jest ts file, so need jest types dep
  • Moved token functions that work for SLP and ALP into a top-level index.ts in new token-protocols dir, including (for now) slpv1 and alp
Test Plan

npm test

Diff Detail

Repository
rABC Bitcoin ABC
Branch
cashtab-alp-genesis
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 31315
Build 62128: Build Diffcashtab-tests
Build 62127: arc lint + arc unit

Event Timeline

Failed tests logs:

====== CashTab Unit Tests: <Token /> available actions rendered ALP token ======
TestingLibraryElementError: Unable to find an element with the text: This token is not yet supported by Cashtab.. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, script, style
<body>
  <div>
    <div
      class="sc-cCbXAZ cGlszB"
    >
      <div
        class="Toastify"
      />
      <div
        class="sc-fHSTwm iKKFtc"
      >
        <div
          class="sc-hdPSEv drRDyR"
        >
          <div
            class="sc-hizQCF iuaOpi"
          >
            <img
              alt="cashtab"
              class="sc-eNPDpu kwpjsm"
              src="test-file-stub"
            />
          </div>
          <div
            class="sc-ekkqgF eMHjbd"
          >
            <select
              class="sc-iBmynh berchQ"
              data-testid="wallet-select"
              id="wallets"
              name="wallets"
            >
              <option
                class="sc-fKGOjr bOTepS"
                value="Token Test"
              >
                Token Test
              </option>
            </select>
            <div
              class="sc-kVrTmx jqgvTq"
            >
              <button
                aria-label="Copy ecash:qqq9f9z3uhpzkxrgdjkd7dxuuey7tmpmugpmnw0kue"
                class="sc-kvZOFW liNaUH"
              >
                <svg
                  title="copy-paste"
                />
              </button>
              <div
                class="sc-gFaPwZ bhfoic"
              >
                <div
                  class="sc-fhYwyz kXwmEk"
                >
                  <input
                    checked=""
                    class="sc-bMvGRv dnGmSn"
                    id="show-hide-balance"
                    name="show-hide-balance"
                    title="show-hide-balance"
                    type="checkbox"
                  />
                  <label
                    class="sc-jzgbtB hsNhPD"
                    for="show-hide-balance"
                  >
                    <span
                      class="sc-gJWqzi dYGNll"
                      data-off=""
                      data-on=""
                    />
                    <span
                      class="sc-rBLzX gWpmmy"
                    />
                  </label>
                </div>
              </div>
            </div>
          </div>
          <div
            class="sc-hlILIN inOePY"
            title="Wallet Info"
          >
            <div
              class="sc-hycgNl jFTmBM"
              title="Balance in XEC"
            >
              9,970.81
               
              XEC
               
            </div>
            <div
              class="sc-chAAoq kjYqmy"
              title="Balance in Local Currency"
            >
              $
              0.30
               
              USD
            </div>
            <p
              class="sc-dTLGrV fvjJeu"
              title="Price in Local Currency"
            >
              1 
              XEC
               = 
              0.00003000
               
              USD
            </p>
          </div>
          <div
            class="sc-cgHJcJ fwEPrl"
          >
            <div
              class="sc-iELTvK ciBjbO"
              height="210"
              width="320"
            >
              <button
                class="sc-kTUwUJ hTRNfw"
              >
                X
              </button>
              <div
                class="sc-jwKygS gwdWts"
                height="210"
              >
                <div
                  class="sc-cmTdod swdPe"
                >
                  ALP
                </div>
                <div
                  class="sc-btzYZH tZEwk"
                >
                  ALP v1 fungible token. Token may be of fixed or variable supply. If you have a mint baton, you can mint more of this token at any time. May have up to 9 decimal places. ALP tokens use EMPP technology, which supports more token actions compared to SLP and more complex combinations of token and app actions. ALP token txs may have up to 127 outputs.
                </div>
              </div>
              <div
                class="sc-lhVmIH eGThRU"
              >
                <button
                  class="sc-bYSBpT sc-elJkPf iByzwq"
                >
                  OK
                </button>
              </div>
            </div>
            <div
              class="sc-dqBHgY hshxLW"
            />
            <div
              class="sc-hzNEM hFuCgt"
            >
              100.0000
               
              Test CRD
               (
              tCRD
              )
            </div>
            <div
              class="sc-iSDuPN hqHiQd"
              title="Token Stats"
            >
              <div
                class="sc-fQejPQ btYqSh"
              >
                <button
                  class="sc-fcdeBU dJwmed"
                >
                  <img
                    alt="icon for 7cd7cd7c54167d306e770f972b564584c44cb412ee45839b4b97bb6e724c8849"
                    height="128"
                    src="https://icons.etokens.cash/128/7cd7cd7c54167d306e770f972b564584c44cb412ee45839b4b97bb6e724c8849.png"
                    width="128"
                  />
                </button>
              </div>
              <div
                class="sc-fQejPQ btYqSh"
              >
                <div
                  class="sc-etwtAo krsiJt"
                >
                  <div
                    class="sc-jXQZqI bVkCnL"
                  >
                    Type:
                  </div>
                  <div
                    class="sc-fQejPQ btYqSh"
                  >
                    <div
                      class="sc-cooIXK hDBkgu"
                    >
                      ALP
                       
                      <button
                        aria-label="Click for more info about this token type"
                        class="sc-kvZOFW liNaUH"
                      >
                        <svg
                          title="More Info"
                        />
                      </button>
                    </div>
                  </div>
                </div>
                <div
                  class="sc-etwtAo krsiJt"
                >
                  <div
                    class="sc-jXQZqI bVkCnL"
                  >
                    Token Id:
                  </div>
                  <div
                    class="sc-fQejPQ btYqSh"
                  >
                    <a
                      href="https://explorer.e.cash/tx/7cd7cd7c54167d306e770f972b564584c44cb412ee45839b4b97bb6e724c8849"
                      rel="noopener noreferrer"
                      target="_blank"
                    >
                      7cd
                      ...
                      849
                    </a>
                  </div>
                  <div
                    class="sc-fQejPQ btYqSh"
                  >
                    <button
                      aria-label="Copy Token ID"
                      class="sc-kvZOFW liNaUH"
                    >
                      <svg
                        title="copy-paste"
                      />
                    </button>
                  </div>
                </div>
                <div
                  class="sc-etwtAo krsiJt"
                >
                  <div
                    class="sc-jXQZqI bVkCnL"
                  >
                    decimals:
                  </div>
                  <div
                    class="sc-fQejPQ btYqSh"
                  >
                    4
                  </div>
                </div>
                <div
                  class="sc-etwtAo krsiJt"
                >
                  <div
                    class="sc-jXQZqI bVkCnL"
                  >
                    url:
                  </div>
                  <div
                    class="sc-fQejPQ sc-clNaTc howJgk"
                  >
                    <a
                      href="https://crd.network/tcrd"
                      rel="noreferrer"
                      target="_blank"
                    >
                      crd.network/tcrd
                    </a>
                  </div>
                </div>
                <div
                  class="sc-etwtAo krsiJt"
                >
                  <div
                    class="sc-jXQZqI bVkCnL"
                  >
                    created:
                  </div>
                  <div
                    class="sc-fQejPQ btYqSh"
                  >
                    Jan 1, 2022
                  </div>
                </div>
                <div
                  class="sc-etwtAo krsiJt"
                >
                  <div
                    class="sc-jXQZqI bVkCnL"
                  >
                    Genesis Qty:
                  </div>
                  <div
                    class="sc-fQejPQ btYqSh"
                  >
                    0.0000
                  </div>
                </div>
                <div
                  class="sc-etwtAo krsiJt"
                >
                  <div
                    class="sc-jXQZqI bVkCnL"
                  >
                    Supply:
                  </div>
                  <div
                    class="sc-fQejPQ btYqSh"
                  >
                    111,367.0000 (var.)
                  </div>
                </div>
              </div>
            </div>
            <div
              class="sc-tilXH dQSSSo"
            >
              Error querying agora for active offers. Try again later.
            </div>
            <div
              class="sc-gmeYpB iKnjIe"
              title="Token Actions"
            >
              <div
                class="sc-iGPElx iHtmSM"
              >
                <div
                  class="sc-gFaPwZ bhfoic"
                >
                  <div
                    class="sc-fhYwyz kZTqdd"
                  >
                    <input
                      class="sc-bMvGRv dnGmSn"
                      id="Toggle Send"
                      name="Toggle Send"
                      title="Toggle Send"
                      type="checkbox"
                    />
                    <label
                      class="sc-jzgbtB hsNhPD"
                      for="Toggle Send"
                    >
                      <span
                        class="sc-gJWqzi gEydeL"
                        data-off="➡️"
                        data-on="➡️"
                      />
                      <span
                        class="sc-rBLzX hAekJS"
                      />
                    </label>
                  </div>
                </div>
                <div
                  class="sc-fYxtnH YMNhn"
                >
                  Send 
                  Test CRD
                   (
                  tCRD
                  )
                </div>
              </div>
              <div
                class="sc-iGPElx iHtmSM"
              >
                <div
                  class="sc-gFaPwZ bhfoic"
                >
                  <div
                    class="sc-fhYwyz kZTqdd"
                  >
                    <input
                      class="sc-bMvGRv dnGmSn"
                      id="Toggle Airdrop"
                      name="Toggle Airdrop"
                      title="Toggle Airdrop"
                      type="checkbox"
                    />
                    <label
                      class="sc-jzgbtB hsNhPD"
                      for="Toggle Airdrop"
                    >
                      <span
                        class="sc-gJWqzi gEydeL"
                        data-off="🪂"
                        data-on="🪂"
                      />
                      <span
                        class="sc-rBLzX hAekJS"
                      />
                    </label>
                  </div>
                </div>
                <div
                  class="sc-fYxtnH YMNhn"
                >
                  Airdrop XEC to 
                  tCRD
                   
                  holders
                </div>
              </div>
              <div
                class="sc-iGPElx iHtmSM"
              >
                <div
                  class="sc-gFaPwZ bhfoic"
                >
                  <div
                    class="sc-fhYwyz kZTqdd"
                  >
                    <input
                      class="sc-bMvGRv dnGmSn"
                      id="Toggle Burn"
                      name="Toggle Burn"
                      title="Toggle Burn"
                      type="checkbox"
                    />
                    <label
                      class="sc-jzgbtB hsNhPD"
                      for="Toggle Burn"
                    >
                      <span
                        class="sc-gJWqzi gEydeL"
                        data-off="🔥"
                        data-on="🔥"
                      />
                      <span
                        class="sc-rBLzX hAekJS"
                      />
                    </label>
                  </div>
                </div>
                <div
                  class="sc-fYxtnH YMNhn"
                >
                  Burn 
                  tCRD
                </div>
              </div>
            </div>
          </div>
        </div>
        <div
          class="sc-cmIlrE dnHym"
        >
          <button
            class="sc-dRCTWM fmkhFW"
          >
            <svg />
          </button>
          <button
            aria-label="Send Screen"
            class="sc-dRCTWM fmkhFW"
            style="padding-bottom: 10px;"
          >
            <div
              class="sc-iwsKbI cuDgAv"
            >
              <svg
                title="tx-sent"
              />
            </div>
          </button>
          <button
            aria-label="Tokens"
            class="sc-dRCTWM fmkhFW"
          >
            <svg
              title="Tokens"
            />
          </button>
          <button
            aria-label="Receive"
            class="sc-dRCTWM fmkhFW"
          >
            <svg
              title="tx-received"
            />
          </button>
          <div
            class="sc-gleUXh dWqiyV"
            title="Show Other Screens"
          >
            <span
              class="sc-doWzTn cMiuQs"
            />
            <div
              class="sc-dBaXSw fRWxca"
              title="Other Screens"
            >
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Wallet Backup
                </p>
                <svg
                  title="wallet"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Wallets
                </p>
                <svg
                  title="wallets"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Listed NFTs
                </p>
                <svg
                  title="NFT"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Agora
                </p>
                <svg
                  title="Meme Agora"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Contacts
                </p>
                <svg
                  title="Contact List"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Airdrop
                </p>
                <svg
                  title="tx-airdrop"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Rewards
                </p>
                <svg
                  title="Cashtab Rewards"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                 
                <p>
                  Swap
                </p>
                <svg
                  title="swap"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                <p>
                  Sign & Verify
                </p>
                <svg
                  class="sc-htpNat bPFBeM"
                />
              </button>
              <button
                class="sc-bNQFlB hhXxlj"
              >
                <p>
                  Settings
                </p>
                <svg
                  title="settings"
                />
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
    at Object.getElementError (/work/cashtab/node_modules/@testing-library/dom/dist/config.js:37:19)
    at /work/cashtab/node_modules/@testing-library/dom/dist/query-helpers.js:76:38
    at /work/cashtab/node_modules/@testing-library/dom/dist/query-helpers.js:52:17
    at /work/cashtab/node_modules/@testing-library/dom/dist/query-helpers.js:95:19
    at Object.getByText (/work/cashtab/src/components/Etokens/__tests__/TokenActions.test.js:1334:20)

Each failure log is accessible here:
CashTab Unit Tests: <Token /> available actions rendered ALP token

Adjust validation for ALP max quantities, add tests for ALP actions, improve how screen handles token cache variables

remove debug logs, improve comments

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

update ALP output description, parse alp burns in tx history

This revision is now accepted and ready to land.Nov 24 2024, 11:23
tobias_ruck added a subscriber: tobias_ruck.
tobias_ruck added inline comments.
cashtab/src/components/Etokens/Token/index.tsx
209 ↗(On Diff #51089)

Here tokenProtocol simplifies things, you can just forward the protocol from Chronik

778 ↗(On Diff #51089)

Similar here: tokenProtocol

1061 ↗(On Diff #51089)

Probably best to add getMaxDecimalizedQty with a tokenProtocol parameter

1170 ↗(On Diff #51089)

Here

1175 ↗(On Diff #51089)

Comment needs to be one if higher

cashtab/src/validation/index.ts
1024 ↗(On Diff #51089)

Same here, see tokenProtocol below

1078 ↗(On Diff #51089)

What about using this? Preferably it being non-optional so people don’t forget it set it

This allows us to add more types if necessary in the future

This revision now requires changes to proceed.Nov 25 2024, 11:52
bytesofman marked an inline comment as done.

add helper functions for alp, organize token methods by token type, move general token methods to higher level methods file, unit test and type updates

Tail of the build log:

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

> ecash-lib@1.0.0 build
> tsc && tsc -p ./tsconfig.build.json && cp -r ./src/ffi ./dist

Installing ecash-agora dependencies...
/work/modules/ecash-agora /work/modules/ecash-lib /work/modules/ecash-lib-wasm /work/modules/ecash-script /work/modules/chronik-client /work/modules/mock-chronik-client /work/modules/ecashaddrjs /work/abc-ci-builds/cashtab-tests

added 364 packages, and audited 367 packages in 1s

60 packages are looking for funding
  run `npm fund` for details

2 vulnerabilities (1 moderate, 1 high)

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

> ecash-agora@0.1.1 build
> tsc && tsc -p ./tsconfig.build.json

/work/cashtab /work/modules/ecash-agora /work/modules/ecash-lib /work/modules/ecash-lib-wasm /work/modules/ecash-script /work/modules/chronik-client /work/modules/mock-chronik-client /work/modules/ecashaddrjs /work/abc-ci-builds/cashtab-tests
npm warn deprecated @humanwhocodes/config-array@0.11.14: Use @eslint/config-array instead
npm warn deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm warn deprecated eslint@8.56.0: This version is no longer supported. Please see https://eslint.org/version-support for other options.

added 1487 packages, and audited 3333 packages in 24s

323 packages are looking for funding
  run `npm fund` for details

4 vulnerabilities (2 moderate, 2 high)

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

> cashtab@2.56.0 build
> node scripts/build.js

Creating an optimized production build...
Failed to compile.

TS2339: Property 'path' does not exist on type 'NonTokenUtxo'.
    215 |         const signedFuelInputs = [];
    216 |         for (const fuelUtxo of acceptFuelInputs) {
  > 217 |             const pathInfo = wallet.paths.get(fuelUtxo.path);
        |                                                        ^^^^
    218 |             if (typeof pathInfo === 'undefined') {
    219 |                 // Should never happen
    220 |                 return toast.error(`No path info for ${fuelUtxo.path}`);


Build cashtab-tests failed with exit code 1
bytesofman added inline comments.
cashtab/src/components/Etokens/Token/index.tsx
209 ↗(On Diff #51089)

updated to match this where it's appropriate to use tokenType.protocol directly as a param

In general, there is still room for optimizing how token type is handled by the token screen. It's an incremental process as more tokens are added. For now, it's handled in the switch statement below.

I find isAlp, isNftChild, isNftParent etc as helpful shorthand...compared to for example using tokenType.type === ALP_TOKEN_TYPE_STANDARD dozens of times throughout the screen.

778 ↗(On Diff #51089)

For now, I've kept in some instances of isAlp as useful shorthand

It's true that there are some cases where a top-level function that calls with protocol as a param could be the best approach. But there are enough edge cases about this that I'm reluctant to make it the standard (for example, send txs for NFTs you are always sending qty 1, but non-NFTs you need this as a param).

I think keeping distinct functions is best for now, since a lot of these functions may also diverge in other ways (i.e. if we support multi-output sends or multi-action txs, SLP and ALP will diverge significantly).

1061 ↗(On Diff #51089)

yes -- in this case def makes sense to have one function that takes protocol as a param. added.

1170 ↗(On Diff #51089)

refactored into an alp method

1175 ↗(On Diff #51089)

refactored into an alp method

bytesofman marked 4 inline comments as done.

patch type update error, implement, lint

tobias_ruck added inline comments.
cashtab/src/token-protocols/alp/index.ts
32

Is this now necessary? Since you changed it to hex

This revision is now accepted and ready to land.Nov 26 2024, 13:34
bytesofman added inline comments.
cashtab/src/token-protocols/alp/index.ts
32

not related to the hex change -- this is now more specific as an input type for the alp-specific cashtab genesis target output building function.

this function always expects authPubKey to be defined, while GenesisInfo is typed such that authPubKey may be undefined.

Same approach in Cashtab for TokenUtxo , where the token key must be defined, though ScriptUtxo it may be undefined.

cashtab/src/token-protocols/alp/index.ts
31–32

ah gotcha
wouldn't this be simpler and clearer then?

bytesofman added inline comments.
cashtab/src/token-protocols/alp/index.ts
31–32

lol

yes this does look much better

this is a typescript knowledge gap on my end, TIL. will update.

This revision was automatically updated to reflect the committed changes.