feat(walletui): rename accounts - #1588
Conversation
WalkthroughAdds inline account rename capability to the web UI: new AccountName component with edit/save, a React Query mutation hook for accountsRename, a JSON-RPC client method, and UI wiring in Account Details screens. Also broadens formatCurrency to accept Amount-like inputs and updates balance rendering. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant UI as AccountName (UI)
participant Hook as useAccountsRename (RQ Mutation)
participant RPC as json_rpc.accountsRename
participant WD as Wallet Daemon Client
participant RQ as React Query Cache
UI->>Hook: mutate({ account, newName })
Hook->>RPC: accountsRename(request)
RPC->>WD: c.accountsRename(request)
WD-->>RPC: AccountsRenameResponse
RPC-->>Hook: response
Hook->>RQ: invalidate(accounts list + account get)
Hook->>RQ: refetch(accounts list)
Hook-->>UI: onSuccess callback
UI->>UI: exit edit mode, update displayed name
Note over UI,Hook: On error: pending disabled, onRenameError invoked
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
applications/tari_walletd/web_ui/src/routes/AssetVault/Components/AccountDetails.tsx (1)
23-27: Incorrect source for substateIdToString (bindings are types-only).@tari-project/typescript-bindings does not provide runtime helpers. Import substateIdToString from local utils.
Based on learnings
Apply:-import { substateIdToString } from "@tari-project/typescript-bindings"; +import { substateIdToString } from "@utils/helpers";
🧹 Nitpick comments (3)
applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts (1)
98-115: Avoid redundant refetch; rely on invalidation.invalidateQueries will refetch active observers; the extra refetchQueries is usually unnecessary and adds duplicate load.
Apply:
onSuccess: (_data, variables) => { queryClient.invalidateQueries({ queryKey: ["accounts"] }); queryClient.invalidateQueries({ queryKey: [`accounts_get_${variables.account}`] }); - queryClient.refetchQueries({ queryKey: ["accounts"] }); },applications/tari_walletd/web_ui/src/components/AccountName.tsx (1)
111-142: Add accessible labels for icon buttons.Improve a11y by adding aria-labels to IconButtons.
-<IconButton +<IconButton size="small" onClick={handleSaveRename} disabled={renameAccountMutation.isPending} - title="Save" + title="Save" + aria-label="Save account name" > ... -<IconButton +<IconButton size="small" onClick={handleCancelEdit} disabled={renameAccountMutation.isPending} - title="Cancel" + title="Cancel" + aria-label="Cancel edit account name" > ... -<IconButton size="small" onClick={handleStartEdit} title="Rename account"> +<IconButton size="small" onClick={handleStartEdit} title="Rename account" aria-label="Rename account">applications/tari_walletd/web_ui/src/utils/helpers.tsx (1)
255-306: Reuse bigintToDecimalString to avoid Number() precision loss and duplicate logic.Converting BigInt to Number can lose precision for large amounts; bigintToDecimalString already formats safely.
Apply:
if (typeof amount === "bigint") { - const divisor = BigInt(CURRENCY.DIVISOR); - const integerPart = amount / divisor; - const remainder = amount % divisor; - - const fractionalPart = remainder.toString().padStart(CURRENCY.DECIMALS, "0"); - - return `${Number(integerPart).toLocaleString("en-US")}.${fractionalPart} ${currencySymbol}`; + return `${bigintToDecimalString(amount, CURRENCY.DECIMALS)} ${currencySymbol}`; } else if (typeof amount === "number") { if (isNaN(amount)) { return `0 ${currencySymbol}`; } const convertedAmount = amount / CURRENCY.DIVISOR; return `${convertedAmount.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: CURRENCY.DECIMALS, })} ${currencySymbol}`; } else if (typeof amount === "string") { - // Handle Amount type - try { - const numericAmount = BigInt(amount); - const divisor = BigInt(CURRENCY.DIVISOR); - const integerPart = numericAmount / divisor; - const remainder = numericAmount % divisor; - - const fractionalPart = remainder.toString().padStart(CURRENCY.DECIMALS, "0"); - - return `${Number(integerPart).toLocaleString("en-US")}.${fractionalPart} ${currencySymbol}`; - } catch (error) { + try { + const numericAmount = BigInt(amount); + return `${bigintToDecimalString(numericAmount, CURRENCY.DECIMALS)} ${currencySymbol}`; + } catch (error) { console.error("Failed to parse Amount:", amount, error); return `0 ${currencySymbol}`; } } else { - // Handle any other type (object, etc.) - try { - const stringValue = String(amount); - const numericAmount = BigInt(stringValue); - const divisor = BigInt(CURRENCY.DIVISOR); - const integerPart = numericAmount / divisor; - const remainder = numericAmount % divisor; - - const fractionalPart = remainder.toString().padStart(CURRENCY.DECIMALS, "0"); - - return `${Number(integerPart).toLocaleString("en-US")}.${fractionalPart} ${currencySymbol}`; - } catch (error) { + try { + const numericAmount = BigInt(String(amount)); + return `${bigintToDecimalString(numericAmount, CURRENCY.DECIMALS)} ${currencySymbol}`; + } catch (error) { console.error("Failed to parse Amount:", amount, error); return `0 ${currencySymbol}`; } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
applications/tari_walletd/web_ui/src/components/AccountName.tsx(1 hunks)applications/tari_walletd/web_ui/src/routes/AccountDetails/AccountDetails.tsx(6 hunks)applications/tari_walletd/web_ui/src/routes/AssetVault/Components/AccountDetails.tsx(3 hunks)applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts(2 hunks)applications/tari_walletd/web_ui/src/utils/helpers.tsx(2 hunks)applications/tari_walletd/web_ui/src/utils/json_rpc.ts(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
applications/tari_walletd/web_ui/src/utils/json_rpc.ts (3)
clients/javascript/wallet_daemon_client/src/index.ts (1)
accountsRename(180-182)bindings/src/types/wallet-daemon-client/AccountsRenameRequest.ts (1)
AccountsRenameRequest(4-4)bindings/src/types/wallet-daemon-client/AccountsRenameResponse.ts (1)
AccountsRenameResponse(3-3)
applications/tari_walletd/web_ui/src/routes/AccountDetails/AccountDetails.tsx (2)
applications/tari_walletd/web_ui/src/utils/helpers.tsx (1)
formatCurrency(255-307)applications/tari_walletd/web_ui/src/components/StyledComponents.ts (1)
InnerHeading(46-53)
applications/tari_walletd/web_ui/src/utils/helpers.tsx (2)
bindings/src/types/Amount.ts (1)
Amount(12-12)applications/tari_walletd/web_ui/src/utils/constants.ts (1)
CURRENCY(23-27)
applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts (3)
bindings/src/types/ComponentAddress.ts (1)
ComponentAddress(6-6)applications/tari_walletd/web_ui/src/utils/json_rpc.ts (1)
accountsRename(276-277)applications/tari_walletd/web_ui/src/services/api/helpers/types.ts (1)
ApiError(23-27)
applications/tari_walletd/web_ui/src/routes/AssetVault/Components/AccountDetails.tsx (1)
applications/tari_walletd/web_ui/src/utils/helpers.tsx (1)
substateIdToString(100-109)
applications/tari_walletd/web_ui/src/components/AccountName.tsx (2)
bindings/src/types/ComponentAddress.ts (1)
ComponentAddress(6-6)applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts (1)
useAccountsRename(98-115)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: test
- GitHub Check: check stable
- GitHub Check: check nightly
- GitHub Check: machete
- GitHub Check: clippy
🔇 Additional comments (9)
applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts (1)
93-97: Type for rename payload is sensible and consistent.applications/tari_walletd/web_ui/src/routes/AssetVault/Components/AccountDetails.tsx (2)
42-45: Local store update on rename is fine.
58-64: AccountName integration LGTM.applications/tari_walletd/web_ui/src/routes/AccountDetails/AccountDetails.tsx (3)
57-59: Balance formatting with formatCurrency looks good.
171-173: Confirm param type matches ComponentAddress.Passing accountAddr directly assumes the route param is a ComponentAddress string. If it’s a tagged SubstateId elsewhere, pass substateIdToString(accountAddr) for consistency.
197-197: Section heading improvements LGTM.Also applies to: 221-221
applications/tari_walletd/web_ui/src/components/AccountName.tsx (2)
64-85: Save/cancel logic with trim and equality check is solid.
105-107: ‘isPending’ is correct for React Query v5
applications/tari_walletd/web_ui/package.json pins @tanstack/react-query v5.85.7, which exposesisPending. No change required.applications/tari_walletd/web_ui/src/utils/json_rpc.ts (1)
33-35: Approve accountsRename wiring Client methodaccountsRenameand itsAccountsRenameRequest/AccountsRenameResponsetypes are present and correctly exported.
| decodeOotleAddressOrNull, | ||
| substateIdToString, | ||
| } from "@tari-project/typescript-bindings"; | ||
| import { BalanceEntry, decodeOotleAddressOrNull, substateIdToString } from "@tari-project/typescript-bindings"; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Likely wrong imports from types-only package.
substateIdToString is a local util, not from @tari-project/typescript-bindings. Also verify decodeOotleAddressOrNull is coming from a runtime module.
Based on learnings
Suggested fix for substateIdToString:
-import { BalanceEntry, decodeOotleAddressOrNull, substateIdToString } from "@tari-project/typescript-bindings";
+import type { BalanceEntry } from "@tari-project/typescript-bindings";
+import { substateIdToString } from "@utils/helpers";
+import { decodeOotleAddressOrNull } from "@utils/helpers"; // update to the actual runtime module that provides this function🏁 Script executed:
#!/bin/bash
# Confirm where substateIdToString and decodeOotleAddressOrNull are defined in the repo
rg -nP -C2 '\bexport\s+(function|const)\s+substateIdToString\b'
rg -nP -C2 '\bexport\s+(function|const)\s+decodeOotleAddressOrNull\b'
# Locate existing imports of these to see the correct module
rg -nP -C2 'substateIdToString.*from'
rg -nP -C2 'decodeOotleAddressOrNull.*from'Length of output: 18528
🏁 Script executed:
#!/bin/bash
echo "Inspecting bindings entrypoint for decodeOotleAddressOrNull exports"
rg -nP 'decodeOotleAddressOrNull' -C1 bindings/src/index.ts || echo "decodeOotleAddressOrNull not found in index.ts"
echo
echo "Checking for re-export of ootleAddress module"
rg -nP 'export.*helpers/ootleAddress' -C1 bindings/src/index.ts || echo "No ootleAddress re-export in index.ts"Length of output: 291
Correct imports in AccountDetails.tsx
-import { BalanceEntry, decodeOotleAddressOrNull, substateIdToString } from "@tari-project/typescript-bindings";
+import type { BalanceEntry } from "@tari-project/typescript-bindings";
+import { decodeOotleAddressOrNull } from "@tari-project/typescript-bindings";
+import { substateIdToString } from "@utils/helpers";📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { BalanceEntry, decodeOotleAddressOrNull, substateIdToString } from "@tari-project/typescript-bindings"; | |
| import type { BalanceEntry } from "@tari-project/typescript-bindings"; | |
| import { decodeOotleAddressOrNull } from "@tari-project/typescript-bindings"; | |
| import { substateIdToString } from "@utils/helpers"; |
🤖 Prompt for AI Agents
In applications/tari_walletd/web_ui/src/routes/AccountDetails/AccountDetails.tsx
around line 39, the import line currently references symbols that are not
correctly imported from the package; update this import to use the actual
exported identifiers used in the file: remove or correct the non-exported
decodeOotleAddressOrNull (either import it from its proper module or drop it)
and ensure BalanceEntry and substateIdToString are imported exactly as exported
by @tari-project/typescript-bindings; then run the TypeScript compiler to
confirm there are no unresolved import errors and adjust the import path/names
accordingly.
Test Results (CI)418 tests - 23 418 ✅ - 10 49m 5s ⏱️ - 32m 47s Results for commit ff2ecc6. ± Comparison against base commit 3950673. This pull request removes 23 tests. |
Description
Adds the ability to rename accounts.
Also some small UI / layout improvements to the Account Details page.
Motivation and Context
The wallet didn't previously have the ability to rename accounts.
How Has This Been Tested?
Manually
What process can a PR reviewer use to test or verify this change?
On the homepage and in account details, click on the pencil icon next to the account name.
Breaking Changes
x
Summary by CodeRabbit
New Features
Improvements