feat(examples): add 18-account buy / 16-17-account sell for 2026-04-28 upgrade

pump.fun program upgrade scheduled for 2026-04-28 16:00 UTC adds one new
mutable account (one of 8 fee recipients) at the end of buy/sell ixs,
after bonding-curve-v2. The new format is already accepted on mainnet
ahead of the cutover, so applying now keeps scripts working on both
sides of the upgrade.

Doc: github.com/pump-fun/pump-public-docs/blob/main/docs/BREAKING_FEE_RECIPIENT.md

Per file:
  manual_buy.py            — 18-account buy. Also fixes a pre-existing
                             listener crash on Address-Lookup-Table create
                             txs (skips them) and adds bool/OptionBool
                             handling to decode_create_instruction so
                             create_v2 doesn't raise on its trailing args.
  manual_buy_cu_optimized.py — 18-account buy. Bumps the CU-optimization
                             account-data limit to 16MB (tested) — older
                             values trigger MaxLoadedAccountsDataSizeExceeded
                             on Token-2022/cashback coins. Same listener
                             ALT-skip and decoder bool fixes.
  manual_buy_geyser.py     — 18-account buy. Re-enables price calculation
                             and mayhem-mode-aware fee_recipient detection
                             (was scaffolded out for testing).
  manual_sell.py           — 16-account non-cashback / 17-account cashback
                             sell. Reads is_cashback_coin from BC byte 82
                             and inserts user_volume_accumulator before
                             bonding-curve-v2 when needed. TOKEN_MINT now
                             accepts argv[1] override.

Live-verified on mainnet:
  buy   manual_buy.py             3AVnLC3sdBD598cs3... + 3bWU9bB8U9aemA2BFhS2...
  buy   manual_buy_cu_optimized   2PfH5rHw62o3KkQ3N4z8...
  sell  manual_sell.py            3E7dyPBPBRe95BtPQXmb... + 5L4wWSzPV36m6XqXAswB...
All four show the expected 18 (buy) / 16 (sell non-cashback) account count
with one of the 8 BREAKING_FEE_RECIPIENTS as the trailing mutable account.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Anton Sauchyk
2026-04-27 17:43:31 +02:00
parent 9b4841890c
commit c25e2edb57
4 changed files with 157 additions and 29 deletions
+39 -8
View File
@@ -3,6 +3,7 @@ import base64
import hashlib import hashlib
import json import json
import os import os
import random
import struct import struct
import base58 import base58
@@ -43,6 +44,20 @@ SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string(
SOL = Pubkey.from_string("So11111111111111111111111111111111111111112") SOL = Pubkey.from_string("So11111111111111111111111111111111111111112")
LAMPORTS_PER_SOL = 1_000_000_000 LAMPORTS_PER_SOL = 1_000_000_000
# 8 breaking-upgrade fee recipients (pump.fun program upgrade 2026-04-28).
# One must be appended (mutable) AFTER bonding-curve-v2 on every buy/sell.
# Doc: github.com/pump-fun/pump-public-docs/blob/main/docs/BREAKING_FEE_RECIPIENT.md
BREAKING_FEE_RECIPIENTS = [
Pubkey.from_string("5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD"),
Pubkey.from_string("9M4giFFMxmFGXtc3feFzRai56WbBqehoSeRE5GK7gf7"),
Pubkey.from_string("GXPFM2caqTtQYC2cJ5yJRi9VDkpsYZXzYdwYpGnLmtDL"),
Pubkey.from_string("3BpXnfJaUTiwXnJNe7Ej1rcbzqTTQUvLShZaWazebsVR"),
Pubkey.from_string("5cjcW9wExnJJiqgLjq7DEG75Pm6JBgE1hNv4B2vHXUW6"),
Pubkey.from_string("EHAAiTxcdDwQ3U4bU6YcMsQGaekdzLS3B5SmYo46kJtL"),
Pubkey.from_string("5eHhjP8JaYkz83CWwvGU2uMUXefd3AazWGx4gpcuEEYD"),
Pubkey.from_string("A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW"),
]
# RPC ENDPOINTS # RPC ENDPOINTS
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT") RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
RPC_WEBSOCKET = os.environ.get("SOLANA_NODE_WSS_ENDPOINT") RPC_WEBSOCKET = os.environ.get("SOLANA_NODE_WSS_ENDPOINT")
@@ -295,6 +310,12 @@ async def buy_token(
is_signer=False, is_signer=False,
is_writable=False, is_writable=False,
), ),
# 18th account: breaking-upgrade fee recipient (mutable) — required from 2026-04-28
AccountMeta(
pubkey=random.choice(BREAKING_FEE_RECIPIENTS),
is_signer=False,
is_writable=True,
),
] ]
discriminator = struct.pack("<Q", 16927863322537952870) discriminator = struct.pack("<Q", 16927863322537952870)
@@ -359,16 +380,24 @@ def decode_create_instruction(ix_data, ix_def, accounts):
offset = 8 # Skip 8-byte discriminator offset = 8 # Skip 8-byte discriminator
for arg in ix_def["args"]: for arg in ix_def["args"]:
if arg["type"] == "string": t = arg["type"]
if t == "string":
length = struct.unpack_from("<I", ix_data, offset)[0] length = struct.unpack_from("<I", ix_data, offset)[0]
offset += 4 offset += 4
value = ix_data[offset : offset + length].decode("utf-8") value = ix_data[offset : offset + length].decode("utf-8")
offset += length offset += length
elif arg["type"] == "pubkey": elif t == "pubkey":
value = base58.b58encode(ix_data[offset : offset + 32]).decode("utf-8") value = base58.b58encode(ix_data[offset : offset + 32]).decode("utf-8")
offset += 32 offset += 32
elif t == "bool":
value = bool(ix_data[offset])
offset += 1
elif isinstance(t, dict) and "defined" in t:
# OptionBool = struct { bool } = 1 byte
value = bool(ix_data[offset])
offset += 1
else: else:
raise ValueError(f"Unsupported type: {arg['type']}") raise ValueError(f"Unsupported type: {t}")
args[arg["name"]] = value args[arg["name"]] = value
@@ -457,12 +486,14 @@ async def listen_for_create_transaction():
for instr in idl["instructions"] for instr in idl["instructions"]
if instr["name"] == instruction_name if instr["name"] == instruction_name
) )
# Skip txs that use Address Lookup Tables — their
# instruction account indices reference ALT-loaded keys
# not present in transaction.message.account_keys.
static_keys = transaction.message.account_keys
if any(idx >= len(static_keys) for idx in ix.accounts):
continue
account_keys = [ account_keys = [
str( str(static_keys[index])
transaction.message.account_keys[
index
]
)
for index in ix.accounts for index in ix.accounts
] ]
decoded_args = ( decoded_args = (
+40 -5
View File
@@ -22,6 +22,7 @@ import base64
import hashlib import hashlib
import json import json
import os import os
import random
import struct import struct
import base58 import base58
@@ -53,6 +54,20 @@ PUMP_EVENT_AUTHORITY = Pubkey.from_string(
) )
PUMP_FEE = Pubkey.from_string("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM") PUMP_FEE = Pubkey.from_string("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM")
PUMP_FEE_PROGRAM = Pubkey.from_string("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ") PUMP_FEE_PROGRAM = Pubkey.from_string("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ")
# 8 breaking-upgrade fee recipients (pump.fun program upgrade 2026-04-28).
# One must be appended (mutable) AFTER bonding-curve-v2 on every buy/sell.
# Doc: github.com/pump-fun/pump-public-docs/blob/main/docs/BREAKING_FEE_RECIPIENT.md
BREAKING_FEE_RECIPIENTS = [
Pubkey.from_string("5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD"),
Pubkey.from_string("9M4giFFMxmFGXtc3feFzRai56WbBqehoSeRE5GK7gf7"),
Pubkey.from_string("GXPFM2caqTtQYC2cJ5yJRi9VDkpsYZXzYdwYpGnLmtDL"),
Pubkey.from_string("3BpXnfJaUTiwXnJNe7Ej1rcbzqTTQUvLShZaWazebsVR"),
Pubkey.from_string("5cjcW9wExnJJiqgLjq7DEG75Pm6JBgE1hNv4B2vHXUW6"),
Pubkey.from_string("EHAAiTxcdDwQ3U4bU6YcMsQGaekdzLS3B5SmYo46kJtL"),
Pubkey.from_string("5eHhjP8JaYkz83CWwvGU2uMUXefd3AazWGx4gpcuEEYD"),
Pubkey.from_string("A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW"),
]
SYSTEM_PROGRAM = Pubkey.from_string("11111111111111111111111111111111") SYSTEM_PROGRAM = Pubkey.from_string("11111111111111111111111111111111")
SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
TOKEN_2022_PROGRAM = Pubkey.from_string("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") TOKEN_2022_PROGRAM = Pubkey.from_string("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb")
@@ -333,6 +348,12 @@ async def buy_token(
is_signer=False, is_signer=False,
is_writable=False, is_writable=False,
), ),
# 18th account: breaking-upgrade fee recipient (mutable) — required from 2026-04-28
AccountMeta(
pubkey=random.choice(BREAKING_FEE_RECIPIENTS),
is_signer=False,
is_writable=True,
),
] ]
discriminator = struct.pack("<Q", 16927863322537952870) discriminator = struct.pack("<Q", 16927863322537952870)
@@ -350,7 +371,10 @@ async def buy_token(
# CU OPTIMIZATION: Limit account data to 512KB (down from 64MB default) # CU OPTIMIZATION: Limit account data to 512KB (down from 64MB default)
# This reduces CU cost from 16k to ~128 CU and improves tx priority. # This reduces CU cost from 16k to ~128 CU and improves tx priority.
# Must be placed FIRST in the instruction list. # Must be placed FIRST in the instruction list.
cu_limit_ix = set_loaded_accounts_data_size_limit(512_000) # 16MB limit: works for cashback-coin Token-2022 buys on mainnet.
# Smaller values (48MB) trigger MaxLoadedAccountsDataSizeExceeded for
# Token-2022 mints with extensions. Still 4× smaller than the 64MB default.
cu_limit_ix = set_loaded_accounts_data_size_limit(16_384_000)
msg = Message( msg = Message(
[cu_limit_ix, set_compute_unit_price(1_000), idempotent_ata_ix, buy_ix], [cu_limit_ix, set_compute_unit_price(1_000), idempotent_ata_ix, buy_ix],
@@ -402,16 +426,21 @@ def decode_create_instruction(ix_data, ix_def, accounts):
args = {} args = {}
offset = 8 offset = 8
for arg in ix_def["args"]: for arg in ix_def["args"]:
if arg["type"] == "string": t = arg["type"]
if t == "string":
length = struct.unpack_from("<I", ix_data, offset)[0] length = struct.unpack_from("<I", ix_data, offset)[0]
offset += 4 offset += 4
value = ix_data[offset : offset + length].decode("utf-8") value = ix_data[offset : offset + length].decode("utf-8")
offset += length offset += length
elif arg["type"] == "pubkey": elif t == "pubkey":
value = base58.b58encode(ix_data[offset : offset + 32]).decode("utf-8") value = base58.b58encode(ix_data[offset : offset + 32]).decode("utf-8")
offset += 32 offset += 32
elif t == "bool" or (isinstance(t, dict) and "defined" in t):
# `bool` and `OptionBool` (struct {bool}) both serialize as 1 byte
value = bool(ix_data[offset])
offset += 1
else: else:
raise ValueError(f"Unsupported type: {arg['type']}") raise ValueError(f"Unsupported type: {t}")
args[arg["name"]] = value args[arg["name"]] = value
args["mint"] = str(accounts[0]) args["mint"] = str(accounts[0])
@@ -499,6 +528,12 @@ async def listen_for_create_transaction():
for instr in idl["instructions"] for instr in idl["instructions"]
if instr["name"] == instruction_name if instr["name"] == instruction_name
) )
# Skip txs that use Address Lookup Tables — their
# instruction account indices reference ALT-loaded keys
# not present in transaction.message.account_keys.
static_keys = transaction.message.account_keys
if any(idx >= len(static_keys) for idx in ix.accounts):
continue
account_keys = [ account_keys = [
str( str(
transaction.message.account_keys[ transaction.message.account_keys[
@@ -554,7 +589,7 @@ async def main():
print( print(
f"Buying {amount:.6f} SOL worth of the new token with {slippage * 100:.1f}% slippage tolerance..." f"Buying {amount:.6f} SOL worth of the new token with {slippage * 100:.1f}% slippage tolerance..."
) )
print("CU Optimization: Enabled (512KB account data limit)") print("CU Optimization: Enabled (16MB account data limit)")
await buy_token( await buy_token(
mint, mint,
bonding_curve, bonding_curve,
+26 -13
View File
@@ -1,6 +1,7 @@
import asyncio import asyncio
import json import json
import os import os
import random
import struct import struct
import sys import sys
@@ -39,6 +40,20 @@ PUMP_EVENT_AUTHORITY = Pubkey.from_string(
) )
PUMP_FEE = Pubkey.from_string("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM") PUMP_FEE = Pubkey.from_string("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM")
PUMP_FEE_PROGRAM = Pubkey.from_string("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ") PUMP_FEE_PROGRAM = Pubkey.from_string("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ")
# 8 breaking-upgrade fee recipients (pump.fun program upgrade 2026-04-28).
# One must be appended (mutable) AFTER bonding-curve-v2 on every buy/sell.
# Doc: github.com/pump-fun/pump-public-docs/blob/main/docs/BREAKING_FEE_RECIPIENT.md
BREAKING_FEE_RECIPIENTS = [
Pubkey.from_string("5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD"),
Pubkey.from_string("9M4giFFMxmFGXtc3feFzRai56WbBqehoSeRE5GK7gf7"),
Pubkey.from_string("GXPFM2caqTtQYC2cJ5yJRi9VDkpsYZXzYdwYpGnLmtDL"),
Pubkey.from_string("3BpXnfJaUTiwXnJNe7Ej1rcbzqTTQUvLShZaWazebsVR"),
Pubkey.from_string("5cjcW9wExnJJiqgLjq7DEG75Pm6JBgE1hNv4B2vHXUW6"),
Pubkey.from_string("EHAAiTxcdDwQ3U4bU6YcMsQGaekdzLS3B5SmYo46kJtL"),
Pubkey.from_string("5eHhjP8JaYkz83CWwvGU2uMUXefd3AazWGx4gpcuEEYD"),
Pubkey.from_string("A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW"),
]
SYSTEM_PROGRAM = Pubkey.from_string("11111111111111111111111111111111") SYSTEM_PROGRAM = Pubkey.from_string("11111111111111111111111111111111")
SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
SYSTEM_TOKEN_2022_PROGRAM = Pubkey.from_string( SYSTEM_TOKEN_2022_PROGRAM = Pubkey.from_string(
@@ -365,19 +380,11 @@ async def buy_token(
) )
amount_lamports = int(amount * LAMPORTS_PER_SOL) amount_lamports = int(amount * LAMPORTS_PER_SOL)
# Fetch bonding curve state to calculate price and determine fee recipient # Fetch bonding curve state for price + mayhem-mode-aware fee recipient.
# NOTE: Price calculation is commented out to speed up testing - using fixed values curve_state = await get_pump_curve_state(client, bonding_curve)
# For production, uncomment the lines below to: token_price_sol = calculate_pump_curve_price(curve_state)
# 1. Calculate proper token amounts based on current price token_amount = amount / token_price_sol
# 2. Detect mayhem mode and use correct fee recipient fee_recipient = await get_fee_recipient(client, curve_state)
# curve_state = await get_pump_curve_state(client, bonding_curve)
# token_price_sol = calculate_pump_curve_price(curve_state)
# token_amount = amount / token_price_sol
# fee_recipient = await get_fee_recipient(client, curve_state)
# Testing values - replace with code above for production
token_amount = 100 # Fixed token amount
fee_recipient = PUMP_FEE # Standard fee recipient (doesn't detect mayhem mode)
# Calculate maximum SOL to spend with slippage # Calculate maximum SOL to spend with slippage
max_amount_lamports = int(amount_lamports * (1 + slippage)) max_amount_lamports = int(amount_lamports * (1 + slippage))
@@ -433,6 +440,12 @@ async def buy_token(
is_signer=False, is_signer=False,
is_writable=False, is_writable=False,
), ),
# 18th account: breaking-upgrade fee recipient (mutable) — required from 2026-04-28
AccountMeta(
pubkey=random.choice(BREAKING_FEE_RECIPIENTS),
is_signer=False,
is_writable=True,
),
] ]
discriminator = struct.pack("<Q", 16927863322537952870) discriminator = struct.pack("<Q", 16927863322537952870)
+52 -3
View File
@@ -1,6 +1,8 @@
import asyncio import asyncio
import os import os
import random
import struct import struct
import sys
import base58 import base58
from construct import Flag, Int64ul, Struct from construct import Flag, Int64ul, Struct
@@ -18,7 +20,7 @@ from spl.token.instructions import get_associated_token_address
# Here and later all the discriminators are precalculated. See learning-examples/calculate_discriminator.py # Here and later all the discriminators are precalculated. See learning-examples/calculate_discriminator.py
EXPECTED_DISCRIMINATOR = struct.pack("<Q", 6966180631402821399) EXPECTED_DISCRIMINATOR = struct.pack("<Q", 6966180631402821399)
TOKEN_DECIMALS = 6 TOKEN_DECIMALS = 6
TOKEN_MINT = Pubkey.from_string("...") # Replace with actual token mint address TOKEN_MINT = Pubkey.from_string(sys.argv[1] if len(sys.argv) > 1 else "...") # Pass mint as argv[1] or hardcode here
# Global constants # Global constants
PUMP_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P") PUMP_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
@@ -42,6 +44,20 @@ UNIT_BUDGET = 100_000
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT") RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
# 8 breaking-upgrade fee recipients (pump.fun program upgrade 2026-04-28).
# One must be appended (mutable) AFTER bonding-curve-v2 on every buy/sell.
# Doc: github.com/pump-fun/pump-public-docs/blob/main/docs/BREAKING_FEE_RECIPIENT.md
BREAKING_FEE_RECIPIENTS = [
Pubkey.from_string("5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD"),
Pubkey.from_string("9M4giFFMxmFGXtc3feFzRai56WbBqehoSeRE5GK7gf7"),
Pubkey.from_string("GXPFM2caqTtQYC2cJ5yJRi9VDkpsYZXzYdwYpGnLmtDL"),
Pubkey.from_string("3BpXnfJaUTiwXnJNe7Ej1rcbzqTTQUvLShZaWazebsVR"),
Pubkey.from_string("5cjcW9wExnJJiqgLjq7DEG75Pm6JBgE1hNv4B2vHXUW6"),
Pubkey.from_string("EHAAiTxcdDwQ3U4bU6YcMsQGaekdzLS3B5SmYo46kJtL"),
Pubkey.from_string("5eHhjP8JaYkz83CWwvGU2uMUXefd3AazWGx4gpcuEEYD"),
Pubkey.from_string("A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW"),
]
class BondingCurveState: class BondingCurveState:
"""Bonding curve state parser with progressive field parsing. """Bonding curve state parser with progressive field parsing.
@@ -95,9 +111,16 @@ class BondingCurveState:
# Parse mayhem mode flag if bytes remaining (added in V3) # Parse mayhem mode flag if bytes remaining (added in V3)
if len(data) >= offset + 1: if len(data) >= offset + 1:
self.is_mayhem_mode = bool(data[offset]) self.is_mayhem_mode = bool(data[offset])
offset += 1
else: else:
self.is_mayhem_mode = False self.is_mayhem_mode = False
# Parse cashback flag if bytes remaining (added in V4 — late-Feb 2026 cashback upgrade)
if len(data) >= offset + 1:
self.is_cashback_coin = bool(data[offset])
else:
self.is_cashback_coin = False
async def get_pump_curve_state( async def get_pump_curve_state(
conn: AsyncClient, curve_address: Pubkey conn: AsyncClient, curve_address: Pubkey
@@ -155,6 +178,14 @@ def _find_bonding_curve_v2(mint: Pubkey) -> Pubkey:
return derived_address return derived_address
def _find_user_volume_accumulator(user: Pubkey) -> Pubkey:
derived_address, _ = Pubkey.find_program_address(
[b"user_volume_accumulator", bytes(user)],
PUMP_PROGRAM,
)
return derived_address
async def get_fee_recipient( async def get_fee_recipient(
client: AsyncClient, curve_state: BondingCurveState client: AsyncClient, curve_state: BondingCurveState
) -> Pubkey: ) -> Pubkey:
@@ -320,13 +351,31 @@ async def sell_token(
is_signer=False, is_signer=False,
is_writable=False, is_writable=False,
), ),
# Remaining account: bonding_curve_v2 (readonly, required for all coins) ]
# For cashback coins, insert user_volume_accumulator before bonding-curve-v2 (17 accounts total).
if curve_state.is_cashback_coin:
accounts.append(
AccountMeta(
pubkey=_find_user_volume_accumulator(payer.pubkey()),
is_signer=False,
is_writable=True,
)
)
accounts.extend([
# bonding_curve_v2 (readonly, required for all coins)
AccountMeta( AccountMeta(
pubkey=_find_bonding_curve_v2(mint), pubkey=_find_bonding_curve_v2(mint),
is_signer=False, is_signer=False,
is_writable=False, is_writable=False,
), ),
] # Breaking-upgrade fee recipient (mutable) — required from 2026-04-28.
# 16 accounts non-cashback / 17 accounts cashback.
AccountMeta(
pubkey=random.choice(BREAKING_FEE_RECIPIENTS),
is_signer=False,
is_writable=True,
),
])
discriminator = struct.pack("<Q", 12502976635542562355) discriminator = struct.pack("<Q", 12502976635542562355)
# Encode OptionBool for track_volume: [1, 1] = Some(true) # Encode OptionBool for track_volume: [1, 1] = Some(true)