Skip to content

feat(crypto): implement validateMnemonic#159

Open
ShantelPeters wants to merge 2 commits intoancore-org:mainfrom
ShantelPeters:feat/validate-mnemonic
Open

feat(crypto): implement validateMnemonic#159
ShantelPeters wants to merge 2 commits intoancore-org:mainfrom
ShantelPeters:feat/validate-mnemonic

Conversation

@ShantelPeters
Copy link
Copy Markdown

@ShantelPeters ShantelPeters commented Mar 26, 2026

Description

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📝 Documentation update
  • 🔧 Configuration change
  • ♻️ Code refactoring
  • ⚡ Performance improvement
  • ✅ Test addition/improvement

Security Impact

  • This change involves cryptographic operations
  • This change affects account validation logic
  • This change modifies smart contracts
  • This change handles user private keys
  • This change affects authorization/authentication
  • No security impact

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • E2E tests added/updated (if applicable)

Test Coverage

  • Current coverage: __%
  • New/modified code coverage: __%

Manual Testing Steps

Breaking Changes

  • This PR introduces breaking changes

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings or errors
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

For High-Security Changes

  • I have documented all security assumptions
  • I have considered attack vectors
  • I have added security-focused test cases
  • I have reviewed against the threat model

Related Issues

Closes #
Related to #

Additional Context

Reviewer Notes


CLOSES #66

Summary by CodeRabbit

  • New Features

    • Enhanced mnemonic validation to enforce strict 12-word requirement and automatically normalize whitespace handling.
  • Tests

    • Added comprehensive test suite for mnemonic validation covering valid phrases, invalid word counts, malformed inputs, and whitespace edge cases.
  • Chores

    • Updated crypto package dependencies and minor code cleanup.

@drips-wave
Copy link
Copy Markdown

drips-wave bot commented Mar 26, 2026

@ShantelPeters Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6a69ce38-f73a-41b6-b516-a24f9af37d0c

📥 Commits

Reviewing files that changed from the base of the PR and between b08ee2c and b3dd388.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • packages/crypto/src/encryption.ts
  • packages/crypto/src/index.ts
  • packages/crypto/src/mnemonic.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/crypto/src/encryption.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/crypto/src/index.ts

📝 Walkthrough

Walkthrough

This PR implements validateMnemonic() in @ancore/crypto to validate BIP39 mnemonics. It adds bip39 and @types/bip39 dependencies, introduces strict 12-word validation with input guards and whitespace normalization, and includes comprehensive test coverage for valid and invalid mnemonic scenarios.

Changes

Cohort / File(s) Summary
Dependencies
packages/crypto/package.json
Added bip39 runtime dependency and @types/bip39 dev dependency for BIP39 mnemonic validation support.
Mnemonic Validation
packages/crypto/src/mnemonic.ts
Implemented validateMnemonic() with input guards (falsy/non-string checks), word-count enforcement (exactly 12 words), whitespace trimming and normalization, and delegation to bip39.validateMnemonic(). Updated function documentation.
Validation Tests
packages/crypto/src/__tests__/mnemonic-validate.test.ts
Added comprehensive Jest test suite covering valid 12-word mnemonics, invalid words, invalid word counts (11 and 15), empty strings, and extra whitespace handling.
Code Cleanup
packages/crypto/src/encryption.ts, packages/crypto/src/index.ts
Removed JSDoc comments from encryption functions and placeholder comments in barrel export; adjusted export formatting and EOF newlines. No functional changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Twelve words now verified, no more, no less,
A rabbit checks each word with careful finesse,
Trim the spaces, split with care,
BIP39 validation floating through the air! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Minor out-of-scope changes detected: JSDoc comments removed from encryption.ts and trailing newline adjusted in index.ts, which are unrelated to validateMnemonic implementation. Remove the JSDoc comment deletions from encryption.ts and trailing newline changes from index.ts, as these are outside the scope of issue #66.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: implementing the validateMnemonic function in the crypto package.
Linked Issues check ✅ Passed All requirements from issue #66 are met: BIP39 dependency added [#66], validateMnemonic implemented returning boolean [#66], invalid lengths/words rejected [#66], comprehensive unit tests provided [#66], and definition of done satisfied.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/crypto/src/encryption.ts (2)

1-1: Consider removing or narrowing the ESLint disable directive.

The file-level /* eslint-disable no-undef */ is overly broad and may mask legitimate issues. If this was added to suppress errors for globalThis, BufferSource, or other Web API globals, these should now be properly typed with "DOM" added to the tsconfig.json lib array.

If specific lines still trigger false positives, prefer targeted inline disables with explanatory comments.

♻️ Proposed fix
-/* eslint-disable no-undef */
 import { Buffer } from 'node:buffer';

If specific globals still need suppression, use inline comments:

// eslint-disable-next-line no-undef -- BufferSource is a DOM global
salt: salt as BufferSource,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/crypto/src/encryption.ts` at line 1, Remove the file-level "/*
eslint-disable no-undef */" in packages/crypto/src/encryption.ts and instead
either add "DOM" to the tsconfig.json "lib" array so globals like BufferSource
and globalThis are properly typed, or replace the broad disable with targeted
inline disables only where needed (for example next to the usage of salt: salt
as BufferSource or any specific global references) including a brief comment
explaining why the inline disable is required.

54-54: Redundant BufferSource casts.

Uint8Array already implements the BufferSource interface, so these explicit casts are unnecessary now that "DOM" is included in the TypeScript lib configuration. They don't cause runtime issues but add visual noise.

♻️ Proposed removal of redundant casts
-      salt: salt as BufferSource,
+      salt,
-      iv: iv as BufferSource,
+      iv,
-      ciphertext as BufferSource
+      ciphertext

Also applies to: 134-134, 171-171, 174-174

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/crypto/src/encryption.ts` at line 54, Remove the redundant "as
BufferSource" casts in packages/crypto/src/encryption.ts: replace occurrences
like "salt: salt as BufferSource" with just "salt" (and similarly drop "as
BufferSource" on the other BufferSource-typed variables in this file). Locate
the objects/payloads that pass the variable named salt (and the two other spots
flagged) and remove the explicit casts so the underlying Uint8Array is used
directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/crypto/package.json`:
- Line 27: The package.json currently declares both "bip39": "^3.1.0" and a
redundant devDependency "@types/bip39"; since bip39 v3.1.0 bundles its own
TypeScript definitions (types/index.d.ts), remove the "@types/bip39" entry from
devDependencies to avoid duplicate type declarations and keep only the existing
"bip39" dependency referenced in package.json.

In `@packages/crypto/src/__tests__/mnemonic-validate.test.ts`:
- Around line 40-45: The test name and behavior disagree: update the test in
mnemonic-validate.test.ts so it asserts the intended behavior (either change the
description to "returns true for strings with extra spaces but correct word
count" or flip the expectation to toBe(false)); also make the whitespace
injection robust by replacing all spaces (e.g., use validMnemonic.replace(/ /g,
'   ') or validMnemonic.replaceAll(' ', '   ')) and keep the assertion to match
the new description; key symbols: the test case itself and the
validateMnemonic(...) call.

---

Nitpick comments:
In `@packages/crypto/src/encryption.ts`:
- Line 1: Remove the file-level "/* eslint-disable no-undef */" in
packages/crypto/src/encryption.ts and instead either add "DOM" to the
tsconfig.json "lib" array so globals like BufferSource and globalThis are
properly typed, or replace the broad disable with targeted inline disables only
where needed (for example next to the usage of salt: salt as BufferSource or any
specific global references) including a brief comment explaining why the inline
disable is required.
- Line 54: Remove the redundant "as BufferSource" casts in
packages/crypto/src/encryption.ts: replace occurrences like "salt: salt as
BufferSource" with just "salt" (and similarly drop "as BufferSource" on the
other BufferSource-typed variables in this file). Locate the objects/payloads
that pass the variable named salt (and the two other spots flagged) and remove
the explicit casts so the underlying Uint8Array is used directly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b18a07d5-81d1-4211-be65-0d83fea63d00

📥 Commits

Reviewing files that changed from the base of the PR and between 6bf7d94 and b08ee2c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • packages/crypto/package.json
  • packages/crypto/src/__tests__/mnemonic-validate.test.ts
  • packages/crypto/src/encryption.ts
  • packages/crypto/src/index.ts
  • packages/crypto/src/mnemonic.ts
  • packages/crypto/tsconfig.json

"@noble/hashes": "^1.4.0",
"@stellar/stellar-sdk": "^12.0.0"
"@stellar/stellar-sdk": "^12.0.0",
"bip39": "^3.1.0"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if bip39 3.1.0 exists and inspect its package info
curl -s https://registry.npmjs.org/bip39/3.1.0 | jq '{name, version, types, typings}'

# Check latest version and if it has bundled types
curl -s https://registry.npmjs.org/bip39/latest | jq '{name, version, types, typings}'

# Check `@types/bip39` info
curl -s https://registry.npmjs.org/@types/bip39/3.0.4 | jq '{name, version}'

Repository: ancore-org/ancore

Length of output: 303


Remove redundant @types/bip39 dependency.

The bip39 package at version 3.1.0 includes bundled TypeScript definitions (./types/index.d.ts), making the @types/bip39 devDependency at line 31 unnecessary. Remove @types/bip39 to eliminate the redundant type definition.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/crypto/package.json` at line 27, The package.json currently declares
both "bip39": "^3.1.0" and a redundant devDependency "@types/bip39"; since bip39
v3.1.0 bundles its own TypeScript definitions (types/index.d.ts), remove the
"@types/bip39" entry from devDependencies to avoid duplicate type declarations
and keep only the existing "bip39" dependency referenced in package.json.

Comment on lines +40 to +45
it('returns false for strings with extra spaces but correct word count', () => {
const validMnemonic = bip39.generateMnemonic(128);
// Extra spaces should be handled correctly by our split logic
const spacedMnemonic = validMnemonic.replace(' ', ' ');
expect(validateMnemonic(spacedMnemonic)).toBe(true);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Test description contradicts the expected result.

The test name says "returns false for strings with extra spaces..." but the assertion expects true. The actual behavior being tested is that extra whitespace is correctly normalized (which is good), but the description is misleading.

Additionally, String.replace(' ', ' ') only replaces the first occurrence. Consider using a regex for more thorough testing.

🐛 Proposed fix
-  it('returns false for strings with extra spaces but correct word count', () => {
+  it('handles strings with extra spaces correctly', () => {
     const validMnemonic = bip39.generateMnemonic(128);
-    // Extra spaces should be handled correctly by our split logic
-    const spacedMnemonic = validMnemonic.replace(' ', '   ');
+    // Extra spaces should be normalized by our split logic
+    const spacedMnemonic = validMnemonic.replace(/ /g, '   ');
     expect(validateMnemonic(spacedMnemonic)).toBe(true);
   });
📝 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.

Suggested change
it('returns false for strings with extra spaces but correct word count', () => {
const validMnemonic = bip39.generateMnemonic(128);
// Extra spaces should be handled correctly by our split logic
const spacedMnemonic = validMnemonic.replace(' ', ' ');
expect(validateMnemonic(spacedMnemonic)).toBe(true);
});
it('handles strings with extra spaces correctly', () => {
const validMnemonic = bip39.generateMnemonic(128);
// Extra spaces should be normalized by our split logic
const spacedMnemonic = validMnemonic.replace(/ /g, ' ');
expect(validateMnemonic(spacedMnemonic)).toBe(true);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/crypto/src/__tests__/mnemonic-validate.test.ts` around lines 40 -
45, The test name and behavior disagree: update the test in
mnemonic-validate.test.ts so it asserts the intended behavior (either change the
description to "returns true for strings with extra spaces but correct word
count" or flip the expectation to toBe(false)); also make the whitespace
injection robust by replacing all spaces (e.g., use validMnemonic.replace(/ /g,
'   ') or validMnemonic.replaceAll(' ', '   ')) and keep the assertion to match
the new description; key symbols: the test case itself and the
validateMnemonic(...) call.

@wheval
Copy link
Copy Markdown
Contributor

wheval commented Mar 27, 2026

@ShantelPeters resolve conflicts

@ShantelPeters
Copy link
Copy Markdown
Author

@ShantelPeters resolve conflicts

Hi @wheval conflicts has been resolved

@ShantelPeters
Copy link
Copy Markdown
Author

Hello @wheval please review my PR

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.

Implement validateMnemonic(mnemonic)

2 participants