Skip to content

fix(withdrawal-manager): use legacy RPCs for tendermint withdrawals#57

Merged
CharlVS merged 6 commits intodevfrom
bugfix/tendermint-withdraw
May 21, 2025
Merged

fix(withdrawal-manager): use legacy RPCs for tendermint withdrawals#57
CharlVS merged 6 commits intodevfrom
bugfix/tendermint-withdraw

Conversation

@takenagain
Copy link
Copy Markdown
Contributor

@takenagain takenagain commented May 19, 2025

Fixes the following

  • Coin activation failing, with PlatformIsAlreadyActivated, requiring the user to navigate back to the coins list to click on the coin again to see coin details.
  • Tendermint withdrawals failing because it is not yet supported by the task-based withdrawal function.

Changes

  • Modified WithdrawalManager to use LegacyWithdrawalManager for Tendermint protocol assets
  • Added retry logic to auto-coin activation in PubkeyManager to resolve coin activation failures in KW and the example preview. This is usually due to the PlatformIsAlreadyActivated error returned because of race conditions with auto-activation. Balance watching requests generally activate the coin before the getPubkeys in AssetPage, resulting in the getPubkeys function throwing an exception that is treated as fatal in KW and the SDK example project.

Summary by CodeRabbit

  • New Features

    • Added support for retrying operations with exponential backoff in key management, improving reliability during asset activation.
    • Enhanced withdrawal functionality to support legacy flows for specific asset types, ensuring compatibility with Tendermint-based assets.
    • Improved fee information parsing to recognize and handle the "Tendermint" type for backward compatibility.
  • Chores

    • Updated dependency overrides to include a new package in multiple modules.
  • Style

    • Minor formatting improvements in withdrawal progress reporting for better readability.

PlatformIsAlreadyActivated error seen in SDK example and KW. Ideal solution is to retry in the SDK before throwing an exception
@takenagain takenagain self-assigned this May 19, 2025
@takenagain takenagain added the bug Something isn't working label May 19, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented May 19, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This update introduces dependency overrides for komodo_coins in two packages, implements a reusable exponential backoff retry utility, integrates retry logic into pubkey activation, and adds conditional logic to handle Tendermint protocol withdrawals via a legacy manager. Additionally, it enhances JSON parsing to support a legacy "Tendermint" fee type.

Changes

File(s) Change Summary
packages/komodo_defi_framework/pubspec_overrides.yaml,
packages/komodo_defi_local_auth/pubspec_overrides.yaml
Added dependency override for komodo_coins, updating comments and specifying a local path override.
packages/komodo_defi_sdk/lib/src/pubkeys/pubkey_manager.dart Introduced retryWithBackoff utility for exponential backoff retries; refactored PubkeyManager methods to use this utility for asset activation, replacing manual error handling with retry logic.
packages/komodo_defi_sdk/lib/src/withdrawals/legacy_withdrawal_manager.dart Reformatted conditional assignment for clarity and modified exception handling to include stack trace, without changing logic.
packages/komodo_defi_sdk/lib/src/withdrawals/withdrawal_manager.dart Added conditional logic to delegate withdrawal and preview operations for Tendermint protocol assets to LegacyWithdrawalManager, maintaining existing flow for other protocols.
packages/komodo_defi_types/lib/src/transactions/fee_info.dart Enhanced FeeInfo.fromJson to support a legacy "Tendermint" type, mapping it to the cosmosGas variant with appropriate field mapping for backward compatibility.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WithdrawalManager
    participant Asset
    participant LegacyWithdrawalManager

    User->>WithdrawalManager: request withdrawal (assetConfigId)
    WithdrawalManager->>Asset: get asset by configId
    WithdrawalManager->>Asset: check protocol type
    alt Asset protocol is Tendermint
        WithdrawalManager->>LegacyWithdrawalManager: instantiate and call withdraw/previewWithdrawal
        LegacyWithdrawalManager-->>User: return result
    else Non-Tendermint asset
        WithdrawalManager->>WithdrawalManager: proceed with task-based withdrawal logic
        WithdrawalManager-->>User: return result
    end
Loading
sequenceDiagram
    participant PubkeyManager
    participant ActivationManager

    PubkeyManager->>retryWithBackoff: call with activation function
    loop Until success or max attempts
        retryWithBackoff->>ActivationManager: activateAsset(asset)
        alt Activation succeeds
            retryWithBackoff-->>PubkeyManager: return result
        else Activation fails and should retry
            retryWithBackoff->>retryWithBackoff: wait (exponential backoff)
        else Activation fails and should not retry
            retryWithBackoff-->>PubkeyManager: throw error
        end
    end
Loading

Poem

A hop and a skip, we override with cheer,
Retry with backoff, our errors disappear!
Tendermint’s legacy, now handled with grace,
Fee types enhanced, no bugs to chase.
With every commit, our code’s more sublime—
🐇 Hopping forward, one fix at a time!


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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented May 19, 2025

Visit the preview URL for this PR (updated for commit 8d9c80a):

https://komodo-defi-sdk--pr57-bugfix-tendermint-wi-nyi0yufa.web.app

(expires Wed, 28 May 2025 12:53:20 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 7f9f5ac39928f333b6e8fcefb7138575e24ed347

exceptions thrown in microtask queues are not caught by traditional try-catch blocks (even when awaited), so run the function to be retried in a guarded zone to catch all exceptions
@takenagain
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented May 20, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Nitpick comments (2)
packages/komodo_defi_framework/pubspec_overrides.yaml (1)

3-4: Add local override for komodo_coins

A new dependency override for komodo_coins with path: ../komodo_coins has been introduced. The path looks correct relative to this package. For clarity, you may want to order the overrides to match the header comment’s sequence or sort them alphabetically.

packages/komodo_defi_local_auth/pubspec_overrides.yaml (1)

3-4: Add komodo_coins dependency override

The override for komodo_coins pointing to ../komodo_coins has been added. Verify that this path resolves correctly and consider reordering the entries to match the header comment’s sequence or for alphabetical consistency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 46350cb and 47ac37d.

📒 Files selected for processing (6)
  • packages/komodo_defi_framework/pubspec_overrides.yaml (1 hunks)
  • packages/komodo_defi_local_auth/pubspec_overrides.yaml (1 hunks)
  • packages/komodo_defi_sdk/lib/src/pubkeys/pubkey_manager.dart (2 hunks)
  • packages/komodo_defi_sdk/lib/src/withdrawals/legacy_withdrawal_manager.dart (3 hunks)
  • packages/komodo_defi_sdk/lib/src/withdrawals/withdrawal_manager.dart (3 hunks)
  • packages/komodo_defi_types/lib/src/transactions/fee_info.dart (1 hunks)
🔇 Additional comments (12)
packages/komodo_defi_framework/pubspec_overrides.yaml (1)

1-1: Include komodo_coins in Melos-managed dependencies comment

The header comment # melos_managed_dependency_overrides has been updated to list komodo_coins, matching the added override entry below. This ensures Melos will track it properly.

packages/komodo_defi_local_auth/pubspec_overrides.yaml (1)

1-1: Update Melos-managed overrides header

The # melos_managed_dependency_overrides comment now includes komodo_coins, reflecting the new override. This keeps the list in sync with the actual overrides.

packages/komodo_defi_sdk/lib/src/pubkeys/pubkey_manager.dart (3)

6-58: Well-implemented retry utility with exponential backoff

The retryWithBackoff utility function is a solid implementation of the exponential backoff pattern. It handles microtask errors properly by using runZonedGuarded and provides flexibility with two retry predicates.

A few strengths of this implementation:

  • Clear distinction between retry conditions that should/shouldn't increment the attempt counter
  • Error propagation via completion of a completer rather than just throwing
  • Exponential delay increase with each retry attempt

70-70: Good integration of retry mechanism

Replacing the direct activation call with the retry utility improves the robustness of the pubkey retrieval process, especially for network-related operations that might experience transient failures.


77-77: Consistent application of retry pattern

Applying the same retry pattern to createNewPubkey ensures a consistent approach to handling potential activation failures across the codebase.

packages/komodo_defi_sdk/lib/src/withdrawals/legacy_withdrawal_manager.dart (3)

48-50: Code formatting improvement

The improved formatting makes the code more readable while maintaining the same logic.


71-73: Consistent formatting application

Applying the same formatting improvements consistently throughout the codebase.


117-117: Enhanced error handling with stack trace capture

Adding the stack trace (s) to the catch block is a good practice for better debugging and error reporting. This will help with troubleshooting issues that might occur during withdrawal previews.

packages/komodo_defi_types/lib/src/transactions/fee_info.dart (1)

50-59: Good backward compatibility for legacy API

Adding support for the "Tendermint" fee type ensures compatibility with the legacy withdraw API. The implementation properly maps it to the existing cosmosGas variant while handling the different field names in the JSON payload.

The comments explaining the rationale are helpful for future maintainers.

packages/komodo_defi_sdk/lib/src/withdrawals/withdrawal_manager.dart (3)

6-6: Required import for the new feature

The import of legacy_withdrawal_manager.dart is necessary for the new conditional handling of Tendermint protocol withdrawals.


46-55: Clean implementation of Tendermint protocol delegation

The implementation correctly identifies assets using the Tendermint protocol and delegates their withdrawal preview to the legacy manager. This separation of concerns is well-structured and maintains a clean code organization.


100-110: Consistent implementation for withdrawal execution

The same pattern used in previewWithdrawal is applied consistently to the withdraw method, creating a unified approach to handling Tendermint protocol assets.

@takenagain takenagain marked this pull request as ready for review May 20, 2025 12:14
@takenagain takenagain requested review from CharlVS and smk762 May 20, 2025 12:16
@CharlVS CharlVS added the QA Ready for QA Testing label May 20, 2025
Comment on lines +6 to +59
/// Retry utility with exponential backoff.
/// If [shouldRetry] returns true, the attempt counter is incremented.
/// If [shouldRetryNoIncrement] returns true, the attempt counter is NOT
/// incremented. Use with caution. The intended application is for
/// false positives, where the error is not a failure of the function
/// E.g. PlatformIsAlreadyActivated
Future<T> retryWithBackoff<T>(
Future<T> Function() fn, {
int maxAttempts = 5,
Duration initialDelay = const Duration(milliseconds: 200),
bool Function(Object error)? shouldRetry,
bool Function(Object error)? shouldRetryNoIncrement,
}) async {
var attempt = 0;
var delay = initialDelay;

while (true) {
final completer = Completer<T>();

// RPC calls are scheduled microtasks, so we need to run them in a zone
// to catch errors that are thrown in the microtask queue, which would
// otherwise be unhandled.
await runZonedGuarded(
() async {
final result = await fn();
if (!completer.isCompleted) {
completer.complete(result);
}
},
(error, stack) {
if (!completer.isCompleted) {
completer.completeError(error, stack);
}
},
);

try {
return await completer.future;
} catch (e) {
if (shouldRetryNoIncrement != null && shouldRetryNoIncrement(e)) {
await Future<void>.delayed(delay);
delay *= 2;
continue;
}
attempt++;
if (attempt >= maxAttempts || (shouldRetry != null && !shouldRetry(e))) {
rethrow;
}
await Future<void>.delayed(delay);
delay *= 2;
}
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since this isn't specific to the SDK or the pubkey manager, please move this to the types utils in the types package.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 47e472e and 8d9c80a

@CharlVS CharlVS merged commit d7dcb80 into dev May 21, 2025
6 of 7 checks passed
@CharlVS CharlVS deleted the bugfix/tendermint-withdraw branch May 21, 2025 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working QA Ready for QA Testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants