Skip to content

fix: sensitive architectural details #477#560

Merged
Junman140 merged 3 commits into
Pi-Defi-world:devfrom
wolfyres:fix/477-remove-security-docs
Jun 27, 2026
Merged

fix: sensitive architectural details #477#560
Junman140 merged 3 commits into
Pi-Defi-world:devfrom
wolfyres:fix/477-remove-security-docs

Conversation

@wolfyres

@wolfyres wolfyres commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Closes #477


Resolved the TypeScript any errors, cleaned up ESLint warnings, and fixed the broken Sentry import.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed deposit limit validation by converting local-currency basket deposits to USD before checking daily/monthly limits, reducing incorrect rejections.
    • Improved validation for unsupported currencies and incomplete/invalid exchange rate data during deposit processing.
  • Documentation
    • Refreshed treasury documentation for readability without changing content.
    • Updated currency-fix implementation and quick-reference guides with clearer steps, examples, and verification guidance.
    • Removed an outdated repository issues document.
  • Database / Performance
    • Added/guarded indexes to optimize treasury query performance.
  • Chores / Tests
    • Updated repository ignore rules for additional generated artifacts.
    • Refreshed related test files without changing test logic.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 019cd870-88fa-4c63-b2fd-50306bfe75a5

📥 Commits

Reviewing files that changed from the base of the PR and between b02b5bc and 84600ff.

📒 Files selected for processing (1)
  • src/services/rates/index.ts
✅ Files skipped from review due to trivial changes (1)
  • src/services/rates/index.ts

📝 Walkthrough

Walkthrough

The PR rewrites currency-fix documentation, re-emits rates-related source and test files without behavior changes, reformats treasury docs and a migration, updates .gitignore, and removes ISSUES.md.

Changes

Currency fix docs and source refresh

Layer / File(s) Summary
Currency fix docs
CURRENCY_FIX_IMPLEMENTATION.md, CURRENCY_FIX_QUICK_REFERENCE.md
The two currency-fix markdown guides now describe the local-to-USD conversion flow, supported currencies, error cases, verification, and test coverage.
Rates files and mint tests
src/services/rates/currencyConverter.ts, src/services/rates/index.ts, src/controllers/mintController.test.ts
The rates converter, export index, and mint controller tests are re-emitted with the same conversion helpers, exports, mocks, and assertions.

Treasury docs and repository cleanup

Layer / File(s) Summary
Treasury docs and migration
docs/treasury.md, prisma/migrations/20260426000000_optimize_treasury_queries/migration.sql
The treasury documentation and optimize_treasury_queries migration are reformatted while preserving the documented flow and SQL index definitions.
Controller tests and ignore rules
src/controllers/enterpriseController.test.ts, .gitignore
The enterprise controller tests keep the same cases, and .gitignore adds heap-snapshot and markdown ignore entries.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~4 minutes

Possibly related PRs

Poem

🐰 I nibbled docs and hopped along,
The USD trail now sings in song.
I tucked old issues out of sight,
And kept the treasury lantern bright.
Hop hop—this patch feels nice tonight.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is missing the required Summary, Scope, Validation, and Links sections from the repository template. Add the template sections for Summary, Scope, Validation, and Links, and briefly describe the change, why it is needed, and what was tested.
Out of Scope Changes check ⚠️ Warning The PR includes substantial unrelated currency-fix, migration, test, and docs rewrites beyond removing the sensitive files for #477. Remove or split out the unrelated currency, migration, test, and documentation changes into separate PRs.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change by referencing the sensitive architectural details cleanup and issue #477.
Linked Issues check ✅ Passed The PR removes the sensitive docs required by #477, satisfying the linked issue's core requirement.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


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.

@drips-wave

drips-wave Bot commented Jun 26, 2026

Copy link
Copy Markdown

@wolfyres 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 coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@prisma/migrations/20260426000000_optimize_treasury_queries/migration.sql`:
- Around line 27-42: Update the migration comment to match the actual OracleRate
indexes defined in schema.prisma: remove the incorrect reference to
oracle_rates.idx_oracle_rates_currency and note that only
idx_oracle_rates_timestamp exists before this change. Keep the analysis accurate
by stating that idx_oracle_rates_currency_timestamp_desc is the new composite
index on OracleRate for currency and timestamp-based lookups.

In `@src/services/rates/currencyConverter.ts`:
- Around line 68-125: The convertLocalToUsd function currently allows negative
localAmount values, which can produce invalid negative USD results and affect
downstream limit checks. Add a non-negative validation at the start of
convertLocalToUsd, alongside the existing currency support checks, and throw an
AppError for any amount below zero before any rate lookups or Decimal conversion
occur.
- Around line 80-82: The `getLatestAcbuRate` call in `currencyConverter` is
swallowing the original failure by converting every error into null, which
removes useful context from logs and monitoring. Update the rate-fetching flow
in the conversion functions to catch the error explicitly, preserve the thrown
error details, and log or rethrow them with enough context to distinguish
timeout, connection, and missing-data cases. Use the existing
`getLatestAcbuRate` and the surrounding conversion helper(s) as the integration
points, and avoid the blanket `.catch(() => null)` 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 11fe7e88-fda7-4c1c-9fc4-f94c3719d51f

📥 Commits

Reviewing files that changed from the base of the PR and between fe6b8ab and b02b5bc.

📒 Files selected for processing (10)
  • .gitignore
  • CURRENCY_FIX_IMPLEMENTATION.md
  • CURRENCY_FIX_QUICK_REFERENCE.md
  • ISSUES.md
  • docs/treasury.md
  • prisma/migrations/20260426000000_optimize_treasury_queries/migration.sql
  • src/controllers/enterpriseController.test.ts
  • src/controllers/mintController.test.ts
  • src/services/rates/currencyConverter.ts
  • src/services/rates/index.ts
💤 Files with no reviewable changes (1)
  • ISSUES.md

Comment on lines +27 to +42
-- ANALYSIS:
-- Current indexes already support primary query patterns:
-- 1. reserves.idx_reserves_currency_segment_timestamp(sort: Desc) - optimal for DISTINCT + ORDER BY
-- 2. oracle_rates.idx_oracle_rates_currency + idx_oracle_rates_timestamp
-- 3. transactions.idx_transactions_user_type already covers core lookups

-- New indexes improve:
-- 1. idx_oracle_rates_currency_timestamp_desc - FX fallback queries (7-day lookback)
-- 2. idx_transactions_type_currency - transaction aggregation by currency
-- 3. idx_reserves_segment_timestamp - reserve health by segment

-- Query Performance Targets (after indexes):
-- - getLatestReservesBySegment(): ~50ms for 10 currencies
-- - getFxRateWithFallback(): ~10ms per currency
-- - aggregateTransactionsBySegment(): ~100ms for 1M transactions
-- - Full getEnterpriseTreasury(): ~500ms for 10 currencies, 1M transactions

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct inaccurate index reference in comment.

Line 30 claims oracle_rates.idx_oracle_rates_currency exists, but schema.prisma only defines idx_oracle_rates_timestamp on OracleRate. There is no single-column currency index. The new idx_oracle_rates_currency_timestamp_desc is the first composite index on (currency, timestamp).

 -- 1. reserves.idx_reserves_currency_segment_timestamp(sort: Desc) - optimal for DISTINCT + ORDER BY
--- 2. oracle_rates.idx_oracle_rates_currency + idx_oracle_rates_timestamp
+-- 2. oracle_rates.idx_oracle_rates_timestamp (existing single-column)
 -- 3. transactions.idx_transactions_user_type already covers core lookups
📝 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
-- ANALYSIS:
-- Current indexes already support primary query patterns:
-- 1. reserves.idx_reserves_currency_segment_timestamp(sort: Desc) - optimal for DISTINCT + ORDER BY
-- 2. oracle_rates.idx_oracle_rates_currency + idx_oracle_rates_timestamp
-- 3. transactions.idx_transactions_user_type already covers core lookups
-- New indexes improve:
-- 1. idx_oracle_rates_currency_timestamp_desc - FX fallback queries (7-day lookback)
-- 2. idx_transactions_type_currency - transaction aggregation by currency
-- 3. idx_reserves_segment_timestamp - reserve health by segment
-- Query Performance Targets (after indexes):
-- - getLatestReservesBySegment(): ~50ms for 10 currencies
-- - getFxRateWithFallback(): ~10ms per currency
-- - aggregateTransactionsBySegment(): ~100ms for 1M transactions
-- - Full getEnterpriseTreasury(): ~500ms for 10 currencies, 1M transactions
-- ANALYSIS:
-- Current indexes already support primary query patterns:
-- 1. reserves.idx_reserves_currency_segment_timestamp(sort: Desc) - optimal for DISTINCT + ORDER BY
-- 2. oracle_rates.idx_oracle_rates_timestamp (existing single-column)
-- 3. transactions.idx_transactions_user_type already covers core lookups
-- New indexes improve:
-- 1. idx_oracle_rates_currency_timestamp_desc - FX fallback queries (7-day lookback)
-- 2. idx_transactions_type_currency - transaction aggregation by currency
-- 3. idx_reserves_segment_timestamp - reserve health by segment
-- Query Performance Targets (after indexes):
-- - getLatestReservesBySegment(): ~50ms for 10 currencies
-- - getFxRateWithFallback(): ~10ms per currency
-- - aggregateTransactionsBySegment(): ~100ms for 1M transactions
-- - Full getEnterpriseTreasury(): ~500ms for 10 currencies, 1M transactions
🤖 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 `@prisma/migrations/20260426000000_optimize_treasury_queries/migration.sql`
around lines 27 - 42, Update the migration comment to match the actual
OracleRate indexes defined in schema.prisma: remove the incorrect reference to
oracle_rates.idx_oracle_rates_currency and note that only
idx_oracle_rates_timestamp exists before this change. Keep the analysis accurate
by stating that idx_oracle_rates_currency_timestamp_desc is the new composite
index on OracleRate for currency and timestamp-based lookups.

Comment on lines +68 to +125
export async function convertLocalToUsd(
localAmount: number,
currency: string,
): Promise<number> {
// Validate currency is supported
if (!CURRENCY_TO_RATE_FIELD[currency]) {
throw new AppError(
`Currency ${currency} not supported for conversion. Please check the supported currency list.`,
400,
);
}

// Fetch the latest exchange rates
const latestRate = await getLatestAcbuRate().catch(() => null);

if (!latestRate) {
throw new AppError(
"Exchange rates not yet available. Please try again in a moment.",
503,
);
}

// Get the rate field name for this currency
const rateFieldName = CURRENCY_TO_RATE_FIELD[currency];

// Retrieve the local-to-ACBU rate (how many units of local currency per 1 ACBU)
const localToAcbuRate = latestRate[rateFieldName as keyof typeof latestRate];

if (!localToAcbuRate || localToAcbuRate.toNumber() <= 0) {
throw new AppError(
`Exchange rate for ${currency} is not available or invalid. Cannot process deposit at this time.`,
503,
);
}

// Convert using high-precision Decimal arithmetic
const localAmountDecimal = new Decimal(localAmount);
const rateDecimal = new Decimal(localToAcbuRate);

// Calculate ACBU equivalent
const acbuAmount = localAmountDecimal.div(rateDecimal);

// Get USD rate per ACBU
const acbuUsdRate = new Decimal(latestRate.acbuUsd);

if (acbuUsdRate.toNumber() <= 0) {
throw new AppError(
"USD conversion rate is invalid. Cannot process deposit at this time.",
503,
);
}

// Convert ACBU to USD
const usdAmount = acbuAmount.mul(acbuUsdRate);

// Return as number with precision
return usdAmount.toNumber();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Validate that localAmount is non-negative.

convertLocalToUsd does not guard against negative localAmount. A negative value would produce negative USD, potentially reducing limit totals or bypassing checks.

  export async function convertLocalToUsd(
    localAmount: number,
    currency: string,
  ): Promise<number> {
+   if (localAmount < 0) {
+     throw new AppError("Amount cannot be negative", 400);
+   }
    // Validate currency is supported
    if (!CURRENCY_TO_RATE_FIELD[currency]) {
📝 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
export async function convertLocalToUsd(
localAmount: number,
currency: string,
): Promise<number> {
// Validate currency is supported
if (!CURRENCY_TO_RATE_FIELD[currency]) {
throw new AppError(
`Currency ${currency} not supported for conversion. Please check the supported currency list.`,
400,
);
}
// Fetch the latest exchange rates
const latestRate = await getLatestAcbuRate().catch(() => null);
if (!latestRate) {
throw new AppError(
"Exchange rates not yet available. Please try again in a moment.",
503,
);
}
// Get the rate field name for this currency
const rateFieldName = CURRENCY_TO_RATE_FIELD[currency];
// Retrieve the local-to-ACBU rate (how many units of local currency per 1 ACBU)
const localToAcbuRate = latestRate[rateFieldName as keyof typeof latestRate];
if (!localToAcbuRate || localToAcbuRate.toNumber() <= 0) {
throw new AppError(
`Exchange rate for ${currency} is not available or invalid. Cannot process deposit at this time.`,
503,
);
}
// Convert using high-precision Decimal arithmetic
const localAmountDecimal = new Decimal(localAmount);
const rateDecimal = new Decimal(localToAcbuRate);
// Calculate ACBU equivalent
const acbuAmount = localAmountDecimal.div(rateDecimal);
// Get USD rate per ACBU
const acbuUsdRate = new Decimal(latestRate.acbuUsd);
if (acbuUsdRate.toNumber() <= 0) {
throw new AppError(
"USD conversion rate is invalid. Cannot process deposit at this time.",
503,
);
}
// Convert ACBU to USD
const usdAmount = acbuAmount.mul(acbuUsdRate);
// Return as number with precision
return usdAmount.toNumber();
}
export async function convertLocalToUsd(
localAmount: number,
currency: string,
): Promise<number> {
if (localAmount < 0) {
throw new AppError("Amount cannot be negative", 400);
}
// Validate currency is supported
if (!CURRENCY_TO_RATE_FIELD[currency]) {
throw new AppError(
`Currency ${currency} not supported for conversion. Please check the supported currency list.`,
400,
);
}
// Fetch the latest exchange rates
const latestRate = await getLatestAcbuRate().catch(() => null);
if (!latestRate) {
throw new AppError(
"Exchange rates not yet available. Please try again in a moment.",
503,
);
}
// Get the rate field name for this currency
const rateFieldName = CURRENCY_TO_RATE_FIELD[currency];
// Retrieve the local-to-ACBU rate (how many units of local currency per 1 ACBU)
const localToAcbuRate = latestRate[rateFieldName as keyof typeof latestRate];
if (!localToAcbuRate || localToAcbuRate.toNumber() <= 0) {
throw new AppError(
`Exchange rate for ${currency} is not available or invalid. Cannot process deposit at this time.`,
503,
);
}
// Convert using high-precision Decimal arithmetic
const localAmountDecimal = new Decimal(localAmount);
const rateDecimal = new Decimal(localToAcbuRate);
// Calculate ACBU equivalent
const acbuAmount = localAmountDecimal.div(rateDecimal);
// Get USD rate per ACBU
const acbuUsdRate = new Decimal(latestRate.acbuUsd);
if (acbuUsdRate.toNumber() <= 0) {
throw new AppError(
"USD conversion rate is invalid. Cannot process deposit at this time.",
503,
);
}
// Convert ACBU to USD
const usdAmount = acbuAmount.mul(acbuUsdRate);
// Return as number with precision
return usdAmount.toNumber();
}
🤖 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/services/rates/currencyConverter.ts` around lines 68 - 125, The
convertLocalToUsd function currently allows negative localAmount values, which
can produce invalid negative USD results and affect downstream limit checks. Add
a non-negative validation at the start of convertLocalToUsd, alongside the
existing currency support checks, and throw an AppError for any amount below
zero before any rate lookups or Decimal conversion occur.

Comment on lines +80 to +82
// Fetch the latest exchange rates
const latestRate = await getLatestAcbuRate().catch(() => null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Preserve error context from getLatestAcbuRate failures.

The .catch(() => null) pattern swallows the original error, making it impossible to distinguish between DB timeouts, connection failures, and missing data in logs/monitoring.

  // Fetch the latest exchange rates
- const latestRate = await getLatestAcbuRate().catch(() => null);
+ const latestRate = await getLatestAcbuRate().catch((err) => {
+   logger.warn("Failed to fetch ACBU rates", { error: err.message });
+   return null;
+ });

Would you like me to generate a patch that adds structured logging to both conversion functions?

🤖 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/services/rates/currencyConverter.ts` around lines 80 - 82, The
`getLatestAcbuRate` call in `currencyConverter` is swallowing the original
failure by converting every error into null, which removes useful context from
logs and monitoring. Update the rate-fetching flow in the conversion functions
to catch the error explicitly, preserve the thrown error details, and log or
rethrow them with enough context to distinguish timeout, connection, and
missing-data cases. Use the existing `getLatestAcbuRate` and the surrounding
conversion helper(s) as the integration points, and avoid the blanket `.catch(()
=> null)` pattern.

@wolfyres wolfyres changed the title fix: resolve ui and linting issues fix: sensitive architectural details #477 Jun 26, 2026
@Junman140 Junman140 merged commit d6fa28a into Pi-Defi-world:dev Jun 27, 2026
2 of 3 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.

SECURITY_FIX_SUMMARY.md and ISSUES.md contain sensitive architectural details

2 participants