Skip to content

fix(Coin): align fromString denom regex with Cosmos denom spec#168

Merged
Vritra4 merged 3 commits into
initia-labs:mainfrom
Nexory:fix/coin-fromstring-denom-regex
May 28, 2026
Merged

fix(Coin): align fromString denom regex with Cosmos denom spec#168
Vritra4 merged 3 commits into
initia-labs:mainfrom
Nexory:fix/coin-fromstring-denom-regex

Conversation

@Nexory
Copy link
Copy Markdown
Contributor

@Nexory Nexory commented May 27, 2026

Fixes #167.

Coin.fromString used the denom character class [0-9a-zA-Z/], which is both narrower and looser than the Cosmos SDK denom spec ([a-zA-Z][a-zA-Z0-9/:._-]{2,127}):

  • Round-trip break: denoms containing : . _ - (e.g. tokenfactory subdenoms like factory/<addr>/my-token) failed to parse, so Coin.fromString(coin.toString()) threw instead of round-tripping.
  • Silent mis-parse: numeric-only strings matched and the trailing digits were treated as the denom — Coin.fromString('5000') returned Coin('0', 500) instead of throwing the documented error.

Change

- const m = str.match(/^(-?[0-9]+(\.[0-9]+)?)([0-9a-zA-Z/]+)$/)
+ const m = str.match(/^(-?[0-9]+(\.[0-9]+)?)([a-zA-Z][0-9a-zA-Z/:._-]*)$/)

The denom group now requires a leading letter and allows the full Cosmos denom charset. Existing denoms (uinit, ibc/<hash>, decimal amounts) parse identically — verified against the current fromString tests.

Tests

  • round-trip parse of a denom containing - (factory/init1abc/my-token), including fromString(coin.toString());
  • numeric-only strings ('5000', '12') now throw.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Denomination parsing updated to require denoms start with a letter, enforce a minimum length, and accept special characters (dash, period, underscore, colon, slash) alongside alphanumerics—reducing invalid or ambiguous denominations.
  • Tests

    • Added coverage for parsing denoms with special characters and for rejecting numeric-only denoms.

Coin.fromString used the denom character class [0-9a-zA-Z/], which is
both narrower and looser than the Cosmos SDK denom spec
([a-zA-Z][a-zA-Z0-9/:._-]{2,127}):

- denoms containing ':' '.' '_' '-' (e.g. tokenfactory subdenoms)
  failed to parse, so fromString(coin.toString()) did not round-trip;
- numeric-only strings (e.g. '5000') matched and were mis-parsed into a
  garbage Coin('0', 500) instead of throwing.

Require the denom to start with a letter and allow the full Cosmos denom
charset. Existing denoms (uinit, ibc/<hash>, decimal amounts) are
unaffected. Adds round-trip and numeric-only tests.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

Warning

Review limit reached

@Nexory, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 54 minutes and 3 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c0114c4d-45d2-414e-b428-5f250d66bafe

📥 Commits

Reviewing files that changed from the base of the PR and between 312c518 and 6ef7ade.

📒 Files selected for processing (1)
  • src/core/Coin.ts

Walkthrough

This PR fixes Coin.fromString to accept Cosmos-compliant denominations. The regex now allows :, ., _, and - characters in denoms and requires denoms to start with a letter, enabling round-trip parsing of tokenfactory-style denoms and rejecting numeric-only strings with an error instead of silent mis-parsing.

Changes

Coin denomination parsing

Layer / File(s) Summary
Denom parsing regex and validation
src/core/Coin.ts, src/core/Coin.spec.ts
The denom regex changes from [0-9a-zA-Z/]+ to [a-zA-Z][0-9a-zA-Z/:._-]*, requiring a leading letter and permitting :._- characters. Tests verify that denoms containing -, ., _ parse correctly in round-trip scenarios and that numeric-only input strings throw an error.

🎯 2 (Simple) | ⏱️ ~10 minutes

🐰 A tiny tweak, a nimble hop,
Denoms that danced can now won't stop.
Dashes, dots, and underscores play,
Numbers alone? They'll bounce away.
Cheers from a rabbit, code in sway!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely describes the main change: aligning the Coin.fromString denom validation regex with the Cosmos SDK specification.
Linked Issues check ✅ Passed The code changes fully address both objectives from issue #167: denom regex now permits ':._-' characters for round-trip parsing, and rejects numeric-only strings by requiring denoms to start with a letter.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the denom regex in Coin.fromString and adding appropriate test coverage; no unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

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

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.

❤️ Share

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: 1

🧹 Nitpick comments (1)
src/core/Coin.spec.ts (1)

151-158: ⚡ Quick win

Make the test match its stated character coverage.

This case only exercises -, but the title says "-", ".", "_". Please either rename the test or add explicit . and _ denom cases.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/Coin.spec.ts` around lines 151 - 158, The test titled to cover "-",
".", and "_" only verifies "-"; update the test in Coin.spec.ts so it actually
exercises denoms with ".", and "_" as well (or rename the test to only mention
"-"). Specifically, add two additional cases using new
Coin('factory/init1abc/my.token', 1001) /
Coin.fromString('1001factory/init1abc/my.token') and new
Coin('factory/init1abc/my_token', 1001) /
Coin.fromString('1001factory/init1abc/my_token'), and assert equality and
round-trip with Coin.fromString(coin.toString()) for each, referencing the Coin
constructor, Coin.fromString and Coin.toString methods.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/Coin.ts`:
- Line 72: The denom regex in the match on the line with "const m =
str.match(...)" currently allows any length (using *) and permits 1–2 character
denoms; update that capture group (the one starting with the leading alphabetic
character) so the part after the initial [a-zA-Z] uses a bounded quantifier of 2
to 127 characters instead of *, ensuring the denom follows Cosmos SDK rules of
an initial letter and total length 3–128; keep the surrounding numeric amount
group and anchors unchanged.

---

Nitpick comments:
In `@src/core/Coin.spec.ts`:
- Around line 151-158: The test titled to cover "-", ".", and "_" only verifies
"-"; update the test in Coin.spec.ts so it actually exercises denoms with ".",
and "_" as well (or rename the test to only mention "-"). Specifically, add two
additional cases using new Coin('factory/init1abc/my.token', 1001) /
Coin.fromString('1001factory/init1abc/my.token') and new
Coin('factory/init1abc/my_token', 1001) /
Coin.fromString('1001factory/init1abc/my_token'), and assert equality and
round-trip with Coin.fromString(coin.toString()) for each, referencing the Coin
constructor, Coin.fromString and Coin.toString methods.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e57b1517-67a6-48d0-8e62-38e13a402335

📥 Commits

Reviewing files that changed from the base of the PR and between da6db00 and d797752.

📒 Files selected for processing (2)
  • src/core/Coin.spec.ts
  • src/core/Coin.ts

Comment thread src/core/Coin.ts Outdated
… _ in round-trip test

Address review feedback on the denom regex:
- bound the denom to the Cosmos default length range ([a-zA-Z][...]{2,127}),
  matching the SDK's reDnmString (total length 3-128) instead of an unbounded
  quantifier;
- extend the round-trip test denom to include '.', '_' and '-' so it matches
  the cases named in the test title.
@Nexory
Copy link
Copy Markdown
Contributor Author

Nexory commented May 27, 2026

Updated to address the review feedback:

  • Bounded the denom to the Cosmos default length range — [a-zA-Z][0-9a-zA-Z/:._-]{2,127} — matching the SDK reDnmString (total length 3–128) rather than an unbounded quantifier.
  • Extended the round-trip test denom to factory/init1abc/my-token_v1.5 so it exercises -, . and _ as the test title states.

Existing cases (uinit, ibc/<hash>, decimal amounts) are unaffected; numeric-only strings still throw.

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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/Coin.ts`:
- Line 72: The long regex in the const m = str.match(...) expression exceeds
line length; refactor by extracting the pattern into multiple concatenated
string parts (or named constants) and build a RegExp before matching (e.g.,
create a const patternParts = ['^', '(-?[0-9]+(\\.[0-9]+)?)',
'([a-zA-Z][0-9a-zA-Z/:._-]{2,127})', '$'].join('') and const re = new
RegExp(patternParts) ) and then replace const m = str.match(...) with const m =
str.match(re) so the regex is split across lines to satisfy Prettier while
preserving the same pattern.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 32cc2d75-2651-42f4-8b05-332bbf2c9c93

📥 Commits

Reviewing files that changed from the base of the PR and between d797752 and 312c518.

📒 Files selected for processing (2)
  • src/core/Coin.spec.ts
  • src/core/Coin.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/Coin.spec.ts

Comment thread src/core/Coin.ts Outdated
Copy link
Copy Markdown
Contributor

@Vritra4 Vritra4 left a comment

Choose a reason for hiding this comment

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

LGTM

@Vritra4 Vritra4 merged commit a4476d3 into initia-labs:main May 28, 2026
2 checks passed
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.

Coin.fromString rejects valid Cosmos denoms (:._-) and silently mis-parses numeric-only strings

2 participants