> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Cara Menggunakan preprocessedSubscribe

> Streaming transaksi Solana praproses melalui WebSocket dengan metode preprocessedSubscribe — berlangganan, filter berdasarkan akun, dan dekode payload biner.

<Note>
  **Beta Publik.** `preprocessedSubscribe` tersedia pada **semua paket berbayar**
  dan dihitung sebesar **0,1 kredit per pesan** (satu pesan per transaksi yang
  dikirimkan).
</Note>

## Apa itu `preprocessedSubscribe`?

`preprocessedSubscribe` adalah metode WebSocket Helius yang melakukan streaming transaksi praproses — transaksi Solana praeksekusi yang dikirimkan **sebelum mencapai tingkat komitmen `processed`**. Helius menggabungkan beberapa sumber praeksekusi — terutama shred yang didekode langsung saat tiba di validator, dilengkapi dengan sinyal [prakonfirmasi](/docs/id/pre-confirmations/overview) — dan mengirimkannya sebagai satu aliran pesan biner ringkas yang telah dideduplikasi, tanpa memerlukan infrastruktur deshredding di sisi Anda.

Transaksi yang bersumber dari sinyal prakonfirmasi tiba lebih lambat di feed ini dibandingkan di produk khusus [Preconfirmations](/docs/id/pre-confirmations/overview), yang tetap menyediakan akses paling awal ke transaksi tersebut.

Ini adalah penerus produk preprocessed LaserStream (gRPC) sebelumnya. Jika saat ini Anda menggunakan transaksi praproses melalui gRPC, beralihlah ke metode ini — metode ini mengirimkan kelas data yang sama melalui koneksi WebSocket biasa dengan latensi lebih rendah, dan pengiriman melalui gRPC akan dihentikan secara bertahap.

| Aliran                                                                             | Waktu relatif                                          | Cakupan                                                       | Data                                                                                                             |
| ---------------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| [Preconfirmations](/docs/id/pre-confirmations/overview)                                 | Paling awal                                            | Transaksi yang dijadwalkan oleh validator yang berpartisipasi | Transaksi dan status eksekusi (khusus prakonfirmasi Helius; prakonfirmasi BAM melaporkan status tidak diketahui) |
| `preprocessedSubscribe`                                                            | Biasanya setelah Preconfirmations, sebelum `processed` | Cakupan transaksi Solana yang luas                            | Transaksi bertanda tangan sebelum eksekusi                                                                       |
| [`transactionSubscribe`](/docs/id/rpc/websocket/transaction-subscribe) pada `processed` | Setelah eksekusi                                       | Transaksi yang telah diproses                                 | Transaksi dengan metadata eksekusi                                                                               |

<Warning>
  `preprocessedSubscribe` adalah **sinyal praeksekusi yang bersifat upaya terbaik**, bukan
  tingkat komitmen. Transaksi yang dialirkan dapat gagal, dihapus, atau masuk ke
  fork yang berbeda. Cocokkan dengan aliran yang telah diproses atau dikonfirmasi sebelum
  menganggapnya final.
</Warning>

## Titik akhir

`preprocessedSubscribe` disediakan dari `wss://beta.helius-rpc.com` — titik akhir Helius Gatekeeper — bukan dari `mainnet.helius-rpc.com`. Lakukan autentikasi menggunakan kunci API Anda sebagai parameter kueri:

```
wss://beta.helius-rpc.com/?api-key=<API_KEY>
```

Setiap kunci API dibatasi hingga **10 koneksi/langganan bersamaan**.

## Berlangganan

Kirim permintaan JSON-RPC dengan metode `preprocessedSubscribe`. `params` memuat filter akun dan wajib disertakan — `accountInclude` dan `accountRequired` harus menentukan setidaknya satu akun di antara keduanya (lihat [Pemfilteran](#pemfilteran)):

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preprocessedSubscribe",
  "params": {
    "accountInclude": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
    "accountExclude": [],
    "accountRequired": []
  }
}
```

Server mengonfirmasi langganan dengan frame teks JSON yang berisi ID langganan:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "result": 1,
  "id": 1
}
```

Setelah konfirmasi ini, pembaruan transaksi tiba sebagai frame WebSocket **biner** — lihat [Payload notifikasi](#payload-notifikasi).

## Pemfilteran

Setiap langganan dibatasi oleh filter akun di `params`. Pemfilteran dilakukan di sisi server sehingga Anda hanya menerima transaksi yang relevan:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preprocessedSubscribe",
  "params": {
    "accountInclude": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
    "accountExclude": ["Vote111111111111111111111111111111111111111"],
    "accountRequired": []
  }
}
```

| Filter            | Perilaku pencocokan                                                      |
| ----------------- | ------------------------------------------------------------------------ |
| `accountInclude`  | Cocok jika transaksi mereferensikan **salah satu** akun yang tercantum.  |
| `accountExclude`  | Hapus transaksi jika mereferensikan **salah satu** akun yang tercantum.  |
| `accountRequired` | Hanya cocok jika transaksi mereferensikan **semua** akun yang tercantum. |

Aturan filter:

* Ketiga filter digabungkan dengan logika AND.
* `accountInclude` dan `accountRequired` harus menentukan **setidaknya satu akun** di antara keduanya — tidak ada aliran penuh tanpa filter.
* Akun adalah kunci publik yang dikodekan dengan base58. Setiap daftar menerima hingga **5.000** alamat.

### Resolusi tabel pencarian alamat (ALT)

Filter akun mencocokkan lebih dari sekadar kunci akun statis transaksi — Helius menyelesaikan [tabel pencarian alamat](/docs/id/glossary#address-lookup-table-alt) di sisi server, sehingga `accountInclude`, `accountExclude`, dan `accountRequired` juga mencocokkan akun yang dimuat transaksi melalui ALT. Cukup berikan kunci publik akun tersebut; Anda tidak perlu memelihara pemetaan ALT atau menyelesaikan tabel sendiri.

## Payload notifikasi

Notifikasi dikirimkan sebagai frame WebSocket **biner** (bukan JSON). Setiap frame memuat satu transaksi dalam tata letak byte yang dipadatkan:

| Byte | Bidang        | Tipe                  | Deskripsi                                                                                              |
| ---- | ------------- | --------------------- | ------------------------------------------------------------------------------------------------------ |
| 0    | `version`     | `u8`                  | Versi skema payload. Saat ini `1`.                                                                     |
| 1–8  | `slot`        | `u64` (little-endian) | Slot tempat transaksi diamati.                                                                         |
| 9–72 | `signature`   | 64 byte               | Tanda tangan pertama transaksi, dalam format biner.                                                    |
| 73+  | `transaction` | `bytes`               | Transaksi bertanda tangan dalam format wire Solana. Lihat [Mendekode transaksi](#mendekode-transaksi). |

Baca prefiks tetap sepanjang 73 byte secara berurutan, lalu dekode byte yang tersisa untuk membaca instruksi, akun, dan pencarian tabel alamat. Tanda tangan disertakan dalam prefiks agar Anda dapat mengidentifikasi dan mendeduplikasi transaksi tanpa mendekode seluruh isi transaksi.

Selalu baca dan periksa byte `version` terlebih dahulu. Jika Helius perlu memperbarui format payload, versinya akan bertambah — buat percabangan berdasarkan versi tersebut agar dekoder Anda tetap berfungsi saat skema berubah.

### Mendekode transaksi

Byte transaksi diteruskan persis seperti yang diamati di jaringan, dalam pengodean wire standar untuk versi transaksi tersebut. Transaksi lama dan v0 menggunakan tata letak yang menempatkan tanda tangan di awal, seperti yang dihasilkan oleh `bincode`. Transaksi v1 ([SIMD-0385](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md)) menggunakan tata letak yang menempatkan pesan di awal dan tanda tangan di akhir, sehingga `bincode` gagal pada payload v1. Gunakan dekoder yang menangani setiap versi:

* **Rust:** [`agave-transaction-view`](https://docs.rs/agave-transaction-view) mengurai transaksi lama, v0, dan v1 secara langsung tanpa salinan perantara. Ini adalah opsi yang direkomendasikan. [`wincode`](https://docs.rs/wincode), serializer kompatibel bincode yang digunakan oleh SDK Solana saat ini, juga mendekode v1 menjadi `VersionedTransaction`.
* **JavaScript / TypeScript:** pastikan versi pustaka Anda mendukung transaksi v1. Implementasi `VersionedTransaction.deserialize` yang lebih lama hanya menangani transaksi lama dan v0. Gunakan `@solana/kit` 8.0+ atau `@solana/web3.js` v3. Lihat [Dukungan transaksi v1](/docs/id/rpc/transaction-v1).

```rust theme={"system"}
use agave_transaction_view::transaction_view::TransactionView;

// `frame` is the full binary WebSocket message
let tx_bytes = &frame[73..];
let tx = TransactionView::try_new_unsanitized(tx_bytes)?;

println!("version: {:?}", tx.version()); // Legacy, V0, or V1
for ix in tx.instructions_iter() {
    println!("program index {}: {} bytes", ix.program_id_index, ix.data.len());
}
```

## Contoh

```javascript theme={"system"}
const WebSocket = require('ws');
const bs58module = require('bs58');
const bs58 = bs58module.default ?? bs58module;

const ws = new WebSocket('wss://beta.helius-rpc.com/?api-key=<API_KEY>');

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'preprocessedSubscribe',
    // Only Jupiter v6 transactions — accountInclude/accountRequired must
    // specify at least one account between them.
    params: {
      accountInclude: ['JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'],
      accountExclude: [],
      accountRequired: []
    }
  }));

  // Keep the connection alive
  setInterval(() => ws.ping(), 30_000);
});

ws.on('message', (data, isBinary) => {
  // The subscribe acknowledgement arrives as a JSON text frame
  if (!isBinary) {
    const msg = JSON.parse(data.toString());
    if (msg.id === 1) console.log('Subscribed, ID:', msg.result);
    return;
  }

  // Notifications arrive as binary frames:
  // version (u8) | slot (u64 LE) | signature ([u8; 64]) | transaction bytes
  const buf = Buffer.from(data);
  const version = buf.readUInt8(0); // currently 1 — branch on this if it changes
  if (version !== 1) return; // unknown schema version; update your decoder
  const slot = buf.readBigUInt64LE(1);
  const signature = bs58.encode(buf.subarray(9, 73));
  const txBytes = buf.subarray(73); // transaction in Solana wire format (legacy, v0, or v1)

  console.log('Preprocessed transaction:', { slot, signature, bytes: txBytes.length });
  // Decode txBytes with a decoder that supports transaction v1 (see "Decoding the transaction")
});

ws.on('error', console.error);
ws.on('close', () => process.exit(1));
```

## Data apa yang tersedia?

Setiap notifikasi memuat transaksi bertanda tangan, tanda tangan pertamanya, dan slot-nya. Karena pengiriman dilakukan sebelum eksekusi, aliran ini **tidak** menyertakan:

* Status atau kesalahan eksekusi
* Saldo sebelum/sesudah atau perubahan saldo token
* Pesan log atau instruksi internal
* Unit komputasi yang digunakan

Anggap ini seperti menerima "proposal" tanpa "hasil" — Anda melihat apa yang berusaha dilakukan pengirim, tetapi bukan apa yang benar-benar terjadi. Pembaruan status akun dan program juga belum ada pada tahap ini; jika Anda memerlukan status akun secara waktu nyata, gunakan [LaserStream gRPC](/docs/id/laserstream) pada komitmen `processed`.

## Tekanan balik

Aliran tidak menyimpan data dalam buffer tanpa batas untuk konsumen yang lambat. Jika klien Anda membaca terlalu lambat dan lebih dari **4.000 pesan** menumpuk di sisi server, Helius akan menutup koneksi — Anda menerima frame penutupan WebSocket yang normal. Kosongkan frame lebih cepat daripada laju kedatangannya: jangan jalankan pekerjaan berat seperti pendekodean transaksi dan logika strategi dalam loop penerimaan, lalu hubungkan kembali dan berlangganan ulang setelah koneksi terputus.

## Jaminan pengiriman

Pengiriman bersifat upaya terbaik, tidak dijamin, dan tidak ada pemutaran ulang historis. Klien sebaiknya:

1. Menghubungkan kembali dan berlangganan ulang setelah koneksi ditutup.
2. Mendeduplikasi berdasarkan tanda tangan transaksi.
3. Memperlakukan slot sebagai pengamatan, bukan finalitas.
4. Mencocokkan dengan aliran yang telah diproses atau dikonfirmasi jika hasil eksekusi penting.

## Harga

`preprocessedSubscribe` tersedia pada **semua paket berbayar** dan dihitung sebesar **0,1 kredit per pesan** — satu pesan per transaksi yang dikirimkan, ditagihkan dari paket Anda. Lihat [Kredit](/docs/id/billing/credits) untuk detailnya.

## Terkait

<CardGroup cols={2}>
  <Card title="Preconfirmations" icon="bolt" href="/docs/id/pre-confirmations/overview">
    Transaksi yang dialirkan sebelum menjadi shred — sinyal transaksi paling awal.
  </Card>

  <Card title="Raw Shreds (UDP)" icon="network-wired" href="/docs/id/shred-delivery/raw-shreds">
    Paket shred yang belum diproses melalui UDP. Anda mengimplementasikan deshredding.
  </Card>

  <Card title="transactionSubscribe" icon="tower-broadcast" href="/docs/id/rpc/websocket/transaction-subscribe">
    Transaksi pascaeksekusi dengan pemfilteran lengkap dan metadata eksekusi.
  </Card>
</CardGroup>
