mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-07-31 01:07:43 +00:00
fix(learning-examples): repair crashing listeners and decoders, prune obsolete paths, unify naming (#181)
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) <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -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
|
||||
|
||||
@@ -38,6 +38,23 @@ registry in `platforms/__init__.py`. Listeners and the trader are
|
||||
platform-agnostic (`Universal*`); anything platform-shaped belongs under
|
||||
`platforms/<name>/`.
|
||||
|
||||
### 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_<what>_from_<method>.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("<BI", 4, n)`
|
||||
against the compute-budget program.
|
||||
|
||||
## Pump.fun protocol notes (gotchas)
|
||||
|
||||
The IDLs under `idl/` are vendored verbatim from `github.com/pump-fun/pump-public-docs`
|
||||
@@ -185,11 +246,24 @@ The IDLs under `idl/` are vendored verbatim from `github.com/pump-fun/pump-publi
|
||||
symbol (str), uri (str), creator (pubkey), is_mayhem_mode (bool),
|
||||
is_cashback_enabled (OptionBool 1B)`. `OptionBool` is a struct wrapping a single
|
||||
bool — serialized as 1 byte, not 2.
|
||||
- **`is_cashback_enabled` can be absent from the wire entirely.** Two mainnet
|
||||
`create_v2` instructions carry `0001` and `00` after `creator`: one sends both
|
||||
trailing args, the other omits the last. A decoder that reads a fixed number of
|
||||
trailing bytes raises `IndexError` on roughly half of all coins. Decode
|
||||
trailing args defensively and report a missing one as unset.
|
||||
- `create_v2` accounts 1-16 are in the IDL; accounts **17-19 are optional
|
||||
remaining accounts** (`quote_mint`, `associated_quote_bonding_curve`,
|
||||
`quote_token_program`) appended only for a non-SOL quote mint. All three or
|
||||
none. This is the only way to read a new coin's quote asset from the
|
||||
instruction rather than the event.
|
||||
`quote_token_program`). All three or none. This is the only way to read a new
|
||||
coin's quote asset from the instruction rather than the event. In practice they
|
||||
are appended for **SOL-paired coins too**, carrying wrapped SOL — a live
|
||||
SOL-paired `create_v2` was observed with 19 accounts and account 17 = WSOL — so
|
||||
do not treat a 19-account `create_v2` as proof of a non-SOL quote asset. Read
|
||||
`quote_mint` off the curve instead.
|
||||
- The **associated bonding curve is an ordinary ATA**, so its address depends on
|
||||
which token program owns the mint: Token2022 for `create_v2` coins, SPL Token
|
||||
for legacy `create`. Deriving with the wrong program returns a valid-looking
|
||||
address that does not exist on chain. Verified: curve `3jJ83ND…` derives to
|
||||
`Cd4iC3Jn…` under Token2022 (matches chain) and `AhNzZsBp…` under SPL Token.
|
||||
- `extreme_fast_mode` skips the curve-state price fetch but still refreshes
|
||||
mayhem/cashback/creator/**quote_mint** from chain, because the wrong quote mint
|
||||
means spending the wrong balance entirely. Event parsers also populate
|
||||
|
||||
@@ -120,16 +120,21 @@ Standalone scripts, runnable with `uv run <path>`. 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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -27,6 +27,36 @@ PUMP_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string(
|
||||
)
|
||||
EXPECTED_DISCRIMINATOR: Final[bytes] = struct.pack("<Q", 6966180631402821399)
|
||||
|
||||
# Shortest account that still reaches quote_mint: 8 discriminator + 41 base fields
|
||||
# + 32 creator + 1 mayhem + 1 cashback + 32 quote_mint.
|
||||
_V5_MIN_LENGTH: Final[int] = 115
|
||||
|
||||
# Quote assets. `quote_mint` is all zeros on SOL-paired coins; the quote-side reserves
|
||||
# are always in the quote mint's raw units (1e9 for SOL, 1e6 for USDC).
|
||||
DEFAULT_QUOTE_MINT: Final[Pubkey] = Pubkey.from_bytes(bytes(32))
|
||||
WSOL_MINT: Final[Pubkey] = Pubkey.from_string(
|
||||
"So11111111111111111111111111111111111111112"
|
||||
)
|
||||
USDC_MINT: Final[Pubkey] = Pubkey.from_string(
|
||||
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
|
||||
)
|
||||
QUOTE_DECIMALS: Final[dict[Pubkey, int]] = {WSOL_MINT: 9, USDC_MINT: 6}
|
||||
QUOTE_SYMBOLS: Final[dict[Pubkey, str]] = {WSOL_MINT: "SOL", USDC_MINT: "USDC"}
|
||||
|
||||
|
||||
def resolve_quote_asset(quote_mint: Pubkey) -> 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:,}")
|
||||
|
||||
|
||||
@@ -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 <MINT>
|
||||
|
||||
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(
|
||||
"<Q", 6966180631402821399
|
||||
) # Pump.fun bonding curve discriminator
|
||||
POLL_INTERVAL: Final[int] = 10 # Seconds between each status check
|
||||
_MIN_ARGC: Final[int] = 2
|
||||
|
||||
# Quote assets. `quote_mint` is all zeros on SOL-paired coins, and the quote-side
|
||||
# reserves are in that mint's raw units — 1e9 for SOL, 1e6 for USDC.
|
||||
DEFAULT_QUOTE_MINT: Final[Pubkey] = Pubkey.from_bytes(bytes(32))
|
||||
WSOL_MINT: Final[Pubkey] = Pubkey.from_string(
|
||||
"So11111111111111111111111111111111111111112"
|
||||
)
|
||||
USDC_MINT: Final[Pubkey] = Pubkey.from_string(
|
||||
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
|
||||
)
|
||||
QUOTE_DECIMALS: Final[dict[Pubkey, int]] = {WSOL_MINT: 9, USDC_MINT: 6}
|
||||
QUOTE_SYMBOLS: Final[dict[Pubkey, str]] = {WSOL_MINT: "SOL", USDC_MINT: "USDC"}
|
||||
|
||||
# Data lengths excluding the 8-byte discriminator, per curve layout version.
|
||||
_LEN_WITH_CREATOR: Final[int] = 73
|
||||
_LEN_WITH_MAYHEM: Final[int] = 74
|
||||
_LEN_WITH_CASHBACK: Final[int] = 75
|
||||
_LEN_WITH_QUOTE_MINT: Final[int] = 107
|
||||
|
||||
# Only used if the Global account cannot be read: 1B supply less 206.9M reserved.
|
||||
FALLBACK_INITIAL_REAL_TOKEN_RESERVES: Final[float] = 793_100_000.0
|
||||
|
||||
|
||||
def get_bonding_curve_address(mint: Pubkey, program_id: Pubkey) -> Pubkey:
|
||||
@@ -83,29 +111,42 @@ def parse_curve_state(data: bytes) -> dict:
|
||||
|
||||
# Parse common fields (present in all versions)
|
||||
fields = struct.unpack_from("<QQQQQ?", data, 8)
|
||||
data_length = len(data) - 8
|
||||
|
||||
# quote_mint decides the scale of the quote-side reserves, so read it before
|
||||
# converting anything.
|
||||
quote_mint = DEFAULT_QUOTE_MINT
|
||||
if data_length >= _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("<Q", data, 89)[0]
|
||||
if raw:
|
||||
return raw / 10**TOKEN_DECIMALS
|
||||
except Exception as e: # noqa: BLE001 - fall back rather than abort the poller
|
||||
print(f"⚠️ Could not read Global, using the fallback baseline: {e}")
|
||||
return FALLBACK_INITIAL_REAL_TOKEN_RESERVES
|
||||
|
||||
|
||||
def print_curve_status(state: dict, baseline: float) -> 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 <MINT>"
|
||||
)
|
||||
sys.exit(1)
|
||||
asyncio.run(track_curve(sys.argv[1]))
|
||||
|
||||
@@ -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 <MINT>
|
||||
|
||||
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 <MINT>"
|
||||
)
|
||||
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__":
|
||||
|
||||
+25
-4
@@ -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("<Q", ix_data, offset)[0]
|
||||
offset += 8
|
||||
@@ -116,9 +140,6 @@ def decode_transaction(tx_data, idl):
|
||||
|
||||
for idl_ix in idl["instructions"]:
|
||||
idl_discriminator = calculate_discriminator(f"global:{idl_ix['name']}")
|
||||
print(
|
||||
f"Checking against IDL instruction: {idl_ix['name']} with discriminator {idl_discriminator:016x}"
|
||||
)
|
||||
|
||||
if discriminator == idl_discriminator:
|
||||
decoded_args = decode_instruction(ix_data, idl_ix)
|
||||
@@ -168,7 +189,7 @@ def decode_transaction(tx_data, idl):
|
||||
tx_file_path = ""
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
tx_file_path = "learning-examples/blockSubscribe-transactions/raw_create_tx_from_blockSubscribe.json"
|
||||
tx_file_path = "learning-examples/blocksubscribe-transactions/raw_create_tx_from_blocksubscribe.json"
|
||||
print(f"No path provided, using the path: {tx_file_path}")
|
||||
else:
|
||||
tx_file_path = sys.argv[1]
|
||||
@@ -1,152 +0,0 @@
|
||||
import json
|
||||
import struct
|
||||
import sys
|
||||
|
||||
import base58
|
||||
|
||||
tx_file_path = ""
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
tx_file_path = "learning-examples/raw_buy_tx_from_getTransaction.json"
|
||||
print(f"No path provided, using the path: {tx_file_path}")
|
||||
else:
|
||||
tx_file_path = sys.argv[1]
|
||||
|
||||
# Load the IDL
|
||||
with open("idl/pump_fun_idl.json") as f:
|
||||
idl = json.load(f)
|
||||
|
||||
# Load the transaction log
|
||||
with open(tx_file_path) as f:
|
||||
tx_log = json.load(f)
|
||||
|
||||
# Extract the transaction data
|
||||
tx_data = tx_log["result"]["transaction"]
|
||||
|
||||
print(json.dumps(tx_data, indent=2))
|
||||
|
||||
|
||||
def decode_create_instruction(data):
|
||||
"""Decode legacy Create instruction (Metaplex tokens).
|
||||
|
||||
IDL args (March 7, 2026 program upgrade): name, symbol, uri, creator (pubkey).
|
||||
"""
|
||||
offset = 8 # Skip the 8-byte discriminator
|
||||
results = []
|
||||
for _ in range(3):
|
||||
length = struct.unpack_from("<I", data, offset)[0]
|
||||
offset += 4
|
||||
string_data = data[offset : offset + length].decode("utf-8")
|
||||
results.append(string_data)
|
||||
offset += length
|
||||
|
||||
creator = base58.b58encode(data[offset : offset + 32]).decode("utf-8") if offset + 32 <= len(data) else None
|
||||
|
||||
return {
|
||||
"name": results[0],
|
||||
"symbol": results[1],
|
||||
"uri": results[2],
|
||||
"creator": creator,
|
||||
"token_standard": "legacy",
|
||||
"is_mayhem_mode": False,
|
||||
}
|
||||
|
||||
|
||||
def decode_create_v2_instruction(data):
|
||||
"""Decode CreateV2 instruction (Token2022 tokens).
|
||||
|
||||
IDL args: name, symbol, uri, creator (pubkey), is_mayhem_mode (bool),
|
||||
is_cashback_enabled (OptionBool = 1 byte).
|
||||
"""
|
||||
offset = 8 # Skip the 8-byte discriminator
|
||||
results = []
|
||||
for _ in range(3):
|
||||
length = struct.unpack_from("<I", data, offset)[0]
|
||||
offset += 4
|
||||
string_data = data[offset : offset + length].decode("utf-8")
|
||||
results.append(string_data)
|
||||
offset += length
|
||||
|
||||
creator = base58.b58encode(data[offset : offset + 32]).decode("utf-8") if offset + 32 <= len(data) else None
|
||||
offset += 32
|
||||
|
||||
is_mayhem_mode = bool(data[offset]) if offset < len(data) else False
|
||||
offset += 1
|
||||
|
||||
is_cashback_enabled = bool(data[offset]) if offset < len(data) else False
|
||||
|
||||
return {
|
||||
"name": results[0],
|
||||
"symbol": results[1],
|
||||
"uri": results[2],
|
||||
"creator": creator,
|
||||
"token_standard": "token2022",
|
||||
"is_mayhem_mode": is_mayhem_mode,
|
||||
"is_cashback_enabled": is_cashback_enabled,
|
||||
}
|
||||
|
||||
|
||||
def decode_buy_instruction(data):
|
||||
# Assuming the buy instruction has a u64 argument for amount
|
||||
amount = struct.unpack_from("<Q", data, 8)[0]
|
||||
return {"amount": amount}
|
||||
|
||||
|
||||
def decode_instruction_data(instruction, accounts, data):
|
||||
if instruction["name"] == "create":
|
||||
return decode_create_instruction(data)
|
||||
elif instruction["name"] == "create_v2":
|
||||
return decode_create_v2_instruction(data)
|
||||
elif instruction["name"] == "buy":
|
||||
return decode_buy_instruction(data)
|
||||
else:
|
||||
return f"Unhandled instruction type: {instruction['name']}"
|
||||
|
||||
|
||||
def find_matching_instruction(accounts, data):
|
||||
if "instructions" not in idl:
|
||||
print("Warning: No instructions found in IDL")
|
||||
return None
|
||||
for instruction in idl["instructions"]:
|
||||
if len(instruction["accounts"]) == len(accounts):
|
||||
return instruction
|
||||
return None
|
||||
|
||||
|
||||
# Parse the transaction
|
||||
tx_message = tx_data["message"]
|
||||
instructions = tx_message["instructions"]
|
||||
|
||||
for ix in instructions:
|
||||
program_id = ix.get("programId")
|
||||
accounts = ix.get("accounts", [])
|
||||
data = ix.get("data", "")
|
||||
|
||||
if "parsed" in ix:
|
||||
print(f"Parsed instruction: {ix['program']} - {ix['parsed']['type']}")
|
||||
print(f"Info: {json.dumps(ix['parsed']['info'], indent=2)}")
|
||||
elif (
|
||||
program_id == "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
||||
): # Pump Fun Program
|
||||
matching_instruction = find_matching_instruction(accounts, data)
|
||||
if matching_instruction:
|
||||
decoded_data = decode_instruction_data(
|
||||
matching_instruction, accounts, base58.b58decode(data)
|
||||
)
|
||||
print(f"Instruction: {matching_instruction['name']}")
|
||||
print(f"Decoded data: {decoded_data}")
|
||||
|
||||
print("\nAccounts:")
|
||||
for i, account in enumerate(accounts):
|
||||
account_info = matching_instruction["accounts"][i]
|
||||
print(f" {account_info['name']}: {account}")
|
||||
else:
|
||||
print(f"Unable to match instruction for program {program_id}")
|
||||
else:
|
||||
print(f"Instruction for program: {program_id}")
|
||||
print(f"Data: {data}\n")
|
||||
|
||||
print("\nTransaction Information:")
|
||||
print(f"Blockhash: {tx_message['recentBlockhash']}")
|
||||
print(f"Fee payer: {tx_message['accountKeys'][0]['pubkey']}")
|
||||
print(f"Signature: {tx_data['signatures'][0]}")
|
||||
+50
-8
@@ -1,14 +1,22 @@
|
||||
import base64
|
||||
import json
|
||||
import struct
|
||||
import sys
|
||||
|
||||
from construct import Bytes, Flag, Int64ul, Struct
|
||||
from solders.pubkey import Pubkey
|
||||
|
||||
LAMPORTS_PER_SOL = 1_000_000_000
|
||||
TOKEN_DECIMALS = 6
|
||||
EXPECTED_DISCRIMINATOR = struct.pack("<Q", 6966180631402821399)
|
||||
|
||||
# Quote assets. A curve's `quote_mint` is all zeros when the coin is SOL-paired, and
|
||||
# the quote-side reserves are always raw units of that mint: 1e9 for SOL, 1e6 for USDC.
|
||||
DEFAULT_QUOTE_MINT = Pubkey.from_bytes(bytes(32))
|
||||
WSOL_MINT = Pubkey.from_string("So11111111111111111111111111111111111111112")
|
||||
USDC_MINT = Pubkey.from_string("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
|
||||
QUOTE_DECIMALS = {WSOL_MINT: 9, USDC_MINT: 6}
|
||||
QUOTE_SYMBOLS = {WSOL_MINT: "SOL", USDC_MINT: "USDC"}
|
||||
|
||||
|
||||
class BondingCurveState:
|
||||
_STRUCT = Struct(
|
||||
@@ -57,20 +65,43 @@ class BondingCurveState:
|
||||
|
||||
if len(data) > 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}")
|
||||
@@ -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:<name>")
|
||||
"""
|
||||
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("<I", data, offset)[0]
|
||||
offset += 4
|
||||
results.append(data[offset : offset + length].decode("utf-8"))
|
||||
offset += length
|
||||
|
||||
creator = (
|
||||
base58.b58encode(data[offset : offset + 32]).decode("utf-8")
|
||||
if offset + 32 <= len(data)
|
||||
else None
|
||||
)
|
||||
|
||||
return {
|
||||
"name": results[0],
|
||||
"symbol": results[1],
|
||||
"uri": results[2],
|
||||
"creator": creator,
|
||||
"token_standard": "legacy",
|
||||
"is_mayhem_mode": False,
|
||||
}
|
||||
|
||||
|
||||
def decode_create_v2_instruction(data: bytes) -> 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("<I", data, offset)[0]
|
||||
offset += 4
|
||||
results.append(data[offset : offset + length].decode("utf-8"))
|
||||
offset += length
|
||||
|
||||
creator = (
|
||||
base58.b58encode(data[offset : offset + 32]).decode("utf-8")
|
||||
if offset + 32 <= len(data)
|
||||
else None
|
||||
)
|
||||
offset += 32
|
||||
|
||||
is_mayhem_mode = bool(data[offset]) if offset < len(data) else False
|
||||
offset += 1
|
||||
|
||||
is_cashback_enabled = bool(data[offset]) if offset < len(data) else False
|
||||
|
||||
return {
|
||||
"name": results[0],
|
||||
"symbol": results[1],
|
||||
"uri": results[2],
|
||||
"creator": creator,
|
||||
"token_standard": "token2022",
|
||||
"is_mayhem_mode": is_mayhem_mode,
|
||||
"is_cashback_enabled": is_cashback_enabled,
|
||||
}
|
||||
|
||||
|
||||
def decode_trade_instruction(data: bytes) -> 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("<QQ", data, 8)
|
||||
return {"amount": amount, "quote_limit": quote_limit}
|
||||
|
||||
|
||||
DECODERS = {
|
||||
"create": decode_create_instruction,
|
||||
"create_v2": decode_create_v2_instruction,
|
||||
"buy": decode_trade_instruction,
|
||||
"buy_v2": decode_trade_instruction,
|
||||
"sell": decode_trade_instruction,
|
||||
"sell_v2": decode_trade_instruction,
|
||||
}
|
||||
|
||||
|
||||
def iter_pump_instructions(result: dict) -> 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("<Q", data[:DISCRIMINATOR_LEN])[0]
|
||||
if len(data) >= 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"<extra {i}>"
|
||||
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()
|
||||
+43
-18
@@ -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())
|
||||
@@ -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 <BONDING_CURVE_ADDRESS>
|
||||
|
||||
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("<Q", 6966180631402821399)
|
||||
|
||||
# Data lengths, excluding the 8-byte discriminator: V2 stops after `creator`, V4
|
||||
# runs through `quote_mint`. Live accounts are 151 bytes, so the tail is padding.
|
||||
_V2_LENGTH: Final[int] = 73
|
||||
_V4_LENGTH: Final[int] = 107
|
||||
|
||||
load_dotenv()
|
||||
|
||||
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||
@@ -27,18 +51,18 @@ class BondingCurveState:
|
||||
|
||||
_STRUCT_V1 = Struct(
|
||||
"virtual_token_reserves" / Int64ul,
|
||||
"virtual_sol_reserves" / Int64ul,
|
||||
"virtual_quote_reserves" / Int64ul,
|
||||
"real_token_reserves" / Int64ul,
|
||||
"real_sol_reserves" / Int64ul,
|
||||
"real_quote_reserves" / Int64ul,
|
||||
"token_total_supply" / Int64ul,
|
||||
"complete" / Flag,
|
||||
)
|
||||
|
||||
_STRUCT_V2 = Struct(
|
||||
"virtual_token_reserves" / Int64ul,
|
||||
"virtual_sol_reserves" / Int64ul,
|
||||
"virtual_quote_reserves" / Int64ul,
|
||||
"real_token_reserves" / Int64ul,
|
||||
"real_sol_reserves" / Int64ul,
|
||||
"real_quote_reserves" / Int64ul,
|
||||
"token_total_supply" / Int64ul,
|
||||
"complete" / Flag,
|
||||
"creator" / Bytes(32),
|
||||
@@ -46,40 +70,104 @@ class BondingCurveState:
|
||||
|
||||
_STRUCT_V3 = Struct(
|
||||
"virtual_token_reserves" / Int64ul,
|
||||
"virtual_sol_reserves" / Int64ul,
|
||||
"virtual_quote_reserves" / Int64ul,
|
||||
"real_token_reserves" / Int64ul,
|
||||
"real_sol_reserves" / Int64ul,
|
||||
"real_quote_reserves" / Int64ul,
|
||||
"token_total_supply" / Int64ul,
|
||||
"complete" / Flag,
|
||||
"creator" / Bytes(32),
|
||||
"is_mayhem_mode" / Flag,
|
||||
)
|
||||
|
||||
def __init__(self, data: bytes) -> 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 <BONDING_CURVE_ADDRESS>")
|
||||
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:
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
@@ -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())
|
||||
@@ -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
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -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: ...
|
||||
@@ -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,
|
||||
)
|
||||
File diff suppressed because one or more lines are too long
@@ -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: ...
|
||||
@@ -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}."
|
||||
)
|
||||
@@ -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())
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
@@ -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("<I", data[offset : offset + 4])[0]
|
||||
offset += 4
|
||||
if offset + length > 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("<Q", data[offset : offset + 8])[0]
|
||||
offset += 8
|
||||
elif field_type == "i64":
|
||||
value = struct.unpack("<q", data[offset : offset + 8])[0]
|
||||
offset += 8
|
||||
elif field_type == "bool":
|
||||
value = bool(data[offset]) if offset < len(data) else False
|
||||
offset += 1
|
||||
parsed_data[field_name] = value
|
||||
|
||||
parsed_data["token_standard"] = token_standard_hint
|
||||
return parsed_data
|
||||
except Exception as e:
|
||||
print(f"❌ Parse Create event error: {e}")
|
||||
print(f" Data length: {len(data)} bytes, offset: {offset}")
|
||||
return None
|
||||
|
||||
|
||||
def parse_create_instruction(data):
|
||||
"""Parse CreateEvent emitted by legacy Create instruction (Metaplex tokens)."""
|
||||
return _parse_create_event(data, token_standard_hint="legacy")
|
||||
|
||||
|
||||
def parse_create_v2_instruction(data):
|
||||
"""Parse CreateEvent emitted by CreateV2 instruction (Token2022 tokens)."""
|
||||
return _parse_create_event(data, token_standard_hint="token2022")
|
||||
|
||||
|
||||
async def listen_for_new_tokens():
|
||||
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": "logsSubscribe",
|
||||
"params": [
|
||||
{"mentions": [str(PUMP_PROGRAM_ID)]},
|
||||
{"commitment": "processed"},
|
||||
],
|
||||
}
|
||||
)
|
||||
await websocket.send(subscription_message)
|
||||
print(
|
||||
f"Listening for new token creations from program: {PUMP_PROGRAM_ID}"
|
||||
)
|
||||
|
||||
# Wait for subscription confirmation
|
||||
response = await websocket.recv()
|
||||
print(f"Subscription response: {response}")
|
||||
|
||||
while True:
|
||||
try:
|
||||
response = await websocket.recv()
|
||||
data = json.loads(response)
|
||||
|
||||
if "method" in data and data["method"] == "logsNotification":
|
||||
log_data = data["params"]["result"]["value"]
|
||||
logs = log_data.get("logs", [])
|
||||
|
||||
# Detect both Create and CreateV2 instructions
|
||||
is_create = any(
|
||||
"Program log: Instruction: Create" in log
|
||||
for log in logs
|
||||
)
|
||||
is_create_v2 = any(
|
||||
"Program log: Instruction: CreateV2" in log
|
||||
for log in logs
|
||||
)
|
||||
|
||||
if is_create or is_create_v2:
|
||||
for log in logs:
|
||||
if "Program data:" in log:
|
||||
try:
|
||||
encoded_data = log.split(": ")[1]
|
||||
decoded_data = base64.b64decode(
|
||||
encoded_data
|
||||
)
|
||||
|
||||
# Check if this is a CreateEvent by validating discriminator
|
||||
if len(decoded_data) < 8:
|
||||
continue
|
||||
|
||||
event_discriminator = decoded_data[:8]
|
||||
if event_discriminator != CREATE_EVENT_DISCRIMINATOR:
|
||||
# Skip non-CreateEvent logs (e.g., TradeEvent, ExtendAccountEvent)
|
||||
continue
|
||||
|
||||
print(f"\n🔍 Found CreateEvent, length: {len(decoded_data)} bytes")
|
||||
print(f" Signature: {log_data.get('signature')}")
|
||||
|
||||
# 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:
|
||||
# Calculate associated bonding curve using PDA derivation
|
||||
mint = Pubkey.from_string(
|
||||
parsed_data["mint"]
|
||||
)
|
||||
bonding_curve = Pubkey.from_string(
|
||||
parsed_data["bondingCurve"]
|
||||
)
|
||||
associated_curve = find_associated_bonding_curve(
|
||||
mint, bonding_curve
|
||||
)
|
||||
|
||||
# Print token information in consistent format
|
||||
print_token_info(
|
||||
parsed_data,
|
||||
signature=log_data.get("signature"),
|
||||
associated_bonding_curve=str(associated_curve)
|
||||
)
|
||||
else:
|
||||
print(f"⚠️ Parsing failed for CreateEvent")
|
||||
except Exception as e:
|
||||
print(f"❌ Error processing log: {e!s}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"An error occurred while processing message: {e}")
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
print(f"Connection error: {e}")
|
||||
print("Reconnecting in 5 seconds...")
|
||||
await asyncio.sleep(5)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(listen_for_new_tokens())
|
||||
@@ -1,262 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import public "solana-storage.proto";
|
||||
|
||||
option go_package = "github.com/rpcpool/yellowstone-grpc/examples/golang/proto";
|
||||
|
||||
package geyser;
|
||||
|
||||
service Geyser {
|
||||
rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeUpdate) {}
|
||||
rpc Ping(PingRequest) returns (PongResponse) {}
|
||||
rpc GetLatestBlockhash(GetLatestBlockhashRequest) returns (GetLatestBlockhashResponse) {}
|
||||
rpc GetBlockHeight(GetBlockHeightRequest) returns (GetBlockHeightResponse) {}
|
||||
rpc GetSlot(GetSlotRequest) returns (GetSlotResponse) {}
|
||||
rpc IsBlockhashValid(IsBlockhashValidRequest) returns (IsBlockhashValidResponse) {}
|
||||
rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {}
|
||||
}
|
||||
|
||||
enum CommitmentLevel {
|
||||
PROCESSED = 0;
|
||||
CONFIRMED = 1;
|
||||
FINALIZED = 2;
|
||||
FIRST_SHRED_RECEIVED = 3;
|
||||
COMPLETED = 4;
|
||||
CREATED_BANK = 5;
|
||||
DEAD = 6;
|
||||
}
|
||||
|
||||
message SubscribeRequest {
|
||||
map<string, SubscribeRequestFilterAccounts> accounts = 1;
|
||||
map<string, SubscribeRequestFilterSlots> slots = 2;
|
||||
map<string, SubscribeRequestFilterTransactions> transactions = 3;
|
||||
map<string, SubscribeRequestFilterTransactions> transactions_status = 10;
|
||||
map<string, SubscribeRequestFilterBlocks> blocks = 4;
|
||||
map<string, SubscribeRequestFilterBlocksMeta> blocks_meta = 5;
|
||||
map<string, SubscribeRequestFilterEntry> 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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("<BI", 4, bytes_limit)
|
||||
return Instruction(COMPUTE_BUDGET_PROGRAM, data, [])
|
||||
|
||||
|
||||
async def buy_token(
|
||||
mint: Pubkey,
|
||||
bonding_curve: Pubkey,
|
||||
@@ -109,6 +155,8 @@ async def buy_token(
|
||||
amount: float,
|
||||
slippage: float = 0.25,
|
||||
max_retries=5,
|
||||
*,
|
||||
cu_optimized: bool = False,
|
||||
):
|
||||
private_key = base58.b58decode(os.environ.get("SOLANA_PRIVATE_KEY"))
|
||||
payer = Keypair.from_bytes(private_key)
|
||||
@@ -142,7 +190,13 @@ async def buy_token(
|
||||
is_mayhem_mode=curve_state.is_mayhem_mode,
|
||||
)
|
||||
|
||||
instructions = [
|
||||
instructions = []
|
||||
if cu_optimized:
|
||||
# Must come first, before the instructions it applies to.
|
||||
instructions.append(
|
||||
set_loaded_accounts_data_size_limit(LOADED_ACCOUNTS_DATA_SIZE_LIMIT)
|
||||
)
|
||||
instructions += [
|
||||
set_compute_unit_price(1_000),
|
||||
create_idempotent_associated_token_account(
|
||||
payer.pubkey(), payer.pubkey(), mint, token_program_id=token_program
|
||||
@@ -350,7 +404,9 @@ async def listen_for_create_transaction():
|
||||
return decoded_args
|
||||
|
||||
|
||||
async def main():
|
||||
async def main(*, cu_optimized: bool = False):
|
||||
if cu_optimized:
|
||||
print("Compute-unit optimization enabled (SetLoadedAccountsDataSizeLimit)")
|
||||
print("Waiting for a new token creation...")
|
||||
token_data = await listen_for_create_transaction()
|
||||
print("New token created:")
|
||||
@@ -393,8 +449,9 @@ async def main():
|
||||
token_program,
|
||||
amount,
|
||||
slippage,
|
||||
cu_optimized=cu_optimized,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
asyncio.run(main(cu_optimized="--cu-optimized" in sys.argv))
|
||||
|
||||
@@ -1,521 +0,0 @@
|
||||
"""
|
||||
Pump.fun Token Buy Script with Compute Unit Optimization
|
||||
|
||||
This script is identical to manual_buy.py but adds SetLoadedAccountsDataSizeLimit
|
||||
instruction. By default, Solana transactions can load up to 64MB of account data
|
||||
(costing 16k CU). By setting a lower limit (512KB), we reduce CU consumption and
|
||||
improve transaction priority.
|
||||
|
||||
Key difference from manual_buy.py:
|
||||
- Adds set_loaded_accounts_data_size_limit(512_000) before other instructions
|
||||
|
||||
NOTE: The CU savings from this optimization are NOT visible in transaction "consumed CU"
|
||||
metrics, which only show execution CU. The 16k CU loaded accounts overhead is counted
|
||||
separately for transaction priority/cost calculation. This makes the real impact hard
|
||||
to measure directly, but it improves priority.
|
||||
|
||||
Reference: https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import struct
|
||||
|
||||
import base58
|
||||
import pump_v2
|
||||
import tx_status
|
||||
import websockets
|
||||
from dotenv import load_dotenv
|
||||
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
|
||||
from solders.transaction import Transaction, VersionedTransaction
|
||||
from spl.token.instructions import (
|
||||
create_idempotent_associated_token_account,
|
||||
)
|
||||
|
||||
# Discriminators
|
||||
EXPECTED_DISCRIMINATOR = pump_v2.BONDING_CURVE_DISCRIMINATOR
|
||||
TOKEN_DECIMALS = 6
|
||||
|
||||
# Global constants
|
||||
PUMP_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
|
||||
PUMP_GLOBAL = Pubkey.from_string("4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf")
|
||||
PUMP_EVENT_AUTHORITY = Pubkey.from_string(
|
||||
"Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1"
|
||||
)
|
||||
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")
|
||||
TOKEN_2022_PROGRAM = Pubkey.from_string("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb")
|
||||
SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string(
|
||||
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
|
||||
)
|
||||
SOL = Pubkey.from_string("So11111111111111111111111111111111111111112")
|
||||
LAMPORTS_PER_SOL = 1_000_000_000
|
||||
COMPUTE_BUDGET_PROGRAM = Pubkey.from_string(
|
||||
"ComputeBudget111111111111111111111111111111"
|
||||
)
|
||||
|
||||
load_dotenv()
|
||||
|
||||
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||
RPC_WEBSOCKET = os.environ.get("SOLANA_NODE_WSS_ENDPOINT")
|
||||
|
||||
# logsSubscribe frames exceed the websockets library's 1 MiB default, which
|
||||
# closes the connection with 1009 ("message too big").
|
||||
WEBSOCKET_MAX_MESSAGE_BYTES = 32 * 1024 * 1024
|
||||
|
||||
|
||||
BondingCurveState = pump_v2.BondingCurveState
|
||||
|
||||
|
||||
async def get_pump_curve_state(
|
||||
conn: AsyncClient, curve_address: Pubkey
|
||||
) -> 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("<BI", 4, bytes_limit)
|
||||
return Instruction(COMPUTE_BUDGET_PROGRAM, data, [])
|
||||
|
||||
|
||||
async def buy_token(
|
||||
mint: Pubkey,
|
||||
bonding_curve: Pubkey,
|
||||
associated_bonding_curve: Pubkey,
|
||||
creator_vault: Pubkey,
|
||||
token_program: Pubkey,
|
||||
amount: float,
|
||||
slippage: float = 0.25,
|
||||
max_retries=5,
|
||||
):
|
||||
private_key = base58.b58decode(os.environ.get("SOLANA_PRIVATE_KEY"))
|
||||
payer = Keypair.from_bytes(private_key)
|
||||
|
||||
async with AsyncClient(RPC_ENDPOINT) as client:
|
||||
# Fetch bonding curve state to calculate price and determine fee recipient
|
||||
curve_state = await get_pump_curve_state(client, bonding_curve)
|
||||
token_price_sol = calculate_pump_curve_price(curve_state)
|
||||
token_amount = amount / token_price_sol
|
||||
|
||||
# Determine fee recipient based on whether token uses mayhem mode
|
||||
|
||||
# buy_v2 takes 27 mandatory accounts in a fixed order for every coin.
|
||||
quote_mint = pump_v2.normalize_quote_mint(
|
||||
getattr(curve_state, "quote_mint", None)
|
||||
)
|
||||
quote_unit = pump_v2.quote_units(quote_mint)
|
||||
print(f"Quote asset: {quote_mint}")
|
||||
|
||||
buy_ix = pump_v2.build_buy_v2_instruction(
|
||||
base_mint=mint,
|
||||
creator=curve_state.creator,
|
||||
user=payer.pubkey(),
|
||||
token_amount_raw=int(token_amount * 10**TOKEN_DECIMALS),
|
||||
max_quote_cost_raw=int(amount * quote_unit * (1 + slippage)),
|
||||
quote_mint=quote_mint,
|
||||
base_token_program=token_program,
|
||||
is_mayhem_mode=curve_state.is_mayhem_mode,
|
||||
)
|
||||
idempotent_ata_ix = create_idempotent_associated_token_account(
|
||||
payer.pubkey(), payer.pubkey(), mint, token_program_id=token_program
|
||||
)
|
||||
|
||||
# CU OPTIMIZATION: Limit account data to 512KB (down from 64MB default)
|
||||
# This reduces CU cost from 16k to ~128 CU and improves tx priority.
|
||||
# Must be placed FIRST in the instruction list.
|
||||
# 16MB limit: works for cashback-coin Token-2022 buys on mainnet.
|
||||
# Smaller values (4–8MB) trigger MaxLoadedAccountsDataSizeExceeded for
|
||||
# Token-2022 mints with extensions. Still 4× smaller than the 64MB default.
|
||||
cu_limit_ix = set_loaded_accounts_data_size_limit(16_384_000)
|
||||
|
||||
msg = Message(
|
||||
[cu_limit_ix, set_compute_unit_price(1_000), idempotent_ata_ix, buy_ix],
|
||||
payer.pubkey(),
|
||||
)
|
||||
recent_blockhash = await client.get_latest_blockhash()
|
||||
opts = TxOpts(skip_preflight=True, preflight_commitment=Confirmed)
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
tx_buy = await client.send_transaction(
|
||||
Transaction(
|
||||
[payer],
|
||||
msg,
|
||||
recent_blockhash.value.blockhash,
|
||||
),
|
||||
opts=opts,
|
||||
)
|
||||
tx_hash = tx_buy.value
|
||||
print(f"Transaction sent: https://explorer.solana.com/tx/{tx_hash}")
|
||||
await tx_status.confirm_and_assert(client, tx_hash)
|
||||
print("Transaction confirmed")
|
||||
return # Success, exit the function
|
||||
except tx_status.TransactionRevertedError as e:
|
||||
# The signature is already on chain and reverted. The message and
|
||||
# blockhash below are fixed, so a retry would resubmit identical
|
||||
# bytes and revert identically — stop instead of burning attempts.
|
||||
print(f"Transaction reverted on-chain, not retrying: {e}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Attempt {attempt + 1} failed: {str(e)[:50]}")
|
||||
if attempt < max_retries - 1:
|
||||
wait_time = 2**attempt
|
||||
print(f"Retrying in {wait_time} seconds...")
|
||||
await asyncio.sleep(wait_time)
|
||||
else:
|
||||
print("Max retries reached. Unable to complete the transaction.")
|
||||
|
||||
|
||||
def load_idl(file_path):
|
||||
with open(file_path) as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def calculate_discriminator(instruction_name):
|
||||
sha = hashlib.sha256()
|
||||
sha.update(instruction_name.encode("utf-8"))
|
||||
return struct.unpack("<Q", sha.digest()[:8])[0]
|
||||
|
||||
|
||||
def decode_create_instruction(ix_data, ix_def, accounts):
|
||||
"""Decode create instruction from transaction data."""
|
||||
args = {}
|
||||
offset = 8
|
||||
for arg in ix_def["args"]:
|
||||
t = arg["type"]
|
||||
if t == "string":
|
||||
length = struct.unpack_from("<I", ix_data, offset)[0]
|
||||
offset += 4
|
||||
value = ix_data[offset : offset + length].decode("utf-8")
|
||||
offset += length
|
||||
elif t == "pubkey":
|
||||
value = base58.b58encode(ix_data[offset : offset + 32]).decode("utf-8")
|
||||
offset += 32
|
||||
elif t == "bool" or (isinstance(t, dict) and "defined" in t):
|
||||
# `bool` and `OptionBool` (struct {bool}) both serialize as 1 byte
|
||||
value = bool(ix_data[offset])
|
||||
offset += 1
|
||||
else:
|
||||
raise ValueError(f"Unsupported type: {t}")
|
||||
args[arg["name"]] = value
|
||||
|
||||
args["mint"] = str(accounts[0])
|
||||
args["bondingCurve"] = str(accounts[2])
|
||||
args["associatedBondingCurve"] = str(accounts[3])
|
||||
args["user"] = str(accounts[7])
|
||||
|
||||
return args
|
||||
|
||||
|
||||
async def listen_for_create_transaction():
|
||||
"""Listen for new token creation on pump.fun."""
|
||||
idl_path = os.path.join(os.path.dirname(__file__), "..", "idl", "pump_fun_idl.json")
|
||||
idl = load_idl(idl_path)
|
||||
create_discriminator = calculate_discriminator("global:create")
|
||||
create_v2_discriminator = calculate_discriminator("global:create_v2")
|
||||
|
||||
async with websockets.connect(
|
||||
RPC_WEBSOCKET, max_size=WEBSOCKET_MAX_MESSAGE_BYTES
|
||||
) as websocket:
|
||||
subscription_message = json.dumps(
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "blockSubscribe",
|
||||
"params": [
|
||||
{"mentionsAccountOrProgram": str(PUMP_PROGRAM)},
|
||||
{
|
||||
"commitment": "confirmed",
|
||||
"encoding": "base64",
|
||||
"showRewards": False,
|
||||
"transactionDetails": "full",
|
||||
"maxSupportedTransactionVersion": 0,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
await websocket.send(subscription_message)
|
||||
print(f"Subscribed to blocks mentioning program: {PUMP_PROGRAM}")
|
||||
|
||||
while True:
|
||||
response = await websocket.recv()
|
||||
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"]:
|
||||
if isinstance(tx, dict) and "transaction" in tx:
|
||||
tx_data_decoded = base64.b64decode(
|
||||
tx["transaction"][0]
|
||||
)
|
||||
transaction = VersionedTransaction.from_bytes(
|
||||
tx_data_decoded
|
||||
)
|
||||
|
||||
for ix in transaction.message.instructions:
|
||||
if str(
|
||||
transaction.message.account_keys[
|
||||
ix.program_id_index
|
||||
]
|
||||
) == str(PUMP_PROGRAM):
|
||||
ix_data = bytes(ix.data)
|
||||
discriminator = struct.unpack(
|
||||
"<Q", ix_data[:8]
|
||||
)[0]
|
||||
|
||||
# Check which create instruction was used
|
||||
instruction_name = None
|
||||
token_program = None
|
||||
|
||||
if discriminator == create_discriminator:
|
||||
instruction_name = "create"
|
||||
token_program = SYSTEM_TOKEN_PROGRAM
|
||||
elif (
|
||||
discriminator == create_v2_discriminator
|
||||
):
|
||||
instruction_name = "create_v2"
|
||||
token_program = TOKEN_2022_PROGRAM
|
||||
|
||||
if instruction_name:
|
||||
create_ix = next(
|
||||
instr
|
||||
for instr in idl["instructions"]
|
||||
if instr["name"] == instruction_name
|
||||
)
|
||||
# Skip txs that use Address Lookup Tables — their
|
||||
# instruction account indices reference ALT-loaded keys
|
||||
# not present in transaction.message.account_keys.
|
||||
static_keys = (
|
||||
transaction.message.account_keys
|
||||
)
|
||||
if any(
|
||||
idx >= len(static_keys)
|
||||
for idx in ix.accounts
|
||||
):
|
||||
continue
|
||||
account_keys = [
|
||||
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())
|
||||
@@ -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":
|
||||
|
||||
@@ -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("<Q", 8576854823835016728)
|
||||
BUY_DISCRIMINATOR: Final[bytes] = struct.pack("<Q", 16927863322537952870)
|
||||
EXTEND_ACCOUNT_DISCRIMINATOR: Final[bytes] = bytes(
|
||||
[234, 102, 194, 203, 150, 72, 62, 229]
|
||||
)
|
||||
@@ -135,38 +121,6 @@ def find_creator_vault(creator: Pubkey) -> 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,
|
||||
|
||||
@@ -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("<Q", 16927863322537952870)
|
||||
EXTEND_ACCOUNT_DISCRIMINATOR: Final[bytes] = bytes(
|
||||
[234, 102, 194, 203, 150, 72, 62, 229]
|
||||
)
|
||||
@@ -151,38 +137,6 @@ def find_mayhem_token_vault(mint: Pubkey) -> 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,
|
||||
|
||||
@@ -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("<H", data[offset : offset + 2])[0]
|
||||
parsed_data[field_name] = value
|
||||
@@ -87,6 +101,11 @@ async def get_market_data(market_address: Pubkey):
|
||||
value = data[offset]
|
||||
parsed_data[field_name] = value
|
||||
offset += 1
|
||||
elif field_type == "bool":
|
||||
parsed_data[field_name] = (
|
||||
bool(data[offset]) if len(data) > 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__":
|
||||
|
||||
@@ -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}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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",
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user