Skip to content

Commit 1d0af27

Browse files
0xrinegadeclaude
andcommitted
fix(stream): CRITICAL - Use TokenTransfer events instead of log parsing
MAJOR REWRITE of stream_pumpfun.ovsm - previous version was fundamentally broken: PROBLEMS FIXED: - ❌ Token mints were 'Unknown' (they're in account keys, not logs) - ❌ Insane amounts like 5.1 trillion tokens (parsing wrong bytes) - ❌ Program IDs shown as wallets (TokenzQdBN... is not a wallet) - ❌ SOL amounts always 'Unknown' (not in log messages) NEW APPROACH: ✅ Use TokenTransfer events (provides: from, to, token, amount, decimals) ✅ Real token mints from parsed events ✅ Accurate amounts (already parsed by stream service) ✅ Keep log_message events only for Buy/Sell/Graduation detection AVAILABLE EVENT TYPES: - transaction: Full tx metadata (signer, program_ids, fee) - account_update: Balance changes - log_message: Program logs (limited data) - token_transfer: Parsed transfers (BEST for token data) - program_invocation: Instruction data + accounts - slot_update: Block updates Result: Clean, accurate Pump.fun monitoring with real data 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent debcc0e commit 1d0af27

File tree

1 file changed

+66
-174
lines changed

1 file changed

+66
-174
lines changed

examples/ovsm_scripts/stream_pumpfun.ovsm

Lines changed: 66 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
1-
;;; Stream Pump.fun Events - PRODUCTION FORENSICS TOOL v2
1+
;;; Stream Pump.fun Events - PRODUCTION FORENSICS TOOL v3
22
;;;
3-
;;; Clean, professional output for blockchain investigation
3+
;;; REWRITTEN: Now uses TokenTransfer events (not logs!)
44
;;; - Full addresses (no truncation)
5-
;;; - Token mints and amounts
5+
;;; - Actual token mints from transfer events
6+
;;; - Real token amounts (not parsed from binary)
67
;;; - Clean single-line output format
78
;;;
89
;;; Usage:
910
;;; 1. Start: osvm stream --programs pumpfun --port 8080
10-
;;; 2. Run: osvm ovsm run stream_pumpfun_v2.ovsm
11+
;;; 2. Run: osvm ovsm run stream_pumpfun.ovsm
1112

1213
(define stream-id (stream-connect "http://localhost:8080" :programs ["pumpfun"]))
1314

1415
(println "")
1516
(println "═══════════════════════════════════════════════════════════════")
16-
(println " OSVM PUMP.FUN FORENSICS MONITOR")
17-
(println " Connected to event stream - monitoring transactions...")
17+
(println " OSVM PUMP.FUN FORENSICS MONITOR V3")
18+
(println " Using TokenTransfer events for accurate data")
1819
(println "═══════════════════════════════════════════════════════════════")
1920
(println "")
2021

2122
;; Initialize counters
2223
(define buy-count 0)
2324
(define sell-count 0)
2425
(define graduation-count 0)
26+
(define transfer-count 0)
2527

2628
;; Main event loop (60 seconds)
2729
(define start-time (now))
@@ -33,186 +35,66 @@
3335
(for (event events)
3436
(define event-type (get event "type"))
3537

36-
(if (= event-type "log_message")
38+
;; ═══════════════════════════════════════════════════════════
39+
;; PROCESS TOKEN TRANSFER EVENTS (BEST SOURCE OF DATA)
40+
;; ═══════════════════════════════════════════════════════════
41+
(if (= event-type "token_transfer")
3742
(do
38-
(define logs (get event "logs"))
43+
(set! transfer-count (+ transfer-count 1))
3944
(define signature (get event "signature"))
40-
(define slot (get event "slot"))
41-
(define logs-text (str logs))
42-
43-
;; Extract wallet from first invoke [1]
44-
(define wallet "Unknown")
45-
(for (line logs)
46-
(if (and (string-contains line "invoke [1]")
47-
(not (string-contains line "ComputeBudget"))
48-
(not (string-contains line "11111111")))
49-
(do
50-
(define parts (split line " "))
51-
(if (>= (length parts) 2)
52-
(set! wallet (get parts 1))
53-
null))
54-
null))
55-
56-
;; Extract program ID
57-
(define program-id "Unknown")
58-
(define program-name "Unknown")
59-
(for (line logs)
60-
(if (and (string-contains line "invoke [1]")
61-
(not (string-contains line "ComputeBudget"))
62-
(not (string-contains line "11111111")))
63-
(do
64-
(define parts (split line " "))
65-
(if (>= (length parts) 2)
66-
(do
67-
(set! program-id (get parts 1))
68-
(if (string-contains program-id "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
69-
(set! program-name "Pump.fun Core") null)
70-
(if (string-contains program-id "MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e")
71-
(set! program-name "Pump.fun Wrapper") null)
72-
(if (string-contains program-id "BLUR9cL8HqZzu5bSaC7VRX25RCG93Hv3T6NPyKxQhWUT")
73-
(set! program-name "BLUR Bot") null)
74-
(if (string-contains program-id "GMgnVFR8Jb39LoXsEVzb3DvBy3ywCmdmJquHUy1Lrkqb")
75-
(set! program-name "GMgn Bot") null))
76-
null))
77-
null))
78-
79-
;; Extract SOL amount
80-
(define sol-amount "Unknown")
81-
(for (line logs)
82-
(if (string-contains line "sol_received:")
83-
(do
84-
(define parts (split line ":"))
85-
(if (>= (length parts) 3)
86-
(do
87-
(define amount-str (get parts 2))
88-
(define amount-parts (split amount-str ","))
89-
(if (>= (length amount-parts) 1)
90-
(set! sol-amount (get amount-parts 0))
91-
null))
92-
null))
93-
null))
94-
95-
;; Extract token program
96-
(define token-program "Unknown")
97-
(for (line logs)
98-
(if (string-contains line "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb")
99-
(set! token-program "Token2022") null)
100-
(if (string-contains line "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
101-
(set! token-program "SPL Token") null))
102-
103-
;; Extract token mint and amount from logs
104-
;; PUMP.FUN TOKEN MINTS ALL END WITH "pump"!
105-
(define token-mint "Unknown")
106-
(define token-amount "Unknown")
107-
(define program-data-b64 "")
108-
109-
;; Strategy 1: Look for base58 addresses ending in "pump"
110-
;; These are Pump.fun token mints created via bonding curve
111-
(for (line logs)
112-
;; Check ALL lines for addresses ending in "pump"
113-
(define parts (split line " "))
114-
(for (part parts)
115-
;; Check if this part is a long base58 address ending in "pump"
116-
(if (and (> (length part) 32)
117-
(string-contains part "pump"))
118-
(do
119-
;; Additional check: must END with "pump" not just contain it
120-
;; Get last 4 chars
121-
(define part-len (length part))
122-
(if (>= part-len 4)
123-
(do
124-
(define last-4 (substring part (- part-len 4) part-len))
125-
(if (= last-4 "pump")
126-
(set! token-mint part)
127-
null))
128-
null))
129-
null))
130-
131-
;; Strategy 2: Extract "Program data:" for amount decoding
132-
(if (string-contains line "Program data:")
133-
(do
134-
(define parts (split line ":"))
135-
(if (>= (length parts) 2)
136-
(do
137-
;; Get the base64 part (after "Program data:")
138-
(define data-part (get parts 1))
139-
;; MUST trim whitespace before base64-decode
140-
(set! program-data-b64 (trim data-part)))
141-
null))
142-
null))
143-
144-
;; Strategy 3: Decode Program data to extract token amount (Borsh format)
145-
;; Pump.fun Borsh structure:
146-
;; - Bytes 0-7: Unknown/discriminator
147-
;; - Bytes 8-15: Token amount (u64 little-endian)
148-
;; - Bytes 16+: Other bonding curve state
149-
(if (> (length program-data-b64) 0)
45+
(define from-wallet (get event "from"))
46+
(define to-wallet (get event "to"))
47+
(define token-mint (get event "token"))
48+
(define amount (get event "amount"))
49+
(define decimals (get event "decimals"))
50+
51+
;; Check if this is a Pump.fun token (ends with "pump")
52+
(define is-pumpfun-token false)
53+
(if (> (length token-mint) 4)
15054
(do
151-
;; base64-decode-raw returns hex string (binary-safe)
152-
(define hex-data (base64-decode-raw program-data-b64))
153-
154-
;; Pump.fun Borsh layout - try common offsets
155-
;; Offset 8 = token amount (most common)
156-
(if (>= (length hex-data) 32) ;; 32 hex chars = 16 bytes minimum
157-
(do
158-
;; Parse u64 at byte offset 8 (= hex offset 16)
159-
(define amount-raw (hex-to-u64-le hex-data 8))
160-
;; Format with decimals (Pump.fun tokens usually have 6 decimals)
161-
(define amount-float (/ amount-raw 1000000.0))
162-
(set! token-amount (str amount-float " tokens (raw: " amount-raw ")")))
163-
(set! token-amount (str "Program data too short: " (length hex-data) " hex chars"))))
55+
(define mint-len (length token-mint))
56+
(define last-4 (substring token-mint (- mint-len 4) mint-len))
57+
(if (= last-4 "pump")
58+
(set! is-pumpfun-token true)
59+
null))
16460
null)
16561

166-
;; Try to find token_transfer event as fallback
167-
(for (evt events)
168-
(if (= (get evt "type") "token_transfer")
169-
(do
170-
(if (= (get evt "signature") signature)
171-
(do
172-
(set! token-mint (get evt "token"))
173-
(set! token-amount (str (get evt "amount") " (decimals: " (get evt "decimals") ")")))
174-
null))
175-
null))
176-
177-
;; Display BUY transactions
178-
(if (string-contains logs-text "Instruction: Buy")
62+
;; Only display Pump.fun token transfers
63+
(if is-pumpfun-token
17964
(do
180-
(set! buy-count (+ buy-count 1))
18165
(println "")
18266
(println "═══════════════════════════════════════════════════════════════")
183-
(println (str "📈 BUY #" buy-count " | Slot: " slot " | Time: " (now)))
67+
(println (str "💸 TOKEN TRANSFER #" transfer-count " | Time: " (now)))
18468
(println "═══════════════════════════════════════════════════════════════")
18569
(println (str "Signature: " signature))
186-
(println (str "Wallet: " wallet))
187-
(println (str "Program: " program-name " (" program-id ")"))
188-
(println (str "Token Std: " token-program))
70+
(println (str "From: " from-wallet))
71+
(println (str "To: " to-wallet))
18972
(println (str "Token Mint: " token-mint))
190-
(println (str "Token Amount: " token-amount))
191-
(println (str "SOL Spent: " sol-amount " lamports"))
73+
(println (str "Amount: " amount " (decimals: " decimals ")"))
19274
(println (str "osvm.ai: https://osvm.ai/tx/" signature))
19375
(println "═══════════════════════════════════════════════════════════════"))
76+
null))
77+
null)
78+
79+
;; ═══════════════════════════════════════════════════════════
80+
;; PROCESS LOG MESSAGES (FOR BUY/SELL/GRADUATION DETECTION)
81+
;; ═══════════════════════════════════════════════════════════
82+
(if (= event-type "log_message")
83+
(do
84+
(define logs (get event "logs"))
85+
(define signature (get event "signature"))
86+
(define slot (get event "slot"))
87+
(define logs-text (str logs))
88+
89+
;; Detect transaction type from logs
90+
(if (string-contains logs-text "Instruction: Buy")
91+
(set! buy-count (+ buy-count 1))
19492
null)
19593

196-
;; Display SELL transactions
19794
(if (string-contains logs-text "Instruction: Sell")
198-
(do
199-
(set! sell-count (+ sell-count 1))
200-
(println "")
201-
(println "═══════════════════════════════════════════════════════════════")
202-
(println (str "📉 SELL #" sell-count " | Slot: " slot " | Time: " (now)))
203-
(println "═══════════════════════════════════════════════════════════════")
204-
(println (str "Signature: " signature))
205-
(println (str "Wallet: " wallet))
206-
(println (str "Program: " program-name " (" program-id ")"))
207-
(println (str "Token Std: " token-program))
208-
(println (str "Token Mint: " token-mint))
209-
(println (str "Token Amount: " token-amount))
210-
(println (str "SOL Received: " sol-amount " lamports"))
211-
(println (str "osvm.ai: https://osvm.ai/tx/" signature))
212-
(println "═══════════════════════════════════════════════════════════════"))
95+
(set! sell-count (+ sell-count 1))
21396
null)
21497

215-
;; Display graduations
21698
(if (or (string-contains logs-text "raydium")
21799
(string-contains logs-text "Instruction: Graduate"))
218100
(do
@@ -222,10 +104,19 @@
222104
(println (str "🎓 TOKEN GRADUATION #" graduation-count " - MIGRATING TO RAYDIUM 🚀"))
223105
(println "🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓")
224106
(println (str "Signature: " signature))
225-
(println (str "Token: " token-mint))
107+
(println (str "Slot: " slot))
226108
(println (str "osvm.ai: https://osvm.ai/tx/" signature))
227109
(println "🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓🎓"))
228110
null))
111+
null)
112+
113+
;; ═══════════════════════════════════════════════════════════
114+
;; PROCESS TRANSACTION EVENTS (FOR WALLET/PROGRAM INFO)
115+
;; ═══════════════════════════════════════════════════════════
116+
(if (= event-type "transaction")
117+
(do
118+
;; Future enhancement: Extract signer, program_ids, fees
119+
null)
229120
null)))
230121

231122
;; Summary
@@ -234,11 +125,12 @@
234125
(println "═══════════════════════════════════════════════════════════════")
235126
(println " FORENSICS SUMMARY")
236127
(println "═══════════════════════════════════════════════════════════════")
237-
(println (str "Duration: " duration " seconds"))
238-
(println (str "Buy Txs: " buy-count))
239-
(println (str "Sell Txs: " sell-count))
240-
(println (str "Graduations: " graduation-count))
241-
(println (str "Total Events: " (+ buy-count sell-count graduation-count)))
128+
(println (str "Duration: " duration " seconds"))
129+
(println (str "Buy Txs: " buy-count))
130+
(println (str "Sell Txs: " sell-count))
131+
(println (str "Token Transfers: " transfer-count))
132+
(println (str "Graduations: " graduation-count))
133+
(println (str "Total Events: " (+ buy-count sell-count graduation-count transfer-count)))
242134
(println "═══════════════════════════════════════════════════════════════")
243135

244136
(stream-close stream-id)

0 commit comments

Comments
 (0)