cache address table

This commit is contained in:
thloyi
2026-01-05 14:38:02 +08:00
parent e6922e4561
commit 8c98ec7875
4 changed files with 33 additions and 71 deletions

View File

@@ -80,11 +80,6 @@ var (
terminalAmmSellTokensIX = []byte{0x40, 0x64, 0x97, 0xb9, 0x16, 0xfa, 0xec, 0xb1}
)
// table lookups
const (
photonTableLookup = "3r6paeFSLpeUVmWtShb5uZtXYpcBE3729kUxkUS7xKi1"
)
type compiledInstruction struct {
ProgramIDIndex uint8
Accounts []uint8
@@ -406,7 +401,7 @@ func parsePumpCreateV2(tx *versionedTransaction, instruction *compiledInstructio
return nil, fmt.Errorf("accounts too short")
}
if len(instruction.Data) < 8 {
return nil, fmt.Errorf("data too short for create v2 args")
return nil, fmt.Errorf("data too short for pump create v2 args, len=%d", len(instruction.Data))
}
staticKeys := tx.Message.StaticAccountKeys
@@ -443,7 +438,7 @@ func parsePumpCreateV2(tx *versionedTransaction, instruction *compiledInstructio
func decodePumpBuyArgs(data []byte) (uint64, uint64, error) {
if len(data) < 9 {
return 0, 0, fmt.Errorf("data too short for buy args")
return 0, 0, fmt.Errorf("data too short for pump buy buy args, len=%d", len(data))
}
var args pumpBuyArgs
@@ -507,7 +502,7 @@ func parsePumpBuy(tx *versionedTransaction, instruction *compiledInstruction) (*
func decodePumpSellArgs(data []byte) (uint64, uint64, error) {
if len(data) < 9 {
return 0, 0, fmt.Errorf("data too short for sell args")
return 0, 0, fmt.Errorf("data too short for pump sell sell args, len=%d", len(data))
}
var args pumpExtendedSellArgs
@@ -597,7 +592,7 @@ func parseAzczAmmBuy(tx *versionedTransaction, instructionIndex int) (*TxSignal,
}
if len(instruction.Data) < 17 {
return nil, fmt.Errorf("data too short for buy args")
return nil, fmt.Errorf("data too short for azcz amm buy args, len=%d", len(instruction.Data))
}
solAmount := binary.LittleEndian.Uint64(instruction.Data[1:9])
@@ -637,7 +632,7 @@ func parseAzczBuy(tx *versionedTransaction, instructionIndex int) (*TxSignal, er
}
if len(instruction.Data) < 2 {
return nil, fmt.Errorf("data too short for buy args")
return nil, fmt.Errorf("data too short for azcz buy args len=%d", len(instruction.Data))
}
var args azczBuyArgs
@@ -691,7 +686,7 @@ func parseF5tfInstruction(tx *versionedTransaction, instructionIndex int) (*TxSi
}
if len(instruction.Data) < 2 {
return nil, fmt.Errorf("data too short for buy args")
return nil, fmt.Errorf("data too short for f5tf buy args len=%d", len(instruction.Data))
}
var args f5tfBuyArgs
@@ -726,8 +721,11 @@ func parseFlasInstruction(tx *versionedTransaction, instructionIndex int) (*TxSi
if len(instruction.Data) == 0 {
return nil, fmt.Errorf("data is empty")
}
if len(instruction.Data) == 10 && instruction.Data[0] == 1 {
return nil, nil
}
if len(instruction.Data) < 20 {
return nil, fmt.Errorf("data too short for args")
return nil, fmt.Errorf("data too short for args flas instruction, len: %d", len(instruction.Data))
}
methodData := instruction.Data[17:20]
if !matchMethod(methodData, flasBuyTokensIX) {
@@ -929,7 +927,7 @@ func parsePhotonBuy(tx *versionedTransaction, instruction *compiledInstruction)
return nil, fmt.Errorf("accounts too short")
}
if len(instruction.Data) < 16 {
return nil, fmt.Errorf("data too short for buy args")
return nil, fmt.Errorf("data too short for photon buy args, len=%d", len(instruction.Data))
}
staticKeys := tx.Message.StaticAccountKeys
@@ -970,7 +968,7 @@ func parsePhotonSwap(tx *versionedTransaction, instruction *compiledInstruction)
return nil, fmt.Errorf("accounts too short")
}
if len(instruction.Data) < 16 {
return nil, fmt.Errorf("data too short for swap args")
return nil, fmt.Errorf("data too short for swap args for photon. len=%d", len(instruction.Data))
}
staticKeys := tx.Message.StaticAccountKeys
@@ -979,12 +977,11 @@ func parsePhotonSwap(tx *versionedTransaction, instruction *compiledInstruction)
return nil, err
}
quoteIndex := int(instruction.Accounts[4])
quote, err := resolveQuoteAccount(tx, quoteIndex, []string{photonTableLookup}, 0)
quote, err := getStaticKey(staticKeys, int(instruction.Accounts[4]))
if err != nil {
return nil, err
}
if quote != wsolMint {
if !quote.Equals(solana.WrappedSol) {
return nil, nil
}
@@ -1173,7 +1170,7 @@ func parseTermSell(tx *versionedTransaction, instruction *compiledInstruction) (
func decodePumpAmmBuyArgs(data []byte) (uint64, uint64, error) {
if len(data) < 9 {
return 0, 0, fmt.Errorf("data too short for buy args")
return 0, 0, fmt.Errorf("data too short for pump amm buy args, len=%d", len(data))
}
var args pumpAmmBuyArgs
@@ -1212,12 +1209,11 @@ func parsePumpAmmBuy(tx *versionedTransaction, instruction *compiledInstruction)
if err != nil {
return nil, err
}
quoteIndex := int(instruction.Accounts[4])
quote, err := resolveQuoteAccount(tx, quoteIndex, nil, 0)
quote, err := getStaticKey(staticKeys, int(instruction.Accounts[4]))
if err != nil {
return nil, err
}
if quote != wsolMint {
if !quote.Equals(solana.WrappedSol) {
return nil, nil
}
@@ -1259,12 +1255,11 @@ func parsePumpAmmSell(tx *versionedTransaction, instruction *compiledInstruction
if err != nil {
return nil, err
}
quoteIndex := int(instruction.Accounts[4])
quote, err := resolveQuoteAccount(tx, quoteIndex, nil, 0)
quote, err := getStaticKey(staticKeys, int(instruction.Accounts[4]))
if err != nil {
return nil, err
}
if quote != wsolMint {
if !quote.Equals(solana.WrappedSol) {
return nil, nil
}
@@ -1308,7 +1303,7 @@ func parseBoboInstruction(tx *versionedTransaction, instructionIndex int) (*TxSi
return nil, fmt.Errorf("accounts too short")
}
if len(instruction.Data) < 16 {
return nil, fmt.Errorf("data too short for buy args")
return nil, fmt.Errorf("data too short for bobo buy args, len=%d", len(instruction.Data))
}
staticKeys := tx.Message.StaticAccountKeys
@@ -1371,7 +1366,7 @@ func parseQtkvSell(tx *versionedTransaction, instructionIndex int) (*TxSignal, e
return nil, fmt.Errorf("accounts too short")
}
if len(instruction.Data) < 24 {
return nil, fmt.Errorf("data too short for sell args")
return nil, fmt.Errorf("data too short for qtkv sell args, len=%d", len(instruction.Data))
}
staticKeys := tx.Message.StaticAccountKeys
@@ -1409,7 +1404,7 @@ func parseQtkvAmmSell(tx *versionedTransaction, instructionIndex int) (*TxSignal
return nil, fmt.Errorf("accounts too short")
}
if len(instruction.Data) < 24 {
return nil, fmt.Errorf("data too short for sell args")
return nil, fmt.Errorf("data too short for qtkv amm sell args, len=%d", len(instruction.Data))
}
staticKeys := tx.Message.StaticAccountKeys
@@ -1497,7 +1492,7 @@ func parseFjszInstruction(tx *versionedTransaction, instructionIndex int) (*TxSi
return nil, fmt.Errorf("accounts too short")
}
if len(instruction.Data) < 16 {
return nil, fmt.Errorf("data too short for buy args")
return nil, fmt.Errorf("data too short for fjzs buy args, len=%d", len(instruction.Data))
}
staticKeys := tx.Message.StaticAccountKeys
@@ -1553,43 +1548,6 @@ func parseTerminalInstruction(tx *versionedTransaction, instructionIndex int) (*
return nil, nil
}
func resolveQuoteAccount(tx *versionedTransaction, quoteIndex int, expectedTableKeys []string, targetIndex uint8) (string, error) {
staticKeys := tx.Message.StaticAccountKeys
if quoteIndex < len(staticKeys) {
quoteKey := staticKeys[quoteIndex].String()
return quoteKey, nil
}
// attempt to load from address table lookup
if len(expectedTableKeys) == 0 || len(tx.Message.AddressTableLookups) != 1 {
return "", fmt.Errorf("parse quote from table lookup failed")
}
table := tx.Message.AddressTableLookups[0]
match := false
for _, key := range expectedTableKeys {
if table.AccountKey.String() == key {
match = true
break
}
}
if !match {
return "", fmt.Errorf("parse quote from table lookup failed")
}
indexOfTarget := indexOf(table.ReadonlyIndexes, targetIndex)
if indexOfTarget < 0 {
return "", fmt.Errorf("parse quote from table lookup failed")
}
expectedIndex := len(staticKeys) + len(table.WritableIndexes) + indexOfTarget
if quoteIndex != expectedIndex {
return "", fmt.Errorf("parse quote from table lookup failed")
}
return wsolMint, nil
}
func indexOf(haystack []uint8, needle uint8) int {
for i, v := range haystack {
if v == needle {