PHANTOM
🇮🇳 IN
Skip to content

feat(swap): use LI.FI error codes for error categorization#217

Open
onyb wants to merge 1 commit intomasterfrom
f/swap/lifi-improve-error-categories
Open

feat(swap): use LI.FI error codes for error categorization#217
onyb wants to merge 1 commit intomasterfrom
f/swap/lifi-improve-error-categories

Conversation

@onyb
Copy link
Member

@onyb onyb commented Feb 26, 2026

Figuring out the SwapError categories from the error code rather than parsing the error messages.

Docs https://docs.li.fi/api-reference/error-codes

@onyb onyb requested a review from a team February 26, 2026 05:44
@onyb onyb self-assigned this Feb 26, 2026
Copilot AI review requested due to automatic review settings February 26, 2026 05:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request refactors the LI.FI error handling to use structured error codes from the LI.FI API instead of parsing error messages. This is a more robust and maintainable approach that aligns with the LI.FI API documentation.

Changes:

  • Replaced message-based error categorization with code-based error categorization
  • Added two new error kinds: RATE_LIMIT_EXCEEDED and TIMEOUT
  • Updated the LifiError model to include a code field instead of an errors field

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
app/api/swap/providers/lifi/utils.py Refactored categorize_error() to map LI.FI error codes (1000-1013) to SwapErrorKind values
app/api/swap/providers/lifi/test_client.py Updated test to verify error categorization and added comprehensive parametrized test for all error codes
app/api/swap/providers/lifi/models.py Changed LifiError model to include code field instead of errors field
app/api/swap/providers/lifi/mocks.py Updated mock error response to include error code instead of nested errors array
app/api/swap/providers/lifi/client.py Simplified error handling to pass entire LifiError object to categorize_error()
app/api/swap/models.py Added RATE_LIMIT_EXCEEDED and TIMEOUT error kinds to SwapErrorKind enum

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 78 to 139
def categorize_error(error: LifiError) -> SwapErrorKind:
"""Map LI.FI error codes to SwapErrorKind.

Ref: https://docs.li.fi/api-reference/error-codes
"""
# DefaultError
if error.code == 1000:
return SwapErrorKind.UNKNOWN

error_lower = error_message.lower()
# FailedToBuildTransactionError
if error.code == 1001:
return SwapErrorKind.INVALID_REQUEST

if any(
phrase in error_lower
for phrase in [
"no possible route",
"no routes found",
"insufficient liquidity",
"not enough liquidity",
]
):
# NoQuoteError
if error.code == 1002:
return SwapErrorKind.INSUFFICIENT_LIQUIDITY

if any(
phrase in error_lower
for phrase in [
"amount too low",
"amount too small",
"fees higher than amount",
]
):
return SwapErrorKind.AMOUNT_TOO_LOW

if any(
phrase in error_lower
for phrase in [
"slippage",
"validation",
"malformed",
]
):
# NotFoundError
if error.code == 1003:
return SwapErrorKind.INVALID_REQUEST

# NotProcessableError
if error.code == 1004:
return SwapErrorKind.INVALID_REQUEST

# RateLimitError
if error.code == 1005:
return SwapErrorKind.RATE_LIMIT_EXCEEDED

# ServerError
if error.code == 1006:
return SwapErrorKind.UNKNOWN

# SlippageError
if error.code == 1007:
return SwapErrorKind.INVALID_REQUEST

# ThirdPartyError
if error.code == 1008:
return SwapErrorKind.UNKNOWN

# TimeoutError
if error.code == 1009:
return SwapErrorKind.TIMEOUT

# UnauthorizedError
if error.code == 1010:
return SwapErrorKind.INVALID_REQUEST

# ValidationError
if error.code == 1011:
return SwapErrorKind.INVALID_REQUEST

# RpcFailure
if error.code == 1012:
return SwapErrorKind.UNKNOWN

# MalformedSchema
if error.code == 1013:
return SwapErrorKind.INVALID_REQUEST

return SwapErrorKind.UNKNOWN
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The error code to SwapErrorKind mapping would be more maintainable and performant using a dictionary instead of a long chain of if statements. Consider refactoring to:

ERROR_CODE_MAPPING: dict[int, SwapErrorKind] = {
    1000: SwapErrorKind.UNKNOWN,  # DefaultError
    1001: SwapErrorKind.INVALID_REQUEST,  # FailedToBuildTransactionError
    1002: SwapErrorKind.INSUFFICIENT_LIQUIDITY,  # NoQuoteError
    1003: SwapErrorKind.INVALID_REQUEST,  # NotFoundError
    1004: SwapErrorKind.INVALID_REQUEST,  # NotProcessableError
    1005: SwapErrorKind.RATE_LIMIT_EXCEEDED,  # RateLimitError
    1006: SwapErrorKind.UNKNOWN,  # ServerError
    1007: SwapErrorKind.INVALID_REQUEST,  # SlippageError
    1008: SwapErrorKind.UNKNOWN,  # ThirdPartyError
    1009: SwapErrorKind.TIMEOUT,  # TimeoutError
    1010: SwapErrorKind.INVALID_REQUEST,  # UnauthorizedError
    1011: SwapErrorKind.INVALID_REQUEST,  # ValidationError
    1012: SwapErrorKind.UNKNOWN,  # RpcFailure
    1013: SwapErrorKind.INVALID_REQUEST,  # MalformedSchema
}

def categorize_error(error: LifiError) -> SwapErrorKind:
    """Map LI.FI error codes to SwapErrorKind.
    
    Ref: https://docs.li.fi/api-reference/error-codes
    """
    if error.code is None:
        return SwapErrorKind.UNKNOWN
    return ERROR_CODE_MAPPING.get(error.code, SwapErrorKind.UNKNOWN)

This approach is more maintainable, easier to extend, and has O(1) lookup time instead of O(n).

Copilot uses AI. Check for mistakes.
@onyb onyb force-pushed the f/swap/lifi-improve-error-categories branch from 4383937 to 9c4a4c4 Compare February 26, 2026 05:52
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