Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | 1x 1x 1x 1x 1x 1x 1x | import base58 from 'bs58';
import { Buffer } from 'buffer';
import { DEX_PROGRAMS, DISCRIMINATORS } from '../../constants';
import { InstructionClassifier } from '../../instruction-classifier';
import { TransactionAdapter } from '../../transaction-adapter';
import {
ClassifiedInstruction,
EventParser,
PumpfunCompleteEvent,
PumpfunCreateEvent,
PumpfunEvent,
PumpfunTradeEvent,
} from '../../types';
import { getInstructionData } from '../../utils';
import { BinaryReader } from '../binary-reader';
export class PumpfunEventParser {
constructor(private readonly adapter: TransactionAdapter) {}
private readonly eventParsers: Record<string, EventParser<any>> = {
TRADE: {
discriminator: DISCRIMINATORS.PUMPFUN.TRADE_EVENT,
decode: this.decodeTradeEvent.bind(this),
},
CREATE: {
discriminator: DISCRIMINATORS.PUMPFUN.CREATE_EVENT,
decode: this.decodeCreateEvent.bind(this),
},
COMPLETE: {
discriminator: DISCRIMINATORS.PUMPFUN.COMPLETE_EVENT,
decode: this.decodeCompleteEvent.bind(this),
},
};
public processEvents(): PumpfunEvent[] {
const instructions = new InstructionClassifier(this.adapter).getInstructions(DEX_PROGRAMS.PUMP_FUN.id);
return this.parseInstructions(instructions);
}
public parseInstructions(instructions: ClassifiedInstruction[]): PumpfunEvent[] {
return instructions
.map(({ instruction, outerIndex, innerIndex }) => {
try {
const data = getInstructionData(instruction);
const discriminator = Buffer.from(data.slice(0, 16));
for (const [type, parser] of Object.entries(this.eventParsers)) {
Iif (discriminator.equals(parser.discriminator)) {
const eventData = parser.decode(data.slice(16));
Iif (!eventData) return null;
return {
type: type as 'TRADE' | 'CREATE' | 'COMPLETE',
data: eventData,
slot: this.adapter.slot,
timestamp: this.adapter.blockTime || 0,
signature: this.adapter.signature,
idx: `${outerIndex}-${innerIndex ?? 0}`,
};
}
}
} catch (error) {
console.error('Failed to parse Pumpfun event:', error);
}
return null;
})
.filter((event): event is PumpfunEvent => event !== null);
}
private decodeTradeEvent(data: Buffer): PumpfunTradeEvent {
const reader = new BinaryReader(data);
return {
mint: base58.encode(Buffer.from(reader.readFixedArray(32))),
solAmount: reader.readU64(),
tokenAmount: reader.readU64(),
isBuy: reader.readU8() === 1,
user: base58.encode(reader.readFixedArray(32)),
timestamp: reader.readI64(),
virtualSolReserves: reader.readU64(),
virtualTokenReserves: reader.readU64(),
};
}
private decodeCreateEvent(data: Buffer): PumpfunCreateEvent {
const reader = new BinaryReader(data);
return {
name: reader.readString(),
symbol: reader.readString(),
uri: reader.readString(),
mint: base58.encode(Buffer.from(reader.readFixedArray(32))),
bondingCurve: base58.encode(reader.readFixedArray(32)),
user: base58.encode(reader.readFixedArray(32)),
};
}
private decodeCompleteEvent(data: Buffer): PumpfunCompleteEvent {
const reader = new BinaryReader(data);
return {
user: base58.encode(reader.readFixedArray(32)),
mint: base58.encode(Buffer.from(reader.readFixedArray(32))),
bondingCurve: base58.encode(reader.readFixedArray(32)),
timestamp: reader.readI64(),
};
}
}
|