98 lines
2.7 KiB
Go
98 lines
2.7 KiB
Go
|
|
package pump_parser
|
||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
|
||
|
|
"github.com/gagliardetto/solana-go"
|
||
|
|
"github.com/shopspring/decimal"
|
||
|
|
)
|
||
|
|
|
||
|
|
var swapPrograms = map[solana.PublicKey]swapParser{
|
||
|
|
pumpAmmProgram: pumpAmmParser,
|
||
|
|
pumpProgram: pumpParser,
|
||
|
|
}
|
||
|
|
|
||
|
|
var actionPrograms = map[solana.PublicKey]actionParser{
|
||
|
|
systemProgram: systemParser,
|
||
|
|
budgGetProgram: budgetParser,
|
||
|
|
}
|
||
|
|
|
||
|
|
func Parser(rawTx *RawTx) (*Tx, error) {
|
||
|
|
accountList := rawTx.getAccountList()
|
||
|
|
var tx = &Tx{
|
||
|
|
TxHash: (*[64]byte)((rawTx.Transaction.Signatures[0][:])),
|
||
|
|
Signer: rawTx.GetSigner(),
|
||
|
|
Block: rawTx.Slot,
|
||
|
|
BlockIndex: uint64(rawTx.IndexWithinBlock),
|
||
|
|
BlockAt: rawTx.BlockTime,
|
||
|
|
|
||
|
|
BeforeSolBalance: decimal.NewFromUint64(rawTx.Meta.PreBalances[0]).Div(decimal.NewFromInt(1e9)),
|
||
|
|
AfterSOLBalance: decimal.NewFromUint64(rawTx.Meta.PostBalances[0]).Div(decimal.NewFromInt(1e9)),
|
||
|
|
}
|
||
|
|
var innersMap = make(map[int]InnerInstructions)
|
||
|
|
for _, inner := range rawTx.Meta.InnerInstructions {
|
||
|
|
innersMap[inner.Index] = inner
|
||
|
|
}
|
||
|
|
for i, instr := range rawTx.Transaction.Message.Instructions {
|
||
|
|
programAccount := accountList[instr.ProgramIDIndex]
|
||
|
|
if p, exists := swapPrograms[programAccount]; exists {
|
||
|
|
swaps, _, err := p(rawTx, instr, innersMap[i], [2]uint{uint(i), uint(0)})
|
||
|
|
if err != nil {
|
||
|
|
if errors.Is(err, InstructionIgnoredError) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
tx.Swaps = append(tx.Swaps, swaps...)
|
||
|
|
} else if p, exists := actionPrograms[programAccount]; exists {
|
||
|
|
_, err := p(rawTx, instr, innersMap[i], [2]uint{uint(i), uint(0)}, tx)
|
||
|
|
if err != nil {
|
||
|
|
if errors.Is(err, InstructionIgnoredError) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
ii := i
|
||
|
|
// unknown program, parser inner instructions
|
||
|
|
innerLength := len(innersMap[i].Instructions)
|
||
|
|
for j := 1; j <= innerLength; {
|
||
|
|
innerInstr := innersMap[i].Instructions[j-1]
|
||
|
|
innerProgramAccount := accountList[innerInstr.ProgramIDIndex]
|
||
|
|
|
||
|
|
if p, exists := swapPrograms[innerProgramAccount]; exists {
|
||
|
|
swaps, offset, err := p(rawTx, innerInstr, innersMap[i], [2]uint{uint(i), uint(j)})
|
||
|
|
if err != nil {
|
||
|
|
if errors.Is(err, InstructionIgnoredError) {
|
||
|
|
j = int(offset[1])
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
tx.Swaps = append(tx.Swaps, swaps...)
|
||
|
|
j = int(offset[1])
|
||
|
|
ii = int(offset[0])
|
||
|
|
} else if p, exists := actionPrograms[innerProgramAccount]; exists {
|
||
|
|
offset, err := p(rawTx, innerInstr, innersMap[i], [2]uint{uint(i), uint(j)}, tx)
|
||
|
|
if err != nil {
|
||
|
|
if errors.Is(err, InstructionIgnoredError) {
|
||
|
|
j = int(offset[1])
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
j = int(offset[1])
|
||
|
|
ii = int(offset[0])
|
||
|
|
} else {
|
||
|
|
j++
|
||
|
|
}
|
||
|
|
if j > innerLength || ii > i {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return tx, nil
|
||
|
|
}
|