From a33f4fd035fdd2b8452168e73557ffc8465c1175 Mon Sep 17 00:00:00 2001 From: Anton Sauchyk <43762166+smypmsa@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:26:26 +0200 Subject: [PATCH] fix(learning-examples): repair crashing listeners and decoders, prune obsolete paths, unify naming (#181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audited every script in learning-examples/ against mainnet. Broken — found by running them, all invisible offline: - listen_geyser.py crashed with IndexError after ~11 coins: it never resolved v0 address-lookup-table accounts, which geyser reports in meta.loaded_writable_addresses / loaded_readonly_addresses. Resolving them removes the crash and brings detections level with the WebSocket listeners, 35 coins each per 150 s. - compare_listeners.py logged 13,090,862 error lines / 888 MB in 150 s and never printed its own 30-second report: the inner recv() loop caught ConnectionClosed in a broad handler that only logged, so every following recv() raised at once and the outer reconnect handler was unreachable. Now 12 KB and exit 0. Same shape fixed in compare_migration_listeners.py, listen_blocksubscribe.py and extract_blocksubscribe_transactions.py; the last two also gained the reconnect loop their siblings already had. - decode_from_gettransaction.py matched instructions on account count instead of discriminator, reporting a real 19-account create_v2 as claim_cashback with every account under the wrong name. It also walked only top-level instructions, and in 40 consecutive pump.fun transactions there was 1 top-level pump instruction against 8 inner ones. - decode_from_blocksubscribe.py crashed on every real create_v2: on chain the trailing args are variable length, 0001 in one tx and 00 in another, so is_cashback_enabled can be absent entirely. - poll_bonding_curve_progress.py polled a hardcoded dead mint and took no argv. Obsolete: - Delete listen_blocksubscribe_old_raydium.py. Seven minutes on mainnet produced 0 initialize2 events while the wrapper listener caught 3 real migrations. - Delete the duplicate geyser stubs and protos under listen-new-tokens/. The protos were byte-identical to src/geyser/proto and the stubs had drifted; both geyser examples now import src.geyser.generated. - Recapture all four fixtures. The old ones were from Aug 2024 and included a 49-byte pre-creator bonding curve. Behind the protocol: - fetch_price.py, get_bonding_curve_status.py, poll_bonding_curve_progress.py and decode_from_getaccountinfo.py never read quote_mint and scaled by a hardcoded 1e9. Against a live USDC-paired curve the price was off by 1000x. - get_pumpswap_pools.py stopped parsing at coin_creator and missed the i128 virtual_quote_reserves. Live pools carry 17.5845 SOL of them, which under-prices by 3.5-23.9% when ignored. Duplication and naming: - Merge manual_buy_cu_optimized.py into manual_buy.py --cu-optimized. The deleted file's docstring said 512 KB while its code used 16 MB; simulation confirms 512 KB and 4 MB both fail MaxLoadedAccountsDataSizeExceeded on Token-2022 mints, so 16 MB is the correct value. - Merge listen_logsubscribe_abc.py into listen_logsubscribe.py. Its ATA derivation hardcoded the legacy token program, so every Associated BC it printed for a Token2022 coin was an address that does not exist on chain. Fixed on merge and cross-checked 59/59 against on-chain accounts. - Remove 19 dead symbols. BREAKING_FEE_RECIPIENTS is still live in the PumpSwap scripts and stays there. - Normalize naming: kebab-case directories, RPC method names as one lowercase token, scripts verb-first. Rules documented in CLAUDE.md. get_graduating_tokens.py is knowingly left broken: getProgramAccounts over the whole pump program is now rejected by providers and it needs a getProgramAccountsV2 rewrite, which belongs in its own PR. Verified: both offline gates pass, all 41 examples parse, every read-only script exercised on mainnet against SOL- and USDC-paired coins, no new ruff findings (427 -> 413). No script that spends real funds was run. Co-authored-by: Claude Opus 5 (1M context) --- .gitignore | 4 +- CLAUDE.md | 84 +- README.md | 11 +- .../raw_create_tx_from_blockSubscribe.json | 274 ----- .../raw_create_tx_from_blocksubscribe.json | 481 +++++++++ .../get_bonding_curve_status.py | 66 +- .../poll_bonding_curve_progress.py | 143 ++- .../compute_associated_bonding_curve.py | 74 +- .../listen_wallet_transactions.py | 0 ...cribe.py => decode_from_blocksubscribe.py} | 29 +- .../decode_from_getTransaction.py | 152 --- ...tInfo.py => decode_from_getaccountinfo.py} | 58 +- .../decode_from_gettransaction.py | 284 ++++++ ...=> extract_blocksubscribe_transactions.py} | 61 +- learning-examples/fetch_price.py | 183 +++- .../compare_migration_listeners.py | 15 + .../listen_blocksubscribe_old_raydium.py | 116 --- .../listen-new-tokens/compare_listeners.py | 21 +- .../listen-new-tokens/generated/__init__.py | 0 .../listen-new-tokens/generated/geyser_pb2.py | 141 --- .../generated/geyser_pb2.pyi | 791 --------------- .../generated/geyser_pb2_grpc.py | 387 -------- .../generated/solana_storage_pb2.py | 76 -- .../generated/solana_storage_pb2.pyi | 385 ------- .../generated/solana_storage_pb2_grpc.py | 28 - .../listen_blocksubscribe.py | 18 +- .../listen-new-tokens/listen_geyser.py | 53 +- .../listen-new-tokens/listen_logsubscribe.py | 65 +- .../listen_logsubscribe_abc.py | 303 ------ .../listen-new-tokens/proto/geyser.proto | 262 ----- .../proto/solana-storage.proto | 149 --- learning-examples/manual_buy.py | 63 +- learning-examples/manual_buy_cu_optimized.py | 521 ---------- learning-examples/manual_buy_geyser.py | 100 -- learning-examples/mint_and_buy.py | 46 - learning-examples/mint_and_buy_v2.py | 46 - .../pumpswap/get_pumpswap_pools.py | 33 +- .../raw_bondingCurve_from_getAccountInfo.json | 1 - ...raw_bonding_curve_from_getaccountinfo.json | 21 + .../raw_buy_tx_from_getTransaction.json | 388 -------- .../raw_buy_tx_from_gettransaction.json | 698 +++++++++++++ .../raw_create_tx_from_getTransaction.json | 706 ------------- .../raw_create_tx_from_gettransaction.json | 938 ++++++++++++++++++ pyproject.toml | 2 +- 44 files changed, 3255 insertions(+), 5022 deletions(-) delete mode 100644 learning-examples/blockSubscribe-transactions/raw_create_tx_from_blockSubscribe.json create mode 100644 learning-examples/blocksubscribe-transactions/raw_create_tx_from_blocksubscribe.json rename learning-examples/{copytrading => copy-trading}/listen_wallet_transactions.py (100%) rename learning-examples/{decode_from_blockSubscribe.py => decode_from_blocksubscribe.py} (87%) delete mode 100644 learning-examples/decode_from_getTransaction.py rename learning-examples/{decode_from_getAccountInfo.py => decode_from_getaccountinfo.py} (60%) create mode 100644 learning-examples/decode_from_gettransaction.py rename learning-examples/{blockSubscribe_extract_transactions.py => extract_blocksubscribe_transactions.py} (62%) delete mode 100644 learning-examples/listen-migrations/listen_blocksubscribe_old_raydium.py delete mode 100644 learning-examples/listen-new-tokens/generated/__init__.py delete mode 100644 learning-examples/listen-new-tokens/generated/geyser_pb2.py delete mode 100644 learning-examples/listen-new-tokens/generated/geyser_pb2.pyi delete mode 100644 learning-examples/listen-new-tokens/generated/geyser_pb2_grpc.py delete mode 100644 learning-examples/listen-new-tokens/generated/solana_storage_pb2.py delete mode 100644 learning-examples/listen-new-tokens/generated/solana_storage_pb2.pyi delete mode 100644 learning-examples/listen-new-tokens/generated/solana_storage_pb2_grpc.py delete mode 100644 learning-examples/listen-new-tokens/listen_logsubscribe_abc.py delete mode 100644 learning-examples/listen-new-tokens/proto/geyser.proto delete mode 100644 learning-examples/listen-new-tokens/proto/solana-storage.proto delete mode 100644 learning-examples/manual_buy_cu_optimized.py delete mode 100644 learning-examples/raw_bondingCurve_from_getAccountInfo.json create mode 100644 learning-examples/raw_bonding_curve_from_getaccountinfo.json delete mode 100644 learning-examples/raw_buy_tx_from_getTransaction.json create mode 100644 learning-examples/raw_buy_tx_from_gettransaction.json delete mode 100644 learning-examples/raw_create_tx_from_getTransaction.json create mode 100644 learning-examples/raw_create_tx_from_gettransaction.json diff --git a/.gitignore b/.gitignore index 102ddd3..6842258 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ trades/* -# written by learning-examples/blockSubscribe_extract_transactions.py -blockSubscribe-transactions/ +# written by learning-examples/extract_blocksubscribe_transactions.py +blocksubscribe-transactions/ .vscode .pylintrc diff --git a/CLAUDE.md b/CLAUDE.md index 60feb52..65a8f26 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,6 +38,23 @@ registry in `platforms/__init__.py`. Listeners and the trader are platform-agnostic (`Universal*`); anything platform-shaped belongs under `platforms//`. +### Naming inside `learning-examples/` + +- **Directories are kebab-case** (`bonding-curve-progress`, `listen-new-tokens`, + `copy-trading`). A single-token product name stays one word (`pumpswap`). +- **Files are snake_case, verb first** — `fetch_price.py`, `decode_from_*.py`, + `extract_blocksubscribe_transactions.py`, `verify_*.py`, `simulate_*.py`. + Exceptions are the shared helper modules `pump_v2.py` and `tx_status.py`, which + are libraries rather than runnable scripts. +- **RPC and service names are lowercased into one token**, never camelCase: + `blocksubscribe`, `logsubscribe`, `programsubscribe`, `getaccountinfo`, + `gettransaction`, `pumpportal`. So `decode_from_gettransaction.py`, not + `decode_from_getTransaction.py`. +- Fixtures are `raw__from_.json` next to the script that reads + them, under the same rules. +- `live_*` marks a script that spends real funds; `simulate_*` and `verify_*` + never do. + ## Commands ```bash @@ -67,8 +84,11 @@ commented-out code). Type-hint public functions, Google-style docstrings, and Python 3.11+ (`requires-python = ">=3.11"`, matching ruff's target). Runtime deps are declared in `[project.dependencies]`; `ruff` and `grpcio-tools` live in `[dependency-groups] dev`, which `uv sync` installs by default. `grpcio-tools` -is protoc — needed only to regenerate the `geyser_pb2` stubs from `proto/`, never -at runtime. +is protoc — needed only to regenerate the `geyser_pb2` stubs in +`src/geyser/generated/` from `src/geyser/proto/`, never at runtime. That is the +**only** copy: the geyser examples reach it by putting the repo root on +`sys.path` and importing `src.geyser.generated`. Don't add a second copy under +`learning-examples/` — the last one drifted out of sync with the protos. ### Verifying pump.fun v2 trade instructions @@ -121,6 +141,47 @@ with `BuybackFeeRecipientMissing` (6062) printed as confirmed buys. and `str()` on it is empty, so the caller logs a blank reason. A slow `getAccountInfo` is enough to take down a whole listener run this way. +### Listener and decoder pitfalls + +Each of these was a live bug in `learning-examples/`, all of them invisible +offline and only visible after a couple of minutes against mainnet. + +- **A `while True: recv()` loop must break out on `websockets.ConnectionClosed`.** + Catching it in a broad `except Exception` that only logs makes the next `recv()` + raise immediately, forever: `compare_listeners.py` produced **13,090,862 error + lines / 888 MB in 150 s** and never reached its own 30-second report. The outer + reconnect handler with its `sleep` is unreachable in that shape. A narrow + `except TimeoutError` or `except json.JSONDecodeError` is fine to swallow — + those are per-message, not per-connection. +- **Resolve v0 lookup-table accounts before indexing them.** An instruction's + account indices can point past `message.account_keys` into the address lookup + table, which geyser reports in `meta.loaded_writable_addresses` then + `loaded_readonly_addresses` (that order). Ignoring them crashed the geyser + example with `IndexError` after ~11 coins in 150 s; resolving them removed the + crash and brought its detection count level with the WebSocket listeners + (35 coins each over the same window). +- **Identify an instruction by its 8-byte discriminator, never by account count.** + Several pump.fun instructions share a count, so counting mislabels them and + then prints every account under the wrong name — a real 19-account `create_v2` + was reported as `claim_cashback`. Note `buy_exact_sol_in` is also 18 accounts + on chain, same as legacy `buy`. +- **Walk `meta.innerInstructions`, not just `message.instructions`.** Most trades + reach the program as a CPI from a router or aggregator: in 40 consecutive + pump.fun transactions there was **1 top-level** pump instruction against + **8 inner** ones. Anchor's event-CPI prefix (`e445a52e51cb9a1d`) accounts for a + good share of the inner instructions; the event's own discriminator follows it. +- **`getProgramAccounts` over the whole pump program is rejected** by current + providers: *"Too many accounts requested (10000001 pubkeys) … use + getProgramAccountsV2 with pagination"*. It still works against pump-amm, which + is small enough. `bonding-curve-progress/get_graduating_tokens.py` is knowingly + broken on this and needs the V2 pagination rewrite. +- **`SetLoadedAccountsDataSizeLimit` must stay generous: 16 MB, not 512 KB.** + Verified by simulation on a Token-2022 mint with extensions — 512 KB and 4 MB + both fail `MaxLoadedAccountsDataSizeExceeded` with `unitsConsumed=0` (never + executed), while 16 MB reaches the buy instruction and is still 4x under the + 64 MB default. solders has no builder for it; encode `struct.pack("`. No bot config needed — they | Path | What it covers | |---|---| | `listen-new-tokens/` | One listener per method (`logs`, `blocks`, `geyser`, `pumpportal`) plus `compare_listeners.py` to race them | -| `listen-migrations/` | Detect a token graduating from the bonding curve to PumpSwap | +| `listen-migrations/` | Detect a token graduating from the bonding curve to PumpSwap, via the migration wrapper program or new pool accounts | | `bonding-curve-progress/` | Curve state, progress polling, and tokens close to graduating | | `pumpswap/` | Manual buy/sell against the PumpSwap AMM, and pool discovery | | `letsbonk-buy-sell/` | Manual exact-in / exact-out buys and sells on letsbonk.fun | -| `copytrading/` | Watch another wallet's transactions | -| `manual_buy.py`, `manual_sell.py`, `fetch_price.py` | The minimal pump.fun trade and price path | +| `copy-trading/` | Watch another wallet's transactions | +| `manual_buy.py`, `manual_sell.py`, `fetch_price.py` | The minimal pump.fun trade and price path. `manual_buy.py --cu-optimized` adds a `SetLoadedAccountsDataSizeLimit` instruction | | `mint_and_buy_v2.py` | Create a coin and buy it in one go | | `decode_from_*.py`, `calculate_discriminator.py` | Decoding account data, transactions, and Anchor discriminators | | `cleanup_accounts.py` | Close leftover empty token accounts | +Most of these take the mint or curve address as the first argument, and print usage if +you leave it off. The `decode_from_*.py` scripts fall back to the saved fixtures beside +them (`raw_*.json`), which are recaptured from mainnet rather than hand-edited — a +stale fixture makes a working decoder look broken and a broken one look fine. + Two examples double as verification scripts to run after any pump.fun program upgrade: ```bash diff --git a/learning-examples/blockSubscribe-transactions/raw_create_tx_from_blockSubscribe.json b/learning-examples/blockSubscribe-transactions/raw_create_tx_from_blockSubscribe.json deleted file mode 100644 index 233abc2..0000000 --- a/learning-examples/blockSubscribe-transactions/raw_create_tx_from_blockSubscribe.json +++ /dev/null @@ -1,274 +0,0 @@ -{ - "transaction": [ - "AYqt4iSMLUKIiCn+roUn59P7c0BroL8VCv5X+0515tjH9d5OCez5MIQdftuWcDwEymBNZMWiqy51LDU76WpahAMBAAoTcFi8Lm3PgW7X4XZm7q8+G4Jf4IaSLzptQdkNfSFrd2kW7510gs4rvSfIQ6BD7SbUQJaGC396SVFLuDF387+XgV1pfIfVUZFTFHxe1tb+5NIGBoToM9rJFbh9akpqDSa8XwszrDDJuVPznYGftPUIqlfBd55SSEGIUQWL6ZogaoujB/IYgIAD1tGqXa268xcm661aIHELJcoHVKW8TJPIRaOJkcMpfWvPuYxyTGf253mdFudiJ5NiHvVmi0CTGjvCsU4N5V6fuoY5br/VSM/4ySAR6se3W6qbLZxqhvWhcUHXqo+wYNgpG0xNR12v92LJa9wNrOs2wBLq0S7TqUhBYfprphss/CT2/qy59h94SA3zpgqeFhalg6tebfEaQX2yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVuD2k2Zaz0TbFWi/F1uqUYnLl/XS/ztlXSu2/W0YsAMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAABt324ddloZPZy+FGzut5rBy0he1fWzeROoz1hX7/AKkG3fbh7nWP3hhCXbzkbM3athr8TYO5DSf+vfko2KGL/Ai2qPUzOEL8dkpbTkkIfplULeP8horDFNap3dmbsYVGOoZeae4PVIDKvPZjV+TcLxjVjUXB6nSJ+zcj2Xk8cqZE+dQlVubfmlZx8g4Yr7VZS6dIqY5CCXXxzYTAYMWwb4yXJY9OJInxuz0QKRSODYMLWhOZ2v8QhASOe9jb6fhZrPE26wH8HE6IPSPItYRKtZo39mrdV8XprDtT4FnTXGT58ypqlPJGff+K9zL4EgTVmKxLEmG7xOccSwzdPrM4LwULAAUCiIoBAAsACQM83OEAAAAAAAkCAAYMAgAAAAAbtwAAAAAAEQYABQAQCQwBAA4PCQwKAgABBQMNDwcQCAQSXgAA4DIpAAAAAAAAAAAAAAAAAMGhI2gAAAAADAkBCgALAQAIDAAABgAEAAIBAQ0ADgEAAxgAZgY9EgHa6+quClnNAQIAAGjN5REAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", - "base64" - ], - "meta": { - "err": null, - "status": { - "Ok": null - }, - "fee": 1500000, - "preBalances": [ - 2005440908, - 0, - 4696550893895, - 13463471281, - 377180764, - 0, - 57019670, - 4441807831495, - 2039280, - 1, - 1141440, - 1, - 934087680, - 1141440, - 1141440, - 290898417, - 1461600, - 731913600, - 137104014 - ], - "postBalances": [ - 1686928628, - 0, - 4696553593895, - 13760771281, - 377329414, - 2039280, - 69019670, - 4441810655845, - 2039280, - 1, - 1141440, - 1, - 934087680, - 1141440, - 1141440, - 290898417, - 1461600, - 731913600, - 137104014 - ], - "innerInstructions": [ - { - "index": 3, - "instructions": [ - { - "programIdIndex": 12, - "accounts": [ - 16 - ], - "data": "84eT", - "stackHeight": 2 - }, - { - "programIdIndex": 9, - "accounts": [ - 0, - 5 - ], - "data": "11119os1e9qSs2u7TsThXqkBSRVFxhmYaFKFZ1waB2X7armDmvK3p5GmLdUxYdg3h7QSrL", - "stackHeight": 2 - }, - { - "programIdIndex": 12, - "accounts": [ - 5 - ], - "data": "P", - "stackHeight": 2 - }, - { - "programIdIndex": 12, - "accounts": [ - 5, - 16 - ], - "data": "6UhFp3r3cKbQWwHQYPuDqtb5CAdjXP45vy8Z8DQwgGRSQ", - "stackHeight": 2 - } - ] - }, - { - "index": 4, - "instructions": [ - { - "programIdIndex": 9, - "accounts": [ - 0, - 2 - ], - "data": "3Bxs4eMeB358Cb5h", - "stackHeight": 2 - }, - { - "programIdIndex": 10, - "accounts": [ - 15, - 7, - 16, - 3, - 8, - 5, - 0, - 9, - 12, - 4, - 18, - 10 - ], - "data": "AJTQ2h9DXrBo1MiibpgfkQHmpSKmNnQgP", - "stackHeight": 2 - }, - { - "programIdIndex": 12, - "accounts": [ - 8, - 5, - 3 - ], - "data": "3SpdELLWnXkK", - "stackHeight": 3 - }, - { - "programIdIndex": 9, - "accounts": [ - 0, - 4 - ], - "data": "3Bxs4VLT5WjmR4oh", - "stackHeight": 3 - }, - { - "programIdIndex": 9, - "accounts": [ - 0, - 3 - ], - "data": "3Bxs46HNXQ8jq79R", - "stackHeight": 3 - }, - { - "programIdIndex": 9, - "accounts": [ - 0, - 7 - ], - "data": "3Bxs4TJNecvxKcVV", - "stackHeight": 3 - }, - { - "programIdIndex": 10, - "accounts": [ - 18 - ], - "data": "2zjR1PvPvgqdhPdZLxuWCL7GiE5h1bKn4ziAcRd2FBFaC3kf2EYsG31a2aigsk9mgAfieqmo561JLMNk2uSKF65QKzv64GtLAULg9zNrDFfLe7DrBDcgQBwTwRqqLVkWBrksYNBFeyBeSPwcQe5DNEEqwfSowV6pk2t9QuN6JDSpxRegP8ekTV5zwc3ytD2hSo7wu9s4ynRb5ccHwRaoy9Lzm7M66sikRLa74mXuFzdjzGuq454PDDP8eqUSWxt1ddTchsUvqsAnv92vMN2BLu7XZ3UcTv96fz8KrV93qqHSsNwfKdCsY7QMwxbCE7R", - "stackHeight": 3 - } - ] - } - ], - "logMessages": [ - "Program ComputeBudget111111111111111111111111111111 invoke [1]", - "Program ComputeBudget111111111111111111111111111111 success", - "Program ComputeBudget111111111111111111111111111111 invoke [1]", - "Program ComputeBudget111111111111111111111111111111 success", - "Program 11111111111111111111111111111111 invoke [1]", - "Program 11111111111111111111111111111111 success", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]", - "Program log: Create", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: GetAccountDataSize", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1569 of 93653 compute units", - "Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program log: Initialize the associated token account", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: InitializeImmutableOwner", - "Program log: Please upgrade to SPL Token 2022 for immutable owner support", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 87066 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: InitializeAccount3", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4188 of 83184 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 21837 of 100550 compute units", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success", - "Program b1oomGGqPKGD6errbyfbVMBuzSC8WtAAYo8MwNafWW1 invoke [1]", - "Program log: Powered by https://telegram.bloombot.app", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", - "Program log: Instruction: Buy", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]", - "Program log: Instruction: Transfer", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 49415 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 11111111111111111111111111111111 invoke [3]", - "Program 11111111111111111111111111111111 success", - "Program 11111111111111111111111111111111 invoke [3]", - "Program 11111111111111111111111111111111 success", - "Program 11111111111111111111111111111111 invoke [3]", - "Program 11111111111111111111111111111111 success", - "Program data: vdt/007mYe5E+dQlVubfmlZx8g4Yr7VZS6dIqY5CCXXxzYTAYMWwbyBwuBEAAAAAT+SenZMEAAABcFi8Lm3PgW7X4XZm7q8+G4Jf4IaSLzptQdkNfSFrd2m6oSNoAAAAALHaOjAKAAAAgP3BigudAgCxLhc0AwAAAIBlrz56ngEA16qPsGDYKRtMTUddr/diyWvcDazrNsAS6tEu06lIQWFfAAAAAAAAAJ4YKwAAAAAAkJajVbvLxqgCZ/z53+NIXoh5GMXQLRXjoGjmO6GR/6UFAAAAAAAAAKpEAgAAAAAA", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [3]", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2006 of 33261 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 40072 of 70491 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program b1oomGGqPKGD6errbyfbVMBuzSC8WtAAYo8MwNafWW1 consumed 48895 of 78713 compute units", - "Program b1oomGGqPKGD6errbyfbVMBuzSC8WtAAYo8MwNafWW1 success" - ], - "preTokenBalances": [ - { - "accountIndex": 8, - "mint": "5eFg3giaX2c3RydHvx1S3yEKpYjBuwtLUsmbAAG9pump", - "uiTokenAmount": { - "uiAmount": 667654902.731215, - "decimals": 6, - "amount": "667654902731215", - "uiAmountString": "667654902.731215" - }, - "owner": "7Q1e26aB8kpyamjKPCt5oD73b2Hx7nAEjAMUwfHmZy7G", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - } - ], - "postTokenBalances": [ - { - "accountIndex": 5, - "mint": "5eFg3giaX2c3RydHvx1S3yEKpYjBuwtLUsmbAAG9pump", - "uiTokenAmount": { - "uiAmount": 5032051.139663, - "decimals": 6, - "amount": "5032051139663", - "uiAmountString": "5032051.139663" - }, - "owner": "8ZZ97eWp2k8gfoK2Jk2WQcdofk9hyJpEGDPGiqFryH1S", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - }, - { - "accountIndex": 8, - "mint": "5eFg3giaX2c3RydHvx1S3yEKpYjBuwtLUsmbAAG9pump", - "uiTokenAmount": { - "uiAmount": 662622851.591552, - "decimals": 6, - "amount": "662622851591552", - "uiAmountString": "662622851.591552" - }, - "owner": "7Q1e26aB8kpyamjKPCt5oD73b2Hx7nAEjAMUwfHmZy7G", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - } - ], - "rewards": null, - "loadedAddresses": { - "writable": [], - "readonly": [] - }, - "computeUnitsConsumed": 71182 - }, - "version": "legacy" -} \ No newline at end of file diff --git a/learning-examples/blocksubscribe-transactions/raw_create_tx_from_blocksubscribe.json b/learning-examples/blocksubscribe-transactions/raw_create_tx_from_blocksubscribe.json new file mode 100644 index 0000000..7ea1860 --- /dev/null +++ b/learning-examples/blocksubscribe-transactions/raw_create_tx_from_blocksubscribe.json @@ -0,0 +1,481 @@ +{ + "transaction": [ + "AtN2HVLNE5opUmngSFetR7lSQu7SZ8CssT5BsuqzkfAojSt18r380T01phxmbrBeKyLv/biulLSRd5eJaYo5HwQrVF3qv963GFTiJcxq4TYHech9QJrYenLiDSQjpOIMjxyoqV81Xx0qKxZEEb+PMn0E3WDy7W7zUp4V3mWI5JIPgAIACRlKQnktFp8fJjipwOpWq+KMs6dxuCT7xE1ftg2m5Ok4dmEkzaw3g7FEdwckLSh+VEI69Gdj+i5xuPZtldUKMuN/BSrl16fapySm6rCnKVSRhVrUoGcWYGdMTgNFWYA9ZaMMNf+pBVqOVo2o97wHVhUnTPHJLKQfQACcUWqkFMJ8cEJDhOG2exOSEqFEYkIFmA7a6IBpWg1QX7Ma05yqMBbGQ55lEMA9ZfrZMeidBL4Ltw1Rlx9RxBX7NEwH20GfISJWguZwRf+BTo08nZUIE1WYnLa7Vc4fD5WvzZwdQsj/YG0+2tkv8bg4waXv2CUBhL8mBfSDgMle1qOWj41yPavDb5q0pPGVjcCpyUw/tywHmVhD7aSF46JPEMaTmfgZlA9ywCps9gXMwprJyuPYimFyhbKnNpz8Jr5L+L5eo+IYNIFJhkVt+i1i+C6+DWShYUbqdjWAHXlzbyrS1zIKfxGqootf0mq0eaapzGy/awsj62GIWjceASCsqRO+7z0TiniyAz6mHIpGfJpPWgEvmMSP2ryJuB99oUO53ulKEcHgi+AEyHzrmPpc5H+AOAb9LHlF0pUklZrsAN7ZeBTzj3hG+gkRpUhjQS1jH04HhwMpbANfDRMzoNnIg41ztxD+bi38dEArL/cxv8VWJEJxTeLXWy2Il8/jfL4srbpuQyN/RwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK2uon2zxvPQTlzwogKfA+M5jwhTle/v7xcfxkr4F0EBVuD2k2Zaz0TbFWi/F1uqUYnLl/XS/ztlXSu2/W0YsAbFwc5jjSVn0mRosF65UdGijcxuEjSCtcZ1FJdw5ivyBt324e51j94YQl285GzN2rYa/E2DuQ0n/r35KNihi/w6hl5p7g9UgMq89mNX5NwvGNWNRcHqdIn7NyPZeTxypoyXJY9OJInxuz0QKRSODYMLWhOZ2v8QhASOe9jb6fhZmvId+FScLqAFyZZGD98s4aLo3WKmwZtOLpMYGA8Q/jes8TbrAfwcTog9I8i1hEq1mjf2at1XxemsO1PgWdNcZEVspp6AJZZQmzmcHbqPffgZh4ufjf2eSNKlcWhS9VN9AxIQARMKDxUAEBQWAhELBgQYEpEB1pBM7F+LMbQGAAAATllYT1JBBgAAAE5ZWE9SQVAAAABodHRwczovL2lwZnMuaW8vaXBmcy9iYWZrcmVpZ3V0dGlpdWZjbDI0eHRuemd4dnZvbmg3YjUzNWEzZGg2dHhyamd3YXgyaHllY3N5ajQ2aUpCeS0Wnx8mOKnA6lar4oyzp3G4JPvETV+2Dabk6Th2ABYGAAkAARAUAQESEhUNAQoPCQAQFAcYEg4MCAMXBRhmBj0SAdrr6oOjd6YzAwAAAPNvBgAAAAAA", + "base64" + ], + "meta": { + "err": null, + "status": { + "Ok": null + }, + "fee": 10000, + "preBalances": [ + 3490250000, + 0, + 11149834, + 6046720, + 0, + 1283540085, + 0, + 0, + 37290293, + 0, + 0, + 46722001573954, + 0, + 9339816446339, + 17016138, + 0, + 1, + 3104160, + 8502112342, + 1020235880, + 70128637, + 4089612038, + 3388605256, + 0, + 168261371 + ], + "postBalances": [ + 3377936405, + 3744480, + 11149834, + 6046720, + 0, + 1284009148, + 0, + 1187131, + 37290293, + 2074080, + 100441298, + 46722001573954, + 1844400, + 9339816915402, + 17016138, + 2074080, + 1, + 3104160, + 8502112342, + 1020235880, + 70128637, + 4089612038, + 3388605256, + 0, + 168261371 + ], + "innerInstructions": [ + { + "index": 0, + "instructions": [ + { + "programIdIndex": 16, + "accounts": [ + 0, + 1 + ], + "data": "11119EX7m7cQ1gzrTFmsb4bvG4q3n4AV3ZE5kapx4y1d1P2PRtFmcfWj9wWQ7kkadAvgLT", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 1 + ], + "data": "GC3i2jSx8awwe9xBfbR9LBTrzgFPUE9b56kGnez3cWMeYXGJnPmgtY5rED1m4XsF3X2uSDMFJ4bev8UjGefVNKbRM8", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 1 + ], + "data": "2zt6UCCHp66bJGRS4G7bTsjdxFh6FQ9sBEyRfGyPQKxYisAw", + "stackHeight": 2 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 10 + ], + "data": "11116K5vvUmhADFUYqW7YpVsZyjKkmyUr9Lhhg2Ww93d5ByeoqECM3GbgJVXShFbqLT6Yw", + "stackHeight": 2 + }, + { + "programIdIndex": 22, + "accounts": [ + 0, + 15, + 10, + 1, + 16, + 20 + ], + "data": "1", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 1 + ], + "data": "84eT", + "stackHeight": 3 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 15 + ], + "data": "11119ExAoTptm6xKUTUcw2V69MKmyEdDmRins3j3bK43o9nHeiYUtSiaT9pc292PhNQvxj", + "stackHeight": 3 + }, + { + "programIdIndex": 20, + "accounts": [ + 15 + ], + "data": "P", + "stackHeight": 3 + }, + { + "programIdIndex": 20, + "accounts": [ + 15, + 1 + ], + "data": "6VqPHofMMfuQJAEzZzrsRAXUWdRq24z8HgDFhn2YiSXg5", + "stackHeight": 3 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 1 + ], + "data": "3Bxs3zyNSVVdrTVR", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 1, + 19, + 1, + 19 + ], + "data": "gbNssdUdrb5FEGwgyBjJC33hzHi7xbozKF4q9fv3KVnZZbJ1tVcJ2ngaKcLfZzLmXdi9suAGYxA7tJa2dP5Z9EXNKmWbWw5HkvJd7MVpxraVGy12dWPgmzYCnYcoe5vJjxDTmv4vVEHrop9nAEM75C6Ve", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 1, + 19 + ], + "data": "BjBG9fDQbu1raSNbBZQYubkmLijGDjgXJHpedBBGGrFrgSFFPaBAwnF", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 1, + 15, + 19 + ], + "data": "6ApXSNCamGdm", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 1, + 19 + ], + "data": "31tb", + "stackHeight": 2 + }, + { + "programIdIndex": 18, + "accounts": [ + 24 + ], + "data": "4yiadJPqQG9uR3FVF217CVcHf3EYXokPGmBLocJxofbVKdZCq5CYegE5y5jdZjmYkQPm6knX6BWfEJVL6jxVN1xo1YMHCSUcwMhF1VDHgCQJAzhBUN2SKFfrDfZZprQZXnNeXrEX6kzFFNNHgZFWDSgzsDUbdE5tKi8kJjeuZ3P8jdkeB7g5cAdWKtvxLA8Z5k8VeXh8FNp5p6fxSLeNQLNTcRZRcvdsv1sUK8bF4ozUJXk55QrUQoU822HUdCe9AVEg2xY75vTVJUaBB2eBoC2YY9vmUcxkdWk3vojUVCCH3bdqALTDffhuwNstu7zFJRTbFA7WubupHct1qnxdeEtM4SfsxBReT7GqCxD1tZYkWmV8cGzP4sKkqivqPijMUrnnxkBoY5MijwoZjCLVkB4K8qYrf97zrYA3T49ipoXjpv6U4nHCatKs5DBNPA5CRwWBQJncVnE2H8UxWZzx8P1ZyXv1FP3jKN2sXzo449RUVPV", + "stackHeight": 2 + } + ] + }, + { + "index": 1, + "instructions": [ + { + "programIdIndex": 20, + "accounts": [ + 1 + ], + "data": "84eT", + "stackHeight": 2 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 9 + ], + "data": "11119ExAoTptm6xKUTUcw2V69MKmyEdDmRins3j3bK43o9nHeiYUtSiaT9pc292PhNQvxj", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 9 + ], + "data": "P", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 9, + 1 + ], + "data": "6S8adZGM4f3gfDTREGfkUZkdqtkpDDBMjf9SeEQBuYaQ5", + "stackHeight": 2 + } + ] + }, + { + "index": 2, + "instructions": [ + { + "programIdIndex": 16, + "accounts": [ + 0, + 12 + ], + "data": "11117Tknd8jUGTWe4i7BMwMh7mt2ibJWfGb66m7z4y7euUA7hvsZ7X6HejbWyRL9L9YtX1", + "stackHeight": 2 + }, + { + "programIdIndex": 3, + "accounts": [ + 8, + 18 + ], + "data": "6E5CZKNB2G93HVu9Syn6kkEUE5ZYBEkjrAWuGVNiSRvGq99", + "stackHeight": 2 + }, + { + "programIdIndex": 20, + "accounts": [ + 15, + 1, + 9, + 10 + ], + "data": "hn8daBDCC8gkd", + "stackHeight": 2 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 7 + ], + "data": "3Bxs3zxRSzKmp61u", + "stackHeight": 2 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 7 + ], + "data": "3Bxs4Ap5JCUQX88o", + "stackHeight": 2 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 10 + ], + "data": "3Bxs4C2nMw6T8d83", + "stackHeight": 2 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 5 + ], + "data": "3Bxs4CkxzAs8qffV", + "stackHeight": 2 + }, + { + "programIdIndex": 16, + "accounts": [ + 0, + 13 + ], + "data": "3Bxs4CkxzAs8qffV", + "stackHeight": 2 + }, + { + "programIdIndex": 18, + "accounts": [ + 24 + ], + "data": "T2jLjveMmM4gJ1fdXs3mfxY8kBWUQACBFmi2dJ8xHBEAbW2nH477LPqiGr2ayJz4FXgjjWBDKS6HwE8t3d6u499nNkzEJJNQXwEUweGnq91fy1vVX31TYSCU3FYa52enUzYUy8REpA7k1mg9uKQFskuMQuAX4k4aa5mv6PJvkfKbfu2oNo1k4Miej9ziFJzbPcxbE1uW5wyV4WiRUmHk4XJ7jPSJodPtB8weghgo4GnrU6VSV67HeJ1VmP7ExfkmvvN5qABdYwYm9eKbsEp48oJrz7nFgjrg5Hmp9sn5YfqYLs4xwCddTtuoFJdad7jn2BTJgkqNSZ3Jueps3bwrNdVK2KK54wbMkovfUaBuKX12br61rM8uZjYYb6RT7BeKZbtCNYqa6QKTsTZeSiq2e1gYCn6R15usAcPgX9azUocZreapm6oGByRKmFZCKFuMP7YjHw6tM5oT7Lm79oVUwN5d7LMMmHdXwcoHYiygMDmPiiLmznZd", + "stackHeight": 2 + } + ] + } + ], + "logMessages": [ + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", + "Program log: Instruction: CreateV2", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: MetadataPointerInstruction::Initialize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 925 of 587718 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: InitializeMint2", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1772 of 585130 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [2]", + "Program log: Create", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]", + "Program log: Instruction: GetAccountDataSize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1447 of 563891 compute units", + "Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [3]", + "Program 11111111111111111111111111111111 success", + "Program log: Initialize the associated token account", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]", + "Program log: Instruction: InitializeImmutableOwner", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 736 of 557622 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]", + "Program log: Instruction: InitializeAccount3", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1969 of 554550 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 16947 of 569224 compute units", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: TokenMetadataInstruction: Initialize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 3514 of 529205 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: TokenMetadataInstruction: UpdateAuthority", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 3871 of 523441 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: MintTo", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1714 of 517396 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: SetAuthority", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1044 of 513743 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program data: G3KpTd7rY3YGAAAATllYT1JBBgAAAE5ZWE9SQVAAAABodHRwczovL2lwZnMuaW8vaXBmcy9iYWZrcmVpZ3V0dGlpdWZjbDI0eHRuemd4dnZvbmg3YjUzNWEzZGg2dHhyamd3YXgyaHllY3N5ajQ2aWEkzaw3g7FEdwckLSh+VEI69Gdj+i5xuPZtldUKMuN/gUmGRW36LWL4Lr4NZKFhRup2NYAdeXNvKtLXMgp/EapKQnktFp8fJjipwOpWq+KMs6dxuCT7xE1ftg2m5Ok4dkpCeS0Wnx8mOKnA6lar4oyzp3G4JPvETV+2Dabk6Th23/NpagAAAAAAENhH488DAACsI/wGAAAAAHjF+1HRAgAAgMakfo0DAAbd9uHudY/eGEJdvORszdq2GvxNg7kNJ/69+SjYoYv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsI/wGAAAA", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2125 of 506400 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 96852 of 600000 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]", + "Program log: CreateIdempotent", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: GetAccountDataSize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1523 of 497888 compute units", + "Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program log: Initialize the associated token account", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: InitializeImmutableOwner", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 736 of 491543 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: InitializeAccount3", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2153 of 488474 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 17110 of 503148 compute units", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", + "Program log: Instruction: Buy", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ invoke [2]", + "Program log: Instruction: GetFees", + "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ consumed 3302 of 446130 compute units", + "Program return: pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ AAAAAAAAAABfAAAAAAAAAB4AAAAAAAAA", + "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: TransferChecked", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2562 of 439352 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program data: vdt/007mYe5hJM2sN4OxRHcHJC0oflRCOvRnY/oucbj2bZXVCjLjf0LO4gUAAAAAg6N3pjMDAAABSkJ5LRafHyY4qcDqVqvijLOncbgk+8RNX7YNpuTpOHbf82lqAAAAAEJ6BgIHAAAAfWxgoa/MAwBCzuIFAAAAAH3UTVUezgIA4ATIfOuY+lzkf4A4Bv0seUXSlSSVmuwA3tl4FPOPeEZfAAAAAAAAAI5QDgAAAAAASkJ5LRafHyY4qcDqVqvijLOncbgk+8RNX7YNpuTpOHYeAAAAAAAAADuFBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAGJ1eQAAAAAAAAAAAAAAAAAAAAAAiBMAAAAAAABHKAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAELO4gUAAAAAQnoGAgcAAABCzuIFAAAAAA==", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2125 of 418049 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 71995 of 486038 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success" + ], + "preTokenBalances": [], + "postTokenBalances": [ + { + "accountIndex": 9, + "mint": "7YD6ZHb39jGb33ki2iFd7kHK11yMkSFCc9kvjJscpump", + "uiTokenAmount": { + "uiAmount": 3520371.073923, + "decimals": 6, + "amount": "3520371073923", + "uiAmountString": "3520371.073923" + }, + "owner": "5zsxd4pGNCQpwyKiBWZ95nCTPsEPoS62xEGnjpW6FRy7", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 15, + "mint": "7YD6ZHb39jGb33ki2iFd7kHK11yMkSFCc9kvjJscpump", + "uiTokenAmount": { + "uiAmount": 996479628.926077, + "decimals": 6, + "amount": "996479628926077", + "uiAmountString": "996479628.926077" + }, + "owner": "9hgcsTpZP48Ttku3uhg5gZ388YFCfErayJ5rHSru9PF7", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + } + ], + "rewards": null, + "loadedAddresses": { + "writable": [], + "readonly": [] + }, + "computeUnitsConsumed": 185957, + "costUnits": 195591 + }, + "version": 0 +} \ No newline at end of file diff --git a/learning-examples/bonding-curve-progress/get_bonding_curve_status.py b/learning-examples/bonding-curve-progress/get_bonding_curve_status.py index c40769c..c144496 100644 --- a/learning-examples/bonding-curve-progress/get_bonding_curve_status.py +++ b/learning-examples/bonding-curve-progress/get_bonding_curve_status.py @@ -27,6 +27,36 @@ PUMP_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string( ) EXPECTED_DISCRIMINATOR: Final[bytes] = struct.pack(" tuple[Pubkey, str, int]: + """Resolve a curve's quote mint to its symbol and raw-unit scale. + + Args: + quote_mint: The curve's raw quote_mint field + + Returns: + (effective mint, display symbol, raw units per whole token) + """ + mint = WSOL_MINT if quote_mint == DEFAULT_QUOTE_MINT else quote_mint + decimals = QUOTE_DECIMALS.get(mint, 9) + return mint, QUOTE_SYMBOLS.get(mint, str(mint)), 10**decimals + class BondingCurveState: """ @@ -78,12 +108,29 @@ class BondingCurveState: "is_cashback_coin" / Flag, ) + # V5: V4 + quote_mint. Live accounts are 151 bytes — this struct covers 107 of the + # 143 data bytes and the remaining 36 are reserved padding. The quote-side reserves + # are in the quote mint's raw units, so a non-SOL coin must not be scaled by 1e9. + _STRUCT_V5 = Struct( + "virtual_token_reserves" / Int64ul, + "virtual_sol_reserves" / Int64ul, + "real_token_reserves" / Int64ul, + "real_sol_reserves" / Int64ul, + "token_total_supply" / Int64ul, + "complete" / Flag, + "creator" / Bytes(32), + "is_mayhem_mode" / Flag, + "is_cashback_coin" / Flag, + "quote_mint" / Bytes(32), + ) + def __init__(self, data: bytes) -> None: """Parse bonding curve data.""" if data[:8] != EXPECTED_DISCRIMINATOR: raise ValueError("Invalid curve state discriminator") total_length = len(data) + self.quote_mint = DEFAULT_QUOTE_MINT if total_length == 81: # V2: Creator only parsed = self._STRUCT_V2.parse(data[8:]) @@ -98,11 +145,17 @@ class BondingCurveState: self.creator = Pubkey.from_bytes(self.creator) self.is_cashback_coin = False - elif total_length >= 83: # V4: Creator + mayhem + cashback + elif total_length < _V5_MIN_LENGTH: # V4: Creator + mayhem + cashback parsed = self._STRUCT_V4.parse(data[8:]) self.__dict__.update(parsed) self.creator = Pubkey.from_bytes(self.creator) + elif total_length >= _V5_MIN_LENGTH: # V5: + quote_mint + parsed = self._STRUCT_V5.parse(data[8:]) + self.__dict__.update(parsed) + self.creator = Pubkey.from_bytes(self.creator) + self.quote_mint = Pubkey.from_bytes(self.quote_mint) + else: raise ValueError(f"Unexpected bonding curve size: {total_length} bytes") @@ -174,9 +227,14 @@ async def check_token_status(mint_address: str) -> None: client, bonding_curve_address ) + quote_mint, quote_symbol, quote_unit = resolve_quote_asset( + curve_state.quote_mint + ) + print("\nBonding curve status:") print("-" * 50) print(f"Creator: {curve_state.creator}") + print(f"Quote asset: {quote_symbol} ({quote_mint})") print( f"Mayhem Mode: {'✅ Enabled' if curve_state.is_mayhem_mode else '❌ Disabled'}" ) @@ -190,11 +248,13 @@ async def check_token_status(mint_address: str) -> None: print("\nBonding curve reserves:") print(f"Virtual Token: {curve_state.virtual_token_reserves:,}") print( - f"Virtual SOL: {curve_state.virtual_sol_reserves:,} lamports" + f"Virtual quote: {curve_state.virtual_sol_reserves:,} raw " + f"({curve_state.virtual_sol_reserves / quote_unit:,.6f} {quote_symbol})" ) print(f"Real Token: {curve_state.real_token_reserves:,}") print( - f"Real SOL: {curve_state.real_sol_reserves:,} lamports" + f"Real quote: {curve_state.real_sol_reserves:,} raw " + f"({curve_state.real_sol_reserves / quote_unit:,.6f} {quote_symbol})" ) print(f"Total Supply: {curve_state.token_total_supply:,}") diff --git a/learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py b/learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py index e094183..04448e6 100644 --- a/learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py +++ b/learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py @@ -1,11 +1,18 @@ -""" -Module for tracking the progress of a bonding curve for a Pump.fun token. -It continuously polls the bonding curve state and prints updates at regular intervals. +"""Track a pump.fun bonding curve's progress toward graduation. + +Usage: + uv run learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py + +Polls the curve every POLL_INTERVAL seconds. Progress is measured against +`Global.initial_real_token_reserves` read from chain rather than a hardcoded +constant, because a mayhem coin can be launched with different virtual params +(`set_mayhem_virtual_params`) and would otherwise show the wrong percentage. """ import asyncio import os import struct +import sys from typing import Final from dotenv import load_dotenv @@ -16,18 +23,39 @@ load_dotenv() # Constants RPC_URL: Final[str] = os.getenv("SOLANA_NODE_RPC_ENDPOINT") -TOKEN_MINT: Final[str] = ( - "5ZHx2GGGj87xpidVJpBqadMUutqBirhL2TqUR9T9taKc" # Replace with actual token mint address -) PUMP_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string( "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" ) -LAMPORTS_PER_SOL: Final[int] = 1_000_000_000 +PUMP_GLOBAL: Final[Pubkey] = Pubkey.from_string( + "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf" +) TOKEN_DECIMALS: Final[int] = 6 EXPECTED_DISCRIMINATOR: Final[bytes] = struct.pack( " Pubkey: @@ -83,29 +111,42 @@ def parse_curve_state(data: bytes) -> dict: # Parse common fields (present in all versions) fields = struct.unpack_from("= _LEN_WITH_QUOTE_MINT: # Has quote_mint + quote_mint = Pubkey.from_bytes(data[83:115]) + effective_quote_mint = WSOL_MINT if quote_mint == DEFAULT_QUOTE_MINT else quote_mint + quote_unit = 10 ** QUOTE_DECIMALS.get(effective_quote_mint, 9) + result = { "virtual_token_reserves": fields[0] / 10**TOKEN_DECIMALS, - "virtual_sol_reserves": fields[1] / LAMPORTS_PER_SOL, + "virtual_quote_reserves": fields[1] / quote_unit, "real_token_reserves": fields[2] / 10**TOKEN_DECIMALS, - "real_sol_reserves": fields[3] / LAMPORTS_PER_SOL, + "real_quote_reserves": fields[3] / quote_unit, "token_total_supply": fields[4] / 10**TOKEN_DECIMALS, "complete": fields[5], + "quote_mint": effective_quote_mint, + "quote_symbol": QUOTE_SYMBOLS.get( + effective_quote_mint, str(effective_quote_mint) + ), } # Parse creator field if present - data_length = len(data) - 8 - if data_length >= 73: # Has creator field + if data_length >= _LEN_WITH_CREATOR: # Has creator field creator_bytes = data[49:81] # 8 (discriminator) + 41 (base fields) = 49 result["creator"] = Pubkey.from_bytes(creator_bytes) # Parse is_mayhem_mode if present - if data_length >= 74: # Has mayhem mode field + if data_length >= _LEN_WITH_MAYHEM: # Has mayhem mode field result["is_mayhem_mode"] = bool(data[81]) else: result["is_mayhem_mode"] = False # Parse is_cashback_coin if present (added in late-Feb 2026 cashback upgrade) - if data_length >= 75: + if data_length >= _LEN_WITH_CASHBACK: result["is_cashback_coin"] = bool(data[82]) else: result["is_cashback_coin"] = False @@ -113,55 +154,87 @@ def parse_curve_state(data: bytes) -> dict: return result -def print_curve_status(state: dict) -> None: +async def fetch_initial_real_token_reserves(client: AsyncClient) -> float: + """Read the launch-time real token reserves from the Global account. + + Global layout up to this field: discriminator(8) + initialized(1) + + authority(32) + fee_recipient(32) + initial_virtual_token_reserves(8) + + initial_virtual_sol_reserves(8), so initial_real_token_reserves sits at 89. + + Args: + client: Connected RPC client + + Returns: + Initial real token reserves in whole tokens, or the fallback constant + """ + try: + resp = await client.get_account_info(PUMP_GLOBAL, encoding="base64") + data = resp.value.data + raw = struct.unpack_from(" None: """ Print the current status of the bonding curve in a readable format. Args: state: The parsed bonding curve state dictionary + baseline: Launch-time real token reserves, used as the 0% mark """ - progress = 0 + progress = 0.0 if state["complete"]: progress = 100.0 - else: - # Pump.fun constants (already converted to human-readable format) - TOTAL_SUPPLY = 1_000_000_000 # 1B tokens - RESERVED_TOKENS = 206_900_000 # 206.9M tokens reserved for migration - - initial_real_token_reserves = TOTAL_SUPPLY - RESERVED_TOKENS # 793.1M tokens - - if initial_real_token_reserves > 0: - left_tokens = state["real_token_reserves"] - progress = 100 - (left_tokens * 100) / initial_real_token_reserves + elif baseline > 0: + left_tokens = state["real_token_reserves"] + progress = 100 - (left_tokens * 100) / baseline + # A coin can hold more real tokens than Global's baseline — verified on a live + # mayhem/USDC coin with 797.17M against Global's 793.10M — which would print a + # negative percentage. Its launch reserves are not recoverable from the curve + # account alone, so treat that case as "nothing sold yet" rather than guess. + progress = max(progress, 0.0) print("=" * 30) print(f"Complete: {'✅' if state['complete'] else '❌'}") print(f"Progress: {progress:.2f}%") print(f"Token reserves: {state['real_token_reserves']:.4f}") - print(f"SOL reserves: {state['real_sol_reserves']:.4f}") + print(f"{state['quote_symbol']} reserves: {state['real_quote_reserves']:.6f}") print("=" * 30, "\n") -async def track_curve() -> None: +async def track_curve(token_mint: str) -> None: """ Continuously track and display the state of a bonding curve. + + Args: + token_mint: The mint address of the coin to follow """ - if not RPC_URL or not TOKEN_MINT: - print("❌ Set SOLANA_NODE_RPC_ENDPOINT and TOKEN_MINT in .env") + if not RPC_URL: + print("❌ Set SOLANA_NODE_RPC_ENDPOINT in .env") return - mint_pubkey: Pubkey = Pubkey.from_string(TOKEN_MINT) + mint_pubkey: Pubkey = Pubkey.from_string(token_mint) curve_pubkey: Pubkey = get_bonding_curve_address(mint_pubkey, PUMP_PROGRAM_ID) print("Tracking bonding curve for:", mint_pubkey) print("Curve address:", curve_pubkey, "\n") async with AsyncClient(RPC_URL) as client: + baseline = await fetch_initial_real_token_reserves(client) + print(f"Graduation baseline: {baseline:,.0f} tokens (from Global)\n") + while True: try: data = await get_account_data(client, curve_pubkey) state = parse_curve_state(data) - print_curve_status(state) + # Never let a coin that launched above Global's baseline read as + # negative progress; see the note in print_curve_status. + baseline = max(baseline, state["real_token_reserves"]) + print_curve_status(state, baseline) except Exception as e: print(f"⚠️ Error: {e}") @@ -169,4 +242,10 @@ async def track_curve() -> None: if __name__ == "__main__": - asyncio.run(track_curve()) + if len(sys.argv) < _MIN_ARGC: + print( + "Usage: uv run learning-examples/bonding-curve-progress/" + "poll_bonding_curve_progress.py " + ) + sys.exit(1) + asyncio.run(track_curve(sys.argv[1])) diff --git a/learning-examples/compute_associated_bonding_curve.py b/learning-examples/compute_associated_bonding_curve.py index c2eba7a..2979238 100644 --- a/learning-examples/compute_associated_bonding_curve.py +++ b/learning-examples/compute_associated_bonding_curve.py @@ -1,11 +1,27 @@ +"""Derive a coin's bonding curve and associated bonding curve, offline. + +Usage: + uv run learning-examples/compute_associated_bonding_curve.py + +The associated bonding curve is an ordinary ATA, so its address depends on which +token program owns the mint. Coins created with `create_v2` are Token2022; older +`create` coins are SPL Token. Deriving against the wrong program returns a +valid-looking address that does not exist on chain, so both are printed here — +this script makes no RPC calls and cannot tell which one a given mint is. +""" + +import sys + from solders.pubkey import Pubkey # Global constants PUMP_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P") SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") +TOKEN_2022_PROGRAM = Pubkey.from_string("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string( "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" ) +MIN_ARGC = 2 def get_bonding_curve_address(mint: Pubkey, program_id: Pubkey) -> tuple[Pubkey, int]: @@ -15,16 +31,25 @@ def get_bonding_curve_address(mint: Pubkey, program_id: Pubkey) -> tuple[Pubkey, return Pubkey.find_program_address([b"bonding-curve", bytes(mint)], program_id) -def find_associated_bonding_curve(mint: Pubkey, bonding_curve: Pubkey) -> Pubkey: +def find_associated_bonding_curve( + mint: Pubkey, bonding_curve: Pubkey, token_program: Pubkey = TOKEN_2022_PROGRAM +) -> Pubkey: """ Find the associated bonding curve for a given mint and bonding curve. This uses the standard ATA derivation. - """ + Args: + mint: The token mint address + bonding_curve: The bonding curve PDA + token_program: Token program owning the mint; Token2022 for create_v2 coins + + Returns: + The derived associated bonding curve address + """ derived_address, _ = Pubkey.find_program_address( [ bytes(bonding_curve), - bytes(SYSTEM_TOKEN_PROGRAM), + bytes(token_program), bytes(mint), ], SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM, @@ -32,29 +57,34 @@ def find_associated_bonding_curve(mint: Pubkey, bonding_curve: Pubkey) -> Pubkey return derived_address -def main(): - mint_address = input("Enter the token mint address: ") +def main() -> None: + """Print the curve PDAs for the mint given on the command line.""" + if len(sys.argv) < MIN_ARGC: + print( + "Usage: uv run learning-examples/compute_associated_bonding_curve.py " + ) + return try: - mint = Pubkey.from_string(mint_address) - - bonding_curve_address, bump = get_bonding_curve_address(mint, PUMP_PROGRAM) - - # Calculate the associated bonding curve - associated_bonding_curve = find_associated_bonding_curve( - mint, bonding_curve_address - ) - - print("\nResults:") - print("-" * 50) - print(f"Token Mint: {mint}") - print(f"Bonding Curve: {bonding_curve_address}") - print(f"Associated Bonding Curve: {associated_bonding_curve}") - print(f"Bonding Curve Bump: {bump}") - print("-" * 50) - + mint = Pubkey.from_string(sys.argv[1]) except ValueError as e: print(f"Error: Invalid address format - {e!s}") + return + + bonding_curve_address, bump = get_bonding_curve_address(mint, PUMP_PROGRAM) + + print("\nResults:") + print("-" * 62) + print(f"Token Mint: {mint}") + print(f"Bonding Curve: {bonding_curve_address}") + print(f"Bonding Curve Bump: {bump}") + for label, program in ( + ("Token2022 (create_v2 coins)", TOKEN_2022_PROGRAM), + ("SPL Token (legacy create)", SYSTEM_TOKEN_PROGRAM), + ): + derived = find_associated_bonding_curve(mint, bonding_curve_address, program) + print(f"Associated BC, {label:19s} {derived}") + print("-" * 62) if __name__ == "__main__": diff --git a/learning-examples/copytrading/listen_wallet_transactions.py b/learning-examples/copy-trading/listen_wallet_transactions.py similarity index 100% rename from learning-examples/copytrading/listen_wallet_transactions.py rename to learning-examples/copy-trading/listen_wallet_transactions.py diff --git a/learning-examples/decode_from_blockSubscribe.py b/learning-examples/decode_from_blocksubscribe.py similarity index 87% rename from learning-examples/decode_from_blockSubscribe.py rename to learning-examples/decode_from_blocksubscribe.py index 25ac706..2b16ae3 100644 --- a/learning-examples/decode_from_blockSubscribe.py +++ b/learning-examples/decode_from_blocksubscribe.py @@ -24,12 +24,36 @@ def decode_instruction(ix_data, ix_def): Supports the primitive scalar types and the `OptionBool` defined type (added in the late-Feb 2026 cashback upgrade — `OptionBool` is a struct wrapping a single bool, so it serializes as 1 byte on the wire). + + Trailing args can be absent from the wire entirely: two real mainnet + `create_v2` instructions carry `0001` and `00` respectively after `creator`, + so `is_cashback_enabled` is there in one and omitted in the other. Anything + the data runs out for is reported as None rather than raising. """ args = {} offset = 8 # Skip 8-byte discriminator + # Width each type needs before it can be read at all; strings carry their own + # 4-byte length prefix. + widths = { + "u64": 8, + "i64": 8, + "u32": 4, + "u16": 2, + "u8": 1, + "bool": 1, + "pubkey": 32, + "string": 4, + } + for arg in ix_def["args"]: t = arg["type"] + needed = widths.get(t, 1) if isinstance(t, str) else 1 + if offset + needed > len(ix_data): + # Truncated trailing arg: the sender omitted it. + args[arg["name"]] = None + continue + if t == "u64": value = struct.unpack_from(" offset: self.is_cashback_coin = bool(data[offset]) + offset += 1 else: self.is_cashback_coin = None + if len(data) >= offset + 32: + self.quote_mint = Pubkey.from_bytes(data[offset : offset + 32]) + else: + self.quote_mint = DEFAULT_QUOTE_MINT + else: self.creator = None self.is_mayhem_mode = None self.is_cashback_coin = None + self.quote_mint = DEFAULT_QUOTE_MINT + + @property + def effective_quote_mint(self) -> Pubkey: + """The quote mint to price against, resolving all-zeros to wrapped SOL.""" + return WSOL_MINT if self.quote_mint == DEFAULT_QUOTE_MINT else self.quote_mint + + @property + def quote_symbol(self) -> str: + """Display symbol of the quote asset.""" + mint = self.effective_quote_mint + return QUOTE_SYMBOLS.get(mint, str(mint)) + + @property + def quote_units(self) -> int: + """Raw units per whole token of the quote asset.""" + return 10 ** QUOTE_DECIMALS.get(self.effective_quote_mint, 9) def calculate_bonding_curve_price(curve_state: BondingCurveState) -> float: if curve_state.virtual_token_reserves <= 0 or curve_state.virtual_sol_reserves <= 0: raise ValueError("Invalid reserve state") - return (curve_state.virtual_sol_reserves / LAMPORTS_PER_SOL) / ( + return (curve_state.virtual_sol_reserves / curve_state.quote_units) / ( curve_state.virtual_token_reserves / 10**TOKEN_DECIMALS ) @@ -82,8 +113,13 @@ def decode_bonding_curve_data(raw_data: str) -> BondingCurveState: return BondingCurveState(decoded_data) -# Load the JSON data -with open("learning-examples/raw_bondingCurve_from_getAccountInfo.json") as file: +# Load the JSON data: pass a getAccountInfo response as argv[1], or use the fixture +curve_file = ( + sys.argv[1] + if len(sys.argv) > 1 + else "learning-examples/raw_bonding_curve_from_getaccountinfo.json" +) +with open(curve_file) as file: json_data = json.load(file) # Extract the base64 encoded data @@ -93,13 +129,19 @@ encoded_data = json_data["result"]["value"]["data"][0] bonding_curve_state = decode_bonding_curve_data(encoded_data) # Calculate and print the token price -token_price_sol = calculate_bonding_curve_price(bonding_curve_state) +token_price = calculate_bonding_curve_price(bonding_curve_state) +symbol = bonding_curve_state.quote_symbol print("Bonding Curve State:") print(f" Virtual Token Reserves: {bonding_curve_state.virtual_token_reserves}") -print(f" Virtual SOL Reserves: {bonding_curve_state.virtual_sol_reserves}") +print( + f" Virtual Quote Reserves: {bonding_curve_state.virtual_sol_reserves} raw {symbol}" +) print(f" Real Token Reserves: {bonding_curve_state.real_token_reserves}") -print(f" Real SOL Reserves: {bonding_curve_state.real_sol_reserves}") +print(f" Real Quote Reserves: {bonding_curve_state.real_sol_reserves} raw {symbol}") print(f" Token Total Supply: {bonding_curve_state.token_total_supply}") print(f" Complete: {bonding_curve_state.complete}") -print(f"\nToken Price: {token_price_sol:.10f} SOL") +print(f" Mayhem Mode: {bonding_curve_state.is_mayhem_mode}") +print(f" Cashback Coin: {bonding_curve_state.is_cashback_coin}") +print(f" Quote Mint: {bonding_curve_state.effective_quote_mint}") +print(f"\nToken Price: {token_price:.10f} {symbol}") diff --git a/learning-examples/decode_from_gettransaction.py b/learning-examples/decode_from_gettransaction.py new file mode 100644 index 0000000..0ddd88f --- /dev/null +++ b/learning-examples/decode_from_gettransaction.py @@ -0,0 +1,284 @@ +"""Decode the pump.fun instructions in a getTransaction response. + +Usage: + uv run learning-examples/decode_from_gettransaction.py [tx.json] + +Two things this example exists to show, because both are easy to get wrong: + +1. Identify an instruction by its **8-byte Anchor discriminator**, not by how many + accounts it carries. Several pump.fun instructions share an account count, so + matching on the count alone silently labels a `create_v2` as `claim_cashback` + and then prints every account under the wrong name. + +2. Read `meta.innerInstructions` as well as `message.instructions`. Most pump.fun + trades reach the program as a CPI from an aggregator or router, so a decoder + that only walks the top level sees almost nothing — in a sample of 40 consecutive + pump.fun transactions there was 1 top-level pump instruction against 8 inner ones. +""" + +import hashlib +import json +import struct +import sys +from collections.abc import Iterator + +import base58 + +PUMP_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" +DEFAULT_TX = "learning-examples/raw_buy_tx_from_gettransaction.json" +IDL_PATH = "idl/pump_fun_idl.json" + +# Anchor's event-CPI prefix. Every emitted event shows up as an inner instruction +# that calls the program itself with this discriminator, followed by the event's own +# 8-byte discriminator. Without recognising it, half the inner instructions in a +# trade look like unknown instructions. +ANCHOR_EVENT_CPI = bytes([0xE4, 0x45, 0xA5, 0x2E, 0x51, 0xCB, 0x9A, 0x1D]) + +DISCRIMINATOR_LEN = 8 +# v2 trade args: discriminator + two u64, with no track_volume OptionBool. +TRADE_DATA_LEN = 24 +EXPECTED_ARGC = 2 + + +def anchor_discriminator(name: str) -> bytes: + """Return the 8-byte Anchor discriminator for an instruction name. + + Args: + name: snake_case instruction name as it appears in the IDL + + Returns: + First 8 bytes of sha256("global:") + """ + return hashlib.sha256(f"global:{name}".encode()).digest()[:8] + + +def build_instruction_index(idl: dict) -> dict[bytes, dict]: + """Map every IDL instruction to its discriminator. + + Args: + idl: Parsed Anchor IDL + + Returns: + discriminator -> IDL instruction definition + """ + return {anchor_discriminator(ix["name"]): ix for ix in idl.get("instructions", [])} + + +def build_event_index(idl: dict) -> dict[bytes, str]: + """Map every IDL event to its discriminator. + + Args: + idl: Parsed Anchor IDL + + Returns: + discriminator -> event name + """ + return { + hashlib.sha256(f"event:{event['name']}".encode()).digest()[:8]: event["name"] + for event in idl.get("events", []) + } + + +def decode_create_instruction(data: bytes) -> dict: + """Decode a legacy `create` instruction (Metaplex tokens). + + Args: + data: Raw instruction data including the discriminator + + Returns: + Decoded args: name, symbol, uri, creator + """ + offset = 8 # Skip the 8-byte discriminator + results = [] + for _ in range(3): + length = struct.unpack_from(" dict: + """Decode a `create_v2` instruction (Token2022 tokens). + + IDL args: name, symbol, uri, creator (pubkey), is_mayhem_mode (bool), + is_cashback_enabled (OptionBool = 1 byte). + + Args: + data: Raw instruction data including the discriminator + + Returns: + Decoded args including the mayhem and cashback flags + """ + offset = 8 # Skip the 8-byte discriminator + results = [] + for _ in range(3): + length = struct.unpack_from(" dict: + """Decode the two u64 args shared by buy/sell and their v2 forms. + + v2 args carry no `track_volume` OptionBool: 24 bytes of data, being the + discriminator plus two u64. The quote-side limit is denominated in the quote + mint's raw units — lamports for SOL, 1e-6 for USDC. + + Args: + data: Raw instruction data including the discriminator + + Returns: + The token amount and the quote-side limit + """ + if len(data) < TRADE_DATA_LEN: + return {"error": f"expected >={TRADE_DATA_LEN} bytes of data, got {len(data)}"} + amount, quote_limit = struct.unpack_from(" Iterator[tuple[str, dict]]: + """Yield every pump.fun instruction in a getTransaction result. + + Args: + result: The `result` object of a jsonParsed getTransaction response + + Yields: + (location, instruction) where location is "top-level" or "inner (ix N)" + """ + for ix in result["transaction"]["message"].get("instructions", []): + if ix.get("programId") == PUMP_PROGRAM and ix.get("data"): + yield "top-level", ix + for group in result.get("meta", {}).get("innerInstructions") or []: + for ix in group.get("instructions", []): + if ix.get("programId") == PUMP_PROGRAM and ix.get("data"): + yield f"inner (ix {group['index']})", ix + + +def describe( + location: str, ix: dict, index: dict[bytes, dict], events: dict[bytes, str] +) -> None: + """Print one pump.fun instruction, resolved against the IDL. + + Args: + location: Where the instruction sits in the transaction + ix: The jsonParsed instruction + index: discriminator -> IDL instruction definition + events: discriminator -> IDL event name + """ + data = base58.b58decode(ix["data"]) + accounts = ix.get("accounts", []) + + if data[:8] == ANCHOR_EVENT_CPI: + event = events.get(data[8:16], "unknown event") + print(f"\n[{location}] anchor event emit -> {event}") + return + + definition = index.get(data[:8]) + + if definition is None: + disc = ( + struct.unpack("= DISCRIMINATOR_LEN + else None + ) + print(f"\n[{location}] unknown pump.fun instruction (discriminator {disc})") + return + + name = definition["name"] + print(f"\n[{location}] {name}") + + decoder = DECODERS.get(name) + print(f" args: {decoder(data) if decoder else '(no decoder in this example)'}") + + # The IDL under-reports the legacy instructions and omits create_v2's optional + # remaining accounts, so name what it covers and list the rest positionally. + idl_accounts = definition.get("accounts", []) + print(f" accounts: {len(accounts)} on chain, {len(idl_accounts)} named in the IDL") + for i, account in enumerate(accounts): + label = idl_accounts[i]["name"] if i < len(idl_accounts) else f"" + print(f" {i:2d} {label}: {account}") + + +def main() -> None: + """Decode the pump.fun instructions of one saved transaction.""" + tx_file_path = sys.argv[1] if len(sys.argv) == EXPECTED_ARGC else DEFAULT_TX + if len(sys.argv) != EXPECTED_ARGC: + print(f"No path provided, using the path: {tx_file_path}") + + with open(IDL_PATH) as f: + idl = json.load(f) + index = build_instruction_index(idl) + events = build_event_index(idl) + + with open(tx_file_path) as f: + result = json.load(f)["result"] + + found = 0 + for location, ix in iter_pump_instructions(result): + describe(location, ix, index, events) + found += 1 + + if not found: + print( + "\nNo pump.fun instruction in this transaction. That is normal for a " + "router transaction whose pump.fun call was not captured in meta." + ) + + message = result["transaction"]["message"] + print("\nTransaction Information:") + print(f"Blockhash: {message['recentBlockhash']}") + print(f"Fee payer: {message['accountKeys'][0]['pubkey']}") + print(f"Signature: {result['transaction']['signatures'][0]}") + print(f"Slot: {result.get('slot')}") + + +if __name__ == "__main__": + main() diff --git a/learning-examples/blockSubscribe_extract_transactions.py b/learning-examples/extract_blocksubscribe_transactions.py similarity index 62% rename from learning-examples/blockSubscribe_extract_transactions.py rename to learning-examples/extract_blocksubscribe_transactions.py index 152202f..c043bf4 100644 --- a/learning-examples/blockSubscribe_extract_transactions.py +++ b/learning-examples/extract_blocksubscribe_transactions.py @@ -18,10 +18,32 @@ WSS_ENDPOINT = os.environ.get("SOLANA_NODE_WSS_ENDPOINT") WEBSOCKET_MAX_MESSAGE_BYTES = 32 * 1024 * 1024 +def extract_signature(tx: dict) -> str | None: + """Pull the first signature out of a blockSubscribe transaction entry. + + The encoding decides the shape: base64 gives `transaction` as a list whose + first element is the signature, jsonParsed gives a dict with `signatures`. + + Args: + tx: One entry from `block["transactions"]` + + Returns: + The signature string, or None if this entry carries no transaction + """ + if not isinstance(tx, dict): + return None + raw = tx.get("transaction") + if isinstance(raw, list) and raw: + return raw[0] + if isinstance(raw, dict) and raw.get("signatures"): + return raw["signatures"][0] + return None + + async def save_transaction(tx_data, tx_signature): - os.makedirs("blockSubscribe-transactions", exist_ok=True) + os.makedirs("blocksubscribe-transactions", exist_ok=True) hashed_signature = hashlib.sha256(tx_signature.encode()).hexdigest() - file_path = os.path.join("blockSubscribe-transactions", f"{hashed_signature}.json") + file_path = os.path.join("blocksubscribe-transactions", f"{hashed_signature}.json") with open(file_path, "w") as f: json.dump(tx_data, f, indent=2) print(f"Saved transaction: {hashed_signature[:8]}...") @@ -64,27 +86,30 @@ async def listen_for_transactions(): if "transactions" in block: transactions = block["transactions"] for tx in transactions: - if isinstance(tx, dict) and "transaction" in tx: - if ( - isinstance(tx["transaction"], list) - and len(tx["transaction"]) > 0 - ): - tx_signature = tx["transaction"][0] - elif ( - isinstance(tx["transaction"], dict) - and "signatures" in tx["transaction"] - ): - tx_signature = tx["transaction"][ - "signatures" - ][0] - else: - continue + tx_signature = extract_signature(tx) + if tx_signature: await save_transaction(tx, tx_signature) elif "result" in data: print("Subscription confirmed") + except websockets.ConnectionClosed: + # Leave the recv loop so main() can reconnect. Swallowing this here + # would make the next recv() raise immediately, spinning the loop. + print("WebSocket connection closed.") + break except Exception as e: print(f"An error occurred: {e!s}") +async def main() -> None: + """Reconnect for as long as the script runs.""" + while True: + try: + await listen_for_transactions() + except (websockets.WebSocketException, OSError) as e: + print(f"Connection error: {e!s}") + print("Reconnecting in 5 seconds...") + await asyncio.sleep(5) + + if __name__ == "__main__": - asyncio.run(listen_for_transactions()) + asyncio.run(main()) diff --git a/learning-examples/fetch_price.py b/learning-examples/fetch_price.py index 25c3f2b..3c6d03b 100644 --- a/learning-examples/fetch_price.py +++ b/learning-examples/fetch_price.py @@ -1,3 +1,14 @@ +"""Read one pump.fun bonding curve and print the token price in its quote asset. + +Usage: + uv run learning-examples/fetch_price.py + +pump.fun coins are not all SOL-paired. The curve carries a `quote_mint`, and the +quote-side reserves are denominated in that mint's raw units — 1e9 for SOL, 1e6 for +USDC. Dividing by a hardcoded 1e9 prints a USDC-paired coin's price 1000x too low. +`quote_mint` is `Pubkey::default()` (all zeros) on SOL-paired coins. +""" + import asyncio import os import struct @@ -9,14 +20,27 @@ from dotenv import load_dotenv from solana.rpc.async_api import AsyncClient from solders.pubkey import Pubkey -LAMPORTS_PER_SOL: Final[int] = 1_000_000_000 TOKEN_DECIMALS: Final[int] = 6 -# Bonding curve address: pass as argv[1], or hardcode here. -CURVE_ADDRESS: Final[str] = sys.argv[1] if len(sys.argv) > 1 else "..." + +WSOL_MINT: Final[Pubkey] = Pubkey.from_string( + "So11111111111111111111111111111111111111112" +) +USDC_MINT: Final[Pubkey] = Pubkey.from_string( + "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" +) +# All-zero quote_mint means the coin is SOL-paired. +DEFAULT_QUOTE_MINT: Final[Pubkey] = Pubkey.from_bytes(bytes(32)) +QUOTE_DECIMALS: Final[dict[Pubkey, int]] = {WSOL_MINT: 9, USDC_MINT: 6} +QUOTE_SYMBOLS: Final[dict[Pubkey, str]] = {WSOL_MINT: "SOL", USDC_MINT: "USDC"} # Here and later all the discriminators are precalculated. See learning-examples/calculate_discriminator.py EXPECTED_DISCRIMINATOR: Final[bytes] = struct.pack(" None: - """Parse bonding curve data - auto-detects version.""" - data_length = len(data) - 8 + # Current layout. The account is 151 bytes: this struct is 107 bytes after the + # 8-byte discriminator, and the remaining 36 are reserved padding. + _STRUCT_V4 = Struct( + "virtual_token_reserves" / Int64ul, + "virtual_quote_reserves" / Int64ul, + "real_token_reserves" / Int64ul, + "real_quote_reserves" / Int64ul, + "token_total_supply" / Int64ul, + "complete" / Flag, + "creator" / Bytes(32), + "is_mayhem_mode" / Flag, + "is_cashback_coin" / Flag, + "quote_mint" / Bytes(32), + ) - if data_length < 73: # V1: without creator and mayhem mode - parsed = self._STRUCT_V1.parse(data[8:]) - self.__dict__.update(parsed) - self.creator = None - self.is_mayhem_mode = False - elif data_length == 73: # V2: with creator, without mayhem mode - parsed = self._STRUCT_V2.parse(data[8:]) - self.__dict__.update(parsed) - if isinstance(self.creator, bytes): - self.creator = Pubkey.from_bytes(self.creator) - self.is_mayhem_mode = False - else: # V3: with creator and mayhem mode - parsed = self._STRUCT_V3.parse(data[8:]) - self.__dict__.update(parsed) - if isinstance(self.creator, bytes): - self.creator = Pubkey.from_bytes(self.creator) + def __init__(self, data: bytes) -> None: + """Parse bonding curve data - auto-detects version. + + Args: + data: Raw account data including the 8-byte discriminator + """ + body = data[8:] + data_length = len(body) + + self.creator = None + self.is_mayhem_mode = False + self.is_cashback_coin = False + self.quote_mint = DEFAULT_QUOTE_MINT + + if data_length < _V2_LENGTH: # V1: without creator and mayhem mode + parsed = self._STRUCT_V1.parse(body) + elif data_length == _V2_LENGTH: # V2: with creator, without mayhem mode + parsed = self._STRUCT_V2.parse(body) + elif data_length < _V4_LENGTH: # V3: with creator and mayhem mode + parsed = self._STRUCT_V3.parse(body) + else: # V4: adds is_cashback_coin and quote_mint + parsed = self._STRUCT_V4.parse(body) + + self.__dict__.update(parsed) + if isinstance(self.creator, bytes): + self.creator = Pubkey.from_bytes(self.creator) + if isinstance(self.quote_mint, bytes): + self.quote_mint = Pubkey.from_bytes(self.quote_mint) + + # The SOL-named fields were renamed when non-SOL quote assets landed. Keep the + # old names working for anything that still reads them. + self.virtual_sol_reserves = self.virtual_quote_reserves + self.real_sol_reserves = self.real_quote_reserves + + +def normalize_quote_mint(quote_mint: Pubkey) -> Pubkey: + """Resolve an all-zero quote mint to wrapped SOL. + + Args: + quote_mint: The curve's raw quote_mint field + + Returns: + The effective quote mint + """ + return WSOL_MINT if quote_mint == DEFAULT_QUOTE_MINT else quote_mint + + +def quote_units(quote_mint: Pubkey) -> int: + """Return the raw units per whole token of the quote mint. + + Args: + quote_mint: The effective quote mint + + Returns: + 1e9 for SOL, 1e6 for USDC, defaulting to 1e9 for an unknown mint + """ + return 10 ** QUOTE_DECIMALS.get(quote_mint, 9) async def get_bonding_curve_state( conn: AsyncClient, curve_address: Pubkey ) -> BondingCurveState: + """Fetch and parse a bonding curve account. + + Args: + conn: Connected RPC client + curve_address: The bonding curve PDA + + Returns: + The parsed curve state + + Raises: + ValueError: If the account is missing or is not a bonding curve + """ response = await conn.get_account_info(curve_address, encoding="base64") if not response.value or not response.value.data: raise ValueError("Invalid curve state: No data") @@ -92,23 +180,50 @@ async def get_bonding_curve_state( def calculate_bonding_curve_price(curve_state: BondingCurveState) -> float: - if curve_state.virtual_token_reserves <= 0 or curve_state.virtual_sol_reserves <= 0: + """Price one token in the curve's quote asset. + + Args: + curve_state: The parsed curve state + + Returns: + Price per token, denominated in the quote mint + + Raises: + ValueError: If either virtual reserve is non-positive + """ + if ( + curve_state.virtual_token_reserves <= 0 + or curve_state.virtual_quote_reserves <= 0 + ): raise ValueError("Invalid reserve state") - return (curve_state.virtual_sol_reserves / LAMPORTS_PER_SOL) / ( + quote_mint = normalize_quote_mint(curve_state.quote_mint) + return (curve_state.virtual_quote_reserves / quote_units(quote_mint)) / ( curve_state.virtual_token_reserves / 10**TOKEN_DECIMALS ) async def main() -> None: + """Print the price of the coin behind the bonding curve given on the CLI.""" + if len(sys.argv) < 2: + print("Usage: uv run learning-examples/fetch_price.py ") + return + try: async with AsyncClient(RPC_ENDPOINT) as conn: - curve_address = Pubkey.from_string(CURVE_ADDRESS) - bonding_curve_state = await get_bonding_curve_state(conn, curve_address) - token_price_sol = calculate_bonding_curve_price(bonding_curve_state) + curve_address = Pubkey.from_string(sys.argv[1]) + state = await get_bonding_curve_state(conn, curve_address) + price = calculate_bonding_curve_price(state) + + quote_mint = normalize_quote_mint(state.quote_mint) + symbol = QUOTE_SYMBOLS.get(quote_mint, str(quote_mint)) print("Token price:") - print(f" {token_price_sol:.10f} SOL") + print(f" {price:.10f} {symbol}") + print(f"\nquote mint: {quote_mint}") + print(f"mayhem: {state.is_mayhem_mode}") + print(f"cashback: {state.is_cashback_coin}") + print(f"complete: {state.complete}") except ValueError as e: print(f"Error: {e}") except Exception as e: diff --git a/learning-examples/listen-migrations/compare_migration_listeners.py b/learning-examples/listen-migrations/compare_migration_listeners.py index 6f5fbd0..543ea38 100644 --- a/learning-examples/listen-migrations/compare_migration_listeners.py +++ b/learning-examples/listen-migrations/compare_migration_listeners.py @@ -538,6 +538,14 @@ async def listen_for_migrations(wss_url, provider_name, tracker, known_events=No except Exception as e: print(f"[ERROR] Failed to decode Program data: {e}") + except websockets.ConnectionClosed: + # Break out so the outer loop reconnects. Swallowing the + # disconnect here makes every following recv() raise + # immediately, spinning the loop instead of retrying. + print( + f"[WARN] Migration listener for {provider_name}: connection closed" + ) + break except Exception as e: print(f"[ERROR] Migration listener for {provider_name}: {e}") @@ -651,6 +659,13 @@ async def listen_for_markets(wss_url, provider_name, tracker, known_markets): except Exception as e: print(f"[ERROR] Failed to decode account: {e}") + except websockets.ConnectionClosed: + # Same reason as the migration listener above: break so the + # outer loop can reconnect instead of spinning on recv(). + print( + f"[WARN] Market listener for {provider_name}: connection closed" + ) + break except Exception as e: print(f"[ERROR] Market listener for {provider_name}: {e}") diff --git a/learning-examples/listen-migrations/listen_blocksubscribe_old_raydium.py b/learning-examples/listen-migrations/listen_blocksubscribe_old_raydium.py deleted file mode 100644 index 4ead3b1..0000000 --- a/learning-examples/listen-migrations/listen_blocksubscribe_old_raydium.py +++ /dev/null @@ -1,116 +0,0 @@ -import asyncio -import json -import os - -import websockets -from dotenv import load_dotenv -from solders.pubkey import Pubkey - -load_dotenv() - -WSS_ENDPOINT = os.environ.get("SOLANA_NODE_WSS_ENDPOINT") - -# Solana's blockSubscribe (and a busy logsSubscribe) sends frames well past -# websockets' 1 MiB default, which kills the connection with a 1009 close -# instead of delivering the message. Same value the bot's own listeners use. -WEBSOCKET_MAX_MESSAGE_BYTES = 32 * 1024 * 1024 -PUMP_MIGRATOR_ID = Pubkey.from_string("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg") - - -def process_initialize2_transaction(data): - """Process and decode an initialize2 transaction""" - try: - signature = data["transaction"]["signatures"][0] - account_keys = data["transaction"]["message"]["accountKeys"] - - # Check raydium_amm_idl.json for the account keys - # The token address is typically the 19th account (index 18) - # The liquidity pool address is typically the 3rd account (index 2) - if len(account_keys) > 18: - token_address = account_keys[18] - liquidity_address = account_keys[2] - - print(f"\nSignature: {signature}") - print(f"Token Address: {token_address}") - print(f"Liquidity Address: {liquidity_address}") - print("=" * 50) - else: - print(f"\nError: Not enough account keys (found {len(account_keys)})") - - except Exception as e: - print(f"\nError: {e!s}") - - -async def listen_for_events(): - while True: - try: - async with websockets.connect( - WSS_ENDPOINT, max_size=WEBSOCKET_MAX_MESSAGE_BYTES - ) as websocket: - subscription_message = json.dumps( - { - "jsonrpc": "2.0", - "id": 1, - "method": "blockSubscribe", - "params": [ - {"mentionsAccountOrProgram": str(PUMP_MIGRATOR_ID)}, - { - "commitment": "confirmed", - "encoding": "json", - "showRewards": False, - "transactionDetails": "full", - "maxSupportedTransactionVersion": 0, - }, - ], - } - ) - - await websocket.send(subscription_message) - response = await websocket.recv() - print(f"Subscription response: {response}") - print("\nListening for Raydium pool initialization events...") - - while True: - try: - response = await asyncio.wait_for(websocket.recv(), timeout=30) - data = json.loads(response) - - if "method" in data and data["method"] == "blockNotification": - if "params" in data and "result" in data["params"]: - block_data = data["params"]["result"] - if ( - "value" in block_data - and "block" in block_data["value"] - ): - block = block_data["value"]["block"] - if "transactions" in block: - for tx in block["transactions"]: - logs = tx.get("meta", {}).get( - "logMessages", [] - ) - - # Check for initialize2 instruction - for log in logs: - if ( - "Program log: initialize2: InitializeInstruction2" - in log - ): - print( - "Found initialize2 instruction!" - ) - process_initialize2_transaction(tx) - break - - except TimeoutError: - print("\nChecking connection...") - print("Connection alive") - continue - - except Exception as e: - print(f"\nConnection error: {e!s}") - print("Retrying in 5 seconds...") - await asyncio.sleep(5) - - -if __name__ == "__main__": - asyncio.run(listen_for_events()) diff --git a/learning-examples/listen-new-tokens/compare_listeners.py b/learning-examples/listen-new-tokens/compare_listeners.py index ed560dc..81195d6 100644 --- a/learning-examples/listen-new-tokens/compare_listeners.py +++ b/learning-examples/listen-new-tokens/compare_listeners.py @@ -38,7 +38,9 @@ import base64 import json import os import struct +import sys import time +from pathlib import Path import base58 import grpc @@ -47,6 +49,9 @@ from dotenv import load_dotenv from solders.pubkey import Pubkey from solders.transaction import VersionedTransaction +# Reach the shared geyser stubs in src/geyser/generated (imported lazily below). +sys.path.insert(0, str(Path(__file__).resolve().parents[2])) + load_dotenv(override=True) # Solana's blockSubscribe (and a busy logsSubscribe) sends frames well past @@ -617,6 +622,15 @@ async def listen_block_subscription(wss_url, provider_name, tracker, known_token except Exception as e: print(f"[ERROR] Failed to process transaction: {e}") + except websockets.ConnectionClosed: + # Break out so the outer loop reconnects. Without this the + # broad handler below swallows the disconnect and recv() + # raises again immediately, spinning at millions of + # iterations per minute. + print( + f"[WARN] Block listener for {provider_name}: connection closed" + ) + break except Exception as e: print(f"[ERROR] Block listener for {provider_name}: {e}") @@ -743,11 +757,12 @@ async def listen_geyser_grpc( Listen for new tokens via Geyser gRPC API """ try: - # Import the generated protobuf modules - from generated import geyser_pb2, geyser_pb2_grpc + # Generated once into src/geyser/generated; see CLAUDE.md for regenerating them. + from src.geyser.generated import geyser_pb2, geyser_pb2_grpc except ImportError: print( - "[ERROR] Could not import geyser_pb2 or geyser_pb2_grpc. Make sure to generate from .proto files" + "[ERROR] Could not import geyser_pb2 or geyser_pb2_grpc. " + "Regenerate them into src/geyser/generated from src/geyser/proto" ) return diff --git a/learning-examples/listen-new-tokens/generated/__init__.py b/learning-examples/listen-new-tokens/generated/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/learning-examples/listen-new-tokens/generated/geyser_pb2.py b/learning-examples/listen-new-tokens/generated/geyser_pb2.py deleted file mode 100644 index a2b1539..0000000 --- a/learning-examples/listen-new-tokens/generated/geyser_pb2.py +++ /dev/null @@ -1,141 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: geyser.proto -# Protobuf Python Version: 5.29.0 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, 5, 29, 0, "", "geyser.proto" -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from generated.solana_storage_pb2 import * - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x0cgeyser.proto\x12\x06geyser\x1a\x14solana-storage.proto"\xf6\t\n\x10SubscribeRequest\x12\x38\n\x08\x61\x63\x63ounts\x18\x01 \x03(\x0b\x32&.geyser.SubscribeRequest.AccountsEntry\x12\x32\n\x05slots\x18\x02 \x03(\x0b\x32#.geyser.SubscribeRequest.SlotsEntry\x12@\n\x0ctransactions\x18\x03 \x03(\x0b\x32*.geyser.SubscribeRequest.TransactionsEntry\x12M\n\x13transactions_status\x18\n \x03(\x0b\x32\x30.geyser.SubscribeRequest.TransactionsStatusEntry\x12\x34\n\x06\x62locks\x18\x04 \x03(\x0b\x32$.geyser.SubscribeRequest.BlocksEntry\x12=\n\x0b\x62locks_meta\x18\x05 \x03(\x0b\x32(.geyser.SubscribeRequest.BlocksMetaEntry\x12\x32\n\x05\x65ntry\x18\x08 \x03(\x0b\x32#.geyser.SubscribeRequest.EntryEntry\x12\x30\n\ncommitment\x18\x06 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x12\x46\n\x13\x61\x63\x63ounts_data_slice\x18\x07 \x03(\x0b\x32).geyser.SubscribeRequestAccountsDataSlice\x12/\n\x04ping\x18\t \x01(\x0b\x32\x1c.geyser.SubscribeRequestPingH\x01\x88\x01\x01\x1aW\n\rAccountsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32&.geyser.SubscribeRequestFilterAccounts:\x02\x38\x01\x1aQ\n\nSlotsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.geyser.SubscribeRequestFilterSlots:\x02\x38\x01\x1a_\n\x11TransactionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.geyser.SubscribeRequestFilterTransactions:\x02\x38\x01\x1a\x65\n\x17TransactionsStatusEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.geyser.SubscribeRequestFilterTransactions:\x02\x38\x01\x1aS\n\x0b\x42locksEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.geyser.SubscribeRequestFilterBlocks:\x02\x38\x01\x1a[\n\x0f\x42locksMetaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.geyser.SubscribeRequestFilterBlocksMeta:\x02\x38\x01\x1aQ\n\nEntryEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.geyser.SubscribeRequestFilterEntry:\x02\x38\x01\x42\r\n\x0b_commitmentB\x07\n\x05_ping"\xbf\x01\n\x1eSubscribeRequestFilterAccounts\x12\x0f\n\x07\x61\x63\x63ount\x18\x02 \x03(\t\x12\r\n\x05owner\x18\x03 \x03(\t\x12=\n\x07\x66ilters\x18\x04 \x03(\x0b\x32,.geyser.SubscribeRequestFilterAccountsFilter\x12#\n\x16nonempty_txn_signature\x18\x05 \x01(\x08H\x00\x88\x01\x01\x42\x19\n\x17_nonempty_txn_signature"\xf3\x01\n$SubscribeRequestFilterAccountsFilter\x12\x44\n\x06memcmp\x18\x01 \x01(\x0b\x32\x32.geyser.SubscribeRequestFilterAccountsFilterMemcmpH\x00\x12\x12\n\x08\x64\x61tasize\x18\x02 \x01(\x04H\x00\x12\x1d\n\x13token_account_state\x18\x03 \x01(\x08H\x00\x12H\n\x08lamports\x18\x04 \x01(\x0b\x32\x34.geyser.SubscribeRequestFilterAccountsFilterLamportsH\x00\x42\x08\n\x06\x66ilter"y\n*SubscribeRequestFilterAccountsFilterMemcmp\x12\x0e\n\x06offset\x18\x01 \x01(\x04\x12\x0f\n\x05\x62ytes\x18\x02 \x01(\x0cH\x00\x12\x10\n\x06\x62\x61se58\x18\x03 \x01(\tH\x00\x12\x10\n\x06\x62\x61se64\x18\x04 \x01(\tH\x00\x42\x06\n\x04\x64\x61ta"m\n,SubscribeRequestFilterAccountsFilterLamports\x12\x0c\n\x02\x65q\x18\x01 \x01(\x04H\x00\x12\x0c\n\x02ne\x18\x02 \x01(\x04H\x00\x12\x0c\n\x02lt\x18\x03 \x01(\x04H\x00\x12\x0c\n\x02gt\x18\x04 \x01(\x04H\x00\x42\x05\n\x03\x63mp"Y\n\x1bSubscribeRequestFilterSlots\x12!\n\x14\x66ilter_by_commitment\x18\x01 \x01(\x08H\x00\x88\x01\x01\x42\x17\n\x15_filter_by_commitment"\xd2\x01\n"SubscribeRequestFilterTransactions\x12\x11\n\x04vote\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x13\n\x06\x66\x61iled\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x16\n\tsignature\x18\x05 \x01(\tH\x02\x88\x01\x01\x12\x17\n\x0f\x61\x63\x63ount_include\x18\x03 \x03(\t\x12\x17\n\x0f\x61\x63\x63ount_exclude\x18\x04 \x03(\t\x12\x18\n\x10\x61\x63\x63ount_required\x18\x06 \x03(\tB\x07\n\x05_voteB\t\n\x07_failedB\x0c\n\n_signature"\xd9\x01\n\x1cSubscribeRequestFilterBlocks\x12\x17\n\x0f\x61\x63\x63ount_include\x18\x01 \x03(\t\x12!\n\x14include_transactions\x18\x02 \x01(\x08H\x00\x88\x01\x01\x12\x1d\n\x10include_accounts\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1c\n\x0finclude_entries\x18\x04 \x01(\x08H\x02\x88\x01\x01\x42\x17\n\x15_include_transactionsB\x13\n\x11_include_accountsB\x12\n\x10_include_entries""\n SubscribeRequestFilterBlocksMeta"\x1d\n\x1bSubscribeRequestFilterEntry"C\n!SubscribeRequestAccountsDataSlice\x12\x0e\n\x06offset\x18\x01 \x01(\x04\x12\x0e\n\x06length\x18\x02 \x01(\x04""\n\x14SubscribeRequestPing\x12\n\n\x02id\x18\x01 \x01(\x05"\x85\x04\n\x0fSubscribeUpdate\x12\x0f\n\x07\x66ilters\x18\x01 \x03(\t\x12\x31\n\x07\x61\x63\x63ount\x18\x02 \x01(\x0b\x32\x1e.geyser.SubscribeUpdateAccountH\x00\x12+\n\x04slot\x18\x03 \x01(\x0b\x32\x1b.geyser.SubscribeUpdateSlotH\x00\x12\x39\n\x0btransaction\x18\x04 \x01(\x0b\x32".geyser.SubscribeUpdateTransactionH\x00\x12\x46\n\x12transaction_status\x18\n \x01(\x0b\x32(.geyser.SubscribeUpdateTransactionStatusH\x00\x12-\n\x05\x62lock\x18\x05 \x01(\x0b\x32\x1c.geyser.SubscribeUpdateBlockH\x00\x12+\n\x04ping\x18\x06 \x01(\x0b\x32\x1b.geyser.SubscribeUpdatePingH\x00\x12+\n\x04pong\x18\t \x01(\x0b\x32\x1b.geyser.SubscribeUpdatePongH\x00\x12\x36\n\nblock_meta\x18\x07 \x01(\x0b\x32 .geyser.SubscribeUpdateBlockMetaH\x00\x12-\n\x05\x65ntry\x18\x08 \x01(\x0b\x32\x1c.geyser.SubscribeUpdateEntryH\x00\x42\x0e\n\x0cupdate_oneof"o\n\x16SubscribeUpdateAccount\x12\x33\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32".geyser.SubscribeUpdateAccountInfo\x12\x0c\n\x04slot\x18\x02 \x01(\x04\x12\x12\n\nis_startup\x18\x03 \x01(\x08"\xc8\x01\n\x1aSubscribeUpdateAccountInfo\x12\x0e\n\x06pubkey\x18\x01 \x01(\x0c\x12\x10\n\x08lamports\x18\x02 \x01(\x04\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x12\n\nexecutable\x18\x04 \x01(\x08\x12\x12\n\nrent_epoch\x18\x05 \x01(\x04\x12\x0c\n\x04\x64\x61ta\x18\x06 \x01(\x0c\x12\x15\n\rwrite_version\x18\x07 \x01(\x04\x12\x1a\n\rtxn_signature\x18\x08 \x01(\x0cH\x00\x88\x01\x01\x42\x10\n\x0e_txn_signature"\x94\x01\n\x13SubscribeUpdateSlot\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x13\n\x06parent\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\'\n\x06status\x18\x03 \x01(\x0e\x32\x17.geyser.CommitmentLevel\x12\x17\n\ndead_error\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_parentB\r\n\x0b_dead_error"g\n\x1aSubscribeUpdateTransaction\x12;\n\x0btransaction\x18\x01 \x01(\x0b\x32&.geyser.SubscribeUpdateTransactionInfo\x12\x0c\n\x04slot\x18\x02 \x01(\x04"\xd8\x01\n\x1eSubscribeUpdateTransactionInfo\x12\x11\n\tsignature\x18\x01 \x01(\x0c\x12\x0f\n\x07is_vote\x18\x02 \x01(\x08\x12?\n\x0btransaction\x18\x03 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.Transaction\x12\x42\n\x04meta\x18\x04 \x01(\x0b\x32\x34.solana.storage.ConfirmedBlock.TransactionStatusMeta\x12\r\n\x05index\x18\x05 \x01(\x04"\xa1\x01\n SubscribeUpdateTransactionStatus\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tsignature\x18\x02 \x01(\x0c\x12\x0f\n\x07is_vote\x18\x03 \x01(\x08\x12\r\n\x05index\x18\x04 \x01(\x04\x12<\n\x03\x65rr\x18\x05 \x01(\x0b\x32/.solana.storage.ConfirmedBlock.TransactionError"\xa0\x04\n\x14SubscribeUpdateBlock\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x37\n\x07rewards\x18\x03 \x01(\x0b\x32&.solana.storage.ConfirmedBlock.Rewards\x12@\n\nblock_time\x18\x04 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UnixTimestamp\x12@\n\x0c\x62lock_height\x18\x05 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.BlockHeight\x12\x13\n\x0bparent_slot\x18\x07 \x01(\x04\x12\x18\n\x10parent_blockhash\x18\x08 \x01(\t\x12"\n\x1a\x65xecuted_transaction_count\x18\t \x01(\x04\x12<\n\x0ctransactions\x18\x06 \x03(\x0b\x32&.geyser.SubscribeUpdateTransactionInfo\x12\x1d\n\x15updated_account_count\x18\n \x01(\x04\x12\x34\n\x08\x61\x63\x63ounts\x18\x0b \x03(\x0b\x32".geyser.SubscribeUpdateAccountInfo\x12\x15\n\rentries_count\x18\x0c \x01(\x04\x12-\n\x07\x65ntries\x18\r \x03(\x0b\x32\x1c.geyser.SubscribeUpdateEntry"\xe2\x02\n\x18SubscribeUpdateBlockMeta\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x37\n\x07rewards\x18\x03 \x01(\x0b\x32&.solana.storage.ConfirmedBlock.Rewards\x12@\n\nblock_time\x18\x04 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UnixTimestamp\x12@\n\x0c\x62lock_height\x18\x05 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.BlockHeight\x12\x13\n\x0bparent_slot\x18\x06 \x01(\x04\x12\x18\n\x10parent_blockhash\x18\x07 \x01(\t\x12"\n\x1a\x65xecuted_transaction_count\x18\x08 \x01(\x04\x12\x15\n\rentries_count\x18\t \x01(\x04"\x9d\x01\n\x14SubscribeUpdateEntry\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\r\n\x05index\x18\x02 \x01(\x04\x12\x12\n\nnum_hashes\x18\x03 \x01(\x04\x12\x0c\n\x04hash\x18\x04 \x01(\x0c\x12"\n\x1a\x65xecuted_transaction_count\x18\x05 \x01(\x04\x12"\n\x1astarting_transaction_index\x18\x06 \x01(\x04"\x15\n\x13SubscribeUpdatePing"!\n\x13SubscribeUpdatePong\x12\n\n\x02id\x18\x01 \x01(\x05"\x1c\n\x0bPingRequest\x12\r\n\x05\x63ount\x18\x01 \x01(\x05"\x1d\n\x0cPongResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x05"\\\n\x19GetLatestBlockhashRequest\x12\x30\n\ncommitment\x18\x01 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment"^\n\x1aGetLatestBlockhashResponse\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x1f\n\x17last_valid_block_height\x18\x03 \x01(\x04"X\n\x15GetBlockHeightRequest\x12\x30\n\ncommitment\x18\x01 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment".\n\x16GetBlockHeightResponse\x12\x14\n\x0c\x62lock_height\x18\x01 \x01(\x04"Q\n\x0eGetSlotRequest\x12\x30\n\ncommitment\x18\x01 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment"\x1f\n\x0fGetSlotResponse\x12\x0c\n\x04slot\x18\x01 \x01(\x04"\x13\n\x11GetVersionRequest"%\n\x12GetVersionResponse\x12\x0f\n\x07version\x18\x01 \x01(\t"m\n\x17IsBlockhashValidRequest\x12\x11\n\tblockhash\x18\x01 \x01(\t\x12\x30\n\ncommitment\x18\x02 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment"7\n\x18IsBlockhashValidResponse\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\r\n\x05valid\x18\x02 \x01(\x08*\x83\x01\n\x0f\x43ommitmentLevel\x12\r\n\tPROCESSED\x10\x00\x12\r\n\tCONFIRMED\x10\x01\x12\r\n\tFINALIZED\x10\x02\x12\x18\n\x14\x46IRST_SHRED_RECEIVED\x10\x03\x12\r\n\tCOMPLETED\x10\x04\x12\x10\n\x0c\x43REATED_BANK\x10\x05\x12\x08\n\x04\x44\x45\x41\x44\x10\x06\x32\x93\x04\n\x06Geyser\x12\x44\n\tSubscribe\x12\x18.geyser.SubscribeRequest\x1a\x17.geyser.SubscribeUpdate"\x00(\x01\x30\x01\x12\x33\n\x04Ping\x12\x13.geyser.PingRequest\x1a\x14.geyser.PongResponse"\x00\x12]\n\x12GetLatestBlockhash\x12!.geyser.GetLatestBlockhashRequest\x1a".geyser.GetLatestBlockhashResponse"\x00\x12Q\n\x0eGetBlockHeight\x12\x1d.geyser.GetBlockHeightRequest\x1a\x1e.geyser.GetBlockHeightResponse"\x00\x12<\n\x07GetSlot\x12\x16.geyser.GetSlotRequest\x1a\x17.geyser.GetSlotResponse"\x00\x12W\n\x10IsBlockhashValid\x12\x1f.geyser.IsBlockhashValidRequest\x1a .geyser.IsBlockhashValidResponse"\x00\x12\x45\n\nGetVersion\x12\x19.geyser.GetVersionRequest\x1a\x1a.geyser.GetVersionResponse"\x00\x42;Z9github.com/rpcpool/yellowstone-grpc/examples/golang/protoP\x00\x62\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "geyser_pb2", _globals) -if not _descriptor._USE_C_DESCRIPTORS: - _globals["DESCRIPTOR"]._loaded_options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = ( - b"Z9github.com/rpcpool/yellowstone-grpc/examples/golang/proto" - ) - _globals["_SUBSCRIBEREQUEST_ACCOUNTSENTRY"]._loaded_options = None - _globals["_SUBSCRIBEREQUEST_ACCOUNTSENTRY"]._serialized_options = b"8\001" - _globals["_SUBSCRIBEREQUEST_SLOTSENTRY"]._loaded_options = None - _globals["_SUBSCRIBEREQUEST_SLOTSENTRY"]._serialized_options = b"8\001" - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSENTRY"]._loaded_options = None - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSENTRY"]._serialized_options = b"8\001" - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY"]._loaded_options = None - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY"]._serialized_options = b"8\001" - _globals["_SUBSCRIBEREQUEST_BLOCKSENTRY"]._loaded_options = None - _globals["_SUBSCRIBEREQUEST_BLOCKSENTRY"]._serialized_options = b"8\001" - _globals["_SUBSCRIBEREQUEST_BLOCKSMETAENTRY"]._loaded_options = None - _globals["_SUBSCRIBEREQUEST_BLOCKSMETAENTRY"]._serialized_options = b"8\001" - _globals["_SUBSCRIBEREQUEST_ENTRYENTRY"]._loaded_options = None - _globals["_SUBSCRIBEREQUEST_ENTRYENTRY"]._serialized_options = b"8\001" - _globals["_COMMITMENTLEVEL"]._serialized_start = 6020 - _globals["_COMMITMENTLEVEL"]._serialized_end = 6151 - _globals["_SUBSCRIBEREQUEST"]._serialized_start = 47 - _globals["_SUBSCRIBEREQUEST"]._serialized_end = 1317 - _globals["_SUBSCRIBEREQUEST_ACCOUNTSENTRY"]._serialized_start = 662 - _globals["_SUBSCRIBEREQUEST_ACCOUNTSENTRY"]._serialized_end = 749 - _globals["_SUBSCRIBEREQUEST_SLOTSENTRY"]._serialized_start = 751 - _globals["_SUBSCRIBEREQUEST_SLOTSENTRY"]._serialized_end = 832 - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSENTRY"]._serialized_start = 834 - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSENTRY"]._serialized_end = 929 - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY"]._serialized_start = 931 - _globals["_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY"]._serialized_end = 1032 - _globals["_SUBSCRIBEREQUEST_BLOCKSENTRY"]._serialized_start = 1034 - _globals["_SUBSCRIBEREQUEST_BLOCKSENTRY"]._serialized_end = 1117 - _globals["_SUBSCRIBEREQUEST_BLOCKSMETAENTRY"]._serialized_start = 1119 - _globals["_SUBSCRIBEREQUEST_BLOCKSMETAENTRY"]._serialized_end = 1210 - _globals["_SUBSCRIBEREQUEST_ENTRYENTRY"]._serialized_start = 1212 - _globals["_SUBSCRIBEREQUEST_ENTRYENTRY"]._serialized_end = 1293 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTS"]._serialized_start = 1320 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTS"]._serialized_end = 1511 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTSFILTER"]._serialized_start = 1514 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTSFILTER"]._serialized_end = 1757 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERMEMCMP"]._serialized_start = 1759 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERMEMCMP"]._serialized_end = 1880 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERLAMPORTS"]._serialized_start = 1882 - _globals["_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERLAMPORTS"]._serialized_end = 1991 - _globals["_SUBSCRIBEREQUESTFILTERSLOTS"]._serialized_start = 1993 - _globals["_SUBSCRIBEREQUESTFILTERSLOTS"]._serialized_end = 2082 - _globals["_SUBSCRIBEREQUESTFILTERTRANSACTIONS"]._serialized_start = 2085 - _globals["_SUBSCRIBEREQUESTFILTERTRANSACTIONS"]._serialized_end = 2295 - _globals["_SUBSCRIBEREQUESTFILTERBLOCKS"]._serialized_start = 2298 - _globals["_SUBSCRIBEREQUESTFILTERBLOCKS"]._serialized_end = 2515 - _globals["_SUBSCRIBEREQUESTFILTERBLOCKSMETA"]._serialized_start = 2517 - _globals["_SUBSCRIBEREQUESTFILTERBLOCKSMETA"]._serialized_end = 2551 - _globals["_SUBSCRIBEREQUESTFILTERENTRY"]._serialized_start = 2553 - _globals["_SUBSCRIBEREQUESTFILTERENTRY"]._serialized_end = 2582 - _globals["_SUBSCRIBEREQUESTACCOUNTSDATASLICE"]._serialized_start = 2584 - _globals["_SUBSCRIBEREQUESTACCOUNTSDATASLICE"]._serialized_end = 2651 - _globals["_SUBSCRIBEREQUESTPING"]._serialized_start = 2653 - _globals["_SUBSCRIBEREQUESTPING"]._serialized_end = 2687 - _globals["_SUBSCRIBEUPDATE"]._serialized_start = 2690 - _globals["_SUBSCRIBEUPDATE"]._serialized_end = 3207 - _globals["_SUBSCRIBEUPDATEACCOUNT"]._serialized_start = 3209 - _globals["_SUBSCRIBEUPDATEACCOUNT"]._serialized_end = 3320 - _globals["_SUBSCRIBEUPDATEACCOUNTINFO"]._serialized_start = 3323 - _globals["_SUBSCRIBEUPDATEACCOUNTINFO"]._serialized_end = 3523 - _globals["_SUBSCRIBEUPDATESLOT"]._serialized_start = 3526 - _globals["_SUBSCRIBEUPDATESLOT"]._serialized_end = 3674 - _globals["_SUBSCRIBEUPDATETRANSACTION"]._serialized_start = 3676 - _globals["_SUBSCRIBEUPDATETRANSACTION"]._serialized_end = 3779 - _globals["_SUBSCRIBEUPDATETRANSACTIONINFO"]._serialized_start = 3782 - _globals["_SUBSCRIBEUPDATETRANSACTIONINFO"]._serialized_end = 3998 - _globals["_SUBSCRIBEUPDATETRANSACTIONSTATUS"]._serialized_start = 4001 - _globals["_SUBSCRIBEUPDATETRANSACTIONSTATUS"]._serialized_end = 4162 - _globals["_SUBSCRIBEUPDATEBLOCK"]._serialized_start = 4165 - _globals["_SUBSCRIBEUPDATEBLOCK"]._serialized_end = 4709 - _globals["_SUBSCRIBEUPDATEBLOCKMETA"]._serialized_start = 4712 - _globals["_SUBSCRIBEUPDATEBLOCKMETA"]._serialized_end = 5066 - _globals["_SUBSCRIBEUPDATEENTRY"]._serialized_start = 5069 - _globals["_SUBSCRIBEUPDATEENTRY"]._serialized_end = 5226 - _globals["_SUBSCRIBEUPDATEPING"]._serialized_start = 5228 - _globals["_SUBSCRIBEUPDATEPING"]._serialized_end = 5249 - _globals["_SUBSCRIBEUPDATEPONG"]._serialized_start = 5251 - _globals["_SUBSCRIBEUPDATEPONG"]._serialized_end = 5284 - _globals["_PINGREQUEST"]._serialized_start = 5286 - _globals["_PINGREQUEST"]._serialized_end = 5314 - _globals["_PONGRESPONSE"]._serialized_start = 5316 - _globals["_PONGRESPONSE"]._serialized_end = 5345 - _globals["_GETLATESTBLOCKHASHREQUEST"]._serialized_start = 5347 - _globals["_GETLATESTBLOCKHASHREQUEST"]._serialized_end = 5439 - _globals["_GETLATESTBLOCKHASHRESPONSE"]._serialized_start = 5441 - _globals["_GETLATESTBLOCKHASHRESPONSE"]._serialized_end = 5535 - _globals["_GETBLOCKHEIGHTREQUEST"]._serialized_start = 5537 - _globals["_GETBLOCKHEIGHTREQUEST"]._serialized_end = 5625 - _globals["_GETBLOCKHEIGHTRESPONSE"]._serialized_start = 5627 - _globals["_GETBLOCKHEIGHTRESPONSE"]._serialized_end = 5673 - _globals["_GETSLOTREQUEST"]._serialized_start = 5675 - _globals["_GETSLOTREQUEST"]._serialized_end = 5756 - _globals["_GETSLOTRESPONSE"]._serialized_start = 5758 - _globals["_GETSLOTRESPONSE"]._serialized_end = 5789 - _globals["_GETVERSIONREQUEST"]._serialized_start = 5791 - _globals["_GETVERSIONREQUEST"]._serialized_end = 5810 - _globals["_GETVERSIONRESPONSE"]._serialized_start = 5812 - _globals["_GETVERSIONRESPONSE"]._serialized_end = 5849 - _globals["_ISBLOCKHASHVALIDREQUEST"]._serialized_start = 5851 - _globals["_ISBLOCKHASHVALIDREQUEST"]._serialized_end = 5960 - _globals["_ISBLOCKHASHVALIDRESPONSE"]._serialized_start = 5962 - _globals["_ISBLOCKHASHVALIDRESPONSE"]._serialized_end = 6017 - _globals["_GEYSER"]._serialized_start = 6154 - _globals["_GEYSER"]._serialized_end = 6685 -# @@protoc_insertion_point(module_scope) diff --git a/learning-examples/listen-new-tokens/generated/geyser_pb2.pyi b/learning-examples/listen-new-tokens/generated/geyser_pb2.pyi deleted file mode 100644 index 8abc78c..0000000 --- a/learning-examples/listen-new-tokens/generated/geyser_pb2.pyi +++ /dev/null @@ -1,791 +0,0 @@ -import solana_storage_pb2 as _solana_storage_pb2 -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from typing import ( - ClassVar as _ClassVar, - Iterable as _Iterable, - Mapping as _Mapping, - Optional as _Optional, - Union as _Union, -) -from solana_storage_pb2 import ConfirmedBlock as ConfirmedBlock -from solana_storage_pb2 import ConfirmedTransaction as ConfirmedTransaction -from solana_storage_pb2 import Transaction as Transaction -from solana_storage_pb2 import Message as Message -from solana_storage_pb2 import MessageHeader as MessageHeader -from solana_storage_pb2 import MessageAddressTableLookup as MessageAddressTableLookup -from solana_storage_pb2 import TransactionStatusMeta as TransactionStatusMeta -from solana_storage_pb2 import TransactionError as TransactionError -from solana_storage_pb2 import InnerInstructions as InnerInstructions -from solana_storage_pb2 import InnerInstruction as InnerInstruction -from solana_storage_pb2 import CompiledInstruction as CompiledInstruction -from solana_storage_pb2 import TokenBalance as TokenBalance -from solana_storage_pb2 import UiTokenAmount as UiTokenAmount -from solana_storage_pb2 import ReturnData as ReturnData -from solana_storage_pb2 import Reward as Reward -from solana_storage_pb2 import Rewards as Rewards -from solana_storage_pb2 import UnixTimestamp as UnixTimestamp -from solana_storage_pb2 import BlockHeight as BlockHeight -from solana_storage_pb2 import NumPartitions as NumPartitions -from solana_storage_pb2 import RewardType as RewardType - -DESCRIPTOR: _descriptor.FileDescriptor -Unspecified: _solana_storage_pb2.RewardType -Fee: _solana_storage_pb2.RewardType -Rent: _solana_storage_pb2.RewardType -Staking: _solana_storage_pb2.RewardType -Voting: _solana_storage_pb2.RewardType - -class CommitmentLevel(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - PROCESSED: _ClassVar[CommitmentLevel] - CONFIRMED: _ClassVar[CommitmentLevel] - FINALIZED: _ClassVar[CommitmentLevel] - FIRST_SHRED_RECEIVED: _ClassVar[CommitmentLevel] - COMPLETED: _ClassVar[CommitmentLevel] - CREATED_BANK: _ClassVar[CommitmentLevel] - DEAD: _ClassVar[CommitmentLevel] - -PROCESSED: CommitmentLevel -CONFIRMED: CommitmentLevel -FINALIZED: CommitmentLevel -FIRST_SHRED_RECEIVED: CommitmentLevel -COMPLETED: CommitmentLevel -CREATED_BANK: CommitmentLevel -DEAD: CommitmentLevel - -class SubscribeRequest(_message.Message): - __slots__ = ( - "accounts", - "slots", - "transactions", - "transactions_status", - "blocks", - "blocks_meta", - "entry", - "commitment", - "accounts_data_slice", - "ping", - ) - class AccountsEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: SubscribeRequestFilterAccounts - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[_Union[SubscribeRequestFilterAccounts, _Mapping]] = ..., - ) -> None: ... - - class SlotsEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: SubscribeRequestFilterSlots - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[_Union[SubscribeRequestFilterSlots, _Mapping]] = ..., - ) -> None: ... - - class TransactionsEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: SubscribeRequestFilterTransactions - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[ - _Union[SubscribeRequestFilterTransactions, _Mapping] - ] = ..., - ) -> None: ... - - class TransactionsStatusEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: SubscribeRequestFilterTransactions - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[ - _Union[SubscribeRequestFilterTransactions, _Mapping] - ] = ..., - ) -> None: ... - - class BlocksEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: SubscribeRequestFilterBlocks - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[_Union[SubscribeRequestFilterBlocks, _Mapping]] = ..., - ) -> None: ... - - class BlocksMetaEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: SubscribeRequestFilterBlocksMeta - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[_Union[SubscribeRequestFilterBlocksMeta, _Mapping]] = ..., - ) -> None: ... - - class EntryEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: SubscribeRequestFilterEntry - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[_Union[SubscribeRequestFilterEntry, _Mapping]] = ..., - ) -> None: ... - - ACCOUNTS_FIELD_NUMBER: _ClassVar[int] - SLOTS_FIELD_NUMBER: _ClassVar[int] - TRANSACTIONS_FIELD_NUMBER: _ClassVar[int] - TRANSACTIONS_STATUS_FIELD_NUMBER: _ClassVar[int] - BLOCKS_FIELD_NUMBER: _ClassVar[int] - BLOCKS_META_FIELD_NUMBER: _ClassVar[int] - ENTRY_FIELD_NUMBER: _ClassVar[int] - COMMITMENT_FIELD_NUMBER: _ClassVar[int] - ACCOUNTS_DATA_SLICE_FIELD_NUMBER: _ClassVar[int] - PING_FIELD_NUMBER: _ClassVar[int] - accounts: _containers.MessageMap[str, SubscribeRequestFilterAccounts] - slots: _containers.MessageMap[str, SubscribeRequestFilterSlots] - transactions: _containers.MessageMap[str, SubscribeRequestFilterTransactions] - transactions_status: _containers.MessageMap[str, SubscribeRequestFilterTransactions] - blocks: _containers.MessageMap[str, SubscribeRequestFilterBlocks] - blocks_meta: _containers.MessageMap[str, SubscribeRequestFilterBlocksMeta] - entry: _containers.MessageMap[str, SubscribeRequestFilterEntry] - commitment: CommitmentLevel - accounts_data_slice: _containers.RepeatedCompositeFieldContainer[ - SubscribeRequestAccountsDataSlice - ] - ping: SubscribeRequestPing - def __init__( - self, - accounts: _Optional[_Mapping[str, SubscribeRequestFilterAccounts]] = ..., - slots: _Optional[_Mapping[str, SubscribeRequestFilterSlots]] = ..., - transactions: _Optional[ - _Mapping[str, SubscribeRequestFilterTransactions] - ] = ..., - transactions_status: _Optional[ - _Mapping[str, SubscribeRequestFilterTransactions] - ] = ..., - blocks: _Optional[_Mapping[str, SubscribeRequestFilterBlocks]] = ..., - blocks_meta: _Optional[_Mapping[str, SubscribeRequestFilterBlocksMeta]] = ..., - entry: _Optional[_Mapping[str, SubscribeRequestFilterEntry]] = ..., - commitment: _Optional[_Union[CommitmentLevel, str]] = ..., - accounts_data_slice: _Optional[ - _Iterable[_Union[SubscribeRequestAccountsDataSlice, _Mapping]] - ] = ..., - ping: _Optional[_Union[SubscribeRequestPing, _Mapping]] = ..., - ) -> None: ... - -class SubscribeRequestFilterAccounts(_message.Message): - __slots__ = ("account", "owner", "filters", "nonempty_txn_signature") - ACCOUNT_FIELD_NUMBER: _ClassVar[int] - OWNER_FIELD_NUMBER: _ClassVar[int] - FILTERS_FIELD_NUMBER: _ClassVar[int] - NONEMPTY_TXN_SIGNATURE_FIELD_NUMBER: _ClassVar[int] - account: _containers.RepeatedScalarFieldContainer[str] - owner: _containers.RepeatedScalarFieldContainer[str] - filters: _containers.RepeatedCompositeFieldContainer[ - SubscribeRequestFilterAccountsFilter - ] - nonempty_txn_signature: bool - def __init__( - self, - account: _Optional[_Iterable[str]] = ..., - owner: _Optional[_Iterable[str]] = ..., - filters: _Optional[ - _Iterable[_Union[SubscribeRequestFilterAccountsFilter, _Mapping]] - ] = ..., - nonempty_txn_signature: bool = ..., - ) -> None: ... - -class SubscribeRequestFilterAccountsFilter(_message.Message): - __slots__ = ("memcmp", "datasize", "token_account_state", "lamports") - MEMCMP_FIELD_NUMBER: _ClassVar[int] - DATASIZE_FIELD_NUMBER: _ClassVar[int] - TOKEN_ACCOUNT_STATE_FIELD_NUMBER: _ClassVar[int] - LAMPORTS_FIELD_NUMBER: _ClassVar[int] - memcmp: SubscribeRequestFilterAccountsFilterMemcmp - datasize: int - token_account_state: bool - lamports: SubscribeRequestFilterAccountsFilterLamports - def __init__( - self, - memcmp: _Optional[ - _Union[SubscribeRequestFilterAccountsFilterMemcmp, _Mapping] - ] = ..., - datasize: _Optional[int] = ..., - token_account_state: bool = ..., - lamports: _Optional[ - _Union[SubscribeRequestFilterAccountsFilterLamports, _Mapping] - ] = ..., - ) -> None: ... - -class SubscribeRequestFilterAccountsFilterMemcmp(_message.Message): - __slots__ = ("offset", "bytes", "base58", "base64") - OFFSET_FIELD_NUMBER: _ClassVar[int] - BYTES_FIELD_NUMBER: _ClassVar[int] - BASE58_FIELD_NUMBER: _ClassVar[int] - BASE64_FIELD_NUMBER: _ClassVar[int] - offset: int - bytes: bytes - base58: str - base64: str - def __init__( - self, - offset: _Optional[int] = ..., - bytes: _Optional[bytes] = ..., - base58: _Optional[str] = ..., - base64: _Optional[str] = ..., - ) -> None: ... - -class SubscribeRequestFilterAccountsFilterLamports(_message.Message): - __slots__ = ("eq", "ne", "lt", "gt") - EQ_FIELD_NUMBER: _ClassVar[int] - NE_FIELD_NUMBER: _ClassVar[int] - LT_FIELD_NUMBER: _ClassVar[int] - GT_FIELD_NUMBER: _ClassVar[int] - eq: int - ne: int - lt: int - gt: int - def __init__( - self, - eq: _Optional[int] = ..., - ne: _Optional[int] = ..., - lt: _Optional[int] = ..., - gt: _Optional[int] = ..., - ) -> None: ... - -class SubscribeRequestFilterSlots(_message.Message): - __slots__ = ("filter_by_commitment",) - FILTER_BY_COMMITMENT_FIELD_NUMBER: _ClassVar[int] - filter_by_commitment: bool - def __init__(self, filter_by_commitment: bool = ...) -> None: ... - -class SubscribeRequestFilterTransactions(_message.Message): - __slots__ = ( - "vote", - "failed", - "signature", - "account_include", - "account_exclude", - "account_required", - ) - VOTE_FIELD_NUMBER: _ClassVar[int] - FAILED_FIELD_NUMBER: _ClassVar[int] - SIGNATURE_FIELD_NUMBER: _ClassVar[int] - ACCOUNT_INCLUDE_FIELD_NUMBER: _ClassVar[int] - ACCOUNT_EXCLUDE_FIELD_NUMBER: _ClassVar[int] - ACCOUNT_REQUIRED_FIELD_NUMBER: _ClassVar[int] - vote: bool - failed: bool - signature: str - account_include: _containers.RepeatedScalarFieldContainer[str] - account_exclude: _containers.RepeatedScalarFieldContainer[str] - account_required: _containers.RepeatedScalarFieldContainer[str] - def __init__( - self, - vote: bool = ..., - failed: bool = ..., - signature: _Optional[str] = ..., - account_include: _Optional[_Iterable[str]] = ..., - account_exclude: _Optional[_Iterable[str]] = ..., - account_required: _Optional[_Iterable[str]] = ..., - ) -> None: ... - -class SubscribeRequestFilterBlocks(_message.Message): - __slots__ = ( - "account_include", - "include_transactions", - "include_accounts", - "include_entries", - ) - ACCOUNT_INCLUDE_FIELD_NUMBER: _ClassVar[int] - INCLUDE_TRANSACTIONS_FIELD_NUMBER: _ClassVar[int] - INCLUDE_ACCOUNTS_FIELD_NUMBER: _ClassVar[int] - INCLUDE_ENTRIES_FIELD_NUMBER: _ClassVar[int] - account_include: _containers.RepeatedScalarFieldContainer[str] - include_transactions: bool - include_accounts: bool - include_entries: bool - def __init__( - self, - account_include: _Optional[_Iterable[str]] = ..., - include_transactions: bool = ..., - include_accounts: bool = ..., - include_entries: bool = ..., - ) -> None: ... - -class SubscribeRequestFilterBlocksMeta(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class SubscribeRequestFilterEntry(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class SubscribeRequestAccountsDataSlice(_message.Message): - __slots__ = ("offset", "length") - OFFSET_FIELD_NUMBER: _ClassVar[int] - LENGTH_FIELD_NUMBER: _ClassVar[int] - offset: int - length: int - def __init__( - self, offset: _Optional[int] = ..., length: _Optional[int] = ... - ) -> None: ... - -class SubscribeRequestPing(_message.Message): - __slots__ = ("id",) - ID_FIELD_NUMBER: _ClassVar[int] - id: int - def __init__(self, id: _Optional[int] = ...) -> None: ... - -class SubscribeUpdate(_message.Message): - __slots__ = ( - "filters", - "account", - "slot", - "transaction", - "transaction_status", - "block", - "ping", - "pong", - "block_meta", - "entry", - ) - FILTERS_FIELD_NUMBER: _ClassVar[int] - ACCOUNT_FIELD_NUMBER: _ClassVar[int] - SLOT_FIELD_NUMBER: _ClassVar[int] - TRANSACTION_FIELD_NUMBER: _ClassVar[int] - TRANSACTION_STATUS_FIELD_NUMBER: _ClassVar[int] - BLOCK_FIELD_NUMBER: _ClassVar[int] - PING_FIELD_NUMBER: _ClassVar[int] - PONG_FIELD_NUMBER: _ClassVar[int] - BLOCK_META_FIELD_NUMBER: _ClassVar[int] - ENTRY_FIELD_NUMBER: _ClassVar[int] - filters: _containers.RepeatedScalarFieldContainer[str] - account: SubscribeUpdateAccount - slot: SubscribeUpdateSlot - transaction: SubscribeUpdateTransaction - transaction_status: SubscribeUpdateTransactionStatus - block: SubscribeUpdateBlock - ping: SubscribeUpdatePing - pong: SubscribeUpdatePong - block_meta: SubscribeUpdateBlockMeta - entry: SubscribeUpdateEntry - def __init__( - self, - filters: _Optional[_Iterable[str]] = ..., - account: _Optional[_Union[SubscribeUpdateAccount, _Mapping]] = ..., - slot: _Optional[_Union[SubscribeUpdateSlot, _Mapping]] = ..., - transaction: _Optional[_Union[SubscribeUpdateTransaction, _Mapping]] = ..., - transaction_status: _Optional[ - _Union[SubscribeUpdateTransactionStatus, _Mapping] - ] = ..., - block: _Optional[_Union[SubscribeUpdateBlock, _Mapping]] = ..., - ping: _Optional[_Union[SubscribeUpdatePing, _Mapping]] = ..., - pong: _Optional[_Union[SubscribeUpdatePong, _Mapping]] = ..., - block_meta: _Optional[_Union[SubscribeUpdateBlockMeta, _Mapping]] = ..., - entry: _Optional[_Union[SubscribeUpdateEntry, _Mapping]] = ..., - ) -> None: ... - -class SubscribeUpdateAccount(_message.Message): - __slots__ = ("account", "slot", "is_startup") - ACCOUNT_FIELD_NUMBER: _ClassVar[int] - SLOT_FIELD_NUMBER: _ClassVar[int] - IS_STARTUP_FIELD_NUMBER: _ClassVar[int] - account: SubscribeUpdateAccountInfo - slot: int - is_startup: bool - def __init__( - self, - account: _Optional[_Union[SubscribeUpdateAccountInfo, _Mapping]] = ..., - slot: _Optional[int] = ..., - is_startup: bool = ..., - ) -> None: ... - -class SubscribeUpdateAccountInfo(_message.Message): - __slots__ = ( - "pubkey", - "lamports", - "owner", - "executable", - "rent_epoch", - "data", - "write_version", - "txn_signature", - ) - PUBKEY_FIELD_NUMBER: _ClassVar[int] - LAMPORTS_FIELD_NUMBER: _ClassVar[int] - OWNER_FIELD_NUMBER: _ClassVar[int] - EXECUTABLE_FIELD_NUMBER: _ClassVar[int] - RENT_EPOCH_FIELD_NUMBER: _ClassVar[int] - DATA_FIELD_NUMBER: _ClassVar[int] - WRITE_VERSION_FIELD_NUMBER: _ClassVar[int] - TXN_SIGNATURE_FIELD_NUMBER: _ClassVar[int] - pubkey: bytes - lamports: int - owner: bytes - executable: bool - rent_epoch: int - data: bytes - write_version: int - txn_signature: bytes - def __init__( - self, - pubkey: _Optional[bytes] = ..., - lamports: _Optional[int] = ..., - owner: _Optional[bytes] = ..., - executable: bool = ..., - rent_epoch: _Optional[int] = ..., - data: _Optional[bytes] = ..., - write_version: _Optional[int] = ..., - txn_signature: _Optional[bytes] = ..., - ) -> None: ... - -class SubscribeUpdateSlot(_message.Message): - __slots__ = ("slot", "parent", "status", "dead_error") - SLOT_FIELD_NUMBER: _ClassVar[int] - PARENT_FIELD_NUMBER: _ClassVar[int] - STATUS_FIELD_NUMBER: _ClassVar[int] - DEAD_ERROR_FIELD_NUMBER: _ClassVar[int] - slot: int - parent: int - status: CommitmentLevel - dead_error: str - def __init__( - self, - slot: _Optional[int] = ..., - parent: _Optional[int] = ..., - status: _Optional[_Union[CommitmentLevel, str]] = ..., - dead_error: _Optional[str] = ..., - ) -> None: ... - -class SubscribeUpdateTransaction(_message.Message): - __slots__ = ("transaction", "slot") - TRANSACTION_FIELD_NUMBER: _ClassVar[int] - SLOT_FIELD_NUMBER: _ClassVar[int] - transaction: SubscribeUpdateTransactionInfo - slot: int - def __init__( - self, - transaction: _Optional[_Union[SubscribeUpdateTransactionInfo, _Mapping]] = ..., - slot: _Optional[int] = ..., - ) -> None: ... - -class SubscribeUpdateTransactionInfo(_message.Message): - __slots__ = ("signature", "is_vote", "transaction", "meta", "index") - SIGNATURE_FIELD_NUMBER: _ClassVar[int] - IS_VOTE_FIELD_NUMBER: _ClassVar[int] - TRANSACTION_FIELD_NUMBER: _ClassVar[int] - META_FIELD_NUMBER: _ClassVar[int] - INDEX_FIELD_NUMBER: _ClassVar[int] - signature: bytes - is_vote: bool - transaction: _solana_storage_pb2.Transaction - meta: _solana_storage_pb2.TransactionStatusMeta - index: int - def __init__( - self, - signature: _Optional[bytes] = ..., - is_vote: bool = ..., - transaction: _Optional[_Union[_solana_storage_pb2.Transaction, _Mapping]] = ..., - meta: _Optional[ - _Union[_solana_storage_pb2.TransactionStatusMeta, _Mapping] - ] = ..., - index: _Optional[int] = ..., - ) -> None: ... - -class SubscribeUpdateTransactionStatus(_message.Message): - __slots__ = ("slot", "signature", "is_vote", "index", "err") - SLOT_FIELD_NUMBER: _ClassVar[int] - SIGNATURE_FIELD_NUMBER: _ClassVar[int] - IS_VOTE_FIELD_NUMBER: _ClassVar[int] - INDEX_FIELD_NUMBER: _ClassVar[int] - ERR_FIELD_NUMBER: _ClassVar[int] - slot: int - signature: bytes - is_vote: bool - index: int - err: _solana_storage_pb2.TransactionError - def __init__( - self, - slot: _Optional[int] = ..., - signature: _Optional[bytes] = ..., - is_vote: bool = ..., - index: _Optional[int] = ..., - err: _Optional[_Union[_solana_storage_pb2.TransactionError, _Mapping]] = ..., - ) -> None: ... - -class SubscribeUpdateBlock(_message.Message): - __slots__ = ( - "slot", - "blockhash", - "rewards", - "block_time", - "block_height", - "parent_slot", - "parent_blockhash", - "executed_transaction_count", - "transactions", - "updated_account_count", - "accounts", - "entries_count", - "entries", - ) - SLOT_FIELD_NUMBER: _ClassVar[int] - BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - REWARDS_FIELD_NUMBER: _ClassVar[int] - BLOCK_TIME_FIELD_NUMBER: _ClassVar[int] - BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] - PARENT_SLOT_FIELD_NUMBER: _ClassVar[int] - PARENT_BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - EXECUTED_TRANSACTION_COUNT_FIELD_NUMBER: _ClassVar[int] - TRANSACTIONS_FIELD_NUMBER: _ClassVar[int] - UPDATED_ACCOUNT_COUNT_FIELD_NUMBER: _ClassVar[int] - ACCOUNTS_FIELD_NUMBER: _ClassVar[int] - ENTRIES_COUNT_FIELD_NUMBER: _ClassVar[int] - ENTRIES_FIELD_NUMBER: _ClassVar[int] - slot: int - blockhash: str - rewards: _solana_storage_pb2.Rewards - block_time: _solana_storage_pb2.UnixTimestamp - block_height: _solana_storage_pb2.BlockHeight - parent_slot: int - parent_blockhash: str - executed_transaction_count: int - transactions: _containers.RepeatedCompositeFieldContainer[ - SubscribeUpdateTransactionInfo - ] - updated_account_count: int - accounts: _containers.RepeatedCompositeFieldContainer[SubscribeUpdateAccountInfo] - entries_count: int - entries: _containers.RepeatedCompositeFieldContainer[SubscribeUpdateEntry] - def __init__( - self, - slot: _Optional[int] = ..., - blockhash: _Optional[str] = ..., - rewards: _Optional[_Union[_solana_storage_pb2.Rewards, _Mapping]] = ..., - block_time: _Optional[ - _Union[_solana_storage_pb2.UnixTimestamp, _Mapping] - ] = ..., - block_height: _Optional[ - _Union[_solana_storage_pb2.BlockHeight, _Mapping] - ] = ..., - parent_slot: _Optional[int] = ..., - parent_blockhash: _Optional[str] = ..., - executed_transaction_count: _Optional[int] = ..., - transactions: _Optional[ - _Iterable[_Union[SubscribeUpdateTransactionInfo, _Mapping]] - ] = ..., - updated_account_count: _Optional[int] = ..., - accounts: _Optional[ - _Iterable[_Union[SubscribeUpdateAccountInfo, _Mapping]] - ] = ..., - entries_count: _Optional[int] = ..., - entries: _Optional[_Iterable[_Union[SubscribeUpdateEntry, _Mapping]]] = ..., - ) -> None: ... - -class SubscribeUpdateBlockMeta(_message.Message): - __slots__ = ( - "slot", - "blockhash", - "rewards", - "block_time", - "block_height", - "parent_slot", - "parent_blockhash", - "executed_transaction_count", - "entries_count", - ) - SLOT_FIELD_NUMBER: _ClassVar[int] - BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - REWARDS_FIELD_NUMBER: _ClassVar[int] - BLOCK_TIME_FIELD_NUMBER: _ClassVar[int] - BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] - PARENT_SLOT_FIELD_NUMBER: _ClassVar[int] - PARENT_BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - EXECUTED_TRANSACTION_COUNT_FIELD_NUMBER: _ClassVar[int] - ENTRIES_COUNT_FIELD_NUMBER: _ClassVar[int] - slot: int - blockhash: str - rewards: _solana_storage_pb2.Rewards - block_time: _solana_storage_pb2.UnixTimestamp - block_height: _solana_storage_pb2.BlockHeight - parent_slot: int - parent_blockhash: str - executed_transaction_count: int - entries_count: int - def __init__( - self, - slot: _Optional[int] = ..., - blockhash: _Optional[str] = ..., - rewards: _Optional[_Union[_solana_storage_pb2.Rewards, _Mapping]] = ..., - block_time: _Optional[ - _Union[_solana_storage_pb2.UnixTimestamp, _Mapping] - ] = ..., - block_height: _Optional[ - _Union[_solana_storage_pb2.BlockHeight, _Mapping] - ] = ..., - parent_slot: _Optional[int] = ..., - parent_blockhash: _Optional[str] = ..., - executed_transaction_count: _Optional[int] = ..., - entries_count: _Optional[int] = ..., - ) -> None: ... - -class SubscribeUpdateEntry(_message.Message): - __slots__ = ( - "slot", - "index", - "num_hashes", - "hash", - "executed_transaction_count", - "starting_transaction_index", - ) - SLOT_FIELD_NUMBER: _ClassVar[int] - INDEX_FIELD_NUMBER: _ClassVar[int] - NUM_HASHES_FIELD_NUMBER: _ClassVar[int] - HASH_FIELD_NUMBER: _ClassVar[int] - EXECUTED_TRANSACTION_COUNT_FIELD_NUMBER: _ClassVar[int] - STARTING_TRANSACTION_INDEX_FIELD_NUMBER: _ClassVar[int] - slot: int - index: int - num_hashes: int - hash: bytes - executed_transaction_count: int - starting_transaction_index: int - def __init__( - self, - slot: _Optional[int] = ..., - index: _Optional[int] = ..., - num_hashes: _Optional[int] = ..., - hash: _Optional[bytes] = ..., - executed_transaction_count: _Optional[int] = ..., - starting_transaction_index: _Optional[int] = ..., - ) -> None: ... - -class SubscribeUpdatePing(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class SubscribeUpdatePong(_message.Message): - __slots__ = ("id",) - ID_FIELD_NUMBER: _ClassVar[int] - id: int - def __init__(self, id: _Optional[int] = ...) -> None: ... - -class PingRequest(_message.Message): - __slots__ = ("count",) - COUNT_FIELD_NUMBER: _ClassVar[int] - count: int - def __init__(self, count: _Optional[int] = ...) -> None: ... - -class PongResponse(_message.Message): - __slots__ = ("count",) - COUNT_FIELD_NUMBER: _ClassVar[int] - count: int - def __init__(self, count: _Optional[int] = ...) -> None: ... - -class GetLatestBlockhashRequest(_message.Message): - __slots__ = ("commitment",) - COMMITMENT_FIELD_NUMBER: _ClassVar[int] - commitment: CommitmentLevel - def __init__( - self, commitment: _Optional[_Union[CommitmentLevel, str]] = ... - ) -> None: ... - -class GetLatestBlockhashResponse(_message.Message): - __slots__ = ("slot", "blockhash", "last_valid_block_height") - SLOT_FIELD_NUMBER: _ClassVar[int] - BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - LAST_VALID_BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] - slot: int - blockhash: str - last_valid_block_height: int - def __init__( - self, - slot: _Optional[int] = ..., - blockhash: _Optional[str] = ..., - last_valid_block_height: _Optional[int] = ..., - ) -> None: ... - -class GetBlockHeightRequest(_message.Message): - __slots__ = ("commitment",) - COMMITMENT_FIELD_NUMBER: _ClassVar[int] - commitment: CommitmentLevel - def __init__( - self, commitment: _Optional[_Union[CommitmentLevel, str]] = ... - ) -> None: ... - -class GetBlockHeightResponse(_message.Message): - __slots__ = ("block_height",) - BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] - block_height: int - def __init__(self, block_height: _Optional[int] = ...) -> None: ... - -class GetSlotRequest(_message.Message): - __slots__ = ("commitment",) - COMMITMENT_FIELD_NUMBER: _ClassVar[int] - commitment: CommitmentLevel - def __init__( - self, commitment: _Optional[_Union[CommitmentLevel, str]] = ... - ) -> None: ... - -class GetSlotResponse(_message.Message): - __slots__ = ("slot",) - SLOT_FIELD_NUMBER: _ClassVar[int] - slot: int - def __init__(self, slot: _Optional[int] = ...) -> None: ... - -class GetVersionRequest(_message.Message): - __slots__ = () - def __init__(self) -> None: ... - -class GetVersionResponse(_message.Message): - __slots__ = ("version",) - VERSION_FIELD_NUMBER: _ClassVar[int] - version: str - def __init__(self, version: _Optional[str] = ...) -> None: ... - -class IsBlockhashValidRequest(_message.Message): - __slots__ = ("blockhash", "commitment") - BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - COMMITMENT_FIELD_NUMBER: _ClassVar[int] - blockhash: str - commitment: CommitmentLevel - def __init__( - self, - blockhash: _Optional[str] = ..., - commitment: _Optional[_Union[CommitmentLevel, str]] = ..., - ) -> None: ... - -class IsBlockhashValidResponse(_message.Message): - __slots__ = ("slot", "valid") - SLOT_FIELD_NUMBER: _ClassVar[int] - VALID_FIELD_NUMBER: _ClassVar[int] - slot: int - valid: bool - def __init__(self, slot: _Optional[int] = ..., valid: bool = ...) -> None: ... diff --git a/learning-examples/listen-new-tokens/generated/geyser_pb2_grpc.py b/learning-examples/listen-new-tokens/generated/geyser_pb2_grpc.py deleted file mode 100644 index 6c38723..0000000 --- a/learning-examples/listen-new-tokens/generated/geyser_pb2_grpc.py +++ /dev/null @@ -1,387 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" - -import grpc - -import generated.geyser_pb2 as geyser__pb2 - -GRPC_GENERATED_VERSION = "1.71.0" -GRPC_VERSION = grpc.__version__ -_version_not_supported = False - -try: - from grpc._utilities import first_version_is_lower - - _version_not_supported = first_version_is_lower( - GRPC_VERSION, GRPC_GENERATED_VERSION - ) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - raise RuntimeError( - f"The grpc package installed is at version {GRPC_VERSION}," - + " but the generated code in geyser_pb2_grpc.py depends on" - + f" grpcio>={GRPC_GENERATED_VERSION}." - + f" Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}" - + f" or downgrade your generated code using grpcio-tools<={GRPC_VERSION}." - ) - - -class GeyserStub: - """Missing associated documentation comment in .proto file.""" - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.Subscribe = channel.stream_stream( - "/geyser.Geyser/Subscribe", - request_serializer=geyser__pb2.SubscribeRequest.SerializeToString, - response_deserializer=geyser__pb2.SubscribeUpdate.FromString, - _registered_method=True, - ) - self.Ping = channel.unary_unary( - "/geyser.Geyser/Ping", - request_serializer=geyser__pb2.PingRequest.SerializeToString, - response_deserializer=geyser__pb2.PongResponse.FromString, - _registered_method=True, - ) - self.GetLatestBlockhash = channel.unary_unary( - "/geyser.Geyser/GetLatestBlockhash", - request_serializer=geyser__pb2.GetLatestBlockhashRequest.SerializeToString, - response_deserializer=geyser__pb2.GetLatestBlockhashResponse.FromString, - _registered_method=True, - ) - self.GetBlockHeight = channel.unary_unary( - "/geyser.Geyser/GetBlockHeight", - request_serializer=geyser__pb2.GetBlockHeightRequest.SerializeToString, - response_deserializer=geyser__pb2.GetBlockHeightResponse.FromString, - _registered_method=True, - ) - self.GetSlot = channel.unary_unary( - "/geyser.Geyser/GetSlot", - request_serializer=geyser__pb2.GetSlotRequest.SerializeToString, - response_deserializer=geyser__pb2.GetSlotResponse.FromString, - _registered_method=True, - ) - self.IsBlockhashValid = channel.unary_unary( - "/geyser.Geyser/IsBlockhashValid", - request_serializer=geyser__pb2.IsBlockhashValidRequest.SerializeToString, - response_deserializer=geyser__pb2.IsBlockhashValidResponse.FromString, - _registered_method=True, - ) - self.GetVersion = channel.unary_unary( - "/geyser.Geyser/GetVersion", - request_serializer=geyser__pb2.GetVersionRequest.SerializeToString, - response_deserializer=geyser__pb2.GetVersionResponse.FromString, - _registered_method=True, - ) - - -class GeyserServicer: - """Missing associated documentation comment in .proto file.""" - - def Subscribe(self, request_iterator, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def Ping(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetLatestBlockhash(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetBlockHeight(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetSlot(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def IsBlockhashValid(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetVersion(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_GeyserServicer_to_server(servicer, server): - rpc_method_handlers = { - "Subscribe": grpc.stream_stream_rpc_method_handler( - servicer.Subscribe, - request_deserializer=geyser__pb2.SubscribeRequest.FromString, - response_serializer=geyser__pb2.SubscribeUpdate.SerializeToString, - ), - "Ping": grpc.unary_unary_rpc_method_handler( - servicer.Ping, - request_deserializer=geyser__pb2.PingRequest.FromString, - response_serializer=geyser__pb2.PongResponse.SerializeToString, - ), - "GetLatestBlockhash": grpc.unary_unary_rpc_method_handler( - servicer.GetLatestBlockhash, - request_deserializer=geyser__pb2.GetLatestBlockhashRequest.FromString, - response_serializer=geyser__pb2.GetLatestBlockhashResponse.SerializeToString, - ), - "GetBlockHeight": grpc.unary_unary_rpc_method_handler( - servicer.GetBlockHeight, - request_deserializer=geyser__pb2.GetBlockHeightRequest.FromString, - response_serializer=geyser__pb2.GetBlockHeightResponse.SerializeToString, - ), - "GetSlot": grpc.unary_unary_rpc_method_handler( - servicer.GetSlot, - request_deserializer=geyser__pb2.GetSlotRequest.FromString, - response_serializer=geyser__pb2.GetSlotResponse.SerializeToString, - ), - "IsBlockhashValid": grpc.unary_unary_rpc_method_handler( - servicer.IsBlockhashValid, - request_deserializer=geyser__pb2.IsBlockhashValidRequest.FromString, - response_serializer=geyser__pb2.IsBlockhashValidResponse.SerializeToString, - ), - "GetVersion": grpc.unary_unary_rpc_method_handler( - servicer.GetVersion, - request_deserializer=geyser__pb2.GetVersionRequest.FromString, - response_serializer=geyser__pb2.GetVersionResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "geyser.Geyser", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) - server.add_registered_method_handlers("geyser.Geyser", rpc_method_handlers) - - -# This class is part of an EXPERIMENTAL API. -class Geyser: - """Missing associated documentation comment in .proto file.""" - - @staticmethod - def Subscribe( - request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.stream_stream( - request_iterator, - target, - "/geyser.Geyser/Subscribe", - geyser__pb2.SubscribeRequest.SerializeToString, - geyser__pb2.SubscribeUpdate.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True, - ) - - @staticmethod - def Ping( - request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.unary_unary( - request, - target, - "/geyser.Geyser/Ping", - geyser__pb2.PingRequest.SerializeToString, - geyser__pb2.PongResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True, - ) - - @staticmethod - def GetLatestBlockhash( - request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.unary_unary( - request, - target, - "/geyser.Geyser/GetLatestBlockhash", - geyser__pb2.GetLatestBlockhashRequest.SerializeToString, - geyser__pb2.GetLatestBlockhashResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True, - ) - - @staticmethod - def GetBlockHeight( - request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.unary_unary( - request, - target, - "/geyser.Geyser/GetBlockHeight", - geyser__pb2.GetBlockHeightRequest.SerializeToString, - geyser__pb2.GetBlockHeightResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True, - ) - - @staticmethod - def GetSlot( - request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.unary_unary( - request, - target, - "/geyser.Geyser/GetSlot", - geyser__pb2.GetSlotRequest.SerializeToString, - geyser__pb2.GetSlotResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True, - ) - - @staticmethod - def IsBlockhashValid( - request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.unary_unary( - request, - target, - "/geyser.Geyser/IsBlockhashValid", - geyser__pb2.IsBlockhashValidRequest.SerializeToString, - geyser__pb2.IsBlockhashValidResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True, - ) - - @staticmethod - def GetVersion( - request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None, - ): - return grpc.experimental.unary_unary( - request, - target, - "/geyser.Geyser/GetVersion", - geyser__pb2.GetVersionRequest.SerializeToString, - geyser__pb2.GetVersionResponse.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True, - ) diff --git a/learning-examples/listen-new-tokens/generated/solana_storage_pb2.py b/learning-examples/listen-new-tokens/generated/solana_storage_pb2.py deleted file mode 100644 index d6fa180..0000000 --- a/learning-examples/listen-new-tokens/generated/solana_storage_pb2.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# NO CHECKED-IN PROTOBUF GENCODE -# source: solana-storage.proto -# Protobuf Python Version: 5.29.0 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import runtime_version as _runtime_version -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -_runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, 5, 29, 0, "", "solana-storage.proto" -) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x14solana-storage.proto\x12\x1dsolana.storage.ConfirmedBlock"\xa1\x03\n\x0e\x43onfirmedBlock\x12\x1a\n\x12previous_blockhash\x18\x01 \x01(\t\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x13\n\x0bparent_slot\x18\x03 \x01(\x04\x12I\n\x0ctransactions\x18\x04 \x03(\x0b\x32\x33.solana.storage.ConfirmedBlock.ConfirmedTransaction\x12\x36\n\x07rewards\x18\x05 \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12@\n\nblock_time\x18\x06 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UnixTimestamp\x12@\n\x0c\x62lock_height\x18\x07 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.BlockHeight\x12\x44\n\x0enum_partitions\x18\x08 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.NumPartitions"\x9b\x01\n\x14\x43onfirmedTransaction\x12?\n\x0btransaction\x18\x01 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.Transaction\x12\x42\n\x04meta\x18\x02 \x01(\x0b\x32\x34.solana.storage.ConfirmedBlock.TransactionStatusMeta"Z\n\x0bTransaction\x12\x12\n\nsignatures\x18\x01 \x03(\x0c\x12\x37\n\x07message\x18\x02 \x01(\x0b\x32&.solana.storage.ConfirmedBlock.Message"\xad\x02\n\x07Message\x12<\n\x06header\x18\x01 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.MessageHeader\x12\x14\n\x0c\x61\x63\x63ount_keys\x18\x02 \x03(\x0c\x12\x18\n\x10recent_blockhash\x18\x03 \x01(\x0c\x12H\n\x0cinstructions\x18\x04 \x03(\x0b\x32\x32.solana.storage.ConfirmedBlock.CompiledInstruction\x12\x11\n\tversioned\x18\x05 \x01(\x08\x12W\n\x15\x61\x64\x64ress_table_lookups\x18\x06 \x03(\x0b\x32\x38.solana.storage.ConfirmedBlock.MessageAddressTableLookup"~\n\rMessageHeader\x12\x1f\n\x17num_required_signatures\x18\x01 \x01(\r\x12$\n\x1cnum_readonly_signed_accounts\x18\x02 \x01(\r\x12&\n\x1enum_readonly_unsigned_accounts\x18\x03 \x01(\r"d\n\x19MessageAddressTableLookup\x12\x13\n\x0b\x61\x63\x63ount_key\x18\x01 \x01(\x0c\x12\x18\n\x10writable_indexes\x18\x02 \x01(\x0c\x12\x18\n\x10readonly_indexes\x18\x03 \x01(\x0c"\xda\x05\n\x15TransactionStatusMeta\x12<\n\x03\x65rr\x18\x01 \x01(\x0b\x32/.solana.storage.ConfirmedBlock.TransactionError\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x14\n\x0cpre_balances\x18\x03 \x03(\x04\x12\x15\n\rpost_balances\x18\x04 \x03(\x04\x12L\n\x12inner_instructions\x18\x05 \x03(\x0b\x32\x30.solana.storage.ConfirmedBlock.InnerInstructions\x12\x1f\n\x17inner_instructions_none\x18\n \x01(\x08\x12\x14\n\x0clog_messages\x18\x06 \x03(\t\x12\x19\n\x11log_messages_none\x18\x0b \x01(\x08\x12G\n\x12pre_token_balances\x18\x07 \x03(\x0b\x32+.solana.storage.ConfirmedBlock.TokenBalance\x12H\n\x13post_token_balances\x18\x08 \x03(\x0b\x32+.solana.storage.ConfirmedBlock.TokenBalance\x12\x36\n\x07rewards\x18\t \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12!\n\x19loaded_writable_addresses\x18\x0c \x03(\x0c\x12!\n\x19loaded_readonly_addresses\x18\r \x03(\x0c\x12>\n\x0breturn_data\x18\x0e \x01(\x0b\x32).solana.storage.ConfirmedBlock.ReturnData\x12\x18\n\x10return_data_none\x18\x0f \x01(\x08\x12#\n\x16\x63ompute_units_consumed\x18\x10 \x01(\x04H\x00\x88\x01\x01\x42\x19\n\x17_compute_units_consumed"\x1f\n\x10TransactionError\x12\x0b\n\x03\x65rr\x18\x01 \x01(\x0c"i\n\x11InnerInstructions\x12\r\n\x05index\x18\x01 \x01(\r\x12\x45\n\x0cinstructions\x18\x02 \x03(\x0b\x32/.solana.storage.ConfirmedBlock.InnerInstruction"x\n\x10InnerInstruction\x12\x18\n\x10program_id_index\x18\x01 \x01(\r\x12\x10\n\x08\x61\x63\x63ounts\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x19\n\x0cstack_height\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\x0f\n\r_stack_height"O\n\x13\x43ompiledInstruction\x12\x18\n\x10program_id_index\x18\x01 \x01(\r\x12\x10\n\x08\x61\x63\x63ounts\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c"\x9d\x01\n\x0cTokenBalance\x12\x15\n\raccount_index\x18\x01 \x01(\r\x12\x0c\n\x04mint\x18\x02 \x01(\t\x12\x45\n\x0fui_token_amount\x18\x03 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UiTokenAmount\x12\r\n\x05owner\x18\x04 \x01(\t\x12\x12\n\nprogram_id\x18\x05 \x01(\t"^\n\rUiTokenAmount\x12\x11\n\tui_amount\x18\x01 \x01(\x01\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\r\x12\x0e\n\x06\x61mount\x18\x03 \x01(\t\x12\x18\n\x10ui_amount_string\x18\x04 \x01(\t".\n\nReturnData\x12\x12\n\nprogram_id\x18\x01 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"\x94\x01\n\x06Reward\x12\x0e\n\x06pubkey\x18\x01 \x01(\t\x12\x10\n\x08lamports\x18\x02 \x01(\x03\x12\x14\n\x0cpost_balance\x18\x03 \x01(\x04\x12>\n\x0breward_type\x18\x04 \x01(\x0e\x32).solana.storage.ConfirmedBlock.RewardType\x12\x12\n\ncommission\x18\x05 \x01(\t"\x87\x01\n\x07Rewards\x12\x36\n\x07rewards\x18\x01 \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12\x44\n\x0enum_partitions\x18\x02 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.NumPartitions""\n\rUnixTimestamp\x12\x11\n\ttimestamp\x18\x01 \x01(\x03"#\n\x0b\x42lockHeight\x12\x14\n\x0c\x62lock_height\x18\x01 \x01(\x04"\'\n\rNumPartitions\x12\x16\n\x0enum_partitions\x18\x01 \x01(\x04*I\n\nRewardType\x12\x0f\n\x0bUnspecified\x10\x00\x12\x07\n\x03\x46\x65\x65\x10\x01\x12\x08\n\x04Rent\x10\x02\x12\x0b\n\x07Staking\x10\x03\x12\n\n\x06Voting\x10\x04\x42;Z9github.com/rpcpool/yellowstone-grpc/examples/golang/protob\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "solana_storage_pb2", _globals) -if not _descriptor._USE_C_DESCRIPTORS: - _globals["DESCRIPTOR"]._loaded_options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = ( - b"Z9github.com/rpcpool/yellowstone-grpc/examples/golang/proto" - ) - _globals["_REWARDTYPE"]._serialized_start = 3042 - _globals["_REWARDTYPE"]._serialized_end = 3115 - _globals["_CONFIRMEDBLOCK"]._serialized_start = 56 - _globals["_CONFIRMEDBLOCK"]._serialized_end = 473 - _globals["_CONFIRMEDTRANSACTION"]._serialized_start = 476 - _globals["_CONFIRMEDTRANSACTION"]._serialized_end = 631 - _globals["_TRANSACTION"]._serialized_start = 633 - _globals["_TRANSACTION"]._serialized_end = 723 - _globals["_MESSAGE"]._serialized_start = 726 - _globals["_MESSAGE"]._serialized_end = 1027 - _globals["_MESSAGEHEADER"]._serialized_start = 1029 - _globals["_MESSAGEHEADER"]._serialized_end = 1155 - _globals["_MESSAGEADDRESSTABLELOOKUP"]._serialized_start = 1157 - _globals["_MESSAGEADDRESSTABLELOOKUP"]._serialized_end = 1257 - _globals["_TRANSACTIONSTATUSMETA"]._serialized_start = 1260 - _globals["_TRANSACTIONSTATUSMETA"]._serialized_end = 1990 - _globals["_TRANSACTIONERROR"]._serialized_start = 1992 - _globals["_TRANSACTIONERROR"]._serialized_end = 2023 - _globals["_INNERINSTRUCTIONS"]._serialized_start = 2025 - _globals["_INNERINSTRUCTIONS"]._serialized_end = 2130 - _globals["_INNERINSTRUCTION"]._serialized_start = 2132 - _globals["_INNERINSTRUCTION"]._serialized_end = 2252 - _globals["_COMPILEDINSTRUCTION"]._serialized_start = 2254 - _globals["_COMPILEDINSTRUCTION"]._serialized_end = 2333 - _globals["_TOKENBALANCE"]._serialized_start = 2336 - _globals["_TOKENBALANCE"]._serialized_end = 2493 - _globals["_UITOKENAMOUNT"]._serialized_start = 2495 - _globals["_UITOKENAMOUNT"]._serialized_end = 2589 - _globals["_RETURNDATA"]._serialized_start = 2591 - _globals["_RETURNDATA"]._serialized_end = 2637 - _globals["_REWARD"]._serialized_start = 2640 - _globals["_REWARD"]._serialized_end = 2788 - _globals["_REWARDS"]._serialized_start = 2791 - _globals["_REWARDS"]._serialized_end = 2926 - _globals["_UNIXTIMESTAMP"]._serialized_start = 2928 - _globals["_UNIXTIMESTAMP"]._serialized_end = 2962 - _globals["_BLOCKHEIGHT"]._serialized_start = 2964 - _globals["_BLOCKHEIGHT"]._serialized_end = 2999 - _globals["_NUMPARTITIONS"]._serialized_start = 3001 - _globals["_NUMPARTITIONS"]._serialized_end = 3040 -# @@protoc_insertion_point(module_scope) diff --git a/learning-examples/listen-new-tokens/generated/solana_storage_pb2.pyi b/learning-examples/listen-new-tokens/generated/solana_storage_pb2.pyi deleted file mode 100644 index 69ec1f9..0000000 --- a/learning-examples/listen-new-tokens/generated/solana_storage_pb2.pyi +++ /dev/null @@ -1,385 +0,0 @@ -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from typing import ( - ClassVar as _ClassVar, - Iterable as _Iterable, - Mapping as _Mapping, - Optional as _Optional, - Union as _Union, -) - -DESCRIPTOR: _descriptor.FileDescriptor - -class RewardType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - Unspecified: _ClassVar[RewardType] - Fee: _ClassVar[RewardType] - Rent: _ClassVar[RewardType] - Staking: _ClassVar[RewardType] - Voting: _ClassVar[RewardType] - -Unspecified: RewardType -Fee: RewardType -Rent: RewardType -Staking: RewardType -Voting: RewardType - -class ConfirmedBlock(_message.Message): - __slots__ = ( - "previous_blockhash", - "blockhash", - "parent_slot", - "transactions", - "rewards", - "block_time", - "block_height", - "num_partitions", - ) - PREVIOUS_BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - PARENT_SLOT_FIELD_NUMBER: _ClassVar[int] - TRANSACTIONS_FIELD_NUMBER: _ClassVar[int] - REWARDS_FIELD_NUMBER: _ClassVar[int] - BLOCK_TIME_FIELD_NUMBER: _ClassVar[int] - BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] - NUM_PARTITIONS_FIELD_NUMBER: _ClassVar[int] - previous_blockhash: str - blockhash: str - parent_slot: int - transactions: _containers.RepeatedCompositeFieldContainer[ConfirmedTransaction] - rewards: _containers.RepeatedCompositeFieldContainer[Reward] - block_time: UnixTimestamp - block_height: BlockHeight - num_partitions: NumPartitions - def __init__( - self, - previous_blockhash: _Optional[str] = ..., - blockhash: _Optional[str] = ..., - parent_slot: _Optional[int] = ..., - transactions: _Optional[ - _Iterable[_Union[ConfirmedTransaction, _Mapping]] - ] = ..., - rewards: _Optional[_Iterable[_Union[Reward, _Mapping]]] = ..., - block_time: _Optional[_Union[UnixTimestamp, _Mapping]] = ..., - block_height: _Optional[_Union[BlockHeight, _Mapping]] = ..., - num_partitions: _Optional[_Union[NumPartitions, _Mapping]] = ..., - ) -> None: ... - -class ConfirmedTransaction(_message.Message): - __slots__ = ("transaction", "meta") - TRANSACTION_FIELD_NUMBER: _ClassVar[int] - META_FIELD_NUMBER: _ClassVar[int] - transaction: Transaction - meta: TransactionStatusMeta - def __init__( - self, - transaction: _Optional[_Union[Transaction, _Mapping]] = ..., - meta: _Optional[_Union[TransactionStatusMeta, _Mapping]] = ..., - ) -> None: ... - -class Transaction(_message.Message): - __slots__ = ("signatures", "message") - SIGNATURES_FIELD_NUMBER: _ClassVar[int] - MESSAGE_FIELD_NUMBER: _ClassVar[int] - signatures: _containers.RepeatedScalarFieldContainer[bytes] - message: Message - def __init__( - self, - signatures: _Optional[_Iterable[bytes]] = ..., - message: _Optional[_Union[Message, _Mapping]] = ..., - ) -> None: ... - -class Message(_message.Message): - __slots__ = ( - "header", - "account_keys", - "recent_blockhash", - "instructions", - "versioned", - "address_table_lookups", - ) - HEADER_FIELD_NUMBER: _ClassVar[int] - ACCOUNT_KEYS_FIELD_NUMBER: _ClassVar[int] - RECENT_BLOCKHASH_FIELD_NUMBER: _ClassVar[int] - INSTRUCTIONS_FIELD_NUMBER: _ClassVar[int] - VERSIONED_FIELD_NUMBER: _ClassVar[int] - ADDRESS_TABLE_LOOKUPS_FIELD_NUMBER: _ClassVar[int] - header: MessageHeader - account_keys: _containers.RepeatedScalarFieldContainer[bytes] - recent_blockhash: bytes - instructions: _containers.RepeatedCompositeFieldContainer[CompiledInstruction] - versioned: bool - address_table_lookups: _containers.RepeatedCompositeFieldContainer[ - MessageAddressTableLookup - ] - def __init__( - self, - header: _Optional[_Union[MessageHeader, _Mapping]] = ..., - account_keys: _Optional[_Iterable[bytes]] = ..., - recent_blockhash: _Optional[bytes] = ..., - instructions: _Optional[_Iterable[_Union[CompiledInstruction, _Mapping]]] = ..., - versioned: bool = ..., - address_table_lookups: _Optional[ - _Iterable[_Union[MessageAddressTableLookup, _Mapping]] - ] = ..., - ) -> None: ... - -class MessageHeader(_message.Message): - __slots__ = ( - "num_required_signatures", - "num_readonly_signed_accounts", - "num_readonly_unsigned_accounts", - ) - NUM_REQUIRED_SIGNATURES_FIELD_NUMBER: _ClassVar[int] - NUM_READONLY_SIGNED_ACCOUNTS_FIELD_NUMBER: _ClassVar[int] - NUM_READONLY_UNSIGNED_ACCOUNTS_FIELD_NUMBER: _ClassVar[int] - num_required_signatures: int - num_readonly_signed_accounts: int - num_readonly_unsigned_accounts: int - def __init__( - self, - num_required_signatures: _Optional[int] = ..., - num_readonly_signed_accounts: _Optional[int] = ..., - num_readonly_unsigned_accounts: _Optional[int] = ..., - ) -> None: ... - -class MessageAddressTableLookup(_message.Message): - __slots__ = ("account_key", "writable_indexes", "readonly_indexes") - ACCOUNT_KEY_FIELD_NUMBER: _ClassVar[int] - WRITABLE_INDEXES_FIELD_NUMBER: _ClassVar[int] - READONLY_INDEXES_FIELD_NUMBER: _ClassVar[int] - account_key: bytes - writable_indexes: bytes - readonly_indexes: bytes - def __init__( - self, - account_key: _Optional[bytes] = ..., - writable_indexes: _Optional[bytes] = ..., - readonly_indexes: _Optional[bytes] = ..., - ) -> None: ... - -class TransactionStatusMeta(_message.Message): - __slots__ = ( - "err", - "fee", - "pre_balances", - "post_balances", - "inner_instructions", - "inner_instructions_none", - "log_messages", - "log_messages_none", - "pre_token_balances", - "post_token_balances", - "rewards", - "loaded_writable_addresses", - "loaded_readonly_addresses", - "return_data", - "return_data_none", - "compute_units_consumed", - ) - ERR_FIELD_NUMBER: _ClassVar[int] - FEE_FIELD_NUMBER: _ClassVar[int] - PRE_BALANCES_FIELD_NUMBER: _ClassVar[int] - POST_BALANCES_FIELD_NUMBER: _ClassVar[int] - INNER_INSTRUCTIONS_FIELD_NUMBER: _ClassVar[int] - INNER_INSTRUCTIONS_NONE_FIELD_NUMBER: _ClassVar[int] - LOG_MESSAGES_FIELD_NUMBER: _ClassVar[int] - LOG_MESSAGES_NONE_FIELD_NUMBER: _ClassVar[int] - PRE_TOKEN_BALANCES_FIELD_NUMBER: _ClassVar[int] - POST_TOKEN_BALANCES_FIELD_NUMBER: _ClassVar[int] - REWARDS_FIELD_NUMBER: _ClassVar[int] - LOADED_WRITABLE_ADDRESSES_FIELD_NUMBER: _ClassVar[int] - LOADED_READONLY_ADDRESSES_FIELD_NUMBER: _ClassVar[int] - RETURN_DATA_FIELD_NUMBER: _ClassVar[int] - RETURN_DATA_NONE_FIELD_NUMBER: _ClassVar[int] - COMPUTE_UNITS_CONSUMED_FIELD_NUMBER: _ClassVar[int] - err: TransactionError - fee: int - pre_balances: _containers.RepeatedScalarFieldContainer[int] - post_balances: _containers.RepeatedScalarFieldContainer[int] - inner_instructions: _containers.RepeatedCompositeFieldContainer[InnerInstructions] - inner_instructions_none: bool - log_messages: _containers.RepeatedScalarFieldContainer[str] - log_messages_none: bool - pre_token_balances: _containers.RepeatedCompositeFieldContainer[TokenBalance] - post_token_balances: _containers.RepeatedCompositeFieldContainer[TokenBalance] - rewards: _containers.RepeatedCompositeFieldContainer[Reward] - loaded_writable_addresses: _containers.RepeatedScalarFieldContainer[bytes] - loaded_readonly_addresses: _containers.RepeatedScalarFieldContainer[bytes] - return_data: ReturnData - return_data_none: bool - compute_units_consumed: int - def __init__( - self, - err: _Optional[_Union[TransactionError, _Mapping]] = ..., - fee: _Optional[int] = ..., - pre_balances: _Optional[_Iterable[int]] = ..., - post_balances: _Optional[_Iterable[int]] = ..., - inner_instructions: _Optional[ - _Iterable[_Union[InnerInstructions, _Mapping]] - ] = ..., - inner_instructions_none: bool = ..., - log_messages: _Optional[_Iterable[str]] = ..., - log_messages_none: bool = ..., - pre_token_balances: _Optional[_Iterable[_Union[TokenBalance, _Mapping]]] = ..., - post_token_balances: _Optional[_Iterable[_Union[TokenBalance, _Mapping]]] = ..., - rewards: _Optional[_Iterable[_Union[Reward, _Mapping]]] = ..., - loaded_writable_addresses: _Optional[_Iterable[bytes]] = ..., - loaded_readonly_addresses: _Optional[_Iterable[bytes]] = ..., - return_data: _Optional[_Union[ReturnData, _Mapping]] = ..., - return_data_none: bool = ..., - compute_units_consumed: _Optional[int] = ..., - ) -> None: ... - -class TransactionError(_message.Message): - __slots__ = ("err",) - ERR_FIELD_NUMBER: _ClassVar[int] - err: bytes - def __init__(self, err: _Optional[bytes] = ...) -> None: ... - -class InnerInstructions(_message.Message): - __slots__ = ("index", "instructions") - INDEX_FIELD_NUMBER: _ClassVar[int] - INSTRUCTIONS_FIELD_NUMBER: _ClassVar[int] - index: int - instructions: _containers.RepeatedCompositeFieldContainer[InnerInstruction] - def __init__( - self, - index: _Optional[int] = ..., - instructions: _Optional[_Iterable[_Union[InnerInstruction, _Mapping]]] = ..., - ) -> None: ... - -class InnerInstruction(_message.Message): - __slots__ = ("program_id_index", "accounts", "data", "stack_height") - PROGRAM_ID_INDEX_FIELD_NUMBER: _ClassVar[int] - ACCOUNTS_FIELD_NUMBER: _ClassVar[int] - DATA_FIELD_NUMBER: _ClassVar[int] - STACK_HEIGHT_FIELD_NUMBER: _ClassVar[int] - program_id_index: int - accounts: bytes - data: bytes - stack_height: int - def __init__( - self, - program_id_index: _Optional[int] = ..., - accounts: _Optional[bytes] = ..., - data: _Optional[bytes] = ..., - stack_height: _Optional[int] = ..., - ) -> None: ... - -class CompiledInstruction(_message.Message): - __slots__ = ("program_id_index", "accounts", "data") - PROGRAM_ID_INDEX_FIELD_NUMBER: _ClassVar[int] - ACCOUNTS_FIELD_NUMBER: _ClassVar[int] - DATA_FIELD_NUMBER: _ClassVar[int] - program_id_index: int - accounts: bytes - data: bytes - def __init__( - self, - program_id_index: _Optional[int] = ..., - accounts: _Optional[bytes] = ..., - data: _Optional[bytes] = ..., - ) -> None: ... - -class TokenBalance(_message.Message): - __slots__ = ("account_index", "mint", "ui_token_amount", "owner", "program_id") - ACCOUNT_INDEX_FIELD_NUMBER: _ClassVar[int] - MINT_FIELD_NUMBER: _ClassVar[int] - UI_TOKEN_AMOUNT_FIELD_NUMBER: _ClassVar[int] - OWNER_FIELD_NUMBER: _ClassVar[int] - PROGRAM_ID_FIELD_NUMBER: _ClassVar[int] - account_index: int - mint: str - ui_token_amount: UiTokenAmount - owner: str - program_id: str - def __init__( - self, - account_index: _Optional[int] = ..., - mint: _Optional[str] = ..., - ui_token_amount: _Optional[_Union[UiTokenAmount, _Mapping]] = ..., - owner: _Optional[str] = ..., - program_id: _Optional[str] = ..., - ) -> None: ... - -class UiTokenAmount(_message.Message): - __slots__ = ("ui_amount", "decimals", "amount", "ui_amount_string") - UI_AMOUNT_FIELD_NUMBER: _ClassVar[int] - DECIMALS_FIELD_NUMBER: _ClassVar[int] - AMOUNT_FIELD_NUMBER: _ClassVar[int] - UI_AMOUNT_STRING_FIELD_NUMBER: _ClassVar[int] - ui_amount: float - decimals: int - amount: str - ui_amount_string: str - def __init__( - self, - ui_amount: _Optional[float] = ..., - decimals: _Optional[int] = ..., - amount: _Optional[str] = ..., - ui_amount_string: _Optional[str] = ..., - ) -> None: ... - -class ReturnData(_message.Message): - __slots__ = ("program_id", "data") - PROGRAM_ID_FIELD_NUMBER: _ClassVar[int] - DATA_FIELD_NUMBER: _ClassVar[int] - program_id: bytes - data: bytes - def __init__( - self, program_id: _Optional[bytes] = ..., data: _Optional[bytes] = ... - ) -> None: ... - -class Reward(_message.Message): - __slots__ = ("pubkey", "lamports", "post_balance", "reward_type", "commission") - PUBKEY_FIELD_NUMBER: _ClassVar[int] - LAMPORTS_FIELD_NUMBER: _ClassVar[int] - POST_BALANCE_FIELD_NUMBER: _ClassVar[int] - REWARD_TYPE_FIELD_NUMBER: _ClassVar[int] - COMMISSION_FIELD_NUMBER: _ClassVar[int] - pubkey: str - lamports: int - post_balance: int - reward_type: RewardType - commission: str - def __init__( - self, - pubkey: _Optional[str] = ..., - lamports: _Optional[int] = ..., - post_balance: _Optional[int] = ..., - reward_type: _Optional[_Union[RewardType, str]] = ..., - commission: _Optional[str] = ..., - ) -> None: ... - -class Rewards(_message.Message): - __slots__ = ("rewards", "num_partitions") - REWARDS_FIELD_NUMBER: _ClassVar[int] - NUM_PARTITIONS_FIELD_NUMBER: _ClassVar[int] - rewards: _containers.RepeatedCompositeFieldContainer[Reward] - num_partitions: NumPartitions - def __init__( - self, - rewards: _Optional[_Iterable[_Union[Reward, _Mapping]]] = ..., - num_partitions: _Optional[_Union[NumPartitions, _Mapping]] = ..., - ) -> None: ... - -class UnixTimestamp(_message.Message): - __slots__ = ("timestamp",) - TIMESTAMP_FIELD_NUMBER: _ClassVar[int] - timestamp: int - def __init__(self, timestamp: _Optional[int] = ...) -> None: ... - -class BlockHeight(_message.Message): - __slots__ = ("block_height",) - BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int] - block_height: int - def __init__(self, block_height: _Optional[int] = ...) -> None: ... - -class NumPartitions(_message.Message): - __slots__ = ("num_partitions",) - NUM_PARTITIONS_FIELD_NUMBER: _ClassVar[int] - num_partitions: int - def __init__(self, num_partitions: _Optional[int] = ...) -> None: ... diff --git a/learning-examples/listen-new-tokens/generated/solana_storage_pb2_grpc.py b/learning-examples/listen-new-tokens/generated/solana_storage_pb2_grpc.py deleted file mode 100644 index 60daa15..0000000 --- a/learning-examples/listen-new-tokens/generated/solana_storage_pb2_grpc.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" - -import grpc -import warnings - - -GRPC_GENERATED_VERSION = "1.71.0" -GRPC_VERSION = grpc.__version__ -_version_not_supported = False - -try: - from grpc._utilities import first_version_is_lower - - _version_not_supported = first_version_is_lower( - GRPC_VERSION, GRPC_GENERATED_VERSION - ) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - raise RuntimeError( - f"The grpc package installed is at version {GRPC_VERSION}," - + f" but the generated code in solana_storage_pb2_grpc.py depends on" - + f" grpcio>={GRPC_GENERATED_VERSION}." - + f" Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}" - + f" or downgrade your generated code using grpcio-tools<={GRPC_VERSION}." - ) diff --git a/learning-examples/listen-new-tokens/listen_blocksubscribe.py b/learning-examples/listen-new-tokens/listen_blocksubscribe.py index f85fe5f..4d7a24c 100644 --- a/learning-examples/listen-new-tokens/listen_blocksubscribe.py +++ b/learning-examples/listen-new-tokens/listen_blocksubscribe.py @@ -382,6 +382,11 @@ async def listen_and_decode_create(): print( f"Received unexpected message type: {data.get('method', 'Unknown')}" ) + except websockets.ConnectionClosed: + # Leave the recv loop so main() can reconnect. Swallowing this here + # would make the next recv() raise immediately, spinning the loop. + print("WebSocket connection closed.") + break except Exception as e: print(f"An error occurred: {e!s}") print(f"Error details: {type(e).__name__}") @@ -389,8 +394,17 @@ async def listen_and_decode_create(): traceback.print_exc() - print("WebSocket connection closed.") + +async def main() -> None: + """Reconnect for as long as the script runs.""" + while True: + try: + await listen_and_decode_create() + except (websockets.WebSocketException, OSError) as e: + print(f"Connection error: {e!s}") + print("Reconnecting in 5 seconds...") + await asyncio.sleep(5) if __name__ == "__main__": - asyncio.run(listen_and_decode_create()) + asyncio.run(main()) diff --git a/learning-examples/listen-new-tokens/listen_geyser.py b/learning-examples/listen-new-tokens/listen_geyser.py index 2f55b1b..dd9d03b 100644 --- a/learning-examples/listen-new-tokens/listen_geyser.py +++ b/learning-examples/listen-new-tokens/listen_geyser.py @@ -18,13 +18,19 @@ Configure via GEYSER_ENDPOINT, GEYSER_API_TOKEN, and AUTH_TYPE variables. import asyncio import os import struct +import sys +from pathlib import Path import base58 import grpc from dotenv import load_dotenv -from generated import geyser_pb2, geyser_pb2_grpc from solders.pubkey import Pubkey +# The geyser stubs are generated once, into src/geyser/generated. Reuse them rather +# than keeping a second copy here that drifts out of sync with proto/. +sys.path.insert(0, str(Path(__file__).resolve().parents[2])) +from src.geyser.generated import geyser_pb2, geyser_pb2_grpc + load_dotenv() @@ -106,6 +112,31 @@ def create_subscription_request(): return request +def resolve_account_keys( + tx: geyser_pb2.SubscribeUpdateTransactionInfo, +) -> list[bytes]: + """Build the full account-key table for one transaction. + + A v0 transaction indexes accounts past the end of `message.account_keys` when it + uses an address lookup table; geyser reports those in the transaction meta, in + this exact order: static keys, then writable loaded, then read-only loaded. + Coins minted through a router (most of them) arrive this way, so a listener that + only reads `message.account_keys` mislabels or drops them. + + Args: + tx: A geyser `SubscribeUpdateTransactionInfo` + + Returns: + Account keys as raw 32-byte values, indexable by an instruction's account list + """ + keys = list(tx.transaction.message.account_keys) + meta = getattr(tx, "meta", None) + if meta is not None: + keys.extend(meta.loaded_writable_addresses) + keys.extend(meta.loaded_readonly_addresses) + return keys + + def decode_create_instruction(ix_data: bytes, keys, accounts) -> dict: """Decode a legacy create instruction (Metaplex) from transaction data.""" # Skip past the 8-byte discriminator prefix @@ -116,6 +147,12 @@ def decode_create_instruction(ix_data: bytes, keys, accounts) -> dict: if index >= len(accounts): return "N/A" account_index = accounts[index] + # A v0 transaction can index accounts that live in an address lookup table, + # which geyser reports under meta.loaded_*_addresses rather than + # message.account_keys. Without this guard those coins raise IndexError and + # kill the listener. + if account_index >= len(keys): + return "N/A" return base58.b58encode(keys[account_index]).decode() # Read string fields (prefixed with length) @@ -170,6 +207,12 @@ def decode_create_v2_instruction(ix_data: bytes, keys, accounts) -> dict: if index >= len(accounts): return "N/A" account_index = accounts[index] + # A v0 transaction can index accounts that live in an address lookup table, + # which geyser reports under meta.loaded_*_addresses rather than + # message.account_keys. Without this guard those coins raise IndexError and + # kill the listener. + if account_index >= len(keys): + return "N/A" return base58.b58encode(keys[account_index]).decode() # Read string fields (prefixed with length) @@ -238,6 +281,8 @@ async def monitor_pump(): if msg is None: continue + keys = resolve_account_keys(update.transaction.transaction) + # Check each instruction in the transaction for ix in msg.instructions: # Check for both Create and CreateV2 instructions @@ -249,11 +294,9 @@ async def monitor_pump(): # Decode based on instruction type if is_create_v2: - info = decode_create_v2_instruction( - ix.data, msg.account_keys, ix.accounts - ) + info = decode_create_v2_instruction(ix.data, keys, ix.accounts) else: - info = decode_create_instruction(ix.data, msg.account_keys, ix.accounts) + info = decode_create_instruction(ix.data, keys, ix.accounts) # Extract transaction signature signature = base58.b58encode( diff --git a/learning-examples/listen-new-tokens/listen_logsubscribe.py b/learning-examples/listen-new-tokens/listen_logsubscribe.py index 65007fd..aca58ba 100644 --- a/learning-examples/listen-new-tokens/listen_logsubscribe.py +++ b/learning-examples/listen-new-tokens/listen_logsubscribe.py @@ -6,13 +6,17 @@ Performance: Usually faster than blockSubscribe, but slower than Geyser. This script uses logsSubscribe which receives program logs containing event data. Event logs include all token fields directly, making parsing simpler and faster than -decoding full transactions. +decoding full transactions. It also derives each coin's associated bonding curve, +which is the token account the curve holds its supply in. WebSocket API Reference: https://solana.com/docs/rpc/websocket/logssubscribe Program Logs and Events: https://solana.com/docs/programs/debugging#logging + +Program Derived Addresses: +https://solana.com/docs/core/pda """ import asyncio @@ -36,19 +40,32 @@ WSS_ENDPOINT = os.environ.get("SOLANA_NODE_WSS_ENDPOINT") WEBSOCKET_MAX_MESSAGE_BYTES = 32 * 1024 * 1024 PUMP_PROGRAM_ID = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P") +# Coins created with `create_v2` are Token2022; legacy `create` coins are SPL Token. +# The associated bonding curve is an ATA, and an ATA's address depends on which token +# program owns the mint — deriving a Token2022 coin's ATA against the legacy program +# yields a valid-looking address that does not exist on chain. +TOKEN_PROGRAM_ID = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") +TOKEN_2022_PROGRAM_ID = Pubkey.from_string("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") +ASSOCIATED_TOKEN_PROGRAM_ID = Pubkey.from_string( + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" +) + # Event discriminator for CreateEvent (8-byte identifier) # This is emitted by both Create and CreateV2 instructions # Calculated using the first 8 bytes of sha256("event:CreateEvent") CREATE_EVENT_DISCRIMINATOR = bytes([27, 114, 169, 77, 222, 235, 99, 118]) -def print_token_info(token_data, signature=None): +def print_token_info( + token_data, signature=None, associated_bonding_curve: str | None = None +): """ Print token information in a consistent, user-friendly format. Args: token_data: Dictionary containing token fields signature: Optional transaction signature + associated_bonding_curve: Optional derived associated bonding curve address """ print("\n" + "=" * 80) print("🎯 NEW TOKEN DETECTED") @@ -59,6 +76,8 @@ def print_token_info(token_data, signature=None): if "bondingCurve" in token_data: print(f"Bonding Curve: {token_data['bondingCurve']}") + if associated_bonding_curve: + print(f"Associated BC: {associated_bonding_curve}") if "user" in token_data: print(f"User: {token_data['user']}") if "creator" in token_data: @@ -76,6 +95,36 @@ def print_token_info(token_data, signature=None): +def find_associated_bonding_curve( + mint: Pubkey, bonding_curve: Pubkey, token_standard: str +) -> Pubkey: + """ + Derive the associated token account the bonding curve holds its supply in. + + ATA derivation: find_program_address( + [bonding_curve, token_program_id, mint], associated_token_program_id + ) + + Args: + mint: The token mint pubkey + bonding_curve: The bonding curve pubkey + token_standard: "token2022" for create_v2 coins, anything else for legacy + + Returns: + The derived associated bonding curve address + """ + token_program = ( + TOKEN_2022_PROGRAM_ID + if token_standard == "token2022" # noqa: S105 - a token standard, not a secret + else TOKEN_PROGRAM_ID + ) + derived_address, _ = Pubkey.find_program_address( + [bytes(bonding_curve), bytes(token_program), bytes(mint)], + ASSOCIATED_TOKEN_PROGRAM_ID, + ) + return derived_address + + def parse_create_instruction(data): """ Parse CreateEvent data from legacy Create instruction (Metaplex tokens). @@ -236,22 +285,30 @@ async def listen_for_new_tokens(): # Both create and create_v2 emit the same CreateEvent # The difference is in the optional is_mayhem_mode field if is_create_v2: + print("📝 Instruction: CreateV2 (Token2022)") parsed_data = parse_create_v2_instruction( decoded_data ) else: + print("📝 Instruction: Create (Legacy/Metaplex)") parsed_data = parse_create_instruction( decoded_data ) if parsed_data and "name" in parsed_data: + associated_curve = find_associated_bonding_curve( + Pubkey.from_string(parsed_data["mint"]), + Pubkey.from_string(parsed_data["bondingCurve"]), + parsed_data.get("token_standard", ""), + ) # Print token information in consistent format print_token_info( parsed_data, - signature=log_data.get("signature") + signature=log_data.get("signature"), + associated_bonding_curve=str(associated_curve), ) else: - print(f"⚠️ Parsing failed for CreateEvent") + print("⚠️ Parsing failed for CreateEvent") except Exception as e: print(f"❌ Error processing log: {e!s}") diff --git a/learning-examples/listen-new-tokens/listen_logsubscribe_abc.py b/learning-examples/listen-new-tokens/listen_logsubscribe_abc.py deleted file mode 100644 index 29afec3..0000000 --- a/learning-examples/listen-new-tokens/listen_logsubscribe_abc.py +++ /dev/null @@ -1,303 +0,0 @@ -""" -Listens for new Pump.fun token creations via Solana WebSocket. -Monitors logs for 'Create' instructions, decodes and prints token details (name, symbol, mint, etc.). -Additionally, calculates the associated bonding curve address for each token using PDA derivation. - -Performance: Usually faster than blockSubscribe, but slower than Geyser. - -This script demonstrates Program Derived Address (PDA) calculation for the associated -bonding curve, which is the token account owned by the bonding curve that holds -the minted tokens. - -WebSocket API Reference: -https://solana.com/docs/rpc/websocket/logssubscribe - -Program Derived Addresses: -https://solana.com/docs/core/pda -""" - -import asyncio -import base64 -import json -import os -import struct - -import base58 -import websockets -from dotenv import load_dotenv -from solders.pubkey import Pubkey - -load_dotenv() - -WSS_ENDPOINT = os.environ.get("SOLANA_NODE_WSS_ENDPOINT") - -# Solana's blockSubscribe (and a busy logsSubscribe) sends frames well past -# websockets' 1 MiB default, which kills the connection with a 1009 close -# instead of delivering the message. Same value the bot's own listeners use. -WEBSOCKET_MAX_MESSAGE_BYTES = 32 * 1024 * 1024 -PUMP_PROGRAM_ID = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P") -TOKEN_PROGRAM_ID = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") -ASSOCIATED_TOKEN_PROGRAM_ID = Pubkey.from_string( - "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" -) - -# Event discriminator for CreateEvent (8-byte identifier) -# This is emitted by both Create and CreateV2 instructions -# Calculated using the first 8 bytes of sha256("event:CreateEvent") -CREATE_EVENT_DISCRIMINATOR = bytes([27, 114, 169, 77, 222, 235, 99, 118]) - - -def print_token_info(token_data, signature=None, associated_bonding_curve=None): - """ - Print token information in a consistent, user-friendly format. - - Args: - token_data: Dictionary containing token fields - signature: Optional transaction signature - associated_bonding_curve: Optional associated bonding curve address - """ - print("\n" + "=" * 80) - print("🎯 NEW TOKEN DETECTED") - print("=" * 80) - print(f"Name: {token_data.get('name', 'N/A')}") - print(f"Symbol: {token_data.get('symbol', 'N/A')}") - print(f"Mint: {token_data.get('mint', 'N/A')}") - - if "bondingCurve" in token_data: - print(f"Bonding Curve: {token_data['bondingCurve']}") - if associated_bonding_curve: - print(f"Associated BC: {associated_bonding_curve}") - if "user" in token_data: - print(f"User: {token_data['user']}") - if "creator" in token_data: - print(f"Creator: {token_data['creator']}") - - print(f"Token Standard: {token_data.get('token_standard', 'N/A')}") - print(f"Mayhem Mode: {token_data.get('is_mayhem_mode', False)}") - - if "uri" in token_data: - print(f"URI: {token_data['uri']}") - if signature: - print(f"Signature: {signature}") - - print("=" * 80 + "\n") - - -def find_associated_bonding_curve(mint: Pubkey, bonding_curve: Pubkey) -> Pubkey: - """ - Calculate the associated token account (ATA) address for the bonding curve. - - The associated bonding curve is a Program Derived Address (PDA) that holds - the token supply controlled by the bonding curve. It's derived using the - standard Associated Token Account (ATA) derivation. - - ATA Derivation: find_program_address( - [bonding_curve_pubkey, token_program_id, mint_pubkey], - associated_token_program_id - ) - - Args: - mint: The token mint pubkey - bonding_curve: The bonding curve pubkey - - Returns: - The derived associated bonding curve address - """ - derived_address, _ = Pubkey.find_program_address( - [ - bytes(bonding_curve), - bytes(TOKEN_PROGRAM_ID), - bytes(mint), - ], - ASSOCIATED_TOKEN_PROGRAM_ID, - ) - return derived_address - - -_CREATE_EVENT_FIELDS = [ - ("name", "string"), - ("symbol", "string"), - ("uri", "string"), - ("mint", "publicKey"), - ("bondingCurve", "publicKey"), - ("user", "publicKey"), - ("creator", "publicKey"), - ("timestamp", "i64"), - ("virtual_token_reserves", "u64"), - ("virtual_sol_reserves", "u64"), - ("real_token_reserves", "u64"), - ("token_total_supply", "u64"), - ("token_program", "publicKey"), - ("is_mayhem_mode", "bool"), - ("is_cashback_enabled", "bool"), -] - - -def _parse_create_event(data, token_standard_hint): - """Parse a CreateEvent payload (same on-chain layout for both create and create_v2).""" - if len(data) < 8: - print(f"⚠️ Data too short for Create event: {len(data)} bytes") - return None - offset = 8 - parsed_data = {} - try: - for field_name, field_type in _CREATE_EVENT_FIELDS: - if field_type == "string": - if offset + 4 > len(data): - raise ValueError(f"Not enough data for {field_name} length at offset {offset}") - length = struct.unpack(" len(data): - raise ValueError(f"Not enough data for {field_name} value (length={length}) at offset {offset}") - value = data[offset : offset + length].decode("utf-8") - offset += length - elif field_type == "publicKey": - if offset + 32 > len(data): - raise ValueError(f"Not enough data for {field_name} at offset {offset}") - value = base58.b58encode(data[offset : offset + 32]).decode("utf-8") - offset += 32 - elif field_type == "u64": - value = struct.unpack(" accounts = 1; - map slots = 2; - map transactions = 3; - map transactions_status = 10; - map blocks = 4; - map blocks_meta = 5; - map entry = 8; - optional CommitmentLevel commitment = 6; - repeated SubscribeRequestAccountsDataSlice accounts_data_slice = 7; - optional SubscribeRequestPing ping = 9; -} - -message SubscribeRequestFilterAccounts { - repeated string account = 2; - repeated string owner = 3; - repeated SubscribeRequestFilterAccountsFilter filters = 4; - optional bool nonempty_txn_signature = 5; -} - -message SubscribeRequestFilterAccountsFilter { - oneof filter { - SubscribeRequestFilterAccountsFilterMemcmp memcmp = 1; - uint64 datasize = 2; - bool token_account_state = 3; - SubscribeRequestFilterAccountsFilterLamports lamports = 4; - } -} - -message SubscribeRequestFilterAccountsFilterMemcmp { - uint64 offset = 1; - oneof data { - bytes bytes = 2; - string base58 = 3; - string base64 = 4; - } -} - -message SubscribeRequestFilterAccountsFilterLamports { - oneof cmp { - uint64 eq = 1; - uint64 ne = 2; - uint64 lt = 3; - uint64 gt = 4; - } -} - -message SubscribeRequestFilterSlots { - optional bool filter_by_commitment = 1; -} - -message SubscribeRequestFilterTransactions { - optional bool vote = 1; - optional bool failed = 2; - optional string signature = 5; - repeated string account_include = 3; - repeated string account_exclude = 4; - repeated string account_required = 6; -} - -message SubscribeRequestFilterBlocks { - repeated string account_include = 1; - optional bool include_transactions = 2; - optional bool include_accounts = 3; - optional bool include_entries = 4; -} - -message SubscribeRequestFilterBlocksMeta {} - -message SubscribeRequestFilterEntry {} - -message SubscribeRequestAccountsDataSlice { - uint64 offset = 1; - uint64 length = 2; -} - -message SubscribeRequestPing { - int32 id = 1; -} - -message SubscribeUpdate { - repeated string filters = 1; - oneof update_oneof { - SubscribeUpdateAccount account = 2; - SubscribeUpdateSlot slot = 3; - SubscribeUpdateTransaction transaction = 4; - SubscribeUpdateTransactionStatus transaction_status = 10; - SubscribeUpdateBlock block = 5; - SubscribeUpdatePing ping = 6; - SubscribeUpdatePong pong = 9; - SubscribeUpdateBlockMeta block_meta = 7; - SubscribeUpdateEntry entry = 8; - } -} - -message SubscribeUpdateAccount { - SubscribeUpdateAccountInfo account = 1; - uint64 slot = 2; - bool is_startup = 3; -} - -message SubscribeUpdateAccountInfo { - bytes pubkey = 1; - uint64 lamports = 2; - bytes owner = 3; - bool executable = 4; - uint64 rent_epoch = 5; - bytes data = 6; - uint64 write_version = 7; - optional bytes txn_signature = 8; -} - -message SubscribeUpdateSlot { - uint64 slot = 1; - optional uint64 parent = 2; - CommitmentLevel status = 3; - optional string dead_error = 4; -} - -message SubscribeUpdateTransaction { - SubscribeUpdateTransactionInfo transaction = 1; - uint64 slot = 2; -} - -message SubscribeUpdateTransactionInfo { - bytes signature = 1; - bool is_vote = 2; - solana.storage.ConfirmedBlock.Transaction transaction = 3; - solana.storage.ConfirmedBlock.TransactionStatusMeta meta = 4; - uint64 index = 5; -} - -message SubscribeUpdateTransactionStatus { - uint64 slot = 1; - bytes signature = 2; - bool is_vote = 3; - uint64 index = 4; - solana.storage.ConfirmedBlock.TransactionError err = 5; -} - -message SubscribeUpdateBlock { - uint64 slot = 1; - string blockhash = 2; - solana.storage.ConfirmedBlock.Rewards rewards = 3; - solana.storage.ConfirmedBlock.UnixTimestamp block_time = 4; - solana.storage.ConfirmedBlock.BlockHeight block_height = 5; - uint64 parent_slot = 7; - string parent_blockhash = 8; - uint64 executed_transaction_count = 9; - repeated SubscribeUpdateTransactionInfo transactions = 6; - uint64 updated_account_count = 10; - repeated SubscribeUpdateAccountInfo accounts = 11; - uint64 entries_count = 12; - repeated SubscribeUpdateEntry entries = 13; -} - -message SubscribeUpdateBlockMeta { - uint64 slot = 1; - string blockhash = 2; - solana.storage.ConfirmedBlock.Rewards rewards = 3; - solana.storage.ConfirmedBlock.UnixTimestamp block_time = 4; - solana.storage.ConfirmedBlock.BlockHeight block_height = 5; - uint64 parent_slot = 6; - string parent_blockhash = 7; - uint64 executed_transaction_count = 8; - uint64 entries_count = 9; -} - -message SubscribeUpdateEntry { - uint64 slot = 1; - uint64 index = 2; - uint64 num_hashes = 3; - bytes hash = 4; - uint64 executed_transaction_count = 5; - uint64 starting_transaction_index = 6; // added in v1.18, for solana 1.17 value is always 0 -} - -message SubscribeUpdatePing {} - -message SubscribeUpdatePong { - int32 id = 1; -} - -// non-streaming methods - -message PingRequest { - int32 count = 1; -} - -message PongResponse { - int32 count = 1; -} - -message GetLatestBlockhashRequest { - optional CommitmentLevel commitment = 1; -} - -message GetLatestBlockhashResponse { - uint64 slot = 1; - string blockhash = 2; - uint64 last_valid_block_height = 3; -} - -message GetBlockHeightRequest { - optional CommitmentLevel commitment = 1; -} - -message GetBlockHeightResponse { - uint64 block_height = 1; -} - -message GetSlotRequest { - optional CommitmentLevel commitment = 1; -} - -message GetSlotResponse { - uint64 slot = 1; -} - -message GetVersionRequest {} - -message GetVersionResponse { - string version = 1; -} - -message IsBlockhashValidRequest { - string blockhash = 1; - optional CommitmentLevel commitment = 2; -} - -message IsBlockhashValidResponse { - uint64 slot = 1; - bool valid = 2; -} \ No newline at end of file diff --git a/learning-examples/listen-new-tokens/proto/solana-storage.proto b/learning-examples/listen-new-tokens/proto/solana-storage.proto deleted file mode 100644 index 56e3eb0..0000000 --- a/learning-examples/listen-new-tokens/proto/solana-storage.proto +++ /dev/null @@ -1,149 +0,0 @@ -syntax = "proto3"; - -package solana.storage.ConfirmedBlock; - -option go_package = "github.com/rpcpool/yellowstone-grpc/examples/golang/proto"; - -message ConfirmedBlock { - string previous_blockhash = 1; - string blockhash = 2; - uint64 parent_slot = 3; - repeated ConfirmedTransaction transactions = 4; - repeated Reward rewards = 5; - UnixTimestamp block_time = 6; - BlockHeight block_height = 7; - NumPartitions num_partitions = 8; -} - -message ConfirmedTransaction { - Transaction transaction = 1; - TransactionStatusMeta meta = 2; -} - -message Transaction { - repeated bytes signatures = 1; - Message message = 2; -} - -message Message { - MessageHeader header = 1; - repeated bytes account_keys = 2; - bytes recent_blockhash = 3; - repeated CompiledInstruction instructions = 4; - bool versioned = 5; - repeated MessageAddressTableLookup address_table_lookups = 6; -} - -message MessageHeader { - uint32 num_required_signatures = 1; - uint32 num_readonly_signed_accounts = 2; - uint32 num_readonly_unsigned_accounts = 3; -} - -message MessageAddressTableLookup { - bytes account_key = 1; - bytes writable_indexes = 2; - bytes readonly_indexes = 3; -} - -message TransactionStatusMeta { - TransactionError err = 1; - uint64 fee = 2; - repeated uint64 pre_balances = 3; - repeated uint64 post_balances = 4; - repeated InnerInstructions inner_instructions = 5; - bool inner_instructions_none = 10; - repeated string log_messages = 6; - bool log_messages_none = 11; - repeated TokenBalance pre_token_balances = 7; - repeated TokenBalance post_token_balances = 8; - repeated Reward rewards = 9; - repeated bytes loaded_writable_addresses = 12; - repeated bytes loaded_readonly_addresses = 13; - ReturnData return_data = 14; - bool return_data_none = 15; - - // Sum of compute units consumed by all instructions. - // Available since Solana v1.10.35 / v1.11.6. - // Set to `None` for txs executed on earlier versions. - optional uint64 compute_units_consumed = 16; -} - -message TransactionError { - bytes err = 1; -} - -message InnerInstructions { - uint32 index = 1; - repeated InnerInstruction instructions = 2; -} - -message InnerInstruction { - uint32 program_id_index = 1; - bytes accounts = 2; - bytes data = 3; - - // Invocation stack height of an inner instruction. - // Available since Solana v1.14.6 - // Set to `None` for txs executed on earlier versions. - optional uint32 stack_height = 4; -} - -message CompiledInstruction { - uint32 program_id_index = 1; - bytes accounts = 2; - bytes data = 3; -} - -message TokenBalance { - uint32 account_index = 1; - string mint = 2; - UiTokenAmount ui_token_amount = 3; - string owner = 4; - string program_id = 5; -} - -message UiTokenAmount { - double ui_amount = 1; - uint32 decimals = 2; - string amount = 3; - string ui_amount_string = 4; -} - -message ReturnData { - bytes program_id = 1; - bytes data = 2; -} - -enum RewardType { - Unspecified = 0; - Fee = 1; - Rent = 2; - Staking = 3; - Voting = 4; -} - -message Reward { - string pubkey = 1; - int64 lamports = 2; - uint64 post_balance = 3; - RewardType reward_type = 4; - string commission = 5; -} - -message Rewards { - repeated Reward rewards = 1; - NumPartitions num_partitions = 2; -} - -message UnixTimestamp { - int64 timestamp = 1; -} - -message BlockHeight { - uint64 block_height = 1; -} - -message NumPartitions { - uint64 num_partitions = 1; -} \ No newline at end of file diff --git a/learning-examples/manual_buy.py b/learning-examples/manual_buy.py index 81a5cff..5bbf5fe 100644 --- a/learning-examples/manual_buy.py +++ b/learning-examples/manual_buy.py @@ -1,9 +1,31 @@ +"""Buy the next pump.fun coin to be created, using buy_v2. + +WARNING: this submits a real transaction and spends real funds. + +Usage: + uv run learning-examples/manual_buy.py + uv run learning-examples/manual_buy.py --cu-optimized + +`--cu-optimized` adds a SetLoadedAccountsDataSizeLimit instruction. A transaction +may load up to 64 MB of account data by default, which is billed at 16k CU toward +the fee and priority calculation. Declaring a smaller ceiling lowers that share. +The saving does not show up in a transaction's reported `unitsConsumed`, which +only covers execution, so it is hard to measure directly from a receipt. + +Do not lower the limit too far: 16 MB is still 4x smaller than the default and +leaves room for Token-2022 mints with extensions, while 512 KB is rejected with +MaxLoadedAccountsDataSizeExceeded on exactly those coins. + +Reference: https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit +""" + import asyncio import base64 import hashlib import json import os import struct +import sys import base58 import pump_v2 @@ -14,6 +36,7 @@ from solana.rpc.async_api import AsyncClient from solana.rpc.commitment import Confirmed from solana.rpc.types import TxOpts from solders.compute_budget import set_compute_unit_price +from solders.instruction import Instruction from solders.keypair import Keypair from solders.message import Message from solders.pubkey import Pubkey @@ -26,6 +49,13 @@ from spl.token.instructions import ( EXPECTED_DISCRIMINATOR = pump_v2.BONDING_CURVE_DISCRIMINATOR TOKEN_DECIMALS = 6 +COMPUTE_BUDGET_PROGRAM = Pubkey.from_string( + "ComputeBudget111111111111111111111111111111" +) +# 16 MB. Enough for Token-2022 mints carrying extensions, and still 4x below the +# 64 MB default; 4-8 MB is rejected with MaxLoadedAccountsDataSizeExceeded. +LOADED_ACCOUNTS_DATA_SIZE_LIMIT = 16_384_000 + # Global constants PUMP_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P") PUMP_GLOBAL = Pubkey.from_string("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf") @@ -100,6 +130,22 @@ def calculate_pump_curve_price(curve_state: pump_v2.BondingCurveState) -> float: return price +def set_loaded_accounts_data_size_limit(bytes_limit: int) -> Instruction: + """Build a SetLoadedAccountsDataSizeLimit compute-budget instruction. + + solders does not ship a helper for this one, so encode it by hand: the + compute-budget program takes a 1-byte discriminator (4) and a u32 limit. + + Args: + bytes_limit: Max account data the transaction may load, in bytes + + Returns: + The compute-budget instruction + """ + data = struct.pack(" BondingCurveState: - response = await conn.get_account_info(curve_address, encoding="base64") - if not response.value or not response.value.data: - raise ValueError("Invalid curve state: No data") - - data = response.value.data - if data[:8] != EXPECTED_DISCRIMINATOR: - raise ValueError("Invalid curve state discriminator") - - return pump_v2.BondingCurveState(data) - - -def calculate_pump_curve_price(curve_state: pump_v2.BondingCurveState) -> float: - """Price of one whole token in whole units of the curve's quote asset. - - Args: - curve_state: Parsed curve state - - Returns: - Price in the quote asset - - Raises: - ValueError: If reserves are empty - """ - price = curve_state.price_per_token() - if price <= 0: - raise ValueError("Invalid reserve state") - return price - - -def _find_creator_vault(creator: Pubkey) -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"creator-vault", bytes(creator)], - PUMP_PROGRAM, - ) - return derived_address - - -def _find_global_volume_accumulator() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"global_volume_accumulator"], - PUMP_PROGRAM, - ) - 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 - - -def _find_fee_config() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"fee_config", bytes(PUMP_PROGRAM)], - PUMP_FEE_PROGRAM, - ) - return derived_address - - -def _find_bonding_curve_v2(mint: Pubkey) -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"bonding-curve-v2", bytes(mint)], - PUMP_PROGRAM, - ) - return derived_address - - -async def get_fee_recipient( - client: AsyncClient, curve_state: BondingCurveState -) -> Pubkey: - """Determine the correct fee recipient based on mayhem mode. - - Mayhem mode tokens use a different fee recipient (reserved_fee_recipient from Global account) - instead of the standard fee recipient. This function checks the bonding curve state - and returns the appropriate fee recipient. - - Args: - client: Solana RPC client to fetch Global account data - curve_state: Parsed bonding curve state containing is_mayhem_mode flag - - Returns: - Appropriate fee recipient pubkey (mayhem or standard) - """ - if not curve_state.is_mayhem_mode: - return PUMP_FEE - - # Fetch Global account to get reserved_fee_recipient for mayhem mode tokens - response = await client.get_account_info(PUMP_GLOBAL, encoding="base64") - if not response.value or not response.value.data: - # Fallback to standard fee if Global account cannot be fetched - return PUMP_FEE - - data = response.value.data - - # Parse reserved_fee_recipient from Global account - # Offset calculation based on pump_fun_idl.json Global struct: - # discriminator(8) + initialized(1) + authority(32) + fee_recipient(32) + - # initial_virtual_token_reserves(8) + initial_virtual_sol_reserves(8) + - # initial_real_token_reserves(8) + token_total_supply(8) + fee_basis_points(8) + - # withdraw_authority(32) + enable_migrate(1) + pool_migration_fee(8) + - # creator_fee_basis_points(8) + fee_recipients[7](224) + set_creator_authority(32) + - # admin_set_creator_authority(32) + create_v2_enabled(1) + whitelist_pda(32) = 483 - RESERVED_FEE_RECIPIENT_OFFSET = 483 - - if len(data) < RESERVED_FEE_RECIPIENT_OFFSET + 32: - # Fallback if account data is too short - return PUMP_FEE - - reserved_fee_recipient_bytes = data[ - RESERVED_FEE_RECIPIENT_OFFSET : RESERVED_FEE_RECIPIENT_OFFSET + 32 - ] - return Pubkey.from_bytes(reserved_fee_recipient_bytes) - - -def set_loaded_accounts_data_size_limit(bytes_limit: int) -> Instruction: - """ - Create SetLoadedAccountsDataSizeLimit instruction to reduce CU consumption. - - Solana defaults to 64MB loaded data limit (16k CU cost: 8 CU per 32KB). - By setting a lower limit, you reduce CU consumption and improve tx priority. - - Args: - bytes_limit: Max account data size in bytes (e.g., 512_000 = 512KB) - - Returns: - Compute Budget instruction (discriminator 4) - """ - data = struct.pack("= len(static_keys) - for idx in ix.accounts - ): - continue - account_keys = [ - str( - transaction.message.account_keys[ - index - ] - ) - for index in ix.accounts - ] - decoded_args = ( - decode_create_instruction( - ix_data, create_ix, account_keys - ) - ) - # Add token program info to decoded args - decoded_args["token_program"] = str( - token_program - ) - decoded_args["is_token_2022"] = ( - token_program == TOKEN_2022_PROGRAM - ) - return decoded_args - - -async def main(): - print("Waiting for a new token creation...") - token_data = await listen_for_create_transaction() - print("New token created:") - print(json.dumps(token_data, indent=2)) - - print("\nWaiting 15 seconds for things to stabilize...") - await asyncio.sleep(15) - - mint = Pubkey.from_string(token_data["mint"]) - bonding_curve = Pubkey.from_string(token_data["bondingCurve"]) - associated_bonding_curve = Pubkey.from_string(token_data["associatedBondingCurve"]) - creator_vault = pump_v2.find_creator_vault( - Pubkey.from_string(token_data["creator"]) - ) - token_program = Pubkey.from_string(token_data["token_program"]) - - # Fetch the token price - async with AsyncClient(RPC_ENDPOINT) as client: - curve_state = await get_pump_curve_state(client, bonding_curve) - token_price_sol = calculate_pump_curve_price(curve_state) - - # Amount of SOL to spend (adjust as needed) - amount = 0.000_001 # 0.00001 SOL - slippage = 0.3 # 30% slippage tolerance - - print(f"Bonding curve address: {bonding_curve}") - print( - f"Token Program: {token_program} ({'Token2022' if token_data['is_token_2022'] else 'Standard Token'})" - ) - print(f"Token price: {token_price_sol:.10f} SOL") - print( - f"Buying {amount:.6f} SOL worth of the new token with {slippage * 100:.1f}% slippage tolerance..." - ) - print("CU Optimization: Enabled (16MB account data limit)") - await buy_token( - mint, - bonding_curve, - associated_bonding_curve, - creator_vault, - token_program, - amount, - slippage, - ) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/learning-examples/manual_buy_geyser.py b/learning-examples/manual_buy_geyser.py index a63557f..67fd135 100644 --- a/learning-examples/manual_buy_geyser.py +++ b/learning-examples/manual_buy_geyser.py @@ -40,19 +40,6 @@ PUMP_EVENT_AUTHORITY = Pubkey.from_string( PUMP_FEE = Pubkey.from_string("CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM") 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_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") SYSTEM_TOKEN_2022_PROGRAM = Pubkey.from_string( @@ -112,93 +99,6 @@ def calculate_pump_curve_price(curve_state: pump_v2.BondingCurveState) -> float: return price -def _find_creator_vault(creator: Pubkey) -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"creator-vault", bytes(creator)], - PUMP_PROGRAM, - ) - return derived_address - - -def _find_global_volume_accumulator() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"global_volume_accumulator"], - PUMP_PROGRAM, - ) - 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 - - -def _find_fee_config() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"fee_config", bytes(PUMP_PROGRAM)], - PUMP_FEE_PROGRAM, - ) - return derived_address - - -def _find_bonding_curve_v2(mint: Pubkey) -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"bonding-curve-v2", bytes(mint)], - PUMP_PROGRAM, - ) - return derived_address - - -async def get_fee_recipient( - client: AsyncClient, curve_state: BondingCurveState -) -> Pubkey: - """Determine the correct fee recipient based on mayhem mode. - - Mayhem mode tokens use a different fee recipient (reserved_fee_recipient from Global account) - instead of the standard fee recipient. This function checks the bonding curve state - and returns the appropriate fee recipient. - - Args: - client: Solana RPC client to fetch Global account data - curve_state: Parsed bonding curve state containing is_mayhem_mode flag - - Returns: - Appropriate fee recipient pubkey (mayhem or standard) - """ - if not curve_state.is_mayhem_mode: - return PUMP_FEE - - # Fetch Global account to get reserved_fee_recipient for mayhem mode tokens - response = await client.get_account_info(PUMP_GLOBAL, encoding="base64") - if not response.value or not response.value.data: - # Fallback to standard fee if Global account cannot be fetched - return PUMP_FEE - - data = response.value.data - - # Parse reserved_fee_recipient from Global account - # Offset calculation based on pump_fun_idl.json Global struct: - # discriminator(8) + initialized(1) + authority(32) + fee_recipient(32) + - # initial_virtual_token_reserves(8) + initial_virtual_sol_reserves(8) + - # initial_real_token_reserves(8) + token_total_supply(8) + fee_basis_points(8) + - # withdraw_authority(32) + enable_migrate(1) + pool_migration_fee(8) + - # creator_fee_basis_points(8) + fee_recipients[7](224) + set_creator_authority(32) + - # admin_set_creator_authority(32) + create_v2_enabled(1) + whitelist_pda(32) = 483 - RESERVED_FEE_RECIPIENT_OFFSET = 483 - - if len(data) < RESERVED_FEE_RECIPIENT_OFFSET + 32: - # Fallback if account data is too short - return PUMP_FEE - - reserved_fee_recipient_bytes = data[ - RESERVED_FEE_RECIPIENT_OFFSET : RESERVED_FEE_RECIPIENT_OFFSET + 32 - ] - return Pubkey.from_bytes(reserved_fee_recipient_bytes) - - async def create_geyser_connection(): """Establish a secure connection to the Geyser endpoint using the configured auth type.""" if AUTH_TYPE == "x-token": diff --git a/learning-examples/mint_and_buy.py b/learning-examples/mint_and_buy.py index fe7824a..bcaa7cb 100644 --- a/learning-examples/mint_and_buy.py +++ b/learning-examples/mint_and_buy.py @@ -49,19 +49,6 @@ PUMP_FEE_PROGRAM: Final[Pubkey] = 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: Final[list[Pubkey]] = [ - 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"), -] PUMP_MINT_AUTHORITY: Final[Pubkey] = Pubkey.from_string( "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM" ) @@ -85,7 +72,6 @@ TOKEN_DECIMALS: Final[int] = 6 # Discriminators CREATE_DISCRIMINATOR: Final[bytes] = struct.pack(" Pubkey: return derived_address -def _find_global_volume_accumulator() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"global_volume_accumulator"], - PUMP_PROGRAM, - ) - 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 - - -def _find_fee_config() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"fee_config", bytes(PUMP_PROGRAM)], - PUMP_FEE_PROGRAM, - ) - return derived_address - - -def _find_bonding_curve_v2(mint: Pubkey) -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"bonding-curve-v2", bytes(mint)], - PUMP_PROGRAM, - ) - return derived_address - - def create_pump_create_instruction( mint: Pubkey, mint_authority: Pubkey, diff --git a/learning-examples/mint_and_buy_v2.py b/learning-examples/mint_and_buy_v2.py index 4291c33..c233451 100644 --- a/learning-examples/mint_and_buy_v2.py +++ b/learning-examples/mint_and_buy_v2.py @@ -50,19 +50,6 @@ PUMP_FEE_PROGRAM: Final[Pubkey] = 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: Final[list[Pubkey]] = [ - 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"), -] PUMP_MINT_AUTHORITY: Final[Pubkey] = Pubkey.from_string( "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM" ) @@ -91,7 +78,6 @@ TOKEN_DECIMALS: Final[int] = 6 # Discriminators CREATE_V2_DISCRIMINATOR: Final[bytes] = bytes([214, 144, 76, 236, 95, 139, 49, 180]) -BUY_DISCRIMINATOR: Final[bytes] = struct.pack(" Pubkey: return get_associated_token_address(SOL_VAULT, mint, TOKEN_2022_PROGRAM) -def _find_global_volume_accumulator() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"global_volume_accumulator"], - PUMP_PROGRAM, - ) - 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 - - -def _find_fee_config() -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"fee_config", bytes(PUMP_PROGRAM)], - PUMP_FEE_PROGRAM, - ) - return derived_address - - -def _find_bonding_curve_v2(mint: Pubkey) -> Pubkey: - derived_address, _ = Pubkey.find_program_address( - [b"bonding-curve-v2", bytes(mint)], - PUMP_PROGRAM, - ) - return derived_address - - def create_pump_create_v2_instruction( mint: Pubkey, mint_authority: Pubkey, diff --git a/learning-examples/pumpswap/get_pumpswap_pools.py b/learning-examples/pumpswap/get_pumpswap_pools.py index 101bc64..7a4b706 100644 --- a/learning-examples/pumpswap/get_pumpswap_pools.py +++ b/learning-examples/pumpswap/get_pumpswap_pools.py @@ -53,6 +53,9 @@ async def get_market_data(market_address: Pubkey): parsed_data = {} offset = 8 + # Fields end at 261; live pool accounts are 301 bytes with trailing padding. + # virtual_quote_reserves is an i128, not a u64 — reading only 8 bytes happens + # to work while the high half is zero, and silently breaks when it isn't. fields = [ ("pool_bump", "u8"), ("index", "u16"), @@ -64,6 +67,9 @@ async def get_market_data(market_address: Pubkey): ("pool_quote_token_account", "pubkey"), ("lp_supply", "u64"), ("coin_creator", "pubkey"), + ("is_mayhem_mode", "bool"), + ("is_cashback_coin", "bool"), + ("virtual_quote_reserves", "i128"), ] for field_name, field_type in fields: @@ -79,6 +85,14 @@ async def get_market_data(market_address: Pubkey): ) parsed_data[field_name] = value offset += 8 + elif field_type == "i128": + if len(data) < offset + 16: + parsed_data[field_name] = 0 + continue + parsed_data[field_name] = int.from_bytes( + data[offset : offset + 16], "little", signed=True + ) + offset += 16 elif field_type == "u16": value = struct.unpack(" offset else False + ) + offset += 1 return parsed_data @@ -98,7 +117,19 @@ async def main(): print(market_address) market_data = await get_market_data(market_address) - print(market_data) + for key, value in market_data.items(): + print(f" {key}: {value}") + + # Quote against effective reserves. Upstream's release note says + # virtual_quote_reserves is 0 on all pools; that is out of date — pools carry + # 17.5845 SOL of virtual reserves, so quoting off the raw vault balance + # under-prices by anywhere from a few percent to over 20%. + virtual = market_data.get("virtual_quote_reserves", 0) + if virtual: + print( + f"\nNote: this pool carries {virtual / 1e9:.9f} SOL of virtual quote " + "reserves. Add them to pool_quote_token_account.amount before quoting." + ) if __name__ == "__main__": diff --git a/learning-examples/raw_bondingCurve_from_getAccountInfo.json b/learning-examples/raw_bondingCurve_from_getAccountInfo.json deleted file mode 100644 index e847a87..0000000 --- a/learning-examples/raw_bondingCurve_from_getAccountInfo.json +++ /dev/null @@ -1 +0,0 @@ -{"jsonrpc":"2.0","result":{"context":{"apiVersion":"1.18.22","slot":285247740},"value":{"data":["F7f4N2DYrGD99rN6is0DALwvcwAHAAAA/V6hLvnOAgC8g08EAAAAAACAxqR+jQMAAA==","base64"],"executable":false,"lamports":73551852,"owner":"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P","rentEpoch":18446744073709551615,"space":49}},"id":1} diff --git a/learning-examples/raw_bonding_curve_from_getaccountinfo.json b/learning-examples/raw_bonding_curve_from_getaccountinfo.json new file mode 100644 index 0000000..f641c44 --- /dev/null +++ b/learning-examples/raw_bonding_curve_from_getaccountinfo.json @@ -0,0 +1,21 @@ +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 435946373, + "apiVersion": "4.3.0-alpha.2" + }, + "value": { + "lamports": 790949926, + "data": [ + "F7f4N2DYrGCHbmgi4bYDANb6KisHAAAAh9ZV1k+4AgDWTgcvAAAAAACAxqR+jQMAAEXn9ErjbXNmON16LY9gtDVntkXAv94W3SK1C3OqM6zeAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "base64" + ], + "owner": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "executable": false, + "rentEpoch": 18446744073709551615, + "space": 151 + } + }, + "id": 1 +} \ No newline at end of file diff --git a/learning-examples/raw_buy_tx_from_getTransaction.json b/learning-examples/raw_buy_tx_from_getTransaction.json deleted file mode 100644 index 134efeb..0000000 --- a/learning-examples/raw_buy_tx_from_getTransaction.json +++ /dev/null @@ -1,388 +0,0 @@ -{ - "jsonrpc": "2.0", - "result": { - "blockTime": 1724126293, - "meta": { - "computeUnitsConsumed": 68322, - "err": null, - "fee": 32000, - "innerInstructions": [ - { - "index": 2, - "instructions": [ - { - "parsed": { - "info": { - "amount": "605426095720", - "authority": "6fogeBTRjgm9Kb9dVtqpjDf6bGvjGgdScmTu5nCVPJPn", - "destination": "DxMF77MqYYYr4NshXWrUdiGzfzwpNhKG7H73B94ETX8S", - "source": "9nj8QEp6mQDsr2G6oGtq8DJakPuKLeUqnWMf4JzgcSCd" - }, - "type": "transfer" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "destination": "6fogeBTRjgm9Kb9dVtqpjDf6bGvjGgdScmTu5nCVPJPn", - "lamports": 24080282, - "source": "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "destination": "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM", - "lamports": 240802, - "source": "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 2 - }, - { - "accounts": [ - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" - ], - "data": "2K7nL28PxCW8ejnyCeuMpbYBaHNNxSWmhNFbMDYBXdWw7nSYrc7woNd4ENfAZMMQjP9TLFxfRvA69i3wPHorNMpqcfCFFFFeAmfcVqdtaPqq3JE1erMrE8gHpGJ8NXA1633JV4iabs9saqZ8Pa7xQrjkoYX8pgbAjh3CnePG1Lq18E9fsPv89nKqmgvb", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": 2 - } - ] - }, - { - "index": 3, - "instructions": [ - { - "parsed": { - "info": { - "amount": "605426095720", - "authority": "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef", - "destination": "9nj8QEp6mQDsr2G6oGtq8DJakPuKLeUqnWMf4JzgcSCd", - "source": "DxMF77MqYYYr4NshXWrUdiGzfzwpNhKG7H73B94ETX8S" - }, - "type": "transfer" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "accounts": [ - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" - ], - "data": "2K7nL28PxCW8ejnyCeuMpbYBaHNNxSWmhNFbMDYBXdWw7nSYrc7woNd4ENfAZMMQjP9RGosGgCYezUhV4mEBVCtoTrbAXXkFVvp72dtBLa7fuvzRsmCgMkydN6Ez8H17gRiXkmmNHUCXcUmfhMG2cGeaukQWu1YD7mkmTzg7QGUF69ArSTS3RHHM6zXh", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": 2 - } - ] - } - ], - "logMessages": [ - "Program ComputeBudget111111111111111111111111111111 invoke [1]", - "Program ComputeBudget111111111111111111111111111111 success", - "Program ComputeBudget111111111111111111111111111111 invoke [1]", - "Program ComputeBudget111111111111111111111111111111 success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", - "Program log: Instruction: Buy", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: Transfer", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 129562 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2003 of 117474 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program data: vdt/007mYe73itfzw580Z6SEg9q3HfHO2n0qXIpNVTcl7oo9jo+CP5pvbwEAAAAAaBY19owAAAABHKbz9pJ3+YMsz+xMr0BHBMU3VB0RDjRv3ae0eInXRhRVFMRmAAAAAFjTeFUIAAAAbRsnNO0xAwBYJ1VZAQAAAG2DFOhbMwIA", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 35954 of 149700 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", - "Program log: Instruction: Sell", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: Transfer", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 93687 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2003 of 85557 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program data: vdt/007mYe73itfzw580Z6SEg9q3HfHO2n0qXIpNVTcl7oo9jo+CP5lvbwEAAAAAaBY19owAAAAAHKbz9pJ3+YMsz+xMr0BHBMU3VB0RDjRv3ae0eInXRhRVFMRmAAAAAL9jCVQIAAAA1TFcKnoyAwC/t+VXAQAAANWZSd7oMwIA", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 31918 of 113746 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program 11111111111111111111111111111111 invoke [1]", - "Program 11111111111111111111111111111111 success" - ], - "postBalances": [ - 706655008, - 5770871791, - 2039280, - 279629252504426, - 2039280, - 97135324113, - 1, - 1141440, - 1, - 1009200, - 934087680, - 2500000, - 731913600, - 0, - 1461600 - ], - "postTokenBalances": [ - { - "accountIndex": 2, - "mint": "HfJVjBdkhAD2ynVM8PdTSii4ECZdsxNTCx5wpEqUpump", - "owner": "6fogeBTRjgm9Kb9dVtqpjDf6bGvjGgdScmTu5nCVPJPn", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "uiTokenAmount": { - "amount": "826925208216021", - "decimals": 6, - "uiAmount": 826925208.216021, - "uiAmountString": "826925208.216021" - } - }, - { - "accountIndex": 4, - "mint": "HfJVjBdkhAD2ynVM8PdTSii4ECZdsxNTCx5wpEqUpump", - "owner": "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "uiTokenAmount": { - "amount": "0", - "decimals": 6, - "uiAmount": null, - "uiAmountString": "0" - } - } - ], - "preBalances": [ - 708131176, - 5770871790, - 2039280, - 279629252022822, - 2039280, - 97134361550, - 1, - 1141440, - 1, - 1009200, - 934087680, - 2500000, - 731913600, - 0, - 1461600 - ], - "preTokenBalances": [ - { - "accountIndex": 2, - "mint": "HfJVjBdkhAD2ynVM8PdTSii4ECZdsxNTCx5wpEqUpump", - "owner": "6fogeBTRjgm9Kb9dVtqpjDf6bGvjGgdScmTu5nCVPJPn", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "uiTokenAmount": { - "amount": "826925208216021", - "decimals": 6, - "uiAmount": 826925208.216021, - "uiAmountString": "826925208.216021" - } - }, - { - "accountIndex": 4, - "mint": "HfJVjBdkhAD2ynVM8PdTSii4ECZdsxNTCx5wpEqUpump", - "owner": "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "uiTokenAmount": { - "amount": "0", - "decimals": 6, - "uiAmount": null, - "uiAmountString": "0" - } - } - ], - "rewards": [], - "status": { - "Ok": null - } - }, - "slot": 284677332, - "transaction": { - "message": { - "accountKeys": [ - { - "pubkey": "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef", - "signer": true, - "source": "transaction", - "writable": true - }, - { - "pubkey": "6fogeBTRjgm9Kb9dVtqpjDf6bGvjGgdScmTu5nCVPJPn", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "9nj8QEp6mQDsr2G6oGtq8DJakPuKLeUqnWMf4JzgcSCd", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "DxMF77MqYYYr4NshXWrUdiGzfzwpNhKG7H73B94ETX8S", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "JBfdxsh3DEXfpeTUrQe94hpKQ8yxBqVRqRiSRvemUA4i", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "11111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "ComputeBudget111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "SysvarRent111111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "HfJVjBdkhAD2ynVM8PdTSii4ECZdsxNTCx5wpEqUpump", - "signer": false, - "source": "transaction", - "writable": false - } - ], - "addressTableLookups": [], - "instructions": [ - { - "accounts": [], - "data": "3JwEwun4YUPH", - "programId": "ComputeBudget111111111111111111111111111111", - "stackHeight": null - }, - { - "accounts": [], - "data": "LEJDE7", - "programId": "ComputeBudget111111111111111111111111111111", - "stackHeight": null - }, - { - "accounts": [ - "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", - "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM", - "HfJVjBdkhAD2ynVM8PdTSii4ECZdsxNTCx5wpEqUpump", - "6fogeBTRjgm9Kb9dVtqpjDf6bGvjGgdScmTu5nCVPJPn", - "9nj8QEp6mQDsr2G6oGtq8DJakPuKLeUqnWMf4JzgcSCd", - "DxMF77MqYYYr4NshXWrUdiGzfzwpNhKG7H73B94ETX8S", - "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef", - "11111111111111111111111111111111", - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "SysvarRent111111111111111111111111111111111", - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", - "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" - ], - "data": "AJTQ2h9DXrBqzdpEhcLVYocNoqujioBxb", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": null - }, - { - "accounts": [ - "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", - "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM", - "HfJVjBdkhAD2ynVM8PdTSii4ECZdsxNTCx5wpEqUpump", - "6fogeBTRjgm9Kb9dVtqpjDf6bGvjGgdScmTu5nCVPJPn", - "9nj8QEp6mQDsr2G6oGtq8DJakPuKLeUqnWMf4JzgcSCd", - "DxMF77MqYYYr4NshXWrUdiGzfzwpNhKG7H73B94ETX8S", - "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef", - "11111111111111111111111111111111", - "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", - "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" - ], - "data": "5jRcjdixRUDSvSh4QXANSHU9rk2He2WMm", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": null - }, - { - "parsed": { - "info": { - "destination": "JBfdxsh3DEXfpeTUrQe94hpKQ8yxBqVRqRiSRvemUA4i", - "lamports": 962563, - "source": "2vr538qDgHCPYmr2mjt5LSjQ3kBYjtw3SDSveUKBVkef" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": null - } - ], - "recentBlockhash": "cqZ8vtKbuAVtwCRHrATJn7X3kohsJH2Qn9zdhEr8sE5" - }, - "signatures": [ - "33LHUzKfhBvU68kYib22oFx2XdQKQZ2sfvTmmdCFEr6YidyP8S3WwAurjz6Suewvr2WUByV79K3stNCZDe7wq3De" - ] - }, - "version": 0 - }, - "id": 1 -} diff --git a/learning-examples/raw_buy_tx_from_gettransaction.json b/learning-examples/raw_buy_tx_from_gettransaction.json new file mode 100644 index 0000000..1c7db6d --- /dev/null +++ b/learning-examples/raw_buy_tx_from_gettransaction.json @@ -0,0 +1,698 @@ +{ + "jsonrpc": "2.0", + "result": { + "slot": 435948490, + "transaction": { + "signatures": [ + "2m5nWLnDSbM5SEGCnRxuftg5PFFZR6kziuNQbmrmqtEhbH81PyKVeEsipiXaFQxnerN8zQYB2XRwozrjoZheFDuG" + ], + "message": { + "accountKeys": [ + { + "pubkey": "Gygj9QQby4j2jryqyqBHvLP7ctv2SaANgh4sCb69BUpA", + "writable": true, + "signer": true, + "source": "transaction" + }, + { + "pubkey": "6w1RMBHu8G269Z1SSp6p7SZyVj3ugGupWhKkeSbs7Vm6", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "9LdJrtQkdqioAWiiyTpd1Vx4utffxHxvssEYhPhuucMv", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "2Y3wfpoDxGWYsuqDhSZKWeVh5Mgg42edV9bd5CFYA679", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "AShUETU4ABeHiBAwLfG56X3mv9CGUZRQ5ZK5RPzte4Th", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "2HA4cjd1kL3d4BbWRAd9tp2XMw29skQeL3HZ1XU2BBB3", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "Ezz2ojEpLcYs3A7uMFW6pgnxtwbhHkJHRAU27zTfiYJU", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "8i6hiPsdTZ7RqMTKb6mnS4qPvHdA2eA9dxkv3wpnESNV", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "FGFrX2q1iAjyAojjeyFDxXqdmvegjPpSWsrPmrJjeQ2f", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "2hcbDhq9CacWu2FZa7n1YbftAgo8FfKRDkVahRo7TwST", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "ComputeBudget111111111111111111111111111111", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "ELya7rmiRHfKyDkE9j5yQZtjD9fABkifmsFw3XSPDfEh", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "13ec7XdrjF3h3YcqBTFDSReRcUFwbCnJaAQspM4j6DDJ", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "GesfTA3X2arioaHp8bbKdjG9vJtskViWACZoYvxp4twS", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "41xY1DU1zzo893bEg2HzTFxPVVM84UvDCNsQm6aKRq8Z", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "6oCkp6gpyjxVTeL6ahMYcekN2x2pzt1KY8g2LqemaTNE", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "11111111111111111111111111111111", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "8FoNgzmjuSmiy86EPCWxvv1q7oJSu2WGA7wPymwki2LJ", + "writable": false, + "signer": false, + "source": "lookupTable" + } + ], + "recentBlockhash": "2aMGsi77kV4cQXNLcKmkSn9ZzfK2Q6WC4yPTyPk5PLG6", + "instructions": [ + { + "programId": "ComputeBudget111111111111111111111111111111", + "accounts": [], + "data": "HMypLP", + "stackHeight": 1 + }, + { + "programId": "ComputeBudget111111111111111111111111111111", + "accounts": [], + "data": "3KSRLvB8X9SP", + "stackHeight": 1 + }, + { + "programId": "MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e", + "accounts": [ + "Gygj9QQby4j2jryqyqBHvLP7ctv2SaANgh4sCb69BUpA", + "13ec7XdrjF3h3YcqBTFDSReRcUFwbCnJaAQspM4j6DDJ", + "6w1RMBHu8G269Z1SSp6p7SZyVj3ugGupWhKkeSbs7Vm6", + "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "9LdJrtQkdqioAWiiyTpd1Vx4utffxHxvssEYhPhuucMv", + "2Y3wfpoDxGWYsuqDhSZKWeVh5Mgg42edV9bd5CFYA679", + "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "11111111111111111111111111111111", + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", + "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "AShUETU4ABeHiBAwLfG56X3mv9CGUZRQ5ZK5RPzte4Th", + "GesfTA3X2arioaHp8bbKdjG9vJtskViWACZoYvxp4twS", + "41xY1DU1zzo893bEg2HzTFxPVVM84UvDCNsQm6aKRq8Z", + "2HA4cjd1kL3d4BbWRAd9tp2XMw29skQeL3HZ1XU2BBB3", + "Ezz2ojEpLcYs3A7uMFW6pgnxtwbhHkJHRAU27zTfiYJU", + "8i6hiPsdTZ7RqMTKb6mnS4qPvHdA2eA9dxkv3wpnESNV", + "ELya7rmiRHfKyDkE9j5yQZtjD9fABkifmsFw3XSPDfEh", + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", + "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y", + "FGFrX2q1iAjyAojjeyFDxXqdmvegjPpSWsrPmrJjeQ2f", + "2hcbDhq9CacWu2FZa7n1YbftAgo8FfKRDkVahRo7TwST", + "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt", + "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ", + "8FoNgzmjuSmiy86EPCWxvv1q7oJSu2WGA7wPymwki2LJ", + "MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e", + "5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD", + "6oCkp6gpyjxVTeL6ahMYcekN2x2pzt1KY8g2LqemaTNE" + ], + "data": "2tpZiHBNBWa1UWDSRdfDd9rxSjLbuHp5xpxmwmZ", + "stackHeight": 1 + } + ], + "addressTableLookups": [ + { + "accountKey": "Hyif6eWb8x88RVrvjPfabsgRYnwkVnyByEXTVTXbUcyP", + "writableIndexes": [ + 18, + 19, + 37, + 95, + 29, + 71 + ], + "readonlyIndexes": [ + 125, + 13, + 10, + 11, + 12, + 1, + 3, + 0, + 4, + 14, + 15, + 20 + ] + } + ] + } + }, + "meta": { + "err": null, + "status": { + "Ok": null + }, + "fee": 24778, + "preBalances": [ + 812758564779, + 1628640, + 2074080, + 2039280, + 1691280, + 2039280, + 2074080, + 5633394, + 2039280, + 1854400, + 2039280, + 1, + 11149834, + 3681840, + 0, + 3104160, + 46718205325026, + 89916349345, + 2039280, + 951841917, + 2039280, + 517251819632, + 3388605256, + 1, + 70128637, + 58238313, + 4089612038, + 168261371, + 8502112342, + 17016138, + 37290293, + 6046720, + 0 + ], + "postBalances": [ + 812758540001, + 1628640, + 2074080, + 2039280, + 1691280, + 2039280, + 2074080, + 5633394, + 2039280, + 1854400, + 2039280, + 1, + 11149834, + 3681840, + 0, + 3104160, + 46718205325026, + 89916349345, + 2039280, + 951841917, + 2039280, + 517251819632, + 3388605256, + 1, + 70128637, + 58238313, + 4089612038, + 168261371, + 8502112342, + 17016138, + 37290293, + 6046720, + 0 + ], + "innerInstructions": [ + { + "index": 2, + "instructions": [ + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", + "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "GesfTA3X2arioaHp8bbKdjG9vJtskViWACZoYvxp4twS", + "41xY1DU1zzo893bEg2HzTFxPVVM84UvDCNsQm6aKRq8Z", + "5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD", + "6oCkp6gpyjxVTeL6ahMYcekN2x2pzt1KY8g2LqemaTNE", + "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "2HA4cjd1kL3d4BbWRAd9tp2XMw29skQeL3HZ1XU2BBB3", + "AShUETU4ABeHiBAwLfG56X3mv9CGUZRQ5ZK5RPzte4Th", + "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "9LdJrtQkdqioAWiiyTpd1Vx4utffxHxvssEYhPhuucMv", + "2Y3wfpoDxGWYsuqDhSZKWeVh5Mgg42edV9bd5CFYA679", + "Ezz2ojEpLcYs3A7uMFW6pgnxtwbhHkJHRAU27zTfiYJU", + "8i6hiPsdTZ7RqMTKb6mnS4qPvHdA2eA9dxkv3wpnESNV", + "ELya7rmiRHfKyDkE9j5yQZtjD9fABkifmsFw3XSPDfEh", + "Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y", + "FGFrX2q1iAjyAojjeyFDxXqdmvegjPpSWsrPmrJjeQ2f", + "2hcbDhq9CacWu2FZa7n1YbftAgo8FfKRDkVahRo7TwST", + "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt", + "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ", + "11111111111111111111111111111111", + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", + "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" + ], + "data": "HnQ14hy6fxGQxczSWyBXHka96z13LiDXm", + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "authority": "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "destination": "9LdJrtQkdqioAWiiyTpd1Vx4utffxHxvssEYhPhuucMv", + "mint": "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "source": "2HA4cjd1kL3d4BbWRAd9tp2XMw29skQeL3HZ1XU2BBB3", + "tokenAmount": { + "amount": "445377137871", + "decimals": 6, + "uiAmount": 445377.137871, + "uiAmountString": "445377.137871" + } + }, + "type": "transferChecked" + }, + "stackHeight": 3 + }, + { + "program": "spl-token", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "parsed": { + "info": { + "authority": "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "destination": "AShUETU4ABeHiBAwLfG56X3mv9CGUZRQ5ZK5RPzte4Th", + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "source": "2Y3wfpoDxGWYsuqDhSZKWeVh5Mgg42edV9bd5CFYA679", + "tokenAmount": { + "amount": "3517192", + "decimals": 6, + "uiAmount": 3.517192, + "uiAmountString": "3.517192" + } + }, + "type": "transferChecked" + }, + "stackHeight": 3 + }, + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" + ], + "data": "T2jLjveMmM4gJ1fdXs3mfxMtZLtJew2gANfsjyRwyyjrfKAURDb9USbZcayqSDHN6b9A2nwWgy4hLExiNxyJNqAwddH69Zhd98G2dMD2c1S9dN4wLwUbXgUSJ8PyhmADh7AD52U1wrr2YpFTDS8pvP9Hbq11RmbC3C3JYPMg9WEvYZMU7npACaGnkETZjSQKUZTbMCcQriEUgcXtzj1ZhnB8bqUfVfYrSWftc3v1YQj8mjRR9rJkVzio6o8GtEuDg2sFoc9iMSyjNvU5BvZZGwQzUPzRx53xpVZ1h55gFVViQoTwrMyNfGQGA8XBoJcuRjWE8Fk8WjoUqmVDamCqNoyNwTm276eCPwwz3iGeJFGeBiDSa722Fsm25w1Y8hRw9Rb4A82jQz9dsuuPFGuM2bdKCazk4W4yVsmgEyVBAi26kMha4bDGvXLHF618cxx7GZjpjKKQ4sAApDXY4dHYAqh4WGxTKtx4Ab6cuxJBCJh5ehb58WkP", + "stackHeight": 3 + }, + { + "programId": "MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e", + "accounts": [ + "8FoNgzmjuSmiy86EPCWxvv1q7oJSu2WGA7wPymwki2LJ" + ], + "data": "HaAvdxyruSvtMDoMtGvePmYV4dda7tWKCLFHadQoSjYsbWWixs1eN1wCF27wUxZao1NgZS9bvKCk9fBzvFqDnPg6QsN9zSkzT9e6xqQywHnLc2LokFDuFWdGqvRU9zoNbt4nY2UuSY4y5ESyEMbB1Jz1U4ibP6pvCw13tDLfnUHMG7yySVJmA2B4Z1AFKZ2WzWtiyisinm6nqWjFuvwGeG8y472DtjpjZDwreJAWNUZHj9M7FkiRmz6Tj4NFidjj7Evwp6f7bKVP75Grxv9stZCiDdPQVWVUuVUkdbTpohhvCsPW749iHWAXJVn6RhV7fgbQzNQXhUb46wJpDhXCmA3a3NuxKDe1BfxTuoFBXF9sio4iVCuvBseBSRqBAjXrHGtK8H1njuk744C4ttf7acF6hejX3fftkDM2Yvyxt", + "stackHeight": 2 + } + ] + } + ], + "logMessages": [ + "Program ComputeBudget111111111111111111111111111111 invoke [1]", + "Program ComputeBudget111111111111111111111111111111 success", + "Program ComputeBudget111111111111111111111111111111 invoke [1]", + "Program ComputeBudget111111111111111111111111111111 success", + "Program MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e invoke [1]", + "Program log: Instruction: BuyV2", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", + "Program log: Instruction: BuyV2", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]", + "Program log: Instruction: TransferChecked", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2562 of 258113 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 105 of 251489 compute units", + "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", + "Program data: vdt/007mYe4wLVmHbP9snyR8drbtFvCd5ld8m8scMo/VKWk60csGDwAAAAAAAAAAz8yLsmcAAAABootf0mq0eaapzGy/awsj62GIWjceASCsqRO+7z0TinjI82lqAAAAAAAAAAAAAAAA8WYcCgzLAwAAAAAAAAAAAPHOCb56zAIA6JMUH7GOnxV02BDheOGeMGBOMXWqLkoy38hgByfRBwkAAAAAAAAAAAAAAAAAAAAAxWk+W+Igi1It2c+yqT2JHBb11+RM14nMlwbpL7MbLsUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAGJ1eQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADG+nrzvtutOj1l82qryXQxsbvkwtL24OR8pgIDRS9dYQirNQAAAAAAOKkISAIAAADsun8BAAAAAA==", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [3]", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2125 of 244477 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 94040 of 333666 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program data: MUh7LW5AsIUAootf0mq0eaapzGy/awsj62GIWjceASCsqRO+7z0TingwLVmHbP9snyR8drbtFvCd5ld8m8scMo/VKWk60csGDwAAAAAAAAAAz8yLsmcAAAAAAAAAAAAAACJFaDvWjwMAAAAAAAAAAAAAAAAAAAAAAN46Xmmo/f////////////8AAAAAAAAAAPFmHAoMywMAAAAAAAAAAAAAAAAAAAAAAMjzaWoAAAAAREVragAAAAAAAAAAAAAAAPHOCb56zAIACgAAALYgCKs1AAAAAAALgVl7MgAAAFye1wAAAAAAAAAAAAAAAAA4qQhIAgAAAPXGOq4cAAAAAAAAAAAAAADsun8BAAAAAMb6evO+2606PWXzaqvJdDGxu+TC0vbg5HymAgNFL11h", + "Program MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e invoke [2]", + "Program MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e consumed 518 of 231520 compute units", + "Program MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e success", + "Program MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e consumed 171799 of 399700 compute units", + "Program MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e success" + ], + "preTokenBalances": [ + { + "accountIndex": 2, + "mint": "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "uiTokenAmount": { + "uiAmount": 1002129835.456595, + "decimals": 6, + "amount": "1002129835456595", + "uiAmountString": "1002129835.456595" + }, + "owner": "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 3, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 216821.345299, + "decimals": 6, + "amount": "216821345299", + "uiAmountString": "216821.345299" + }, + "owner": "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 5, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 21.630948, + "decimals": 6, + "amount": "21630948", + "uiAmountString": "21.630948" + }, + "owner": "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 6, + "mint": "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "uiTokenAmount": { + "uiAmount": 995122876.94944, + "decimals": 6, + "amount": "995122876949440", + "uiAmountString": "995122876.94944" + }, + "owner": "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 8, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "Ezz2ojEpLcYs3A7uMFW6pgnxtwbhHkJHRAU27zTfiYJU", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 10, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "FGFrX2q1iAjyAojjeyFDxXqdmvegjPpSWsrPmrJjeQ2f", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 18, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 252.158865, + "decimals": 6, + "amount": "252158865", + "uiAmountString": "252.158865" + }, + "owner": "GesfTA3X2arioaHp8bbKdjG9vJtskViWACZoYvxp4twS", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 20, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 0.000806, + "decimals": 6, + "amount": "806", + "uiAmountString": "0.000806" + }, + "owner": "5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "postTokenBalances": [ + { + "accountIndex": 2, + "mint": "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "uiTokenAmount": { + "uiAmount": 1002575212.594466, + "decimals": 6, + "amount": "1002575212594466", + "uiAmountString": "1002575212.594466" + }, + "owner": "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 3, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 216817.828107, + "decimals": 6, + "amount": "216817828107", + "uiAmountString": "216817.828107" + }, + "owner": "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 5, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 25.14814, + "decimals": 6, + "amount": "25148140", + "uiAmountString": "25.14814" + }, + "owner": "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 6, + "mint": "4F4gGVBAWuKi3EpmYdhntXvCVFqZZqmrb1cqNGawpump", + "uiTokenAmount": { + "uiAmount": 994677499.811569, + "decimals": 6, + "amount": "994677499811569", + "uiAmountString": "994677499.811569" + }, + "owner": "HR8M4iQmzagQ7vUDREycE2XSHuELmiQSFSrCa4eKytn5", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 8, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "Ezz2ojEpLcYs3A7uMFW6pgnxtwbhHkJHRAU27zTfiYJU", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 10, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "FGFrX2q1iAjyAojjeyFDxXqdmvegjPpSWsrPmrJjeQ2f", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 18, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 252.158865, + "decimals": 6, + "amount": "252158865", + "uiAmountString": "252.158865" + }, + "owner": "GesfTA3X2arioaHp8bbKdjG9vJtskViWACZoYvxp4twS", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 20, + "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + "uiTokenAmount": { + "uiAmount": 0.000806, + "decimals": 6, + "amount": "806", + "uiAmountString": "0.000806" + }, + "owner": "5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "rewards": [], + "computeUnitsConsumed": 172099, + "costUnits": 181305 + }, + "version": 0, + "blockTime": 1785328584 + } +} \ No newline at end of file diff --git a/learning-examples/raw_create_tx_from_getTransaction.json b/learning-examples/raw_create_tx_from_getTransaction.json deleted file mode 100644 index 2d141a0..0000000 --- a/learning-examples/raw_create_tx_from_getTransaction.json +++ /dev/null @@ -1,706 +0,0 @@ -{ - "jsonrpc": "2.0", - "result": { - "blockTime": 1724128600, - "meta": { - "computeUnitsConsumed": 179064, - "err": null, - "fee": 88750, - "innerInstructions": [ - { - "index": 3, - "instructions": [ - { - "parsed": { - "info": { - "lamports": 1461600, - "newAccount": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "space": 82 - }, - "type": "createAccount" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "decimals": 6, - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "mintAuthority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM" - }, - "type": "initializeMint2" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "lamports": 1231920, - "newAccount": "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH", - "owner": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "space": 49 - }, - "type": "createAccount" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "account": "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF", - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "systemProgram": "11111111111111111111111111111111", - "tokenProgram": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "wallet": "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH" - }, - "type": "create" - }, - "program": "spl-associated-token-account", - "programId": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "extensionTypes": [ - "immutableOwner" - ], - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp" - }, - "type": "getAccountDataSize" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 3 - }, - { - "parsed": { - "info": { - "lamports": 2039280, - "newAccount": "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF", - "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "space": 165 - }, - "type": "createAccount" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 3 - }, - { - "parsed": { - "info": { - "account": "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF" - }, - "type": "initializeImmutableOwner" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 3 - }, - { - "parsed": { - "info": { - "account": "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF", - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "owner": "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH" - }, - "type": "initializeAccount3" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 3 - }, - { - "accounts": [ - "H6LkmMUuAiJhAcH9ejScvMVXFhUSzxwYPiczL7zW3aAj", - "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", - "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", - "11111111111111111111111111111111" - ], - "data": "e5DmuZMrE66La6keggPtmZttXAHyPqrUdsWHGdAwjTu9Zi4QvU6WzPSyxrXtdgYkxfoP9G7ETiVjf1oBwq2u8NmkRUqrtiw4R1Hx6mNAPVHXxtGrCDcVg4AwcJ3hqcdndudCkB4b9GkJjFu", - "programId": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "destination": "H6LkmMUuAiJhAcH9ejScvMVXFhUSzxwYPiczL7zW3aAj", - "lamports": 15616720, - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 3 - }, - { - "parsed": { - "info": { - "account": "H6LkmMUuAiJhAcH9ejScvMVXFhUSzxwYPiczL7zW3aAj", - "space": 679 - }, - "type": "allocate" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 3 - }, - { - "parsed": { - "info": { - "account": "H6LkmMUuAiJhAcH9ejScvMVXFhUSzxwYPiczL7zW3aAj", - "owner": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" - }, - "type": "assign" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 3 - }, - { - "parsed": { - "info": { - "account": "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF", - "amount": "1000000000000000", - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "mintAuthority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM" - }, - "type": "mintTo" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "authority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", - "authorityType": "mintTokens", - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "newAuthority": null - }, - "type": "setAuthority" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "accounts": [ - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" - ], - "data": "5xcpNtotVBphT5Ckdf46pY6eeCiYbvrziarwLuSnoKaMkWNb2cZaD9feuADHprV4j7wcAP8E6tEGJk43TyUVXuCUjnP5YXBquQK7TCHwvqjiY1TM8sdvHQW9ciLj25dQuQC7JZ3Pgr832WvmExjr8F9mypGDRTavTfrBcfeUQzg4bTeYcGeTDCyEWFPgmGeT37grRSKj6PK5jP6JiW2q4gCEbgGxiLCfML9Qy2iovLEJ6uXwxLrTyiZ4x3G7eFLHkzjKN6CLRquMqD123t22UxZBhugGRT", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": 2 - } - ] - }, - { - "index": 4, - "instructions": [ - { - "parsed": { - "info": { - "extensionTypes": [ - "immutableOwner" - ], - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp" - }, - "type": "getAccountDataSize" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "lamports": 2039280, - "newAccount": "BfUATFeQBKLdaTGdCT9bKkxXrYTYaRkcjtQ4iFwMGVq1", - "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "space": 165 - }, - "type": "createAccount" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "account": "BfUATFeQBKLdaTGdCT9bKkxXrYTYaRkcjtQ4iFwMGVq1" - }, - "type": "initializeImmutableOwner" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "account": "BfUATFeQBKLdaTGdCT9bKkxXrYTYaRkcjtQ4iFwMGVq1", - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "owner": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5" - }, - "type": "initializeAccount3" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - } - ] - }, - { - "index": 5, - "instructions": [ - { - "parsed": { - "info": { - "amount": "37951768488745", - "authority": "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH", - "destination": "BfUATFeQBKLdaTGdCT9bKkxXrYTYaRkcjtQ4iFwMGVq1", - "source": "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF" - }, - "type": "transfer" - }, - "program": "spl-token", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "destination": "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH", - "lamports": 1100000000, - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 2 - }, - { - "parsed": { - "info": { - "destination": "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM", - "lamports": 11000000, - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": 2 - }, - { - "accounts": [ - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" - ], - "data": "2K7nL28PxCW8ejnyCeuMpbXg4p3TxoCZETw2SodjK89Y1dHFkcjQaBAgMqnf4KDfhbC4774odcRcjDbB7G7xsGx95mVCrqiNQcX59kbAV5fx2XHu3WoCTiu9yyVbtyyuHqHPZuL18cevQMPTtggdQtDyzfxLKCEt4FnTfX2oRD7csmk3vFncJgCDcBQB", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": 2 - } - ] - } - ], - "logMessages": [ - "Program ComputeBudget111111111111111111111111111111 invoke [1]", - "Program ComputeBudget111111111111111111111111111111 success", - "Program 11111111111111111111111111111111 invoke [1]", - "Program 11111111111111111111111111111111 success", - "Program ComputeBudget111111111111111111111111111111 invoke [1]", - "Program ComputeBudget111111111111111111111111111111 success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", - "Program log: Instruction: Create", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: InitializeMint2", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2780 of 237974 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [2]", - "Program log: Create", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]", - "Program log: Instruction: GetAccountDataSize", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1595 of 214078 compute units", - "Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 11111111111111111111111111111111 invoke [3]", - "Program 11111111111111111111111111111111 success", - "Program log: Initialize the associated token account", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]", - "Program log: Instruction: InitializeImmutableOwner", - "Program log: Please upgrade to SPL Token 2022 for immutable owner support", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 207465 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]", - "Program log: Instruction: InitializeAccount3", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4214 of 203581 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 21990 of 221053 compute units", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success", - "Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s invoke [2]", - "Program log: IX: Create Metadata Accounts v3", - "Program 11111111111111111111111111111111 invoke [3]", - "Program 11111111111111111111111111111111 success", - "Program log: Allocate space for the account", - "Program 11111111111111111111111111111111 invoke [3]", - "Program 11111111111111111111111111111111 success", - "Program log: Assign the account to the owning program", - "Program 11111111111111111111111111111111 invoke [3]", - "Program 11111111111111111111111111111111 success", - "Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s consumed 36258 of 183748 compute units", - "Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s success", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: MintTo", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4492 of 144975 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: SetAuthority", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2911 of 138336 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2003 of 131120 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program data: G3KpTd7rY3YHAAAAZXhjaXRlZAcAAABleGNpdGVkRwAAAGh0dHBzOi8vY2YtaXBmcy5jb20vaXBmcy9RbWNEaVA5d0FaOFFlaWpyTnJ0d0xlTUdrNDZ2S0FBZTh5dmZXdHVtQlpiVVJxx09pPxZatyeZoNyW2ve9tDfrT5dl7bJ0JjqTw0Orr0/T20gu0JUEOdSfmHbuZqF6sdH2JuMaAwa4lWuHXNGtQN0QsFdumei71UE0T9w/IatQ85pk4JEI1dEkqI1gmS5+", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 122356 of 249550 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]", - "Program log: Create", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: GetAccountDataSize", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1569 of 121831 compute units", - "Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program log: Initialize the associated token account", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: InitializeImmutableOwner", - "Program log: Please upgrade to SPL Token 2022 for immutable owner support", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 115244 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: InitializeAccount3", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4188 of 111364 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 20301 of 127194 compute units", - "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", - "Program log: Instruction: Buy", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]", - "Program log: Instruction: Transfer", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 86752 compute units", - "Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program 11111111111111111111111111111111 invoke [2]", - "Program 11111111111111111111111111111111 success", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2003 of 74664 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", - "Program data: vdt/007mYe7HT2k/Flq3J5mg3Jba9720N+tPl2XtsnQmOpPDQ6uvTwCrkEEAAAAAKeutVYQiAAAB3RCwV26Z6LvVQTRP3D8hq1DzmmTgkQjV0SSojWCZLn5YHcRmAAAAAABXtD0HAAAA1yQq8l6tAwAAq5BBAAAAANeMF6bNrgIA", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 35957 of 106893 compute units", - "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success" - ], - "postBalances": [ - 122171125343, - 1461600, - 733959725969, - 1101231920, - 2039280, - 15616720, - 2039280, - 279706994391733, - 1, - 1, - 1141440, - 323296939, - 2500000, - 1141440, - 934087680, - 731913600, - 1009200, - 0 - ], - "postTokenBalances": [ - { - "accountIndex": 4, - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "owner": "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "uiTokenAmount": { - "amount": "962048231511255", - "decimals": 6, - "uiAmount": 962048231.511255, - "uiAmountString": "962048231.511255" - } - }, - { - "accountIndex": 6, - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "owner": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "uiTokenAmount": { - "amount": "37951768488745", - "decimals": 6, - "uiAmount": 37951768.488745, - "uiAmountString": "37951768.488745" - } - } - ], - "preBalances": [ - 123308602893, - 0, - 733955725969, - 0, - 0, - 0, - 0, - 279706983391733, - 1, - 1, - 1141440, - 323296939, - 2500000, - 1141440, - 934087680, - 731913600, - 1009200, - 0 - ], - "preTokenBalances": [], - "rewards": [], - "status": { - "Ok": null - } - }, - "slot": 284682639, - "transaction": { - "message": { - "accountKeys": [ - { - "pubkey": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "signer": true, - "source": "transaction", - "writable": true - }, - { - "pubkey": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "signer": true, - "source": "transaction", - "writable": true - }, - { - "pubkey": "HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "H6LkmMUuAiJhAcH9ejScvMVXFhUSzxwYPiczL7zW3aAj", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "BfUATFeQBKLdaTGdCT9bKkxXrYTYaRkcjtQ4iFwMGVq1", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM", - "signer": false, - "source": "transaction", - "writable": true - }, - { - "pubkey": "ComputeBudget111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "11111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "SysvarRent111111111111111111111111111111111", - "signer": false, - "source": "transaction", - "writable": false - }, - { - "pubkey": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", - "signer": false, - "source": "transaction", - "writable": false - } - ], - "addressTableLookups": [], - "instructions": [ - { - "accounts": [], - "data": "HnkkG7", - "programId": "ComputeBudget111111111111111111111111111111", - "stackHeight": null - }, - { - "parsed": { - "info": { - "destination": "HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY", - "lamports": 4000000, - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5" - }, - "type": "transfer" - }, - "program": "system", - "programId": "11111111111111111111111111111111", - "stackHeight": null - }, - { - "accounts": [], - "data": "3ZfX8LdfViHV", - "programId": "ComputeBudget111111111111111111111111111111", - "stackHeight": null - }, - { - "accounts": [ - "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", - "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH", - "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF", - "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", - "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", - "H6LkmMUuAiJhAcH9ejScvMVXFhUSzxwYPiczL7zW3aAj", - "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "11111111111111111111111111111111", - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - "SysvarRent111111111111111111111111111111111", - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", - "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" - ], - "data": "U5L9Srg16xJSo5n5mGEnUQaep1FgNe24zh1oYXVbcVpSyAPk5QWVT8RNVbaJeebkjgPqHUHnWwPyPFmJ21HDBYXgTd8HTU7QfbiY7cn26rn4zxi724rGkbWKwnJHghce74jdF8dLeGwvYnU", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": null - }, - { - "parsed": { - "info": { - "account": "BfUATFeQBKLdaTGdCT9bKkxXrYTYaRkcjtQ4iFwMGVq1", - "mint": "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "source": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "systemProgram": "11111111111111111111111111111111", - "tokenProgram": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "wallet": "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5" - }, - "type": "create" - }, - "program": "spl-associated-token-account", - "programId": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", - "stackHeight": null - }, - { - "accounts": [ - "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", - "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM", - "ER2N5eaDoC68kNhj7LyaScimzq7deaqxiw88rewvxaKp", - "FFzxakVNzpirwMFtLyD22UZ6UM3KLF2EAGC2RxNPaYoH", - "6eTEMemDi58KJE1rPEagqMsgn34xUWTkzdZTKM8EVbYF", - "BfUATFeQBKLdaTGdCT9bKkxXrYTYaRkcjtQ4iFwMGVq1", - "Fswrw3tgQL597kCexxLEhft6a7Su4CDoqwRMqqj4BEp5", - "11111111111111111111111111111111", - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", - "SysvarRent111111111111111111111111111111111", - "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", - "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" - ], - "data": "AJTQ2h9DXrBiKPvzMVAo11jUarcFAxcz3", - "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", - "stackHeight": null - } - ], - "recentBlockhash": "4LkonCgzoF4HF4ZmrczNCntkk5QJzoBfwEG67o99S6yR" - }, - "signatures": [ - "52ar89rghM8EwKZkxFnBMC4LaMReqtVdpxqXxGWBCMYV1DnYdLrdsqJo8Hbn9KjVpckAokqGNHzTSVfK5xuLepdC", - "SpE85aiJConP43xzaqrri6TRmEbKZdiSJoXeTixJPuMkYUSQZbyjxrb3NbatshfoggYacnyd1YWJf98iPV5YYqm" - ] - }, - "version": 0 - }, - "id": 1 -} diff --git a/learning-examples/raw_create_tx_from_gettransaction.json b/learning-examples/raw_create_tx_from_gettransaction.json new file mode 100644 index 0000000..f4f1f88 --- /dev/null +++ b/learning-examples/raw_create_tx_from_gettransaction.json @@ -0,0 +1,938 @@ +{ + "jsonrpc": "2.0", + "result": { + "slot": 435946190, + "transaction": { + "signatures": [ + "2RoRJxatbF9Qkv87jei19u7ei2ckyjjnrCHZBRRAXi4GFJi68kra2iPSk7aoQ9Ugnf5FK5Mdp274hMaVSzn6SN5M", + "JMq7H9uF7WZSDAXh87MZ35WK3VFQGFGvdMRDcfVibeyLn6R5Q7xCmsAUEtP334hgvozVi9n8axCTBVhHQxxJbJv" + ], + "message": { + "accountKeys": [ + { + "pubkey": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "writable": true, + "signer": true, + "source": "transaction" + }, + { + "pubkey": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "writable": true, + "signer": true, + "source": "transaction" + }, + { + "pubkey": "moonQBUKBpkifLcTd78bfxxt4PYLwmJ5admLW6cBBs8", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "DnZP8kkE9F1rjtRA5c6XV19pVy7jmejz3ogrQvXSiE28", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "FK84ZzCXoeEsuMv1xZVZt8C4d1Ga3aZmsT4pRBoyAx8", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "HgY6tnTruYkYVNxutwL2wNgJFQ6sNWUznAzY241sy3UN", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "HkugJFWzibGu4qpCcXRnhgtcLfzoUoFxvNVA53ntg3aL", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "AFqUN4G2XKAiZHn2g4WQvfc5h5V6F44RwJbc4xo8mwq7", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "J37uRkBuK3YTyKRDRQE2tBsCn4tSgych29jtov9xvT87", + "writable": true, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "11111111111111111111111111111111", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "CFL2VF5HJMMr594er6eFmNrGwtB9NFTFwkoPeS1j36JH", + "writable": false, + "signer": false, + "source": "transaction" + }, + { + "pubkey": "uxtoRPdPjRekYmxs1uUqVRZWh38iqonc9KgPuZXPeSY", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW", + "writable": true, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "13ec7XdrjF3h3YcqBTFDSReRcUFwbCnJaAQspM4j6DDJ", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "So11111111111111111111111111111111111111112", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "writable": false, + "signer": false, + "source": "lookupTable" + }, + { + "pubkey": "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt", + "writable": false, + "signer": false, + "source": "lookupTable" + } + ], + "recentBlockhash": "DJUAWKW6ZfJaZsCWVpNb6UxGZKzHrqii9PFSCgsXnLXG", + "instructions": [ + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "moonQBUKBpkifLcTd78bfxxt4PYLwmJ5admLW6cBBs8", + "lamports": 3000000, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 1 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "uxtoRPdPjRekYmxs1uUqVRZWh38iqonc9KgPuZXPeSY", + "lamports": 27000000, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 1 + }, + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", + "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", + "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "11111111111111111111111111111111", + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e", + "13ec7XdrjF3h3YcqBTFDSReRcUFwbCnJaAQspM4j6DDJ", + "BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s", + "DnZP8kkE9F1rjtRA5c6XV19pVy7jmejz3ogrQvXSiE28", + "FK84ZzCXoeEsuMv1xZVZt8C4d1Ga3aZmsT4pRBoyAx8", + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", + "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "So11111111111111111111111111111111111111112", + "HgY6tnTruYkYVNxutwL2wNgJFQ6sNWUznAzY241sy3UN", + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + ], + "data": "4g1G41E9F3d9vExc4Do9u7QxfRzozMvDWZ7LG2YW2SfQo1zakKNegdCUVJ8hQdNbb8cpcZvz2LHX23G9uy7kggnr6wnws9BzxvYTozDqQM1WY7Zor5AYYvnqzYVshCX4MPZz5GSBrvfyfHZZtmS9nWpk4aw5EyMCMeQKowWH4ULLj7ywjHDS5SA9e", + "stackHeight": 1 + }, + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "11111111111111111111111111111111", + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", + "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" + ], + "data": "gCzGGoTR6NG", + "stackHeight": 1 + }, + { + "program": "spl-associated-token-account", + "programId": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "parsed": { + "info": { + "account": "HkugJFWzibGu4qpCcXRnhgtcLfzoUoFxvNVA53ntg3aL", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "systemProgram": "11111111111111111111111111111111", + "tokenProgram": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "wallet": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "createIdempotent" + }, + "stackHeight": 1 + }, + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf", + "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "HkugJFWzibGu4qpCcXRnhgtcLfzoUoFxvNVA53ntg3aL", + "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "11111111111111111111111111111111", + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "AFqUN4G2XKAiZHn2g4WQvfc5h5V6F44RwJbc4xo8mwq7", + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1", + "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y", + "J37uRkBuK3YTyKRDRQE2tBsCn4tSgych29jtov9xvT87", + "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt", + "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ", + "CFL2VF5HJMMr594er6eFmNrGwtB9NFTFwkoPeS1j36JH", + "A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW" + ], + "data": "PvwdRapqdNv7Ry3voaEfX8BUqgdxDijhcK", + "stackHeight": 1 + } + ], + "addressTableLookups": [ + { + "accountKey": "HQ4G6FjmW8yZ15XGoiQdGDvbi5C7fJKktNg6pzCzdHg4", + "writableIndexes": [ + 42, + 4, + 6, + 43, + 8, + 10, + 21 + ], + "readonlyIndexes": [ + 22, + 11, + 1, + 5, + 12, + 23, + 24, + 9 + ] + } + ] + } + }, + "meta": { + "err": null, + "status": { + "Ok": null + }, + "fee": 10000, + "preBalances": [ + 98807226520, + 0, + 6160686613, + 0, + 0, + 0, + 0, + 0, + 0, + 23859389, + 1844400, + 1, + 8502112342, + 3388605256, + 0, + 422099136126, + 11149834, + 46700153690375, + 23556978269591, + 17016138, + 6046720, + 2044091537, + 1020235880, + 4089612038, + 70128637, + 3104160, + 168261371, + 1630911579072, + 58238313, + 37290293 + ], + "postBalances": [ + 95767458600, + 3667920, + 6163686613, + 2964904802, + 2074080, + 0, + 0, + 0, + 2074080, + 23859389, + 10733289, + 1, + 8502112342, + 3388605256, + 0, + 422126136126, + 11149834, + 46700153690375, + 23556992343666, + 17016138, + 6046720, + 2058165611, + 1020235880, + 4089612038, + 70128637, + 3104160, + 168261371, + 1630911579072, + 58238313, + 37290293 + ], + "innerInstructions": [ + { + "index": 2, + "instructions": [ + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "lamports": 2519520, + "newAccount": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "space": 234 + }, + "type": "createAccount" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "metadataAddress": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump" + }, + "type": "initializeMetadataPointer" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "decimals": 6, + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "mintAuthority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM" + }, + "type": "initializeMint2" + }, + "stackHeight": 2 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "lamports": 1691280, + "newAccount": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "owner": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "space": 115 + }, + "type": "createAccount" + }, + "stackHeight": 2 + }, + { + "program": "spl-associated-token-account", + "programId": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", + "parsed": { + "info": { + "account": "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "systemProgram": "11111111111111111111111111111111", + "tokenProgram": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "wallet": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3" + }, + "type": "create" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "extensionTypes": [ + "immutableOwner" + ], + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump" + }, + "type": "getAccountDataSize" + }, + "stackHeight": 3 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "lamports": 2074080, + "newAccount": "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "space": 170 + }, + "type": "createAccount" + }, + "stackHeight": 3 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "account": "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF" + }, + "type": "initializeImmutableOwner" + }, + "stackHeight": 3 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "account": "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "owner": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3" + }, + "type": "initializeAccount3" + }, + "stackHeight": 3 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "lamports": 1148400, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "metadata": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "mintAuthority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", + "name": "The Ass Statue", + "symbol": "TAS", + "updateAuthority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", + "uri": "https://meta.uxento.io/data/714b0bec-90cb-4cbb-9598-b7bcbcd3bd06" + }, + "type": "initializeTokenMetadata" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "metadata": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "newAuthority": null, + "updateAuthority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM" + }, + "type": "updateTokenMetadataAuthority" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "account": "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "amount": "1000000000000000", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "mintAuthority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM" + }, + "type": "mintTo" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "authority": "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM", + "authorityType": "mintTokens", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "newAuthority": null + }, + "type": "setAuthority" + }, + "stackHeight": 2 + }, + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" + ], + "data": "4do6MfY17mvDg86G3wa87MbF75DmJaC7cBgnhtjcQbn9UzTH5Ncjub9UFW4hQS4qsriGnaXRED1wxWGrXLxmb5RuREEG5w2nTLgVJJ6cSCpzQoQTaqqwpobcRRLsbVzDVVY188Whbgn7dPi95hd91TYKCXuyvgkEWhacHfJJAyta1Pe51Ej9YoJJqyWdt3q68pfKgnU1L8usTUy31rj38fVcJvo6xHMUPvD7YpCg4gXW3rMpJbqRjjvLD9mW8Tvxjb79pe3DWmM6HorNcP8QW47gSULHrJMxWZbXvoPuTCXqeHRAoa252qKut5aSu91DnqVqBRH8xAULcCdMhekZAGYrvuqugBZz7jXGYCS3ce1hirxY2zvPhrUUah8ss2zxZhiVwa6xTsefwzhNQxuKNRK9Ff3W4cDBiM2ZjD7kef6m6HTGnoBN1NBokv6YYC9gyd38wi3PBXYiwTSKD3Rjoy8mMifRQa6b", + "stackHeight": 2 + } + ] + }, + { + "index": 3, + "instructions": [ + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "lamports": 250560, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 2 + }, + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" + ], + "data": "21448NTnPMYUBkX8r9jEFxShLqQHYei1N5cxdsxoe8cAXgrWuM1b46WUHHYJknU1k1xic4fTYpRZmztRmBatNfWd9RSzFrVMnQpaoJsaipjePKurznQLJgKhCnrmJjeXaxCup1xKfU7ttco", + "stackHeight": 2 + } + ] + }, + { + "index": 4, + "instructions": [ + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "extensionTypes": [ + "immutableOwner" + ], + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump" + }, + "type": "getAccountDataSize" + }, + "stackHeight": 2 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "lamports": 2074080, + "newAccount": "HkugJFWzibGu4qpCcXRnhgtcLfzoUoFxvNVA53ntg3aL", + "owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "space": 170 + }, + "type": "createAccount" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "account": "HkugJFWzibGu4qpCcXRnhgtcLfzoUoFxvNVA53ntg3aL" + }, + "type": "initializeImmutableOwner" + }, + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "account": "HkugJFWzibGu4qpCcXRnhgtcLfzoUoFxvNVA53ntg3aL", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "owner": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "initializeAccount3" + }, + "stackHeight": 2 + } + ] + }, + { + "index": 5, + "instructions": [ + { + "programId": "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ", + "accounts": [ + "8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt", + "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" + ], + "data": "6E5CZKNB2G93HVu9Syn6kkEUE5ZYBEkjrAW4Dfp9EBMjXR9", + "stackHeight": 2 + }, + { + "program": "spl-token", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "parsed": { + "info": { + "authority": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "destination": "HkugJFWzibGu4qpCcXRnhgtcLfzoUoFxvNVA53ntg3aL", + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "source": "Cd4iC3Jndc2WVud6rAs1cwx8SkUQhCN5TxXbfRtbHLCF", + "tokenAmount": { + "amount": "96449438144093", + "decimals": 6, + "uiAmount": 96449438.144093, + "uiAmountString": "96449438.144093" + } + }, + "type": "transferChecked" + }, + "stackHeight": 2 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "J37uRkBuK3YTyKRDRQE2tBsCn4tSgych29jtov9xvT87", + "lamports": 8888889, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 2 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "lamports": 2962962962, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 2 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW", + "lamports": 14074074, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 2 + }, + { + "program": "system", + "programId": "11111111111111111111111111111111", + "parsed": { + "info": { + "destination": "62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV", + "lamports": 14074075, + "source": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM" + }, + "type": "transfer" + }, + "stackHeight": 2 + }, + { + "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", + "accounts": [ + "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1" + ], + "data": "Aa2dSnituwvkDoueD1F3asXiWzpxqmNfp9C24GrpjGgE6UHyGsZt48W7w6XScmSwucWX9oiKNrq9a2Lb1ckvnRT5dTRbWraqoWC3p1Lq6b24bzoMQ2cKJbC59Kp49F4uHZZWB4eARcWciKf5juykotVy9fKZCH27LrpHKtW454BLVkyVLSheDB7gtLxEemn5r6J8jwEs6dQUG9w6LzWbWoCxC1AZkEHj5DMwE7kZ4Z55sGJXR9auHiU7DwdYQPfN1xfLTV8tVY4xLrQ8pcMN4Bu2L89SjqMFNghEAvNEMtKfoCskSH1ibyDLGkis1aR22ezM9WJfHQFcrGoEmJS3WxB63paeXY59xB8uZoi8aFqWc9bKfFmbq4BNnq8cDtYMbiEFLwXc8JzwLpehM6FkfuZWGYmhGNcGK63G4uwJcVoF5qrJ5eJkKpLeYACAbZPoAWegLA7EGT6vgz3Wtu3wmiRMDBGCKMzhjVvJZMxFEarifxE6K71KKd5vYSDowKAido7wQb", + "stackHeight": 2 + } + ] + } + ], + "logMessages": [ + "Program 11111111111111111111111111111111 invoke [1]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [1]", + "Program 11111111111111111111111111111111 success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", + "Program log: Instruction: CreateV2", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: MetadataPointerInstruction::Initialize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 925 of 792685 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: InitializeMint2", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1772 of 790097 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [2]", + "Program log: Create", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]", + "Program log: Instruction: GetAccountDataSize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1447 of 768858 compute units", + "Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [3]", + "Program 11111111111111111111111111111111 success", + "Program log: Initialize the associated token account", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]", + "Program log: Instruction: InitializeImmutableOwner", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 736 of 762589 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]", + "Program log: Instruction: InitializeAccount3", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1969 of 759517 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 16947 of 774191 compute units", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: TokenMetadataInstruction: Initialize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 3522 of 732525 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: TokenMetadataInstruction: UpdateAuthority", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 3866 of 726753 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: MintTo", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1714 of 720713 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: SetAuthority", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1044 of 717060 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program data: G3KpTd7rY3YOAAAAVGhlIEFzcyBTdGF0dWUDAAAAVEFTQAAAAGh0dHBzOi8vbWV0YS51eGVudG8uaW8vZGF0YS83MTRiMGJlYy05MGNiLTRjYmItOTU5OC1iN2JjYmNkM2JkMDarDUVGkFAyRzCsYxVgJvZmb/09juzXRcgA2DNBRiFAnyiNIIamJQRxRzVeoOuuRwVPIoHsLN6K2zqPUbEf9bssRef0SuNtc2Y43Xotj2C0NWe2RcC/3hbdIrULc6ozrN5F5/RK421zZjjdei2PYLQ1Z7ZFwL/eFt0itQtzqjOs3gLwaWoAAAAAABDYR+PPAwAArCP8BgAAAAB4xftR0QIAAIDGpH6NAwAG3fbh7nWP3hhCXbzkbM3athr8TYO5DSf+vfko2KGL/AABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArCP8BgAAAA==", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2125 of 709816 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 99196 of 805700 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", + "Program log: Instruction: ExtendAccount", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program data: YWHXkF2SFnwojSCGpiUEcUc1XqDrrkcFTyKB7Czeits6j1GxH/W7LEXn9ErjbXNmON16LY9gtDVntkXAv94W3SK1C3OqM6zecwAAAAAAAACXAAAAAAAAAALwaWoAAAAA", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2125 of 697247 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 11575 of 706504 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]", + "Program log: CreateIdempotent", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: GetAccountDataSize", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1523 of 683669 compute units", + "Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program log: Initialize the associated token account", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: InitializeImmutableOwner", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 736 of 677324 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: InitializeAccount3", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2153 of 674255 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 23110 of 694929 compute units", + "Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]", + "Program log: Instruction: BuyExactSolIn", + "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ invoke [2]", + "Program log: Instruction: GetFees", + "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ consumed 3302 of 633697 compute units", + "Program return: pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ AAAAAAAAAABfAAAAAAAAAB4AAAAAAAAA", + "Program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ success", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]", + "Program log: Instruction: TransferChecked", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2562 of 625274 compute units", + "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program 11111111111111111111111111111111 invoke [2]", + "Program 11111111111111111111111111111111 success", + "Program data: vdt/007mYe6rDUVGkFAyRzCsYxVgJvZmb/09juzXRcgA2DNBRiFAnxI6m7AAAAAAXdZ/YrhXAAABRef0SuNtc2Y43Xotj2C0NWe2RcC/3hbdIrULc6ozrN4C8GlqAAAAABLmvqwHAAAAozlY5Sp4AwASOpuwAAAAAKOhRZmZeQIASsL40N1cvJfjKJwZfLUGKlTz2Va5zm5RFfllZ6pcs+ZfAAAAAAAAALWBrQEAAAAARef0SuNtc2Y43Xotj2C0NWe2RcC/3hbdIrULc6ozrN4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGJ1eV9leGFjdF9zb2xfaW4AHgAAAAAAAAA5oocAAAAAAIgTAAAAAAAA2sDWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASOpuwAAAAABLmvqwHAAAAEjqbsAAAAAA=", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2125 of 604471 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 71354 of 671819 compute units", + "Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success" + ], + "preTokenBalances": [], + "postTokenBalances": [ + { + "accountIndex": 4, + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "uiTokenAmount": { + "uiAmount": 903550561.855907, + "decimals": 6, + "amount": "903550561855907", + "uiAmountString": "903550561.855907" + }, + "owner": "3jJ83NDorkbFkF1JKbEfFWGeX16aXUiwby9RwJm9kat3", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 8, + "mint": "CWiTGbCiDd8BKtNYNE2boT9fJGFG2MU53Uf6HQk4pump", + "uiTokenAmount": { + "uiAmount": 96449438.144093, + "decimals": 6, + "amount": "96449438144093", + "uiAmountString": "96449438.144093" + }, + "owner": "5htGpHK2oV9g2BcDqLdRBqjCLdy8mc3fsESfR5DU73eM", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + } + ], + "rewards": [], + "computeUnitsConsumed": 205535, + "costUnits": 215799 + }, + "version": 0, + "blockTime": 1785327618 + } +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index e2c95cc..035b264 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ dependencies = [ [dependency-groups] dev = [ "ruff>=0.10.0", - # protoc; only needed to regenerate the geyser_pb2 stubs from proto/ + # protoc; only needed to regenerate src/geyser/generated from src/geyser/proto "grpcio-tools>=1.71.0", ]