Skip to content

fix(wallet): accept newline-separated seed words on import#3186

Open
0xPepeSilvia wants to merge 2 commits intotari-project:mainfrom
0xPepeSilvia:fix/seed-import-newlines-3128
Open

fix(wallet): accept newline-separated seed words on import#3186
0xPepeSilvia wants to merge 2 commits intotari-project:mainfrom
0xPepeSilvia:fix/seed-import-newlines-3128

Conversation

@0xPepeSilvia
Copy link
Copy Markdown

@0xPepeSilvia 0xPepeSilvia commented Apr 10, 2026

Summary

The seed-words regex required exactly single-space separators, and the downstream `split(' ')` consumers only split on a literal space. This meant users who typed one word per line (pressing Enter between words), or pasted a comma-separated phrase, would hit the confusing error:

`setError: Could not import seed words: Mnemonic Error: Only ChineseSimplified, ChineseTraditional, English, French, Italian, Japanese, Korean and Spanish are defined natural languages`

and the confirmation tick would never become available.

Changes

  • `Edit.tsx`: Broadened `SEEDWORD_REGEX` to accept any run of whitespace or commas as a separator (24 alphabetic words, optional surrounding whitespace). Added a shared `normalizeSeedWordsInput()` helper. The paste handler now uses the normalizer and passes `shouldValidate`/`shouldDirty` so the tick updates immediately on paste.
  • `SeedWords.tsx` + `EmptySeedWords.tsx`: `handleApply` now splits on `/[\s,]+/` and filters empties so the array sent to the Tauri `import_seed_words` command is clean regardless of whether the user typed spaces, newlines, tabs, or commas.

Closes #3128

Test plan

  • Type a 24-word seed phrase one word per line (Enter between words) → tick becomes available → import succeeds
  • Type the phrase space-separated as before → import still succeeds
  • Paste a copy of the phrase (space-separated) → tick available immediately → import succeeds
  • Paste a comma-separated list → normalized to spaces → import succeeds
  • Invalid seed phrase still shows the `invalid-seed-words` error

🤖 Generated with Claude Code


Bounty payout

If this PR is accepted as a bounty submission, please direct funds to the following Tari wallet address:

123JbAxCZ4Vrh4jCjFLXTu4z8sLeggUR87fejwNunsB55NMBSH9RpkjNiw1WL2GkKr8JhqRZhbrsSREchGanchw2Nhb

The seed-words regex required exactly single-space separators, and the
downstream split(' ') consumers only split on a literal space. This
meant that users typing one word per line (pressing Enter between
words) or pasting a comma-separated phrase would see the mnemonic
error "Only ChineseSimplified, ChineseTraditional, English, ... are
defined natural languages" and the confirmation tick would never
become available.

- Broadened SEEDWORD_REGEX to accept any run of whitespace or commas
  as a separator (24 alphabetic words, optional surrounding whitespace)
- Added normalizeSeedWordsInput() helper that collapses whitespace /
  commas into single spaces
- Paste handler now uses the shared normalizer and passes
  shouldValidate/shouldDirty so the tick updates immediately
- SeedWords and EmptySeedWords handleApply now split on /[\s,]+/ and
  filter empties so the array sent to the Tauri import_seed_words
  command is clean regardless of input format

Closes tari-project#3128

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances seed word parsing by supporting commas and multiple whitespace formats, and introduces a normalization utility for consistent input handling. Key feedback includes expanding the validation regex to support non-English seed words and removing a redundant manual validation trigger in the paste handler.

// means validation — and therefore the confirmation tick — works whether the
// user types words separated by spaces, presses Enter between words, or
// pastes a comma-separated list.
const SEEDWORD_REGEX = /^\s*([a-zA-Z]+)([\s,]+[a-zA-Z]+){23}\s*$/;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The regex [a-zA-Z]+ is too restrictive for BIP-39 seed words. As noted in the error message mentioned in the PR description, the wallet supports multiple languages including Japanese, Chinese, and Spanish, which contain non-ASCII characters or accents that do not match [a-zA-Z]. Using a more inclusive pattern like [^\s,]+ (any character except whitespace or commas) ensures that valid seed phrases in all supported languages can pass frontend validation.

Suggested change
const SEEDWORD_REGEX = /^\s*([a-zA-Z]+)([\s,]+[a-zA-Z]+){23}\s*$/;
const SEEDWORD_REGEX = /^\s*([^\s,]+)([\s,]+[^\s,]+){23}\s*$/;

Comment on lines 37 to 40
setValue('seedWords', formattedSeedText, { shouldValidate: true, shouldDirty: true });
trigger('seedWords');
},
[setValue, trigger]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The call to trigger('seedWords') is redundant because setValue is already invoked with { shouldValidate: true }, which automatically triggers validation for the field. Additionally, trigger should be removed from the useCallback dependency array if it is no longer used within the function.

Suggested change
setValue('seedWords', formattedSeedText, { shouldValidate: true, shouldDirty: true });
trigger('seedWords');
},
[setValue, trigger]
setValue('seedWords', formattedSeedText, { shouldValidate: true, shouldDirty: true });
},
[setValue]

Addresses two review comments on the seed-word import:

* Widen SEEDWORD_REGEX from [a-zA-Z]+ to [^\s,]+ with the /u flag so
  Japanese, Chinese (Simplified/Traditional), Korean, Spanish, French,
  and Italian BIP-39 phrases — all supported by the backend — also pass
  the frontend confirmation-tick check. The previous class silently
  rejected any non-ASCII wordlist even though the backend would accept
  it, funnelling users back into the same "Only ChineseSimplified, …
  are defined natural languages" error path this PR was trying to fix.
* Remove the redundant trigger('seedWords') call in handlePaste: the
  preceding setValue(..., { shouldValidate: true }) already runs the
  validator, so calling trigger again just caused an extra form
  re-render. Drop it from the useCallback dependency array too.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

seed wallet import problem

1 participant