Skip to content

The fee's currency is a config convention, not the chain's answer #68

Closed

Description

@devdudeio

Surfaced while reviewing #67 (the fix for #53), raised independently by all three
reviewers, and deliberately left out of that PR.

What is true today

Every panel that labels a fee reads settings.profile.currency — the ticker
string from the config file. fee_currency() in src/cmd/currency.rs now
documents this honestly, but documenting it is not fixing it.

Why it can be wrong

The SDK's notion of the fee currency is chain_info().chain_id, which is an
i-address, not a ticker. That a readable ticker appears on the panel at all is a
convention of the profile, not something the chain confirmed.

--node is a global override. Point a profile whose currency = "VRSCTEST"
at a different chain and every fee row on every panel confidently names the wrong
coin, on the screen shown immediately before money moves.

Why it was not fixed in #67

native_currency_id() returns a CurrencyId, not a name. Getting a ticker from
the node needs a second currency_definition lookup, a new failure path, and a
name that is itself untrusted — and to stay consistent it would have to happen at
every site that labels a native amount:

  • src/cmd/currency.rs — mint, preconvert, convert, and launch_panel
  • src/cmd/send.rs
  • src/cmd/id.rs
  • src/cmd/wallet.rs
  • src/cmd/lifecycle.rs
  • src/cmd/airgap.rs

That is a repo-wide change. #53 was rated low severity and small effort, and
growing it there would have put an unreviewed cross-cutting change inside a
consistency fix.

Suggested shape

Resolve the chain's own currency name once, where the node is already in hand,
and thread it the way Token { id, shown } already threads a currency the user
named — id and name travelling together so the two cannot silently disagree.
Where the lookup fails, the three-state verdict in src/currency_name.rs already
says how to render an unknown without claiming a nothing.

Worth checking at the same time whether --json should carry the fee currency on
mint, preconvert and convert. It does not today, and #67 left that alone as a
separate contract.

Activity

  1. added
    dxCLI ergonomics and scriptability
    minorWorth fixing, low urgency
    on Aug 24, 2026
  2. added
    claude:approvedSpec is complete; implementation starts on this label
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    and removed
    claude:approvedSpec is complete; implementation starts on this label
    on Sep 1, 2026
  3. added
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    and removed
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    on Sep 1, 2026
  4. added
    claude:needs-specSpec gate found gaps; see its numbered questions on the issue
    and removed
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    on Sep 1, 2026
  5. added
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    and removed
    claude:needs-specSpec gate found gaps; see its numbered questions on the issue
    on Sep 1, 2026
  6. chainvue-claude-automation commented on Sep 1, 2026

    @chainvue-claude-automation

    Spec gate: needs work

    Risk: high — test
    Estimated diff: ~800 lines including tests

    test

    Open questions

    1. a
    2. b

    Answer these in a comment, then re-apply claude:ready.

    Too large for one pull request

    Suggested split:

    • a
    • b
    Machine-readable verdict
    {
      "begruendung": "test",
      "estimated_diff_lines": 800,
      "plan": {
        "ansatz": "",
        "dateien": [],
        "tests": []
      },
      "risk": "high",
      "risk_begruendung": "test",
      "rueckfragen": [
        "a",
        "b"
      ],
      "split_vorschlag": [
        "a",
        "b"
      ],
      "verdict": "needs_spec"
    }

    Spec gate · run log

  7. added
    claude:needs-specSpec gate found gaps; see its numbered questions on the issue
    and removed
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    on Sep 1, 2026
  8. added
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    and removed
    claude:needs-specSpec gate found gaps; see its numbered questions on the issue
    risk:highBlast radius: money, key material, identity control, or CI itself
    on Sep 1, 2026
  9. added
    claude:needs-specSpec gate found gaps; see its numbered questions on the issue
    and removed
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    on Sep 1, 2026
  10. chainvue-claude-automation commented on Sep 1, 2026

    @chainvue-claude-automation

    Spec gate: run failed

    The spec gate did not produce a verdict. This is a fault in the automation, not in the issue. Run log

    Re-apply claude:ready to try again.

  11. added
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    and removed
    claude:needs-specSpec gate found gaps; see its numbered questions on the issue
    on Sep 1, 2026
  12. chainvue-claude-automation commented on Sep 1, 2026

    @chainvue-claude-automation

    Spec gate: needs work

    Risk: high — The fix as scoped by the issue touches src/cmd/send.rs, src/cmd/airgap.rs, src/cmd/id.rs and src/cmd/lifecycle.rs (all listed high in .github/claude-risk-paths.yml, because they move money, run the air-gap ceremony, or control identities) plus src/cmd/currency.rs, src/cmd/wallet.rs and src/currency_name.rs (medium). Any path set that reaches the high tier makes the whole PR high.
    Estimated diff: ~750 lines including tests

    The issue (src/cmd/currency.rs:2129 fee_currency(), confirmed still returning &settings.profile.currency, and the ~20 call sites found across currency.rs/send.rs/id.rs/wallet.rs/lifecycle.rs/airgap.rs) accurately describes a real, unfixed problem and correctly points at src/currency_name.rs's existing three-state verdict as the pattern tx.rs already follows. But it is written as analysis plus a 'suggested shape,' not a specification: it names an open question on --json scope without answering it, gives no exact row wording or JSON shape to assert on, and leaves the air-gap case (no node in hand) undecided. At roughly twenty call sites across four high-risk files it is also too large for one review as written.

    Open questions

    1. Should this land as one pull request touching all six files (currency.rs, send.rs, id.rs, wallet.rs, lifecycle.rs, airgap.rs), or split along the lines the issue itself describes, given close to twenty separate call sites are involved and four of the six files are high blast radius?
    2. For air-gapped sign, which never has a node in hand, what should the fee currency label show — the profile ticker unchanged, an explicit unresolved/offline marker, or something else? The issue's 'resolve it once, where the node is already in hand' implies node-backed commands only but does not say what the offline steps should do instead.
    3. Is adding a fee_currency/fee_currency_name field to --json on currency mint, preconvert and convert in scope for this issue, or deferred the way Mint, preconvert and convert printed money without saying in what #67 deferred the panel fix — the issue raises it as 'worth checking' rather than deciding it?
    4. When the lookup comes back Absent or Failed (src/currency_name.rs's three-state verdict), what exact text should each fee/amount row show in place of the config ticker, and should the panel rendering and the --json field say the same thing or different things?
    5. Is the name looked up once per command invocation and threaded to every row it labels, or does each call site do its own lookup — this decides whether the new logic is one shared helper in src/currency_name.rs or something built per command?

    Answer these in a comment, then re-apply claude:ready.

    Too large for one pull request

    Suggested split:

    • Shared native-currency-name resolution helper - add a resolve/verdict helper in src/currency_name.rs that asks the node once for the chain's own currency name and returns the same Known/Absent/Failed verdict look_up_names already uses, with tests mirroring tests/currency_name.rs's scripted-node cases.
    • Thread the resolved fee currency through wallet and currency panels - src/cmd/wallet.rs and src/cmd/currency.rs (fee_currency, mint/preconvert/convert/launch_panel) stop reading settings.profile.currency directly and use the resolved verdict, with tests asserting the row text for each of Known/Absent/Failed.
    • Thread it through send, id and lifecycle panels - src/cmd/send.rs, src/cmd/id.rs and src/cmd/lifecycle.rs adopt the same helper for their fee/amount rows, with tests.
    • Decide and implement the air-gap case - src/cmd/airgap.rs's plan/sign/broadcast split has steps with no node in hand; this sub-issue settles and implements what an offline step should print instead of a resolved name.
    • Carry fee_currency in --json for mint, preconvert and convert - the open question the issue raises but does not decide, kept separate exactly as Mint, preconvert and convert printed money without saying in what #67 kept it separate from the panel fix.
    How the gate got there

    I read src/currency_name.rs (the three-state Known/Absent/Failed verdict and look_up_names, which the issue points to as the pattern to reuse) and src/cmd/currency.rs's fee_currency(), which today just returns &settings.profile.currency. A grep for settings.profile.currency / fee_currency / native_currency_id across src/ confirms the issue's own list: roughly twenty call sites across src/cmd/currency.rs, send.rs, id.rs, wallet.rs, lifecycle.rs and airgap.rs all label an amount or fee row from the config ticker rather than a chain-verified name, while tx.rs already does it the right way (transfer.fee_currency resolved through verdict(names, ...)) — which is the precedent the issue wants copied. .github/claude-risk-paths.yml puts send.rs, airgap.rs, id.rs and lifecycle.rs in the high tier and currency.rs/wallet.rs/currency_name.rs in medium, so touching all six makes this a high-risk PR outright. The issue itself is candid that it deliberately left the shape open ('Suggested shape', not a decision) and flags an explicit open question about whether --json should carry the fee currency on mint/preconvert/convert. It gives no acceptance criterion I can turn into a concrete assertion — no exact panel wording, no exact JSON field name/shape, no decision on what an air-gapped sign step (no node in hand) should print instead of a resolved name, and no decision on whether the ~20 sites land in one PR or several. I could not construct a single 'given command X, expect output Y' from the text as written. The prior automated comment on this issue (test/a/b placeholders) is visibly a broken run, not a real prior verdict, so I disregarded it and re-derived independently.

    Machine-readable verdict
    {
      "analyse": "I read src/currency_name.rs (the three-state Known/Absent/Failed verdict and look_up_names, which the issue points to as the pattern to reuse) and src/cmd/currency.rs's fee_currency(), which today just returns &settings.profile.currency. A grep for settings.profile.currency / fee_currency / native_currency_id across src/ confirms the issue's own list: roughly twenty call sites across src/cmd/currency.rs, send.rs, id.rs, wallet.rs, lifecycle.rs and airgap.rs all label an amount or fee row from the config ticker rather than a chain-verified name, while tx.rs already does it the right way (transfer.fee_currency resolved through verdict(names, ...)) — which is the precedent the issue wants copied. .github/claude-risk-paths.yml puts send.rs, airgap.rs, id.rs and lifecycle.rs in the high tier and currency.rs/wallet.rs/currency_name.rs in medium, so touching all six makes this a high-risk PR outright. The issue itself is candid that it deliberately left the shape open ('Suggested shape', not a decision) and flags an explicit open question about whether --json should carry the fee currency on mint/preconvert/convert. It gives no acceptance criterion I can turn into a concrete assertion — no exact panel wording, no exact JSON field name/shape, no decision on what an air-gapped sign step (no node in hand) should print instead of a resolved name, and no decision on whether the ~20 sites land in one PR or several. I could not construct a single 'given command X, expect output Y' from the text as written. The prior automated comment on this issue (test/a/b placeholders) is visibly a broken run, not a real prior verdict, so I disregarded it and re-derived independently.",
      "begruendung": "The issue (src/cmd/currency.rs:2129 fee_currency(), confirmed still returning &settings.profile.currency, and the ~20 call sites found across currency.rs/send.rs/id.rs/wallet.rs/lifecycle.rs/airgap.rs) accurately describes a real, unfixed problem and correctly points at src/currency_name.rs's existing three-state verdict as the pattern tx.rs already follows. But it is written as analysis plus a 'suggested shape,' not a specification: it names an open question on --json scope without answering it, gives no exact row wording or JSON shape to assert on, and leaves the air-gap case (no node in hand) undecided. At roughly twenty call sites across four high-risk files it is also too large for one review as written.",
      "estimated_diff_lines": 750,
      "plan": {
        "ansatz": "",
        "dateien": [],
        "tests": []
      },
      "risk": "high",
      "risk_begruendung": "The fix as scoped by the issue touches src/cmd/send.rs, src/cmd/airgap.rs, src/cmd/id.rs and src/cmd/lifecycle.rs (all listed `high` in .github/claude-risk-paths.yml, because they move money, run the air-gap ceremony, or control identities) plus src/cmd/currency.rs, src/cmd/wallet.rs and src/currency_name.rs (`medium`). Any path set that reaches the high tier makes the whole PR high.",
      "rueckfragen": [
        "Should this land as one pull request touching all six files (currency.rs, send.rs, id.rs, wallet.rs, lifecycle.rs, airgap.rs), or split along the lines the issue itself describes, given close to twenty separate call sites are involved and four of the six files are `high` blast radius?",
        "For air-gapped `sign`, which never has a node in hand, what should the fee currency label show — the profile ticker unchanged, an explicit unresolved/offline marker, or something else? The issue's 'resolve it once, where the node is already in hand' implies node-backed commands only but does not say what the offline steps should do instead.",
        "Is adding a fee_currency/fee_currency_name field to `--json` on `currency mint`, `preconvert` and `convert` in scope for this issue, or deferred the way #67 deferred the panel fix — the issue raises it as 'worth checking' rather than deciding it?",
        "When the lookup comes back Absent or Failed (src/currency_name.rs's three-state verdict), what exact text should each fee/amount row show in place of the config ticker, and should the panel rendering and the --json field say the same thing or different things?",
        "Is the name looked up once per command invocation and threaded to every row it labels, or does each call site do its own lookup — this decides whether the new logic is one shared helper in src/currency_name.rs or something built per command?"
      ],
      "split_vorschlag": [
        "Shared native-currency-name resolution helper - add a resolve/verdict helper in src/currency_name.rs that asks the node once for the chain's own currency name and returns the same Known/Absent/Failed verdict look_up_names already uses, with tests mirroring tests/currency_name.rs's scripted-node cases.",
        "Thread the resolved fee currency through wallet and currency panels - src/cmd/wallet.rs and src/cmd/currency.rs (fee_currency, mint/preconvert/convert/launch_panel) stop reading settings.profile.currency directly and use the resolved verdict, with tests asserting the row text for each of Known/Absent/Failed.",
        "Thread it through send, id and lifecycle panels - src/cmd/send.rs, src/cmd/id.rs and src/cmd/lifecycle.rs adopt the same helper for their fee/amount rows, with tests.",
        "Decide and implement the air-gap case - src/cmd/airgap.rs's plan/sign/broadcast split has steps with no node in hand; this sub-issue settles and implements what an offline step should print instead of a resolved name.",
        "Carry fee_currency in --json for mint, preconvert and convert - the open question the issue raises but does not decide, kept separate exactly as #67 kept it separate from the panel fix."
      ],
      "verdict": "needs_spec"
    }

    Spec gate · run log

  13. added
    claude:needs-specSpec gate found gaps; see its numbered questions on the issue
    and removed
    claude:readyReady for the spec gate -- set this by hand when the issue is written
    on Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude:needs-specSpec gate found gaps; see its numbered questions on the issuedxCLI ergonomics and scriptabilityminorWorth fixing, low urgencyrisk:highBlast radius: money, key material, identity control, or CI itself

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions