feat(core): add support for creator fee update

This commit is contained in:
smypmsa
2025-05-12 20:07:51 +00:00
parent d979427662
commit e41a5f4f4f
18 changed files with 5951 additions and 441 deletions
+8 -3
View File
@@ -5,7 +5,7 @@ Bonding curve operations for pump.fun tokens.
import struct
from typing import Final
from construct import Flag, Int64ul, Struct
from construct import Bytes, Flag, Int64ul, Struct
from solders.pubkey import Pubkey
from core.client import SolanaClient
@@ -28,6 +28,7 @@ class BondingCurveState:
"real_sol_reserves" / Int64ul,
"token_total_supply" / Int64ul,
"complete" / Flag,
"creator" / Bytes(32), # Added new creator field - 32 bytes for Pubkey
)
def __init__(self, data: bytes) -> None:
@@ -44,6 +45,10 @@ class BondingCurveState:
parsed = self._STRUCT.parse(data[8:])
self.__dict__.update(parsed)
# Convert raw bytes to Pubkey for creator field
if hasattr(self, 'creator') and isinstance(self.creator, bytes):
self.creator = Pubkey.from_bytes(self.creator)
def calculate_price(self) -> float:
"""Calculate token price in SOL.
@@ -103,8 +108,8 @@ class BondingCurveManager:
return BondingCurveState(account.data)
except Exception as e:
logger.error(f"Failed to get curve state: {str(e)}")
raise ValueError(f"Invalid curve state: {str(e)}")
logger.error(f"Failed to get curve state: {e!s}")
raise ValueError(f"Invalid curve state: {e!s}")
async def calculate_price(self, curve_address: Pubkey) -> float:
"""Calculate the current price of a token.
+29 -4
View File
@@ -7,9 +7,11 @@ import json
import struct
from typing import Any
import base58
from solders.pubkey import Pubkey
from solders.transaction import VersionedTransaction
from core.pubkeys import PumpAddresses
from trading.base import TokenInfo
from utils.logger import get_logger
@@ -41,7 +43,7 @@ class PumpEventProcessor:
with open("idl/pump_fun_idl.json") as f:
return json.load(f)
except Exception as e:
logger.error(f"Failed to load IDL: {str(e)}")
logger.error(f"Failed to load IDL: {e!s}")
# Create a minimal IDL with just what we need
return {
"instructions": [
@@ -111,6 +113,8 @@ class PumpEventProcessor:
decoded_args = self._decode_create_instruction(
ix_data, create_ix, account_keys
)
creator = Pubkey.from_string(decoded_args["creator"])
creator_vault = self._find_creator_vault(creator)
return TokenInfo(
name=decoded_args["name"],
@@ -122,10 +126,12 @@ class PumpEventProcessor:
decoded_args["associatedBondingCurve"]
),
user=Pubkey.from_string(decoded_args["user"]),
creator=creator,
creator_vault=creator_vault,
)
except Exception as e:
logger.error(f"Error processing transaction: {str(e)}")
logger.error(f"Error processing transaction: {e!s}")
return None
@@ -151,8 +157,8 @@ class PumpEventProcessor:
offset += 4
value = ix_data[offset : offset + length].decode("utf-8")
offset += length
elif arg["type"] == "publicKey":
value = base64.b64encode(ix_data[offset : offset + 32]).decode("utf-8")
elif arg["type"] == "pubkey":
value = base58.b58encode(ix_data[offset : offset + 32]).decode("utf-8")
offset += 32
else:
logger.warning(f"Unsupported type: {arg['type']}")
@@ -166,3 +172,22 @@ class PumpEventProcessor:
args["user"] = str(accounts[7])
return args
def _find_creator_vault(self, creator: Pubkey) -> Pubkey:
"""
Find the creator vault for a creator.
Args:
creator: Creator address
Returns:
Creator vault address
"""
derived_address, _ = Pubkey.find_program_address(
[
b"creator-vault",
bytes(creator)
],
PumpAddresses.PROGRAM,
)
return derived_address
+32
View File
@@ -5,8 +5,10 @@ Event processing for pump.fun tokens using Geyser data.
import struct
from typing import Final
import base58
from solders.pubkey import Pubkey
from core.pubkeys import PumpAddresses
from trading.base import TokenInfo
from utils.logger import get_logger
@@ -55,6 +57,12 @@ class GeyserEventProcessor:
offset += length
return value
def read_pubkey():
nonlocal offset
value = base58.b58encode(instruction_data[offset : offset + 32]).decode("utf-8")
offset += 32
return Pubkey.from_string(value)
# Helper to get account key
def get_account_key(index):
if index >= len(accounts):
@@ -67,11 +75,14 @@ class GeyserEventProcessor:
name = read_string()
symbol = read_string()
uri = read_string()
creator = read_pubkey()
mint = get_account_key(0)
bonding_curve = get_account_key(2)
associated_bonding_curve = get_account_key(3)
user = get_account_key(7)
creator_vault = self._find_creator_vault(creator)
if not all([mint, bonding_curve, associated_bonding_curve, user]):
logger.warning("Missing required account keys in token creation")
@@ -85,8 +96,29 @@ class GeyserEventProcessor:
bonding_curve=bonding_curve,
associated_bonding_curve=associated_bonding_curve,
user=user,
creator=creator,
creator_vault=creator_vault,
)
except Exception as e:
logger.error(f"Failed to process transaction data: {e}")
return None
def _find_creator_vault(self, creator: Pubkey) -> Pubkey:
"""
Find the creator vault for a creator.
Args:
creator: Creator address
Returns:
Creator vault address
"""
derived_address, _ = Pubkey.find_program_address(
[
b"creator-vault",
bytes(creator)
],
PumpAddresses.PROGRAM,
)
return derived_address
+25 -1
View File
@@ -9,7 +9,7 @@ from typing import Final
import base58
from solders.pubkey import Pubkey
from core.pubkeys import SystemAddresses
from core.pubkeys import PumpAddresses, SystemAddresses
from trading.base import TokenInfo
from utils.logger import get_logger
@@ -62,6 +62,8 @@ class LogsEventProcessor:
associated_curve = self._find_associated_bonding_curve(
mint, bonding_curve
)
creator = Pubkey.from_string(parsed_data["creator"])
creator_vault = self._find_creator_vault(creator)
return TokenInfo(
name=parsed_data["name"],
@@ -71,6 +73,8 @@ class LogsEventProcessor:
bonding_curve=bonding_curve,
associated_bonding_curve=associated_curve,
user=Pubkey.from_string(parsed_data["user"]),
creator=creator,
creator_vault=creator_vault,
)
except Exception as e:
logger.error(f"Failed to process log data: {e}")
@@ -106,6 +110,7 @@ class LogsEventProcessor:
("mint", "publicKey"),
("bondingCurve", "publicKey"),
("user", "publicKey"),
("creator", "publicKey"),
]
try:
@@ -149,3 +154,22 @@ class LogsEventProcessor:
SystemAddresses.ASSOCIATED_TOKEN_PROGRAM,
)
return derived_address
def _find_creator_vault(self, creator: Pubkey) -> Pubkey:
"""
Find the creator vault for a creator.
Args:
creator: Creator address
Returns:
Creator vault address
"""
derived_address, _ = Pubkey.find_program_address(
[
b"creator-vault",
bytes(creator)
],
PumpAddresses.PROGRAM,
)
return derived_address
+6
View File
@@ -22,6 +22,8 @@ class TokenInfo:
bonding_curve: Pubkey
associated_bonding_curve: Pubkey
user: Pubkey
creator: Pubkey
creator_vault: Pubkey
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "TokenInfo":
@@ -41,6 +43,8 @@ class TokenInfo:
bonding_curve=Pubkey.from_string(data["bondingCurve"]),
associated_bonding_curve=Pubkey.from_string(data["associatedBondingCurve"]),
user=Pubkey.from_string(data["user"]),
creator=Pubkey.from_string(data["creator"]),
creator_vault=Pubkey.from_string(data["creator_vault"]),
)
def to_dict(self) -> dict[str, str]:
@@ -57,6 +61,8 @@ class TokenInfo:
"bondingCurve": str(self.bonding_curve),
"associatedBondingCurve": str(self.associated_bonding_curve),
"user": str(self.user),
"creator": str(self.creator),
"creatorVault": str(self.creator_vault),
}
+1 -1
View File
@@ -176,7 +176,7 @@ class TokenBuyer(Trader):
pubkey=SystemAddresses.TOKEN_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=SystemAddresses.RENT, is_signer=False, is_writable=False
pubkey=token_info.creator_vault, is_signer=False, is_writable=True
),
AccountMeta(
pubkey=PumpAddresses.EVENT_AUTHORITY, is_signer=False, is_writable=False
+3 -5
View File
@@ -128,7 +128,7 @@ class TokenSeller(Trader):
)
except Exception as e:
logger.error(f"Sell operation failed: {str(e)}")
logger.error(f"Sell operation failed: {e!s}")
return TradeResult(success=False, error_message=str(e))
async def _send_sell_transaction(
@@ -175,9 +175,7 @@ class TokenSeller(Trader):
pubkey=SystemAddresses.PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=SystemAddresses.ASSOCIATED_TOKEN_PROGRAM,
is_signer=False,
is_writable=False,
pubkey=token_info.creator_vault, is_signer=False, is_writable=True,
),
AccountMeta(
pubkey=SystemAddresses.TOKEN_PROGRAM, is_signer=False, is_writable=False
@@ -209,5 +207,5 @@ class TokenSeller(Trader):
),
)
except Exception as e:
logger.error(f"Sell transaction failed: {str(e)}")
logger.error(f"Sell transaction failed: {e!s}")
raise