-
Notifications
You must be signed in to change notification settings - Fork 57
feat(wallet): add accounts.rename call
#1583
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -143,6 +143,7 @@ async fn handler( | |
| }, | ||
| "stealth_transfer" => call_handler(context, value, token, accounts::handle_stealth_transfer).await, | ||
| "set_default" => call_handler(context, value, token, accounts::handle_set_default).await, | ||
| "rename" => call_handler(context, value, token, accounts::handle_rename).await, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainRoute wiring for accounts.rename looks correct; verify validation/uniqueness. 🏁 Script executed: #!/bin/bash
# Locate rename_account implementation and callers for validation/uniqueness checks
rg -n -C3 --type=rust '\brename_account\s*\('
rg -n -C3 --type=rust 'struct\s+AccountsRenameRequest|enum\s+AccountsRenameRequest'
rg -n -C3 --type=rust 'UNIQUE|unique|accounts_get_by_name'Length of output: 35011 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== crates/wallet/sdk/src/apis/accounts.rs ==="
sed -n '1,420p' crates/wallet/sdk/src/apis/accounts.rs || true
echo
echo "=== applications/tari_walletd/src/handlers/accounts.rs ==="
sed -n '1,360p' applications/tari_walletd/src/handlers/accounts.rs || true
echo
echo "=== crates/wallet/sdk/src/storage.rs ==="
sed -n '1,260p' crates/wallet/sdk/src/storage.rs || true
echo
echo "=== crates/wallet/storage_sqlite/src/reader.rs (accounts_get_by_name) ==="
sed -n '380,460p' crates/wallet/storage_sqlite/src/reader.rs || true
echo
echo "=== crates/wallet/storage_sqlite/src/writer.rs (accounts_update) ==="
sed -n '1,320p' crates/wallet/storage_sqlite/src/writer.rs || true
echo
echo "=== crates/wallet/sdk/src/apis/errors.rs (if exists) & AccountsApiError in accounts.rs ==="
rg -n "enum\s+AccountsApiError" || true
rg -n "AccountsApiError" crates/wallet/sdk/src -n -S || trueLength of output: 56713 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== Search for accounts_update definitions/calls ==="
rg -n --type=rust '\bfn\s+accounts_update\b' || true
rg -n --type=rust '\baccounts_update\s*\(' || true
echo
echo "=== Show surrounding code for writer::accounts_update (if found) ==="
FILES=$(rg -n --type=rust '\bfn\s+accounts_update\b' -g 'crates/**' -g 'applications/**' -g '*/src/**' -S --no-line-number || true)
if [ -n "$FILES" ]; then
for f in $(echo "$FILES" | cut -d: -f1 | sort -u); do
echo "----- $f -----"
sed -n '1,240p' "$f" || true
echo
done
else
echo "No explicit fn accounts_update found; searching for trait method implementation 'accounts_update' in WalletStoreWriter impls..."
rg -n --type=rust 'accounts_update' -S || true
fi
echo
echo "=== Search for AccountUpdate struct/type ==="
rg -n --type=rust 'struct\s+AccountUpdate\b' || true
rg -n --type=rust 'pub struct\s+AccountUpdate\b' || true
rg -n --type=rust '\benum\s+AccountUpdate\b' || true
rg -n --type=rust '\bAccountUpdate\b' -S || true
echo
echo "=== Show models file(s) that define Account/AccountUpdate ==="
rg -n --type=rust 'struct\s+Account\b' -S || true
rg -n --type=rust 'mod models' -S || true
rg -n --hidden --no-ignore -g 'crates/**/src/**' 'AccountUpdate' -n -S || trueLength of output: 21275 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== AccountUpdate struct ==="
sed -n '1,240p' crates/wallet/sdk/src/models/account.rs || true
echo
echo "=== storage_sqlite writer.accounts_update implementation ==="
sed -n '500,660p' crates/wallet/storage_sqlite/src/writer.rs || true
echo
echo "=== storage_sqlite models/account.rs ==="
sed -n '1,240p' crates/wallet/storage_sqlite/src/models/account.rs || true
echo
echo "=== Diesel schema for accounts (schema.rs) ==="
rg -n --hidden -S "table!.*accounts" || true
sed -n '1,240p' crates/wallet/storage_sqlite/src/schema.rs || true
echo
echo "=== storage_sqlite tests for accounts ==="
sed -n '1,240p' crates/wallet/storage_sqlite/tests/accounts.rs || trueLength of output: 16863 Reject empty/duplicate account names on rename (server-side) rename_account (crates/wallet/sdk/src/apis/accounts.rs) calls accounts_update directly and does not validate new_name or check for existing names; the storage writer accepts empty/duplicate names. Add checks in rename_account to reject new_name.trim().is_empty() and to call tx.accounts_get_by_name(name).optional()? and return AccountsApiError::AccountNameAlreadyExists on duplicates. Update applications/tari_walletd/src/handlers/accounts.rs::handle_rename to map that error to an invalid_request (same mapping as create_account) so JSON‑RPC returns a clear client error. 🤖 Prompt for AI Agents |
||
| "create_free_test_coins" => { | ||
| call_handler(context, value, token, accounts::handle_create_free_test_coins).await | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. | ||
| import type { ComponentAddressOrName } from "./ComponentAddressOrName"; | ||
|
|
||
| export type AccountsRenameRequest = { account: ComponentAddressOrName; new_name: string }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. | ||
|
|
||
| export type AccountsRenameResponse = Record<string, never>; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -126,7 +126,7 @@ impl<'a, TStore: WalletStore, TNetworkInterface> AccountsApi<'a, TStore, TNetwor | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn update_account( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| account_address: &ComponentAddress, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update: AccountUpdate, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update: AccountUpdate<'_>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Result<(), AccountsApiError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.store.with_write_tx(|tx| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tx.accounts_update(account_address, update)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -282,6 +282,16 @@ impl<'a, TStore: WalletStore, TNetworkInterface> AccountsApi<'a, TStore, TNetwor | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(exists) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn rename_account(&self, account_addr: &ComponentAddress, new_name: &str) -> Result<(), AccountsApiError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut tx = self.store.create_write_tx()?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tx.accounts_update(account_addr, AccountUpdate { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Some(new_name), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ..Default::default() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tx.commit()?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+285
to
+294
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent duplicate account names and validate input on rename. Currently, rename does not check for an existing account with the same name. This can lead to duplicates or a DB constraint violation if a unique index exists. Also trim the new name and allow no-op when unchanged. Apply this diff: pub fn rename_account(&self, account_addr: &ComponentAddress, new_name: &str) -> Result<(), AccountsApiError> {
- let mut tx = self.store.create_write_tx()?;
- tx.accounts_update(account_addr, AccountUpdate {
- name: Some(new_name),
- ..Default::default()
- })?;
- tx.commit()?;
- Ok(())
+ let new_name = new_name.trim();
+ if new_name.is_empty() {
+ // Mirror other API patterns by surfacing a store error for bad input without adding a new variant
+ return Err(WalletStorageError::bad_query("accounts_rename", "new_name cannot be empty").into());
+ }
+
+ let mut tx = self.store.create_write_tx()?;
+ if let Some(existing) = tx.accounts_get_by_name(new_name).optional()? {
+ // Allow renaming to the same name on the same account, otherwise reject
+ if existing.component_address != *account_addr {
+ return Err(AccountsApiError::AccountNameAlreadyExists { name: new_name.to_string() });
+ }
+ }
+
+ tx.accounts_update(
+ account_addr,
+ AccountUpdate {
+ name: Some(new_name),
+ ..Default::default()
+ },
+ )?;
+ tx.commit()?;
+ Ok(())
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn set_default_account(&self, account_addr: &ComponentAddress) -> Result<(), AccountsApiError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut tx = self.store.create_write_tx()?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tx.accounts_set_default(account_addr)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Map duplicate-name error to a client error (consistency with create).
rename_accountmay returnAccountNameAlreadyExists. Likehandle_create, map it toinvalid_requestinstead of propagating a generic error.Apply this diff:
📝 Committable suggestion
🤖 Prompt for AI Agents