93 lines
3.5 KiB
Python
93 lines
3.5 KiB
Python
"""
|
|
Parser for the Jupiter Aggregator swap instructions
|
|
"""
|
|
import base64
|
|
from typing import Dict, List, Optional, Tuple
|
|
|
|
from app.parsers.base import SwapParser
|
|
|
|
|
|
# Jupiter Program IDs
|
|
JUPITER_PROGRAM_ID = "JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB" # Jupiter V4
|
|
JUPITER_V3_PROGRAM_ID = "JUP3c2Uh3WA4Ng34tw6kPd2G4C5BB21Xo36Je1s32Ph" # Jupiter V3
|
|
JUPITER_V6_PROGRAM_ID = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" # Jupiter V6
|
|
|
|
|
|
class JupiterParser(SwapParser):
|
|
"""
|
|
Parser for the Jupiter Aggregator swap instructions
|
|
"""
|
|
|
|
@property
|
|
def program_id(self) -> str:
|
|
return JUPITER_PROGRAM_ID
|
|
|
|
def can_handle(self, program_id: str) -> bool:
|
|
"""
|
|
Check if this parser can handle instructions from a given program
|
|
"""
|
|
return program_id in [JUPITER_PROGRAM_ID, JUPITER_V3_PROGRAM_ID, JUPITER_V6_PROGRAM_ID]
|
|
|
|
def parse_instruction(self, instruction: Dict, accounts: List[str], instruction_data: bytes) -> Dict:
|
|
"""
|
|
Parse a Jupiter instruction
|
|
"""
|
|
if not instruction_data:
|
|
return {"type": "unknown", "error": "No instruction data"}
|
|
|
|
# Get accounts referenced by the instruction
|
|
instruction_accounts = instruction.get("accounts", [])
|
|
referenced_accounts = [accounts[idx] for idx in instruction_accounts if idx < len(accounts)]
|
|
|
|
# Basic metadata about the instruction
|
|
result = {
|
|
"type": "jupiter_swap",
|
|
"program": "jupiter_aggregator",
|
|
"program_id": instruction.get("programId", JUPITER_PROGRAM_ID),
|
|
"accounts": referenced_accounts,
|
|
"data": base64.b64encode(instruction_data).decode("utf-8"),
|
|
}
|
|
|
|
# Jupiter instructions are complex and version-dependent
|
|
# Here we'll implement a simplified version for demonstration
|
|
|
|
# In Jupiter V4+, the accounts typically follow this pattern:
|
|
# 0: Token program
|
|
# 1: User's token account (source)
|
|
# 2: User's token account (destination)
|
|
# 3: User's wallet
|
|
# (additional accounts depend on the route)
|
|
|
|
if len(referenced_accounts) >= 4:
|
|
result.update({
|
|
"source_account": referenced_accounts[1],
|
|
"destination_account": referenced_accounts[2],
|
|
"user_wallet": referenced_accounts[3],
|
|
})
|
|
|
|
# Note: Parsing the exact amount and path would require deeper
|
|
# instruction-specific knowledge and likely additional context
|
|
|
|
return result
|
|
|
|
def extract_swap_info(self, parsed_instruction: Dict) -> Tuple[Optional[str], Optional[str], Optional[float], Optional[float]]:
|
|
"""
|
|
Extract swap information from a parsed instruction
|
|
|
|
Returns:
|
|
Tuple of (token_in_address, token_out_address, amount_in, amount_out)
|
|
"""
|
|
if parsed_instruction.get("type") != "jupiter_swap":
|
|
return None, None, None, None
|
|
|
|
# For a full implementation, we would need to:
|
|
# 1. Look up token mint addresses from the token accounts
|
|
# 2. Parse amounts from instruction data
|
|
# 3. Handle different Jupiter versions
|
|
|
|
# This is a simplified implementation
|
|
source_account = parsed_instruction.get("source_account")
|
|
destination_account = parsed_instruction.get("destination_account")
|
|
|
|
# We don't have enough information to determine amounts from just the instruction
|
|
return None, source_account, destination_account, None |