Skip to content

Unifying DeFi errors to a common format#393

Merged
TrueCarry merged 14 commits into
mainfrom
feat/codegen-features
Jun 17, 2026
Merged

Unifying DeFi errors to a common format#393
TrueCarry merged 14 commits into
mainfrom
feat/codegen-features

Conversation

@heyllog

@heyllog heyllog commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced error handling for failed deposit operations in crypto onramp with clearer error messaging.

@heyllog heyllog self-assigned this May 14, 2026
@heyllog heyllog requested a review from a team as a code owner May 14, 2026 10:30
@vercel

vercel Bot commented May 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
appkit-minter Ready Ready Preview, Comment Jun 17, 2026 4:06pm
kit-demo-wallet Ready Ready Preview, Comment Jun 17, 2026 4:06pm

Request Review

@heyllog heyllog changed the base branch from feat/TON-622-crypto-onramp-design to main May 26, 2026 05:50
@heyllog heyllog changed the base branch from main to feat/TON-622-crypto-onramp-design May 26, 2026 05:51
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

More reviews will be available in 1 minute and 31 seconds. Learn how PR review limits work.

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

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

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 82f5ebc7-3a98-4b07-94c0-33199b02e809

📥 Commits

Reviewing files that changed from the base of the PR and between 7c6aeaa and 36622da.

📒 Files selected for processing (11)
  • .changeset/defi-error-handling.md
  • packages/appkit-react/src/features/onramp/widgets/crypto-onramp/utils/map-crypto-onramp-error.ts
  • packages/appkit-react/src/locales/en.ts
  • packages/appkit-react/src/utils/map-defi-error.ts
  • packages/walletkit/src/defi/crypto-onramp/CryptoOnrampManager.ts
  • packages/walletkit/src/defi/errors.ts
  • packages/walletkit/src/defi/gasless/GaslessManager.ts
  • packages/walletkit/src/defi/gasless/tonapi/TonApiGaslessProvider.ts
  • packages/walletkit/src/defi/staking/StakingManager.ts
  • packages/walletkit/src/defi/staking/tonstakers/TonStakersStakingProvider.ts
  • packages/walletkit/src/defi/swap/SwapManager.ts
📝 Walkthrough

Walkthrough

The PR removes the protected abstract createError factory pattern from DefiManager and all subclasses (GaslessManager, SwapManager), replacing it with direct DefiError construction inline in the base class. CryptoOnrampManager gains a new DepositFailed error code with normalized catch handling. StakingManager replaces log-and-rethrow patterns with typed StakingError throws. The UI layer adds an i18n string and error-mapping case for the new deposit error.

Changes

DeFi Error Handling Refactor

Layer / File(s) Summary
DefiManager: remove abstract createError, throw directly
packages/walletkit/src/defi/DefiManager.ts, packages/walletkit/src/defi/gasless/GaslessManager.ts, packages/walletkit/src/defi/swap/SwapManager.ts
DefiManager consolidates its error imports, removes the protected abstract createError declaration, and replaces all call sites in registerProvider, setDefaultProvider, and getProvider with inline new DefiError(...). GaslessManager and SwapManager remove their createError overrides and now-unused error-type imports.
CryptoOnramp: DepositFailed error code and catch handling
packages/walletkit/src/defi/crypto-onramp/errors.ts, packages/walletkit/src/defi/crypto-onramp/CryptoOnrampManager.ts
CryptoOnrampErrorCode gains DepositFailed = 'DEPOSIT_FAILED'. CryptoOnrampManager consolidates imports, updates createDeposit's catch block to rethrow existing CryptoOnrampError and wrap others with DepositFailed, and removes the protected createError method.
StakingManager: normalize provider errors to StakingError
packages/walletkit/src/defi/staking/StakingManager.ts
getQuote, buildStakeTransaction, getStakedBalance, getStakingProviderInfo, and getStakingProviderMetadata each replace log-and-rethrow catch blocks with new StakingError(..., InvalidParams) throws carrying contextual detail payloads.
UI error mapping, i18n, and test assertions
packages/appkit-react/src/locales/en.ts, packages/appkit-react/src/features/onramp/.../map-crypto-onramp-error.ts, packages/walletkit/src/defi/gasless/GaslessManager.spec.ts
English locale adds depositFailed: 'Failed to create deposit'. mapCryptoOnrampError adds a switch case for CryptoOnrampErrorCode.DepositFailed. GaslessManager tests import DefiError and assert setDefaultProvider now throws DefiError instead of GaslessError.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit hopped through error land,
Where abstract factories once were planned.
Now DefiError stands straight and tall,
DepositFailed answers the call.
No more createError in sight—
The burrow's errors wrapped up right! 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately reflects the main objective of the changeset: unifying DeFi error handling across multiple manager classes to a common format by removing subclass-specific createError methods and normalizing error construction.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/codegen-features

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.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/walletkit/src/defi/crypto-onramp/CryptoOnrampManager.ts (1)

102-120: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve provider-selection errors instead of collapsing them into DepositFailed.

Line [103] can throw DefiError (NoDefaultProvider/ProviderNotFound) from DefiManager.getProvider, but Lines [116]-[120] currently wrap that as CryptoOnrampErrorCode.DepositFailed. This masks the real failure mode and breaks downstream error mapping behavior.

Suggested fix
-        try {
-            const deposit = await this.getProvider(selectedProviderId).createDeposit(params);
+        const provider = this.getProvider(selectedProviderId);
+        try {
+            const deposit = await provider.createDeposit(params);
@@
         } catch (error) {
             log.error('Failed to create crypto onramp deposit', { error, params });
             if (error instanceof CryptoOnrampError) throw error;
             throw new CryptoOnrampError(
                 'Failed to create crypto onramp deposit',
                 CryptoOnrampErrorCode.DepositFailed,
                 error,
             );
         }
🤖 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 `@packages/walletkit/src/defi/crypto-onramp/CryptoOnrampManager.ts` around
lines 102 - 120, The catch block in the createDeposit method is wrapping all
errors as DepositFailed, but it should preserve provider-selection errors from
getProvider. Add a check after the CryptoOnrampError instanceof check to detect
if the error is a DefiError (which can be thrown from getProvider when it cannot
find the provider), and re-throw that error as-is without wrapping it. Only wrap
the error as DepositFailed when it is neither a CryptoOnrampError nor a
DefiError, ensuring that provider-selection failures maintain their original
error type for downstream error mapping.
🤖 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 `@packages/walletkit/src/defi/gasless/GaslessManager.spec.ts`:
- Around line 113-118: The test for the setDefaultProvider method only verifies
that a DefiError is thrown, but does not assert the specific error code. Update
the expect statement to check for both the error class and the specific
ProviderNotFound error code or error message to ensure the correct error
semantics are maintained. Use a more specific assertion pattern (such as
checking the error code property or error message) alongside the DefiError class
check in the setDefaultProvider test.

In `@packages/walletkit/src/defi/staking/StakingManager.ts`:
- Around line 49-50: The code is collapsing all caught errors into
StakingErrorCode.InvalidParams across multiple methods, losing the original
error semantics. In all five error handling blocks (the catch block around line
49-50, the blocks at lines 63-67, 90-95, 112, and 130-134), replace the blanket
InvalidParams normalization with conditional error handling: if the caught error
is already a StakingError, re-throw it unchanged; if it's a DefiError from
getProvider, map it to an appropriate StakingErrorCode; only use InvalidParams
when the error is actually due to invalid parameters. This pattern should be
applied consistently across all catch blocks in the affected methods to preserve
actionable error semantics for callers.

---

Outside diff comments:
In `@packages/walletkit/src/defi/crypto-onramp/CryptoOnrampManager.ts`:
- Around line 102-120: The catch block in the createDeposit method is wrapping
all errors as DepositFailed, but it should preserve provider-selection errors
from getProvider. Add a check after the CryptoOnrampError instanceof check to
detect if the error is a DefiError (which can be thrown from getProvider when it
cannot find the provider), and re-throw that error as-is without wrapping it.
Only wrap the error as DepositFailed when it is neither a CryptoOnrampError nor
a DefiError, ensuring that provider-selection failures maintain their original
error type for downstream error mapping.
🪄 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: 23c76cc9-27b8-450d-b8b6-95ea5a62ef7c

📥 Commits

Reviewing files that changed from the base of the PR and between 721d033 and 7c6aeaa.

📒 Files selected for processing (9)
  • packages/appkit-react/src/features/onramp/widgets/crypto-onramp/utils/map-crypto-onramp-error.ts
  • packages/appkit-react/src/locales/en.ts
  • packages/walletkit/src/defi/DefiManager.ts
  • packages/walletkit/src/defi/crypto-onramp/CryptoOnrampManager.ts
  • packages/walletkit/src/defi/crypto-onramp/errors.ts
  • packages/walletkit/src/defi/gasless/GaslessManager.spec.ts
  • packages/walletkit/src/defi/gasless/GaslessManager.ts
  • packages/walletkit/src/defi/staking/StakingManager.ts
  • packages/walletkit/src/defi/swap/SwapManager.ts
💤 Files with no reviewable changes (2)
  • packages/walletkit/src/defi/gasless/GaslessManager.ts
  • packages/walletkit/src/defi/swap/SwapManager.ts

Comment on lines +113 to 118
it('throws DefiError when the providerId is not registered', () => {
const { manager } = makeManager();
manager.registerProvider(makeProvider('first'));

expect(() => manager.setDefaultProvider('missing')).toThrow(GaslessError);
expect(() => manager.setDefaultProvider('missing')).toThrow(DefiError);
});

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 | ⚡ Quick win

Assert the specific ProviderNotFound behavior, not just the error class.

Line [117] only checks DefiError, which can hide regressions in error-code semantics for this path.

Suggested test tightening
-import { DefiError } from '../errors';
+import { DefiError, DefiErrorCode } from '../errors';
@@
-        expect(() => manager.setDefaultProvider('missing')).toThrow(DefiError);
+        expect(() => manager.setDefaultProvider('missing')).toThrowError(
+            expect.objectContaining({ name: 'DefiError', code: DefiErrorCode.ProviderNotFound }),
+        );

As per coding guidelines, "Test behaviors, not implementation details. Always update existing tests related to your changes."

📝 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('throws DefiError when the providerId is not registered', () => {
const { manager } = makeManager();
manager.registerProvider(makeProvider('first'));
expect(() => manager.setDefaultProvider('missing')).toThrow(GaslessError);
expect(() => manager.setDefaultProvider('missing')).toThrow(DefiError);
});
it('throws DefiError when the providerId is not registered', () => {
const { manager } = makeManager();
manager.registerProvider(makeProvider('first'));
expect(() => manager.setDefaultProvider('missing')).toThrowError(
expect.objectContaining({ name: 'DefiError', code: DefiErrorCode.ProviderNotFound }),
);
});
🤖 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 `@packages/walletkit/src/defi/gasless/GaslessManager.spec.ts` around lines 113
- 118, The test for the setDefaultProvider method only verifies that a DefiError
is thrown, but does not assert the specific error code. Update the expect
statement to check for both the error class and the specific ProviderNotFound
error code or error message to ensure the correct error semantics are
maintained. Use a more specific assertion pattern (such as checking the error
code property or error message) alongside the DefiError class check in the
setDefaultProvider test.

Source: Coding guidelines

Comment on lines 49 to 50
throw new StakingError('Failed to get staking quote', StakingErrorCode.InvalidParams, { error, params });
}

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 | 🟠 Major | ⚡ Quick win

Do not normalize all failures to StakingErrorCode.InvalidParams.

Lines [49], [63]-[67], [90]-[95], [112], and [130]-[134] currently convert every caught error (including DefiError from getProvider and existing typed staking/provider errors) into InvalidParams. That erases actionable error semantics for callers and UI mapping.

Suggested pattern (apply across all five methods)
+import { DefiError } from '../errors';
@@
-        try {
-            const quote = await this.getProvider(providerId).getQuote(params);
+        const provider = this.getProvider(providerId);
+        try {
+            const quote = await provider.getQuote(params);
             log.debug('Received staking quote', quote);
             return quote;
         } catch (error) {
+            if (error instanceof DefiError || error instanceof StakingError) throw error;
             throw new StakingError('Failed to get staking quote', StakingErrorCode.InvalidParams, { error, params });
         }

Also applies to: 63-67, 90-95, 112-113, 130-134

🤖 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 `@packages/walletkit/src/defi/staking/StakingManager.ts` around lines 49 - 50,
The code is collapsing all caught errors into StakingErrorCode.InvalidParams
across multiple methods, losing the original error semantics. In all five error
handling blocks (the catch block around line 49-50, the blocks at lines 63-67,
90-95, 112, and 130-134), replace the blanket InvalidParams normalization with
conditional error handling: if the caught error is already a StakingError,
re-throw it unchanged; if it's a DefiError from getProvider, map it to an
appropriate StakingErrorCode; only use InvalidParams when the error is actually
due to invalid parameters. This pattern should be applied consistently across
all catch blocks in the affected methods to preserve actionable error semantics
for callers.

@heyllog heyllog changed the title Code changes after docs review Unifying DeFi errors to a common format Jun 17, 2026
@TrueCarry TrueCarry merged commit 50b227e into main Jun 17, 2026
7 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.

2 participants