Skip to content

feat: add local transfer fee configuration to support dynamic fee calculation#382

Merged
onahprosper merged 2 commits intomainfrom
cherry-pick-local-transfer-fee
Feb 24, 2026
Merged

feat: add local transfer fee configuration to support dynamic fee calculation#382
onahprosper merged 2 commits intomainfrom
cherry-pick-local-transfer-fee

Conversation

@Dprof-in-tech
Copy link
Copy Markdown
Collaborator

@Dprof-in-tech Dprof-in-tech commented Feb 24, 2026

Description

This pull request introduces configurable environment variables for local transfer fees and updates the fee calculation logic to use these new settings. The main goal is to make the local transfer fee percentage and fee cap easily adjustable through environment variables, rather than hardcoding them in the codebase.

Configuration enhancements:

  • Added NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT and NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP to .env.example to allow configuration of the local transfer fee percentage and cap via environment variables.
  • Updated app/lib/config.ts to read and export localTransferFeePercent and localTransferFeeCap from environment variables, providing default values if not set.

Fee calculation logic updates:

  • Modified app/utils.ts to import the new fee configuration values and use them in the calculateSenderFee function, replacing the previously hardcoded values for local transfer fee percent and cap. [1] [2]

References

Testing

Describe how this can be tested by reviewers. Be specific about anything not tested and reasons why. If this project has unit and/or integration testing, tests should be added for new functionality and existing tests should complete without errors.

Please include any manual steps for testing end-to-end or functionality not covered by unit/integration tests.

Also include details of the environment this PR was developed in (language/platform/browser version)

  • This change adds test coverage for new/changed/fixed functionality

Checklist

  • I have added documentation and tests for new/changed functionality in this PR
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not main

By submitting a PR, I agree to Paycrest's Contributor Code of Conduct and Contribution Guide.

Summary by CodeRabbit

  • Chores
    • Local transfer fees are now configurable via environment variables (NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT and NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP). Defaults remain 0.1% and 10000 respectively, preserving existing behavior while allowing customization of both the fee percentage and the maximum cap.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 24, 2026

📝 Walkthrough

Walkthrough

Adds two new environment variables and corresponding config exports to make the local transfer fee percent and cap configurable, and updates fee calculation to read those values instead of using hard-coded numbers.

Changes

Cohort / File(s) Summary
Environment Configuration
\.env.example
Added NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT and NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP declarations with default values.
Config Exports
app/lib/config.ts
Added localTransferFeePercent and localTransferFeeCap exports parsed from env with fallback defaults.
Fee Calculation Logic
app/utils.ts
Replaced hard-coded local fee percent and cap with imports from app/lib/config.ts; fee computation now uses these configurable values.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • chibie
  • 5ran6
  • onahprosper

Poem

🐰 I nibbled code by moonlit tap,
New vars now steer the fee and cap.
No more constants stuck in glue,
Flexible hops for me and you. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the main changes and objectives but is incomplete: it is missing specific details in the Testing section (no actual testing approach described, template placeholders remain), and the checklist items are unchecked indicating missing documentation and tests. Complete the Testing section with specific testing steps and environment details. Address the unchecked checklist items by either adding tests/documentation or explaining why they are not applicable.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly describes the main change: adding local transfer fee configuration to support dynamic fee calculation, which aligns with the changeset of introducing environment variables and updating fee calculation logic.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cherry-pick-local-transfer-fee

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

🧹 Nitpick comments (2)
.env.example (1)

15-16: Optional: alphabetise the new keys to satisfy dotenv-linter.

NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP sorts before NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT; swapping them resolves the [UnorderedKey] lint warning.

🔧 Proposed fix
-NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT=0.1
-NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP=10000
+NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP=10000
+NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT=0.1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.example around lines 15 - 16, The dotenv keys in .env.example are out
of alphabetical order causing dotenv-linter's [UnorderedKey] warning; reorder
the two keys so NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP appears before
NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT (swap the positions of
NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP and NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT)
to satisfy the linter while keeping their values unchanged.
app/utils.ts (1)

14-19: Combine both ./lib/config imports into a single statement.

Lines 14 and 15–19 both import from the same module.

♻️ Proposed refactor
-import config from "./lib/config";
-import {
-  feeRecipientAddress,
-  localTransferFeePercent,
-  localTransferFeeCap,
-} from "./lib/config";
+import config, {
+  feeRecipientAddress,
+  localTransferFeePercent,
+  localTransferFeeCap,
+} from "./lib/config";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/utils.ts` around lines 14 - 19, Duplicate imports from "./lib/config"
should be combined: replace the two import statements with a single line that
imports the default export config and the named exports feeRecipientAddress,
localTransferFeePercent, and localTransferFeeCap together (e.g. import config, {
feeRecipientAddress, localTransferFeePercent, localTransferFeeCap } from
"./lib/config";), removing the separate import blocks so only one import for
that module remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/lib/config.ts`:
- Around line 40-47: The exports localTransferFeePercent and localTransferFeeCap
currently export parseFloat results without validation, allowing NaN or
non-integer values to propagate; update the logic to parse the env strings,
validate Number.isFinite(parsed) for percent (fallback to 0.1 on invalid) and
validate Number.isFinite(parsed) && Number.isInteger(parsed) for cap (fallback
to 10000 on invalid or non-integer), and ensure these validated fallback
assignments replace the current ternary expressions in the config so downstream
code (e.g., calculateSenderFee) never receives NaN or fractional BigInt inputs.

In `@app/utils.ts`:
- Around line 1243-1244: The calculation of maxFeeCapInBaseUnits uses
BigInt(localTransferFeeCap) which throws for non-integer values; change the
conversion to first coerce to an integer (e.g., Math.floor) before converting to
BigInt so decimals are truncated safely. Locate the expression assigning
maxFeeCapInBaseUnits that references localTransferFeeCap and decimalsMultiplier
and replace BigInt(localTransferFeeCap) with
BigInt(Math.floor(Number(localTransferFeeCap))) (or equivalent safe integer
coercion) to avoid RangeError while keeping the multiplier usage unchanged.

---

Nitpick comments:
In @.env.example:
- Around line 15-16: The dotenv keys in .env.example are out of alphabetical
order causing dotenv-linter's [UnorderedKey] warning; reorder the two keys so
NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP appears before
NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT (swap the positions of
NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP and NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT)
to satisfy the linter while keeping their values unchanged.

In `@app/utils.ts`:
- Around line 14-19: Duplicate imports from "./lib/config" should be combined:
replace the two import statements with a single line that imports the default
export config and the named exports feeRecipientAddress,
localTransferFeePercent, and localTransferFeeCap together (e.g. import config, {
feeRecipientAddress, localTransferFeePercent, localTransferFeeCap } from
"./lib/config";), removing the separate import blocks so only one import for
that module remains.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a452fae and 983ee20.

📒 Files selected for processing (3)
  • .env.example
  • app/lib/config.ts
  • app/utils.ts

Comment thread app/lib/config.ts Outdated
Comment thread app/utils.ts Outdated
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)
app/lib/config.ts (1)

38-48: Harden fee config against negative values.

Right now negative percent/cap values pass validation; a misconfigured env could invert fees or create negative caps. Recommend enforcing non-negative values before exporting.

♻️ Suggested guardrails
-const parsedFeePercent = parseFloat(process.env.NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT ?? "");
-export const localTransferFeePercent: number = Number.isFinite(parsedFeePercent)
-  ? parsedFeePercent
-  : 0.1;
+const parsedFeePercent = parseFloat(
+  process.env.NEXT_PUBLIC_LOCAL_TRANSFER_FEE_PERCENT ?? "",
+);
+export const localTransferFeePercent: number =
+  Number.isFinite(parsedFeePercent) && parsedFeePercent >= 0
+    ? parsedFeePercent
+    : 0.1;

-const parsedFeeCap = parseFloat(process.env.NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP ?? "");
+const parsedFeeCap = parseFloat(
+  process.env.NEXT_PUBLIC_LOCAL_TRANSFER_FEE_CAP ?? "",
+);
 export const localTransferFeeCap: number =
-  Number.isFinite(parsedFeeCap) && Number.isInteger(parsedFeeCap)
+  Number.isFinite(parsedFeeCap) &&
+  Number.isInteger(parsedFeeCap) &&
+  parsedFeeCap >= 0
     ? parsedFeeCap
     : 10000;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/lib/config.ts` around lines 38 - 48, The current parsing for
parsedFeePercent/localTransferFeePercent and parsedFeeCap/localTransferFeeCap
allows negative values; update the validation to enforce non-negative numbers:
when computing parsedFeePercent and parsedFeeCap ensure you clamp negatives to 0
(e.g., validate Number.isFinite(parsedFeePercent) && parsedFeePercent >= 0
before using it, and for parsedFeeCap require Number.isFinite(parsedFeeCap),
Number.isInteger(parsedFeeCap) and parsedFeeCap >= 0), falling back to the
existing defaults (0.1 for percent, 10000 for cap) if validation fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/lib/config.ts`:
- Around line 38-48: The current parsing for
parsedFeePercent/localTransferFeePercent and parsedFeeCap/localTransferFeeCap
allows negative values; update the validation to enforce non-negative numbers:
when computing parsedFeePercent and parsedFeeCap ensure you clamp negatives to 0
(e.g., validate Number.isFinite(parsedFeePercent) && parsedFeePercent >= 0
before using it, and for parsedFeeCap require Number.isFinite(parsedFeeCap),
Number.isInteger(parsedFeeCap) and parsedFeeCap >= 0), falling back to the
existing defaults (0.1 for percent, 10000 for cap) if validation fails.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 983ee20 and 819ca9a.

📒 Files selected for processing (2)
  • app/lib/config.ts
  • app/utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/utils.ts

@onahprosper onahprosper merged commit 681b369 into main Feb 24, 2026
1 check passed
@onahprosper onahprosper deleted the cherry-pick-local-transfer-fee branch February 24, 2026 11:12
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.

3 participants