Skip to content

feat: add currency name to currency code conversion utilities#3223

Open
slurpyone wants to merge 1 commit intoXRPLF:mainfrom
slurpyone:issue-2185-currency-conversion
Open

feat: add currency name to currency code conversion utilities#3223
slurpyone wants to merge 1 commit intoXRPLF:mainfrom
slurpyone:issue-2185-currency-conversion

Conversation

@slurpyone
Copy link
Copy Markdown

Description

This PR adds utility functions to convert between human-readable currency names and XRPL currency codes, addressing a common need for developers working with custom currencies.

Changes Made

  • Added currencyNameToCode() function to convert human-readable names to XRPL currency codes
  • Added currencyCodeToName() function to convert XRPL currency codes back to readable names
  • Added isStandardCurrencyCode() and isHexCurrencyCode() helper functions
  • Support for both 3-character ASCII codes (USD, EUR) and hex-encoded longer names
  • Proper validation and error handling for oversized names (>20 bytes when UTF-8 encoded)
  • Full TypeScript support with comprehensive JSDoc documentation

Usage Examples

import { currencyNameToCode, currencyCodeToName } from 'xrpl'

// Standard 3-character codes
currencyNameToCode('USD')  // Returns: 'USD'
currencyNameToCode('EUR')  // Returns: 'EUR'

// Longer custom token names
currencyNameToCode('MyCustomToken')  
// Returns: '4D79437573746F6D546F6B656E000000000000000000000000'

// Reverse conversion
currencyCodeToName('USD')  // Returns: 'USD'
currencyCodeToName('4D79437573746F6D546F6B656E000000000000000000000000')  
// Returns: 'MyCustomToken'

// Helper functions
isStandardCurrencyCode('USD')  // Returns: true
isHexCurrencyCode('4D79437573746F6D546F6B656E000000000000000000000000')  // Returns: true

Related Issues

Fixes #2185

Testing

  • Created comprehensive test suite covering all conversion scenarios
  • Validates proper handling of edge cases (empty strings, XRP, oversized names)
  • Confirms proper padding to 40-character hex strings for XRPL compatibility

Breaking Changes

None - this adds new utility functions without modifying existing functionality.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new currency conversion utility module exporting four functions, re-exports them from the utils barrel, and adds two Node.js test scripts that exercise encoding/decoding, 40-char padding/trimming, and edge cases including XRP handling.

Changes

Cohort / File(s) Summary
Currency Conversion Implementation
packages/xrpl/src/utils/currencyConversion.ts
New module implementing currencyNameToCode, currencyCodeToName, isStandardCurrencyCode, and isHexCurrencyCode with input validation, ASCII↔hex conversion, 40-character padding/trimming, and explicit error messages.
Utils Barrel Export
packages/xrpl/src/utils/index.ts
Imports and re-exports the four new currency conversion utilities to expose them from the utils public API.
Test Scripts
test-currency-conversion.js, test-currency-simple.js
Adds two standalone test scripts demonstrating and validating conversion behavior, round-trips, padding/trimming rules, XRP special-case behavior, and expected failure scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nibble bytes and hop through hex,
I pad with zeros, and prune what vex,
Short names bounce, long names encode,
XRP sleeps on its simple road,
Tests clap softly as I trot the code.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive The PR includes production code in currencyConversion.ts and utils/index.ts, but also adds two Node.js test scripts (test-currency-conversion.js, test-currency-simple.js) that appear to be standalone test files outside the main codebase. Clarify the purpose of test-currency-conversion.js and test-currency-simple.js; if they are temporary test scripts, move them to the proper test directory or remove them before merging.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding currency name to code conversion utilities, matching the core functionality introduced in the PR.
Description check ✅ Passed The PR description is comprehensive and covers high-level overview, context, type of change (new feature), usage examples, related issues, testing approach, and breaking changes statement.
Linked Issues check ✅ Passed All objectives from issue #2185 are met: utilities convert between currency names and codes, support both 3-character and hex-encoded formats, enforce size validation (>20 bytes UTF-8), and ensure 40-character padding.

✏️ 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
Contributor

@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: 5

🤖 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/xrpl/src/utils/currencyConversion.ts`:
- Around line 91-99: The code is stripping hex nibbles with
currencyCode.replace(/0+$/u, '') which corrupts valid payloads; update the
trimming to remove only padding bytes ('00') from the end of currencyCode (e.g.,
strip repeating "00" byte sequences) before calling convertHexToString, keep the
existing check that throws if the result is empty, and ensure trimmedHex has an
even length (or otherwise error) so convertHexToString receives valid
byte-aligned hex; refer to the variables/function names currencyCode, trimmedHex
and convertHexToString in currencyConversion.ts when making the change.
- Around line 29-35: The short-path for treating 1–3 character inputs as
standard ASCII codes must only be taken after normalizing and verifying ASCII
letters; in currencyNameToCode normalize (trim and toUpperCase) the input first,
check for reserved 'XRP' after normalization, then only return the uppercase
code for length <= 3 if it matches /^[A-Z]{1,3}$/ (or reuse
isStandardCurrencyCode after making it enforce ASCII A–Z), and update the
corresponding short-code checks in the other occurrences (the other branches
using the same fast-path) to use the same normalized + ASCII-gated logic.

In `@test-currency-conversion.js`:
- Around line 4-68: The test reimplements conversion logic (currencyNameToCode,
currencyCodeToName) instead of using the canonical exported helpers and misses
the 20-byte length validation; update the test to import and use the utility
from packages/xrpl/src/utils/currencyConversion.ts (or the package export)
rather than redefining convertStringToHex/convertHexToString, and ensure the
test asserts the same validation rules (including the exact 40-hex / 20-byte
check and error messages for invalid hex/padding cases) so the script exercises
the same codepaths and validations as the real helpers.
- Line 2: The test imports TypeScript source via
require('./packages/xrpl/src/utils/stringConversion') which will fail at
runtime; instead update the import to a runtime-resolvable module or move the
test into the package test harness: either change the require to the built
package path that exists at runtime (e.g.,
require('xrpl/utils/stringConversion')) so convertStringToHex and
convertHexToString resolve, or move this test file into packages/xrpl/test/ and
run it through Jest (or inline the functions like test-currency-simple.js does)
so the convertStringToHex and convertHexToString implementations are available
at test time.

In `@test-currency-simple.js`:
- Around line 1-123: This demo script reimplements currency helpers and only
logs results; replace the local implementations and ad-hoc console checks with
imports of the canonical exported functions (currencyNameToCode and
currencyCodeToName) from the repository's currency conversion module and convert
the script into proper automated tests using the repo test runner (assert exact
return values and error cases rather than printing), removing the duplicated
functions (stringToHex/hexToString/currencyNameToCode/currencyCodeToName) and
any manual console-based "All tests passed" logic so the real helpers are
exercised and failures surface in CI.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 17a3a004-f320-4cd2-86d6-d44098c89a29

📥 Commits

Reviewing files that changed from the base of the PR and between 928be9a and 1ce2ae7.

📒 Files selected for processing (4)
  • packages/xrpl/src/utils/currencyConversion.ts
  • packages/xrpl/src/utils/index.ts
  • test-currency-conversion.js
  • test-currency-simple.js

Comment on lines +29 to +35
if (currencyName === 'XRP') {
throw new Error('XRP cannot be used as a currency code')
}

// For names 3 characters or less, use as-is (standard ASCII codes like USD, EUR)
if (currencyName.length <= 3) {
return currencyName.toUpperCase()
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.

⚠️ Potential issue | 🟠 Major

Validate short codes before taking the fast path.

Right now any 1–3 code-unit string is accepted as a “standard” code. That lets currencyNameToCode('xrp') return reserved XRP, and helpers like isStandardCurrencyCode('€') report true even though the API/docs describe these as ASCII codes. Normalize first, then gate the short-code path with a shared ASCII check.

Also applies to: 79-81, 120-125

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

In `@packages/xrpl/src/utils/currencyConversion.ts` around lines 29 - 35, The
short-path for treating 1–3 character inputs as standard ASCII codes must only
be taken after normalizing and verifying ASCII letters; in currencyNameToCode
normalize (trim and toUpperCase) the input first, check for reserved 'XRP' after
normalization, then only return the uppercase code for length <= 3 if it matches
/^[A-Z]{1,3}$/ (or reuse isStandardCurrencyCode after making it enforce ASCII
A–Z), and update the corresponding short-code checks in the other occurrences
(the other branches using the same fast-path) to use the same normalized +
ASCII-gated logic.

Comment on lines +91 to +99
try {
// Remove trailing zeros and convert from hex
const trimmedHex = currencyCode.replace(/0+$/u, '')
if (trimmedHex.length === 0) {
throw new Error('Invalid currency code: empty after removing padding')
}

return convertHexToString(trimmedHex)
} catch (error) {
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.

⚠️ Potential issue | 🔴 Critical

Trim 00 padding bytes, not individual 0 nibbles.

replace(/0+$/u, '') corrupts valid payloads whose UTF-8 hex legitimately ends in 0. For example, a name ending with ASCII 0 produces a final byte of 30; this code strips the trailing 0, leaves odd-length hex, and makes the round-trip fail for a valid currency name.

🐛 Proposed fix
-      const trimmedHex = currencyCode.replace(/0+$/u, '')
+      const trimmedHex = currencyCode.replace(/(?:00)+$/u, '')
📝 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
try {
// Remove trailing zeros and convert from hex
const trimmedHex = currencyCode.replace(/0+$/u, '')
if (trimmedHex.length === 0) {
throw new Error('Invalid currency code: empty after removing padding')
}
return convertHexToString(trimmedHex)
} catch (error) {
try {
// Remove trailing zeros and convert from hex
const trimmedHex = currencyCode.replace(/(?:00)+$/u, '')
if (trimmedHex.length === 0) {
throw new Error('Invalid currency code: empty after removing padding')
}
return convertHexToString(trimmedHex)
} catch (error) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/xrpl/src/utils/currencyConversion.ts` around lines 91 - 99, The code
is stripping hex nibbles with currencyCode.replace(/0+$/u, '') which corrupts
valid payloads; update the trimming to remove only padding bytes ('00') from the
end of currencyCode (e.g., strip repeating "00" byte sequences) before calling
convertHexToString, keep the existing check that throws if the result is empty,
and ensure trimmedHex has an even length (or otherwise error) so
convertHexToString receives valid byte-aligned hex; refer to the
variables/function names currencyCode, trimmedHex and convertHexToString in
currencyConversion.ts when making the change.

Comment on lines +4 to +68
function currencyNameToCode(currencyName) {
if (typeof currencyName !== 'string') {
throw new Error('Currency name must be a string')
}

if (currencyName.length === 0) {
throw new Error('Currency name cannot be empty')
}

if (currencyName === 'XRP') {
throw new Error('XRP cannot be used as a currency code')
}

// For names 3 characters or less, use as-is (standard ASCII codes like USD, EUR)
if (currencyName.length <= 3) {
return currencyName.toUpperCase()
}

// For longer names, convert to 40-character hex string
const hexString = convertStringToHex(currencyName).toUpperCase()

// Pad to 40 characters (20 bytes) with zeros
return hexString.padEnd(40, '0')
}

function currencyCodeToName(currencyCode) {
if (typeof currencyCode !== 'string') {
throw new Error('Currency code must be a string')
}

if (currencyCode.length === 0) {
throw new Error('Currency code cannot be empty')
}

if (currencyCode === 'XRP') {
return 'XRP'
}

// If it's a short code (3 characters or less), return as-is
if (currencyCode.length <= 3) {
return currencyCode
}

// If it's a 40-character hex string, convert back to string
if (currencyCode.length === 40) {
// Check if it's valid hex
if (!/^[0-9A-Fa-f]+$/u.test(currencyCode)) {
throw new Error('Invalid currency code: not valid hexadecimal')
}

try {
// Remove trailing zeros and convert from hex
const trimmedHex = currencyCode.replace(/0+$/u, '')
if (trimmedHex.length === 0) {
throw new Error('Invalid currency code: empty after removing padding')
}

return convertHexToString(trimmedHex)
} catch (error) {
throw new Error(`Invalid currency code: ${error instanceof Error ? error.message : 'conversion failed'}`)
}
}

throw new Error('Invalid currency code: must be 3 characters or less, or exactly 40 characters hex')
}
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.

⚠️ Potential issue | 🟠 Major

This still isn’t validating the shipped utility.

The file redefines the conversion logic locally, only prints outputs, and already diverges from packages/xrpl/src/utils/currencyConversion.ts by omitting the 20-byte length check. That means regressions in the exported helpers can slip through even when this script reports success.

Also applies to: 70-92

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

In `@test-currency-conversion.js` around lines 4 - 68, The test reimplements
conversion logic (currencyNameToCode, currencyCodeToName) instead of using the
canonical exported helpers and misses the 20-byte length validation; update the
test to import and use the utility from
packages/xrpl/src/utils/currencyConversion.ts (or the package export) rather
than redefining convertStringToHex/convertHexToString, and ensure the test
asserts the same validation rules (including the exact 40-hex / 20-byte check
and error messages for invalid hex/padding cases) so the script exercises the
same codepaths and validations as the real helpers.

Comment on lines +1 to +123
// Simple standalone test for currency conversion functions
function stringToHex(str) {
return Buffer.from(str, 'utf8').toString('hex')
}

function hexToString(hex) {
return Buffer.from(hex, 'hex').toString('utf8')
}

function currencyNameToCode(currencyName) {
if (typeof currencyName !== 'string') {
throw new Error('Currency name must be a string')
}

if (currencyName.length === 0) {
throw new Error('Currency name cannot be empty')
}

if (currencyName === 'XRP') {
throw new Error('XRP cannot be used as a currency code')
}

// For names 3 characters or less, use as-is (standard ASCII codes like USD, EUR)
if (currencyName.length <= 3) {
return currencyName.toUpperCase()
}

// For longer names, convert to hex string
const hexString = stringToHex(currencyName).toUpperCase()

// Check if the hex string is too long (more than 40 characters = 20 bytes)
if (hexString.length > 40) {
throw new Error(`Currency name "${currencyName}" is too long. Maximum length is 20 bytes when UTF-8 encoded.`)
}

// Pad to exactly 40 characters (20 bytes) with zeros
return hexString.padEnd(40, '0')
}

function currencyCodeToName(currencyCode) {
if (typeof currencyCode !== 'string') {
throw new Error('Currency code must be a string')
}

if (currencyCode.length === 0) {
throw new Error('Currency code cannot be empty')
}

if (currencyCode === 'XRP') {
return 'XRP'
}

// If it's a short code (3 characters or less), return as-is
if (currencyCode.length <= 3) {
return currencyCode
}

// If it's a 40-character hex string, convert back to string
if (currencyCode.length === 40) {
// Check if it's valid hex
if (!/^[0-9A-Fa-f]+$/u.test(currencyCode)) {
throw new Error('Invalid currency code: not valid hexadecimal')
}

try {
// Remove trailing zeros and convert from hex
const trimmedHex = currencyCode.replace(/0+$/u, '')
if (trimmedHex.length === 0) {
throw new Error('Invalid currency code: empty after removing padding')
}

return hexToString(trimmedHex)
} catch (error) {
throw new Error(`Invalid currency code: ${error instanceof Error ? error.message : 'conversion failed'}`)
}
}

throw new Error('Invalid currency code: must be 3 characters or less, or exactly 40 characters hex')
}

// Test cases
console.log('Testing currency conversion functions...\n');

try {
// Test standard 3-char codes
console.log('USD ->', currencyNameToCode('USD'));
console.log('EUR ->', currencyNameToCode('EUR'));
console.log('BTC ->', currencyNameToCode('BTC'));

// Test longer names
console.log('MyCustomToken ->', currencyNameToCode('MyCustomToken'));
console.log('GOLD ->', currencyNameToCode('GOLD'));
console.log('MediumLengthToken ->', currencyNameToCode('MediumLengthToken'));

// Test reverse conversion
const hexCode1 = currencyNameToCode('MyCustomToken');
console.log('\nReverse conversions:');
console.log(hexCode1, '->', currencyCodeToName(hexCode1));

const hexCode2 = currencyNameToCode('MediumLengthToken');
console.log(hexCode2, '->', currencyCodeToName(hexCode2));

// Test standard codes reverse
console.log('USD reverse:', currencyCodeToName('USD'));
console.log('EUR reverse:', currencyCodeToName('EUR'));

// Test edge cases
console.log('\nEdge cases:');
console.log('XRP reverse:', currencyCodeToName('XRP'));

// Test error case
console.log('\nTesting error case:');
try {
currencyNameToCode('SomeVeryLongTokenNameThatExceedsTwentyBytes');
} catch (error) {
console.log('Expected error for long name:', error.message);
}

console.log('\n✅ All tests passed!');

} catch (error) {
console.error('❌ Test failed:', error.message);
} No newline at end of file
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.

⚠️ Potential issue | 🟠 Major

This is a demo script, not an automated test.

The file reimplements the conversion helpers locally and only logs outputs, so regressions in packages/xrpl/src/utils/currencyConversion.ts can still finish with “All tests passed”. Please import the exported helpers and assert exact results in the repo test runner instead.

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

In `@test-currency-simple.js` around lines 1 - 123, This demo script reimplements
currency helpers and only logs results; replace the local implementations and
ad-hoc console checks with imports of the canonical exported functions
(currencyNameToCode and currencyCodeToName) from the repository's currency
conversion module and convert the script into proper automated tests using the
repo test runner (assert exact return values and error cases rather than
printing), removing the duplicated functions
(stringToHex/hexToString/currencyNameToCode/currencyCodeToName) and any manual
console-based "All tests passed" logic so the real helpers are exercised and
failures surface in CI.

@slurpyone slurpyone force-pushed the issue-2185-currency-conversion branch from 1ce2ae7 to 34623fa Compare March 14, 2026 12:41
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
test-currency-simple.js (1)

2-123: ⚠️ Potential issue | 🟠 Major

Use canonical exports with real assertions instead of self-testing duplicated logic.

Line 2 through Line 123 currently re-implements the conversion helpers locally and validates behavior via console.log, which means regressions in packages/xrpl/src/utils/currencyConversion.ts can still slip through CI. Please convert this into an actual repo test that imports the exported utilities and asserts exact outputs/errors.

Suggested direction
- function stringToHex(str) { ... }
- function hexToString(hex) { ... }
- function currencyNameToCode(currencyName) { ... }
- function currencyCodeToName(currencyCode) { ... }
- // console.log-based test harness
+ import { strict as assert } from 'assert'
+ import { currencyNameToCode, currencyCodeToName } from '<canonical utils export path>'
+
+ assert.equal(currencyNameToCode('USD'), 'USD')
+ assert.equal(currencyCodeToName('USD'), 'USD')
+ assert.throws(
+   () => currencyNameToCode('SomeVeryLongTokenNameThatExceedsTwentyBytes'),
+   /too long/i
+ )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test-currency-simple.js` around lines 2 - 123, Replace the self-contained
helpers and console-based checks with a real unit test that imports the
canonical exports currencyNameToCode and currencyCodeToName from
packages/xrpl/src/utils/currencyConversion.ts and uses your test framework
assertions (e.g., assert.strictEqual / expect) to assert exact outputs and
thrown errors; specifically test: 3-char codes (USD, EUR, BTC) return same
uppercase code, long names produce 40-char padded hex (verify hex format and
round-trip with currencyCodeToName), 'XRP' behavior, and that overly long UTF-8
names throw the expected error; remove the local stringToHex/hexToString
implementations and all console.log usage so the test exercises the real
exported functions and their error messages exactly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@test-currency-simple.js`:
- Around line 2-123: Replace the self-contained helpers and console-based checks
with a real unit test that imports the canonical exports currencyNameToCode and
currencyCodeToName from packages/xrpl/src/utils/currencyConversion.ts and uses
your test framework assertions (e.g., assert.strictEqual / expect) to assert
exact outputs and thrown errors; specifically test: 3-char codes (USD, EUR, BTC)
return same uppercase code, long names produce 40-char padded hex (verify hex
format and round-trip with currencyCodeToName), 'XRP' behavior, and that overly
long UTF-8 names throw the expected error; remove the local
stringToHex/hexToString implementations and all console.log usage so the test
exercises the real exported functions and their error messages exactly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d9f55989-272a-4986-940a-5ca7fdb6b44e

📥 Commits

Reviewing files that changed from the base of the PR and between 1ce2ae7 and 34623fa.

📒 Files selected for processing (4)
  • packages/xrpl/src/utils/currencyConversion.ts
  • packages/xrpl/src/utils/index.ts
  • test-currency-conversion.js
  • test-currency-simple.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/xrpl/src/utils/currencyConversion.ts
  • packages/xrpl/src/utils/index.ts
  • test-currency-conversion.js

@slurpyone slurpyone force-pushed the issue-2185-currency-conversion branch from 34623fa to 2f5d10b Compare March 17, 2026 00:41
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
test-currency-simple.js (1)

1-123: ⚠️ Potential issue | 🟠 Major

Use canonical exports + real assertions instead of reimplementing and logging.

Line 1-Line 79 duplicates conversion logic, and Line 81-Line 123 only logs output. This can report “✅ All tests passed!” even if packages/xrpl/src/utils/currencyConversion.ts regresses. Please convert this into repo-runner assertions that import the exported helpers directly (currencyNameToCode, currencyCodeToName, and related validators).

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

In `@test-currency-simple.js` around lines 1 - 123, Replace the local duplicate
implementations of stringToHex, hexToString, currencyNameToCode and
currencyCodeToName with imports of the canonical exports (currencyNameToCode,
currencyCodeToName and any validators) from the package module, and convert
console-logging tests into repo-runner style assertions (use the repo's
assertion helpers or plain assert) to validate expected outputs and error cases
(e.g., assert(currencyNameToCode('USD') === 'USD'), assert.throws(() =>
currencyNameToCode(longName), /too long/), and
assert(currencyCodeToName(hexCode) === 'MyCustomToken')); ensure tests reference
the exported symbols (currencyNameToCode, currencyCodeToName) only and remove
the duplicated local functions and loose console output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@test-currency-simple.js`:
- Around line 1-123: Replace the local duplicate implementations of stringToHex,
hexToString, currencyNameToCode and currencyCodeToName with imports of the
canonical exports (currencyNameToCode, currencyCodeToName and any validators)
from the package module, and convert console-logging tests into repo-runner
style assertions (use the repo's assertion helpers or plain assert) to validate
expected outputs and error cases (e.g., assert(currencyNameToCode('USD') ===
'USD'), assert.throws(() => currencyNameToCode(longName), /too long/), and
assert(currencyCodeToName(hexCode) === 'MyCustomToken')); ensure tests reference
the exported symbols (currencyNameToCode, currencyCodeToName) only and remove
the duplicated local functions and loose console output.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 99e32753-0652-43a7-80b4-30c37cca6b3e

📥 Commits

Reviewing files that changed from the base of the PR and between 34623fa and 2f5d10b.

📒 Files selected for processing (4)
  • packages/xrpl/src/utils/currencyConversion.ts
  • packages/xrpl/src/utils/index.ts
  • test-currency-conversion.js
  • test-currency-simple.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/xrpl/src/utils/index.ts
  • packages/xrpl/src/utils/currencyConversion.ts
  • test-currency-conversion.js

@slurpyone slurpyone force-pushed the issue-2185-currency-conversion branch from 2f5d10b to b4e4e3f Compare March 25, 2026 00:41
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (2)
test-currency-conversion.js (2)

4-68: ⚠️ Potential issue | 🟠 Major

Test logic is duplicated and already diverges from production behavior.

This script re-implements conversion instead of calling packages/xrpl/src/utils/currencyConversion.ts, and it misses the 20-byte UTF-8 max-length validation. It can mask regressions in the real exported helpers.

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

In `@test-currency-conversion.js` around lines 4 - 68, This file re-implements
currency conversion logic (currencyNameToCode and currencyCodeToName) and
diverges from the production helpers; replace the local implementations by
importing and calling the canonical helpers from
packages/xrpl/src/utils/currencyConversion.ts instead of re-implementing
convertStringToHex/convertHexToString here, and ensure the production validation
for UTF-8 max 20-byte names (reject names whose UTF-8 encoding > 20 bytes) is
preserved; remove duplicated conversion code and any differing error messages so
tests exercise the real exported helpers directly.

2-2: ⚠️ Potential issue | 🟠 Major

Runtime module resolution is likely broken at Line 2.

require('./packages/xrpl/src/utils/stringConversion') points to TS source from a plain JS script; this typically fails under raw Node before tests execute.

#!/bin/bash
# Verify whether this script is executed via raw Node or a TS-aware test harness,
# and whether a runtime-resolvable JS target exists.

set -euo pipefail

rg -n "test-currency-conversion\\.js|node test-currency-conversion\\.js" package.json packages/xrpl/package.json || true
rg -n "require\\('./packages/xrpl/src/utils/stringConversion'\\)" test-currency-conversion.js
fd '^stringConversion\.(ts|js)$' packages/xrpl/src/utils packages/xrpl/dist/npm/utils 2>/dev/null || true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test-currency-conversion.js` at line 2, The test imports TS source directly
(require('./packages/xrpl/src/utils/stringConversion')) which will fail under
raw Node; update test-currency-conversion.js to load the runtime JS build
instead (use the built module under
packages/xrpl/dist/npm/utils/stringConversion) or adjust the test runner to use
a TS-aware loader (e.g., ts-node/register) so convertStringToHex and
convertHexToString resolve at runtime; locate the require of stringConversion in
test-currency-conversion.js and replace it with a runtime-resolvable module path
or enable TS transpilation in the test harness.
🧹 Nitpick comments (1)
test-currency-conversion.js (1)

70-92: Use assertions instead of console logs for deterministic test outcomes.

Current checks are output-based and can pass without validating exact behavior. Please switch to assertion-based tests (or move this into the project test harness).

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

In `@test-currency-conversion.js` around lines 70 - 92, Replace the
console.log-based checks in the test block with deterministic assertions: import
or require Node's assert and use assert.strictEqual/assert.ok to verify
currencyNameToCode and currencyCodeToName return the exact expected values
(e.g., assert.strictEqual(currencyNameToCode('USD'), 'USD') and
assert.strictEqual(currencyCodeToName(currencyNameToCode('MyCustomToken')),
'MyCustomToken')); remove noisy console output, keep the try/catch only to
rethrow or fail the test harness, and ensure tests call currencyNameToCode and
currencyCodeToName (the functions referenced) with explicit expected values so
failures surface as assertion errors instead of passing via logs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@test-currency-conversion.js`:
- Around line 4-68: This file re-implements currency conversion logic
(currencyNameToCode and currencyCodeToName) and diverges from the production
helpers; replace the local implementations by importing and calling the
canonical helpers from packages/xrpl/src/utils/currencyConversion.ts instead of
re-implementing convertStringToHex/convertHexToString here, and ensure the
production validation for UTF-8 max 20-byte names (reject names whose UTF-8
encoding > 20 bytes) is preserved; remove duplicated conversion code and any
differing error messages so tests exercise the real exported helpers directly.
- Line 2: The test imports TS source directly
(require('./packages/xrpl/src/utils/stringConversion')) which will fail under
raw Node; update test-currency-conversion.js to load the runtime JS build
instead (use the built module under
packages/xrpl/dist/npm/utils/stringConversion) or adjust the test runner to use
a TS-aware loader (e.g., ts-node/register) so convertStringToHex and
convertHexToString resolve at runtime; locate the require of stringConversion in
test-currency-conversion.js and replace it with a runtime-resolvable module path
or enable TS transpilation in the test harness.

---

Nitpick comments:
In `@test-currency-conversion.js`:
- Around line 70-92: Replace the console.log-based checks in the test block with
deterministic assertions: import or require Node's assert and use
assert.strictEqual/assert.ok to verify currencyNameToCode and currencyCodeToName
return the exact expected values (e.g.,
assert.strictEqual(currencyNameToCode('USD'), 'USD') and
assert.strictEqual(currencyCodeToName(currencyNameToCode('MyCustomToken')),
'MyCustomToken')); remove noisy console output, keep the try/catch only to
rethrow or fail the test harness, and ensure tests call currencyNameToCode and
currencyCodeToName (the functions referenced) with explicit expected values so
failures surface as assertion errors instead of passing via logs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 56da08e9-568d-4d74-bba7-7bdeac3a9481

📥 Commits

Reviewing files that changed from the base of the PR and between 2f5d10b and b4e4e3f.

📒 Files selected for processing (4)
  • packages/xrpl/src/utils/currencyConversion.ts
  • packages/xrpl/src/utils/index.ts
  • test-currency-conversion.js
  • test-currency-simple.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • test-currency-simple.js
  • packages/xrpl/src/utils/currencyConversion.ts

@slurpyone slurpyone force-pushed the issue-2185-currency-conversion branch from b4e4e3f to cc12a99 Compare March 26, 2026 00:41
Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
test-currency-conversion.js (1)

70-92: Tests lack assertions—script always reports "passed" regardless of correctness.

The test section only logs outputs without verifying them. If conversions produce incorrect results, the script still prints "All tests passed!" because no actual assertions fail.

♻️ Proposed fix with assertions
 // Test cases
 console.log('Testing currency conversion functions...\n');

 try {
   // Test standard 3-char codes
-  console.log('USD ->', currencyNameToCode('USD'));
-  console.log('EUR ->', currencyNameToCode('EUR'));
+  const usdCode = currencyNameToCode('USD');
+  if (usdCode !== 'USD') throw new Error(`Expected 'USD', got '${usdCode}'`);
+  console.log('USD ->', usdCode);
+
+  const eurCode = currencyNameToCode('EUR');
+  if (eurCode !== 'EUR') throw new Error(`Expected 'EUR', got '${eurCode}'`);
+  console.log('EUR ->', eurCode);
   
   // Test longer names  
-  console.log('MyCustomToken ->', currencyNameToCode('MyCustomToken'));
+  const customCode = currencyNameToCode('MyCustomToken');
+  if (customCode.length !== 40) throw new Error(`Expected 40-char hex, got length ${customCode.length}`);
+  console.log('MyCustomToken ->', customCode);
   
   // Test reverse conversion
-  const hexCode = currencyNameToCode('MyCustomToken');
-  console.log('Reverse conversion:', hexCode, '->', currencyCodeToName(hexCode));
+  const reversed = currencyCodeToName(customCode);
+  if (reversed !== 'MyCustomToken') throw new Error(`Round-trip failed: expected 'MyCustomToken', got '${reversed}'`);
+  console.log('Reverse conversion:', customCode, '->', reversed);
   
   // Test standard codes reverse
-  console.log('USD reverse:', currencyCodeToName('USD'));
+  const usdReverse = currencyCodeToName('USD');
+  if (usdReverse !== 'USD') throw new Error(`Expected 'USD', got '${usdReverse}'`);
+  console.log('USD reverse:', usdReverse);
   
   console.log('\nAll tests passed!');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test-currency-conversion.js` around lines 70 - 92, Add real assertions to the
test block so failures stop the script instead of always printing "All tests
passed!". Replace the current console-only checks by verifying expected values
from currencyNameToCode and currencyCodeToName: assert that
currencyNameToCode('USD') === expectedCodeForUSD and currencyNameToCode('EUR')
=== expectedCodeForEUR, assert that currencyNameToCode('MyCustomToken') returns
the expected hex and that
currencyCodeToName(currencyNameToCode('MyCustomToken')) equals 'MyCustomToken',
and assert that currencyCodeToName('USD') yields the expected name; throw an
Error or exit nonzero when any assertion fails so the catch block reports real
failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test-currency-conversion.js`:
- Around line 70-92: Add real assertions to the test block so failures stop the
script instead of always printing "All tests passed!". Replace the current
console-only checks by verifying expected values from currencyNameToCode and
currencyCodeToName: assert that currencyNameToCode('USD') === expectedCodeForUSD
and currencyNameToCode('EUR') === expectedCodeForEUR, assert that
currencyNameToCode('MyCustomToken') returns the expected hex and that
currencyCodeToName(currencyNameToCode('MyCustomToken')) equals 'MyCustomToken',
and assert that currencyCodeToName('USD') yields the expected name; throw an
Error or exit nonzero when any assertion fails so the catch block reports real
failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7613b3ef-489c-4a9e-befa-4857c0b521c3

📥 Commits

Reviewing files that changed from the base of the PR and between b4e4e3f and cc12a99.

📒 Files selected for processing (4)
  • packages/xrpl/src/utils/currencyConversion.ts
  • packages/xrpl/src/utils/index.ts
  • test-currency-conversion.js
  • test-currency-simple.js
✅ Files skipped from review due to trivial changes (1)
  • packages/xrpl/src/utils/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test-currency-simple.js

@slurpyone slurpyone force-pushed the issue-2185-currency-conversion branch from cc12a99 to 3af772b Compare March 27, 2026 00:41
- Add currencyNameToCode() to convert human-readable names to XRPL currency codes
- Add currencyCodeToName() to convert XRPL currency codes back to readable names
- Add isStandardCurrencyCode() and isHexCurrencyCode() helper functions
- Support both 3-character ASCII codes (USD, EUR) and hex-encoded longer names
- Include proper validation and error handling for oversized names
- Addresses issue XRPLF#2185
@slurpyone slurpyone force-pushed the issue-2185-currency-conversion branch from 3af772b to 8fcaba7 Compare March 27, 2026 12:41
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.

Methods to convert currency name to currency code

1 participant