sol-parser-sdk-python 0.5.6__py3-none-any.whl → 0.5.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -102,17 +102,23 @@ _DISC_CLMM_SWAP_V2 = _d(43, 4, 237, 11, 26, 201, 30, 98)
102
102
  _DISC_CLMM_INC_LIQ = _d(133, 29, 89, 223, 69, 238, 176, 10)
103
103
  _DISC_CLMM_DEC_LIQ = _d(58, 127, 188, 62, 79, 82, 196, 96)
104
104
  _DISC_CLMM_CREATE = _d(233, 146, 209, 142, 207, 104, 64, 188)
105
+ _DISC_CLMM_CREATE_CUSTOMIZABLE_POOL = _d(43, 68, 212, 167, 89, 47, 164, 1)
106
+ _DISC_CLMM_OPEN_POSITION = _d(135, 128, 47, 77, 15, 152, 240, 49)
105
107
  _DISC_CLMM_OPEN_POSITION_V2 = _d(77, 184, 74, 214, 112, 86, 241, 199)
106
108
  _DISC_CLMM_OPEN_POSITION_WITH_TOKEN_22_NFT = _d(77, 255, 174, 82, 125, 29, 201, 46)
107
109
  _DISC_CLMM_CLOSE_POSITION = _d(123, 134, 81, 0, 49, 68, 98, 98)
108
110
 
109
111
  _DISC_CPMM_SWAP = _d(143, 190, 90, 218, 196, 30, 51, 222)
112
+ _DISC_CPMM_SWAP_OUT = _d(55, 217, 98, 86, 163, 74, 180, 173)
113
+ _DISC_CPMM_INITIALIZE = _d(175, 175, 109, 31, 13, 152, 155, 237)
110
114
  _DISC_CPMM_DEP = _d(242, 35, 198, 137, 82, 225, 242, 182)
111
115
  _DISC_CPMM_WIT = _d(183, 18, 70, 156, 148, 109, 161, 34)
112
116
 
113
- _DISC_ORCA_SWAP = _d(225, 202, 73, 175, 147, 43, 160, 150)
114
- _DISC_ORCA_INC_LIQ = _d(30, 7, 144, 181, 102, 254, 155, 161)
115
- _DISC_ORCA_DEC_LIQ = _d(166, 1, 36, 71, 112, 202, 181, 171)
117
+ _DISC_ORCA_SWAP = _d(248, 198, 158, 145, 225, 117, 135, 200)
118
+ _DISC_ORCA_SWAP_V2 = _d(43, 4, 237, 11, 26, 201, 30, 98)
119
+ _DISC_ORCA_INC_LIQ = _d(46, 156, 243, 118, 13, 205, 251, 178)
120
+ _DISC_ORCA_DEC_LIQ = _d(160, 38, 208, 111, 104, 91, 44, 1)
121
+ _DISC_ORCA_INIT_POOL = _d(17, 43, 80, 74, 168, 202, 6, 113)
116
122
 
117
123
  _DISC_RAYDIUM_LAUNCHLAB_TRADE = _d(189, 219, 127, 211, 78, 230, 97, 238)
118
124
  _DISC_RAYDIUM_LAUNCHLAB_POOL_CREATE = _d(151, 215, 226, 9, 118, 161, 115, 174)
@@ -129,11 +135,13 @@ _IX_RAYDIUM_LAUNCHLAB_SELL_EXACT_OUT = _d(95, 200, 71, 34, 8, 9, 11, 166)
129
135
  _DISC_PFEES_CREATE_FEE_SHARING = _d(195, 78, 86, 76, 111, 52, 251, 213)
130
136
  _DISC_PFEES_INITIALIZE_FEE_CONFIG = _d(62, 162, 20, 133, 121, 65, 145, 27)
131
137
  _DISC_PFEES_RESET_FEE_SHARING = _d(10, 2, 182, 95, 16, 127, 129, 186)
138
+ _DISC_PFEES_RESET_FEE_SHARING_V2 = _d(169, 245, 17, 209, 94, 91, 248, 128)
132
139
  _DISC_PFEES_REVOKE_FEE_SHARING = _d(18, 233, 158, 39, 185, 207, 58, 104)
133
140
  _DISC_PFEES_TRANSFER_FEE_SHARING = _d(202, 10, 75, 200, 164, 34, 210, 96)
134
141
  _DISC_PFEES_UPDATE_ADMIN = _d(161, 176, 40, 213, 60, 184, 179, 228)
135
142
  _DISC_PFEES_UPDATE_FEE_CONFIG = _d(104, 184, 103, 242, 88, 151, 107, 20)
136
143
  _DISC_PFEES_UPDATE_FEE_SHARES = _d(189, 13, 136, 99, 187, 164, 237, 35)
144
+ _DISC_PFEES_UPDATE_FEE_SHARES_V2 = _d(111, 251, 49, 6, 78, 78, 106, 18)
137
145
  _DISC_PFEES_UPSERT_FEE_TIERS = _d(227, 23, 150, 12, 77, 86, 94, 4)
138
146
 
139
147
  _DISC_PUMPFUN_CREATE = _d(24, 30, 200, 40, 5, 28, 7, 119)
@@ -304,6 +312,133 @@ def parse_instruction_unified(
304
312
  return None
305
313
 
306
314
 
315
+ def _disc8(instruction_data: bytes) -> Optional[int]:
316
+ if len(instruction_data) < 8:
317
+ return None
318
+ return struct.unpack_from("<Q", instruction_data, 0)[0]
319
+
320
+
321
+ def normal_instruction_data_may_parse(program_id: str, instruction_data: bytes) -> bool:
322
+ if not instruction_data:
323
+ return False
324
+ if program_id == RAYDIUM_AMM_V4_PROGRAM_ID:
325
+ return instruction_data[0] in (1, 3, 4, 7, 9, 11)
326
+ if program_id == METEORA_DLMM_PROGRAM_ID:
327
+ return instruction_data[0] in (0, 1, 2, 7, 8, 11, 13, 14)
328
+ disc = _disc8(instruction_data)
329
+ if disc is None:
330
+ return False
331
+ if program_id == METEORA_DAMM_V2_PROGRAM_ID:
332
+ return disc == _DISC_DAMM_INIT
333
+ if program_id == PUMPFUN_PROGRAM_ID:
334
+ return disc in (
335
+ _DISC_PUMPFUN_CREATE,
336
+ _DISC_PUMPFUN_CREATE_V2,
337
+ _DISC_PUMPFUN_BUY,
338
+ _DISC_PUMPFUN_SELL,
339
+ _DISC_PUMPFUN_BUY_EXACT_SOL_IN,
340
+ _DISC_PUMPFUN_BUY_V2,
341
+ _DISC_PUMPFUN_BUY_EXACT_QUOTE_IN_V2,
342
+ _DISC_PUMPFUN_SELL_V2,
343
+ )
344
+ if program_id == PUMPSWAP_PROGRAM_ID:
345
+ return disc in (
346
+ _DISC_PUMPSWAP_BUY,
347
+ _DISC_PUMPSWAP_SELL,
348
+ _d(233, 146, 209, 142, 207, 104, 64, 188),
349
+ _DISC_PUMPSWAP_BUY_EXACT_QUOTE_IN,
350
+ _d(242, 35, 198, 137, 82, 225, 242, 182),
351
+ _d(183, 18, 70, 156, 148, 109, 161, 34),
352
+ )
353
+ if program_id == PUMP_FEES_PROGRAM_ID:
354
+ return disc in (
355
+ _DISC_PFEES_CREATE_FEE_SHARING,
356
+ _DISC_PFEES_INITIALIZE_FEE_CONFIG,
357
+ _DISC_PFEES_RESET_FEE_SHARING,
358
+ _DISC_PFEES_RESET_FEE_SHARING_V2,
359
+ _DISC_PFEES_REVOKE_FEE_SHARING,
360
+ _DISC_PFEES_TRANSFER_FEE_SHARING,
361
+ _DISC_PFEES_UPDATE_ADMIN,
362
+ _DISC_PFEES_UPDATE_FEE_CONFIG,
363
+ _DISC_PFEES_UPDATE_FEE_SHARES,
364
+ _DISC_PFEES_UPDATE_FEE_SHARES_V2,
365
+ _DISC_PFEES_UPSERT_FEE_TIERS,
366
+ )
367
+ if program_id == RAYDIUM_LAUNCHLAB_PROGRAM_ID:
368
+ return disc in (
369
+ _IX_RAYDIUM_LAUNCHLAB_BUY_EXACT_IN,
370
+ _IX_RAYDIUM_LAUNCHLAB_BUY_EXACT_OUT,
371
+ _IX_RAYDIUM_LAUNCHLAB_SELL_EXACT_IN,
372
+ _IX_RAYDIUM_LAUNCHLAB_SELL_EXACT_OUT,
373
+ _IX_RAYDIUM_LAUNCHLAB_INITIALIZE,
374
+ _IX_RAYDIUM_LAUNCHLAB_INITIALIZE_V2,
375
+ _IX_RAYDIUM_LAUNCHLAB_INITIALIZE_WITH_TOKEN_2022,
376
+ )
377
+ if program_id == RAYDIUM_CPMM_PROGRAM_ID:
378
+ return disc in (
379
+ _DISC_CPMM_SWAP,
380
+ _DISC_CPMM_SWAP_OUT,
381
+ _DISC_CPMM_INITIALIZE,
382
+ _DISC_CPMM_DEP,
383
+ _DISC_CPMM_WIT,
384
+ )
385
+ if program_id == RAYDIUM_CLMM_PROGRAM_ID:
386
+ return disc in (
387
+ _DISC_CLMM_SWAP,
388
+ _DISC_CLMM_SWAP_V2,
389
+ _DISC_CLMM_INC_LIQ,
390
+ _DISC_CLMM_DEC_LIQ,
391
+ _DISC_CLMM_CREATE,
392
+ _DISC_CLMM_CREATE_CUSTOMIZABLE_POOL,
393
+ _DISC_CLMM_OPEN_POSITION,
394
+ _DISC_CLMM_OPEN_POSITION_V2,
395
+ _DISC_CLMM_OPEN_POSITION_WITH_TOKEN_22_NFT,
396
+ _DISC_CLMM_CLOSE_POSITION,
397
+ )
398
+ if program_id == ORCA_WHIRLPOOL_PROGRAM_ID:
399
+ return disc in (
400
+ _DISC_ORCA_SWAP,
401
+ _DISC_ORCA_SWAP_V2,
402
+ _DISC_ORCA_INC_LIQ,
403
+ _DISC_ORCA_DEC_LIQ,
404
+ _DISC_ORCA_INIT_POOL,
405
+ )
406
+ if program_id == METEORA_POOLS_PROGRAM_ID:
407
+ return disc in (
408
+ _DISC_METEORA_POOLS_SWAP,
409
+ _DISC_METEORA_POOLS_ADD_LIQUIDITY,
410
+ _DISC_METEORA_POOLS_REMOVE_LIQUIDITY,
411
+ _DISC_METEORA_POOLS_CREATE_POOL,
412
+ )
413
+ return False
414
+
415
+
416
+ def parse_inner_compiled_instruction_if_supported(
417
+ instruction_data: bytes,
418
+ accounts: List[str],
419
+ signature: str,
420
+ slot: int,
421
+ tx_index: int,
422
+ block_time_us: Optional[int],
423
+ grpc_recv_us: int,
424
+ filter: Optional[EventTypeFilter],
425
+ program_id: str,
426
+ ) -> Optional[DexEvent]:
427
+ if not normal_instruction_data_may_parse(program_id, instruction_data):
428
+ return None
429
+ return parse_instruction_unified(
430
+ instruction_data,
431
+ accounts,
432
+ signature,
433
+ slot,
434
+ tx_index,
435
+ block_time_us,
436
+ grpc_recv_us,
437
+ filter,
438
+ program_id,
439
+ )
440
+
441
+
307
442
  def parse_pumpfun_instruction(
308
443
  data: bytes,
309
444
  accounts: List[str],
@@ -661,7 +796,9 @@ def _parse_pumpfun_create_v2(data: bytes, accounts: List[str], meta: EventMetada
661
796
  token_total_supply=0,
662
797
  is_mayhem_mode=is_mayhem_mode,
663
798
  is_cashback_enabled=is_cashback_enabled,
664
- quote_mint=Z,
799
+ quote_mint=_get_account_safe(accounts, 16) or Z,
800
+ quote_vault=_get_account_safe(accounts, 17),
801
+ quote_token_program=_get_account_safe(accounts, 18),
665
802
  virtual_quote_reserves=0,
666
803
  observed_fee_recipient="",
667
804
  ),
@@ -1066,7 +1203,7 @@ def parse_pump_fees_instruction(
1066
1203
  ),
1067
1204
  )
1068
1205
 
1069
- if discriminator == _DISC_PFEES_UPDATE_FEE_SHARES:
1206
+ if discriminator in (_DISC_PFEES_UPDATE_FEE_SHARES, _DISC_PFEES_UPDATE_FEE_SHARES_V2):
1070
1207
  if len(accounts) < 8:
1071
1208
  return None
1072
1209
  o = [8]
@@ -1100,19 +1237,19 @@ def parse_pump_fees_instruction(
1100
1237
  ),
1101
1238
  )
1102
1239
 
1103
- if discriminator == _DISC_PFEES_RESET_FEE_SHARING:
1104
- if len(accounts) < 5:
1240
+ if discriminator in (_DISC_PFEES_RESET_FEE_SHARING, _DISC_PFEES_RESET_FEE_SHARING_V2):
1241
+ if len(accounts) < 7:
1105
1242
  return None
1106
1243
  return DexEvent(
1107
1244
  type=EventType.PUMP_FEES_RESET_FEE_SHARING_CONFIG,
1108
1245
  data=PumpFeesResetFeeSharingConfigEvent(
1109
1246
  metadata=meta,
1110
1247
  timestamp=0,
1111
- mint=accounts[3],
1112
- sharing_config=accounts[4],
1113
- old_admin=accounts[0],
1248
+ mint=accounts[5],
1249
+ sharing_config=accounts[6],
1250
+ old_admin=accounts[3],
1114
1251
  old_shareholders=[],
1115
- new_admin=accounts[2],
1252
+ new_admin=accounts[0],
1116
1253
  new_shareholders=[],
1117
1254
  ),
1118
1255
  )
@@ -1224,61 +1361,93 @@ def parse_raydium_clmm_instruction(
1224
1361
  meta = _make_meta(signature, slot, tx_index, block_time_us, grpc_recv_us)
1225
1362
 
1226
1363
  if discriminator in (_DISC_CLMM_SWAP, _DISC_CLMM_SWAP_V2):
1227
- if len(data) < 8 + 8 + 8 + 8 + 1:
1364
+ if len(data) < 8 + 8 + 8 + 16 + 1:
1228
1365
  return None
1229
- sqrt_price_x64 = struct.unpack_from("<Q", data, 24)[0]
1230
- is_base_input = data[32] == 1
1366
+ sqrt_price_x64 = int.from_bytes(data[24:40], "little")
1367
+ is_base_input = data[40] == 1
1231
1368
  return legacy_dict_to_dex_event({"RaydiumClmmSwap": {
1232
1369
  "metadata": meta,
1233
- "pool_state": _get_account_safe(accounts, 0),
1234
- "sender": _get_account_safe(accounts, 1),
1235
- "token_account_0": Z, "token_account_1": Z,
1370
+ "pool_state": _get_account_safe(accounts, 2),
1371
+ "sender": _get_account_safe(accounts, 0),
1372
+ "token_account_0": _get_account_safe(accounts, 3), "token_account_1": _get_account_safe(accounts, 4),
1236
1373
  "amount_0": 0, "amount_1": 0, "zero_for_one": is_base_input,
1237
1374
  "sqrt_price_x64": str(sqrt_price_x64), "liquidity": "0",
1238
1375
  "transfer_fee_0": 0, "transfer_fee_1": 0, "tick": 0,
1239
1376
  }})
1240
1377
  if discriminator == _DISC_CLMM_INC_LIQ:
1241
- if len(data) < 8 + 8 + 8 + 8:
1378
+ if len(data) < 8 + 16 + 8 + 8:
1242
1379
  return None
1243
- liquidity, amount0_max, amount1_max = struct.unpack_from("<QQQ", data, 8)
1380
+ liquidity = int.from_bytes(data[8:24], "little")
1381
+ amount0_max, amount1_max = struct.unpack_from("<QQ", data, 24)
1244
1382
  return legacy_dict_to_dex_event({"RaydiumClmmIncreaseLiquidity": {
1245
1383
  "metadata": meta,
1246
- "pool": _get_account_safe(accounts, 0),
1384
+ "pool": _get_account_safe(accounts, 2),
1247
1385
  "position_nft_mint": _get_account_safe(accounts, 1),
1248
- "user": _get_account_safe(accounts, 2),
1249
- "liquidity": str(liquidity), "amount0_max": amount0_max, "amount1_max": amount1_max,
1386
+ "user": _get_account_safe(accounts, 0),
1387
+ "liquidity": str(liquidity),
1388
+ "amount_0": 0, "amount_1": 0,
1389
+ "amount_0_transfer_fee": 0, "amount_1_transfer_fee": 0,
1390
+ "amount0_max": amount0_max, "amount1_max": amount1_max,
1250
1391
  }})
1251
1392
  if discriminator == _DISC_CLMM_DEC_LIQ:
1252
- if len(data) < 8 + 8 + 8 + 8:
1393
+ if len(data) < 8 + 16 + 8 + 8:
1253
1394
  return None
1254
- liquidity, amount0_min, amount1_min = struct.unpack_from("<QQQ", data, 8)
1395
+ liquidity = int.from_bytes(data[8:24], "little")
1396
+ amount0_min, amount1_min = struct.unpack_from("<QQ", data, 24)
1255
1397
  return legacy_dict_to_dex_event({"RaydiumClmmDecreaseLiquidity": {
1256
1398
  "metadata": meta,
1257
- "pool": _get_account_safe(accounts, 0),
1399
+ "pool": _get_account_safe(accounts, 3),
1258
1400
  "position_nft_mint": _get_account_safe(accounts, 1),
1259
- "user": _get_account_safe(accounts, 2),
1260
- "liquidity": str(liquidity), "amount0_min": amount0_min, "amount1_min": amount1_min,
1401
+ "user": _get_account_safe(accounts, 0),
1402
+ "liquidity": str(liquidity),
1403
+ "decrease_amount_0": 0, "decrease_amount_1": 0,
1404
+ "fee_amount_0": 0, "fee_amount_1": 0,
1405
+ "reward_amounts": [0, 0, 0],
1406
+ "transfer_fee_0": 0, "transfer_fee_1": 0,
1407
+ "amount0_min": amount0_min, "amount1_min": amount1_min,
1261
1408
  }})
1262
1409
  if discriminator == _DISC_CLMM_CREATE:
1263
- if len(data) < 8 + 8 + 8:
1410
+ if len(data) < 8 + 16 + 8:
1264
1411
  return None
1265
- sqrt_price_x64, open_time = struct.unpack_from("<QQ", data, 8)
1412
+ sqrt_price_x64 = int.from_bytes(data[8:24], "little")
1413
+ open_time = struct.unpack_from("<Q", data, 24)[0]
1266
1414
  return legacy_dict_to_dex_event({"RaydiumClmmCreatePool": {
1267
1415
  "metadata": meta,
1268
- "pool": _get_account_safe(accounts, 0),
1269
- "creator": _get_account_safe(accounts, 1),
1270
- "token_0_mint": _get_account_safe(accounts, 2),
1271
- "token_1_mint": _get_account_safe(accounts, 3),
1272
- "tick_spacing": 0, "fee_rate": 0, "sqrt_price_x64": str(sqrt_price_x64), "open_time": open_time,
1416
+ "pool": _get_account_safe(accounts, 2),
1417
+ "creator": _get_account_safe(accounts, 0),
1418
+ "token_0_mint": _get_account_safe(accounts, 3),
1419
+ "token_1_mint": _get_account_safe(accounts, 4),
1420
+ "tick_spacing": 0, "fee_rate": 0, "sqrt_price_x64": str(sqrt_price_x64),
1421
+ "tick": 0, "token_vault_0": _get_account_safe(accounts, 5), "token_vault_1": _get_account_safe(accounts, 6),
1422
+ "open_time": open_time,
1273
1423
  }})
1274
- if discriminator in (_DISC_CLMM_OPEN_POSITION_V2, _DISC_CLMM_OPEN_POSITION_WITH_TOKEN_22_NFT):
1275
- if len(data) < 8 + 4 + 4 + 4 + 4 + 8 + 8 + 8:
1424
+ if discriminator == _DISC_CLMM_CREATE_CUSTOMIZABLE_POOL:
1425
+ if len(data) < 8 + 16:
1426
+ return None
1427
+ sqrt_price_x64 = int.from_bytes(data[8:24], "little")
1428
+ return legacy_dict_to_dex_event({"RaydiumClmmCreatePool": {
1429
+ "metadata": meta,
1430
+ "pool": _get_account_safe(accounts, 2),
1431
+ "creator": _get_account_safe(accounts, 0),
1432
+ "token_0_mint": _get_account_safe(accounts, 3),
1433
+ "token_1_mint": _get_account_safe(accounts, 4),
1434
+ "tick_spacing": 0, "fee_rate": 0, "sqrt_price_x64": str(sqrt_price_x64),
1435
+ "tick": 0, "token_vault_0": _get_account_safe(accounts, 5), "token_vault_1": _get_account_safe(accounts, 6),
1436
+ "open_time": 0,
1437
+ }})
1438
+ if discriminator in (
1439
+ _DISC_CLMM_OPEN_POSITION,
1440
+ _DISC_CLMM_OPEN_POSITION_V2,
1441
+ _DISC_CLMM_OPEN_POSITION_WITH_TOKEN_22_NFT,
1442
+ ):
1443
+ if len(data) < 8 + 4 + 4 + 4 + 4 + 16 + 8 + 8:
1276
1444
  return None
1277
1445
  tick_lower_index, tick_upper_index = struct.unpack_from("<ii", data, 8)
1278
- liquidity = struct.unpack_from("<Q", data, 24)[0]
1446
+ liquidity = int.from_bytes(data[24:40], "little")
1447
+ pool_index = 4 if discriminator == _DISC_CLMM_OPEN_POSITION_WITH_TOKEN_22_NFT else 5
1279
1448
  return legacy_dict_to_dex_event({"RaydiumClmmOpenPosition": {
1280
1449
  "metadata": meta,
1281
- "pool": _get_account_safe(accounts, 0),
1450
+ "pool": _get_account_safe(accounts, pool_index),
1282
1451
  "user": _get_account_safe(accounts, 1),
1283
1452
  "position_nft_mint": _get_account_safe(accounts, 2),
1284
1453
  "tick_lower_index": tick_lower_index,
@@ -1288,9 +1457,9 @@ def parse_raydium_clmm_instruction(
1288
1457
  if discriminator == _DISC_CLMM_CLOSE_POSITION:
1289
1458
  return legacy_dict_to_dex_event({"RaydiumClmmClosePosition": {
1290
1459
  "metadata": meta,
1291
- "pool": _get_account_safe(accounts, 0),
1292
- "user": _get_account_safe(accounts, 1),
1293
- "position_nft_mint": _get_account_safe(accounts, 2),
1460
+ "pool": Z,
1461
+ "user": _get_account_safe(accounts, 0),
1462
+ "position_nft_mint": _get_account_safe(accounts, 1),
1294
1463
  }})
1295
1464
 
1296
1465
  return None
@@ -1313,27 +1482,58 @@ def parse_raydium_cpmm_instruction(
1313
1482
  meta = _make_meta(signature, slot, tx_index, block_time_us, grpc_recv_us)
1314
1483
 
1315
1484
  if discriminator == _DISC_CPMM_SWAP:
1485
+ if len(data) < 8 + 8 + 8:
1486
+ return None
1316
1487
  return legacy_dict_to_dex_event({"RaydiumCpmmSwap": {
1317
1488
  "metadata": meta,
1318
- "pool_id": _get_account_safe(accounts, 2),
1489
+ "pool_id": Z,
1319
1490
  "input_amount": 0, "output_amount": 0,
1320
1491
  "input_vault_before": 0, "output_vault_before": 0,
1321
1492
  "input_transfer_fee": 0, "output_transfer_fee": 0,
1322
1493
  "base_input": True,
1323
1494
  }})
1495
+ if discriminator == _DISC_CPMM_SWAP_OUT:
1496
+ if len(data) < 8 + 8 + 8:
1497
+ return None
1498
+ return legacy_dict_to_dex_event({"RaydiumCpmmSwap": {
1499
+ "metadata": meta,
1500
+ "pool_id": Z,
1501
+ "input_amount": 0, "output_amount": 0,
1502
+ "input_vault_before": 0, "output_vault_before": 0,
1503
+ "input_transfer_fee": 0, "output_transfer_fee": 0,
1504
+ "base_input": False,
1505
+ }})
1506
+ if discriminator == _DISC_CPMM_INITIALIZE:
1507
+ if len(data) < 8 + 8 + 8:
1508
+ return None
1509
+ return legacy_dict_to_dex_event({"RaydiumCpmmInitialize": {
1510
+ "metadata": meta,
1511
+ "pool": _get_account_safe(accounts, 0),
1512
+ "creator": _get_account_safe(accounts, 1),
1513
+ "init_amount0": struct.unpack_from("<Q", data, 8)[0],
1514
+ "init_amount1": struct.unpack_from("<Q", data, 16)[0],
1515
+ }})
1324
1516
  if discriminator == _DISC_CPMM_DEP:
1517
+ if len(data) < 8 + 8 + 8 + 8:
1518
+ return None
1325
1519
  return legacy_dict_to_dex_event({"RaydiumCpmmDeposit": {
1326
1520
  "metadata": meta,
1327
- "pool": _get_account_safe(accounts, 2),
1328
- "user": _get_account_safe(accounts, 0),
1329
- "lp_token_amount": 0, "token0_amount": 0, "token1_amount": 0,
1521
+ "pool": _get_account_safe(accounts, 0),
1522
+ "user": _get_account_safe(accounts, 1),
1523
+ "lp_token_amount": struct.unpack_from("<Q", data, 8)[0],
1524
+ "token0_amount": struct.unpack_from("<Q", data, 16)[0],
1525
+ "token1_amount": struct.unpack_from("<Q", data, 24)[0],
1330
1526
  }})
1331
1527
  if discriminator == _DISC_CPMM_WIT:
1528
+ if len(data) < 8 + 8 + 8 + 8:
1529
+ return None
1332
1530
  return legacy_dict_to_dex_event({"RaydiumCpmmWithdraw": {
1333
1531
  "metadata": meta,
1334
- "pool": _get_account_safe(accounts, 2),
1335
- "user": _get_account_safe(accounts, 0),
1336
- "lp_token_amount": 0, "token0_amount": 0, "token1_amount": 0,
1532
+ "pool": _get_account_safe(accounts, 0),
1533
+ "user": _get_account_safe(accounts, 1),
1534
+ "lp_token_amount": struct.unpack_from("<Q", data, 8)[0],
1535
+ "token0_amount": struct.unpack_from("<Q", data, 16)[0],
1536
+ "token1_amount": struct.unpack_from("<Q", data, 24)[0],
1337
1537
  }})
1338
1538
 
1339
1539
  return None
@@ -1391,36 +1591,72 @@ def parse_orca_whirlpool_instruction(
1391
1591
  discriminator = struct.unpack_from("<Q", data, 0)[0]
1392
1592
  meta = _make_meta(signature, slot, tx_index, block_time_us, grpc_recv_us)
1393
1593
 
1394
- if discriminator == _DISC_ORCA_SWAP:
1594
+ if discriminator in (_DISC_ORCA_SWAP, _DISC_ORCA_SWAP_V2):
1595
+ if len(data) < 8 + 8 + 8 + 16 + 1 + 1:
1596
+ return None
1597
+ amount = struct.unpack_from("<Q", data, 8)[0]
1598
+ other_amount_threshold = struct.unpack_from("<Q", data, 16)[0]
1599
+ sqrt_price_limit = int.from_bytes(data[24:40], "little")
1600
+ amount_specified_is_input = data[40] != 0
1601
+ a_to_b = data[41] != 0
1395
1602
  return legacy_dict_to_dex_event({"OrcaWhirlpoolSwap": {
1396
1603
  "metadata": meta,
1397
- "whirlpool": _get_account_safe(accounts, 2),
1398
- "a_to_b": True,
1399
- "pre_sqrt_price": "0", "post_sqrt_price": "0",
1400
- "input_amount": 0, "output_amount": 0,
1604
+ "whirlpool": _get_account_safe(accounts, 1),
1605
+ "a_to_b": a_to_b,
1606
+ "pre_sqrt_price": str(sqrt_price_limit), "post_sqrt_price": "0",
1607
+ "input_amount": amount if amount_specified_is_input else 0,
1608
+ "output_amount": other_amount_threshold if amount_specified_is_input else amount,
1401
1609
  "input_transfer_fee": 0, "output_transfer_fee": 0,
1402
1610
  "lp_fee": 0, "protocol_fee": 0,
1403
1611
  }})
1404
1612
  if discriminator == _DISC_ORCA_INC_LIQ:
1613
+ if len(data) < 8 + 16 + 8 + 8:
1614
+ return None
1615
+ liquidity = int.from_bytes(data[8:24], "little")
1616
+ token_max_a = struct.unpack_from("<Q", data, 24)[0]
1617
+ token_max_b = struct.unpack_from("<Q", data, 32)[0]
1405
1618
  return legacy_dict_to_dex_event({"OrcaWhirlpoolLiquidityIncreased": {
1406
1619
  "metadata": meta,
1407
1620
  "whirlpool": _get_account_safe(accounts, 1),
1408
1621
  "position": _get_account_safe(accounts, 3),
1409
1622
  "tick_lower_index": 0, "tick_upper_index": 0,
1410
- "liquidity": "0",
1411
- "token_a_amount": 0, "token_b_amount": 0,
1623
+ "liquidity": str(liquidity),
1624
+ "token_a_amount": token_max_a, "token_b_amount": token_max_b,
1412
1625
  "token_a_transfer_fee": 0, "token_b_transfer_fee": 0,
1413
1626
  }})
1414
1627
  if discriminator == _DISC_ORCA_DEC_LIQ:
1628
+ if len(data) < 8 + 16 + 8 + 8:
1629
+ return None
1630
+ liquidity = int.from_bytes(data[8:24], "little")
1631
+ token_min_a = struct.unpack_from("<Q", data, 24)[0]
1632
+ token_min_b = struct.unpack_from("<Q", data, 32)[0]
1415
1633
  return legacy_dict_to_dex_event({"OrcaWhirlpoolLiquidityDecreased": {
1416
1634
  "metadata": meta,
1417
1635
  "whirlpool": _get_account_safe(accounts, 1),
1418
1636
  "position": _get_account_safe(accounts, 3),
1419
1637
  "tick_lower_index": 0, "tick_upper_index": 0,
1420
- "liquidity": "0",
1421
- "token_a_amount": 0, "token_b_amount": 0,
1638
+ "liquidity": str(liquidity),
1639
+ "token_a_amount": token_min_a, "token_b_amount": token_min_b,
1422
1640
  "token_a_transfer_fee": 0, "token_b_transfer_fee": 0,
1423
1641
  }})
1642
+ if discriminator == _DISC_ORCA_INIT_POOL:
1643
+ if len(data) < 8 + 2 + 16:
1644
+ return None
1645
+ tick_spacing = struct.unpack_from("<H", data, 8)[0]
1646
+ initial_sqrt_price = int.from_bytes(data[10:26], "little")
1647
+ return legacy_dict_to_dex_event({"OrcaWhirlpoolPoolInitialized": {
1648
+ "metadata": meta,
1649
+ "whirlpool": _get_account_safe(accounts, 1),
1650
+ "whirlpools_config": _get_account_safe(accounts, 2),
1651
+ "token_mint_a": _get_account_safe(accounts, 3),
1652
+ "token_mint_b": _get_account_safe(accounts, 4),
1653
+ "tick_spacing": tick_spacing,
1654
+ "token_program_a": _get_account_safe(accounts, 8),
1655
+ "token_program_b": _get_account_safe(accounts, 9),
1656
+ "decimals_a": 0,
1657
+ "decimals_b": 0,
1658
+ "initial_sqrt_price": str(initial_sqrt_price),
1659
+ }})
1424
1660
 
1425
1661
  return None
1426
1662
 
@@ -78,7 +78,7 @@ def _dedupe_key(ev: DexEvent, pumpfun_lane_counts: Dict[PumpfunLaneBase, int]) -
78
78
  if t == EventType.PUMP_FUN_CREATE:
79
79
  return f"PumpFunCreate|{getattr(data, 'mint', '')}"
80
80
  if t == EventType.PUMP_FUN_CREATE_V2:
81
- return f"PumpFunCreateV2|{getattr(data, 'mint', '')}"
81
+ return f"PumpFunCreate|{getattr(data, 'mint', '')}"
82
82
  if t == EventType.PUMP_FUN_MIGRATE:
83
83
  return (
84
84
  f"PumpFunMigrate|{getattr(data, 'mint', '')}|"
@@ -174,10 +174,36 @@ def _merge_pumpfun_trade(log: Any, ix: Any) -> None:
174
174
 
175
175
 
176
176
  def _merge_pumpfun_create(log: Any, ix: Any) -> None:
177
- for attr in ("name", "symbol", "uri", "bonding_curve", "user", "creator", "token_program", "quote_mint"):
177
+ for attr in (
178
+ "name",
179
+ "symbol",
180
+ "uri",
181
+ "mint",
182
+ "bonding_curve",
183
+ "user",
184
+ "creator",
185
+ "token_program",
186
+ "quote_mint",
187
+ "quote_vault",
188
+ "quote_token_program",
189
+ ):
178
190
  _fill_attr(log, attr, ix)
179
- if getattr(log, "virtual_quote_reserves", 0) == 0 and getattr(ix, "virtual_quote_reserves", 0) != 0:
180
- log.virtual_quote_reserves = ix.virtual_quote_reserves
191
+ for attr in (
192
+ "timestamp",
193
+ "virtual_token_reserves",
194
+ "virtual_sol_reserves",
195
+ "real_token_reserves",
196
+ "token_total_supply",
197
+ "virtual_quote_reserves",
198
+ ):
199
+ if getattr(log, attr, 0) == 0 and getattr(ix, attr, 0) != 0:
200
+ setattr(log, attr, getattr(ix, attr))
201
+ log.is_mayhem_mode = bool(getattr(log, "is_mayhem_mode", False)) or bool(
202
+ getattr(ix, "is_mayhem_mode", False)
203
+ )
204
+ log.is_cashback_enabled = bool(getattr(log, "is_cashback_enabled", False)) or bool(
205
+ getattr(ix, "is_cashback_enabled", False)
206
+ )
181
207
 
182
208
 
183
209
  def _merge_pumpfun_create_v2(log: Any, ix: Any) -> None:
@@ -232,6 +258,10 @@ def _merge_grpc_instruction_into_log(log_ev: DexEvent, ix_ev: DexEvent) -> None:
232
258
 
233
259
  if log_ev.type in PUMPFUN_TRADE_TYPES and ix_ev.type in PUMPFUN_TRADE_TYPES:
234
260
  _merge_pumpfun_trade(log, ix)
261
+ elif log_ev.type == EventType.PUMP_FUN_CREATE and ix_ev.type == EventType.PUMP_FUN_CREATE_V2:
262
+ _merge_pumpfun_create(log, ix)
263
+ elif log_ev.type == EventType.PUMP_FUN_CREATE_V2 and ix_ev.type == EventType.PUMP_FUN_CREATE:
264
+ _merge_pumpfun_create_v2(log, ix)
235
265
  elif log_ev.type == EventType.PUMP_FUN_CREATE and ix_ev.type == EventType.PUMP_FUN_CREATE:
236
266
  _merge_pumpfun_create(log, ix)
237
267
  elif log_ev.type == EventType.PUMP_FUN_CREATE_V2 and ix_ev.type == EventType.PUMP_FUN_CREATE_V2: