> ## 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.

# Cómo usar transactionSubscribe

> Transmite actualizaciones de transacciones de Solana en tiempo real con `transactionSubscribe`. Monitorea la actividad de la blockchain, filtra por cuentas y recibe notificaciones instantáneas.

## ¿Qué es `transactionSubscribe`?

El método WebSocket `transactionSubscribe` (una extensión de Helius para la API WebSocket estándar de Solana) habilita eventos de transacciones en tiempo real.

Para usarlo, proporciona un `TransactionSubscribeFilter` y, si lo deseas, incluye `TransactionSubscribeOptions` para personalizarlo aún más.

`transactionSubscribe` se encuentra en los mismos [puntos de conexión](https://www.helius.dev/docs/api-reference/endpoints) unificados `wss://mainnet.helius-rpc.com` e `wss://devnet.helius-rpc.com` que los métodos de suscripción estándar de Solana.

### `TransactionSubscribeFilter`

* `vote`: indicador booleano para incluir o excluir transacciones relacionadas con votos
* `failed`: indicador booleano para incluir o excluir transacciones fallidas
* `signature`: filtra las actualizaciones de una transacción específica según su firma
* `accountInclude`: lista de cuentas de las que quieres recibir actualizaciones de transacciones. Solo una de las cuentas debe estar incluida en las actualizaciones de transacciones (p. ej., cuenta 1 O 2).
* `accountExclude`: lista de cuentas que quieres excluir de las actualizaciones de transacciones
* `accountRequired`: las transacciones deben incluir todas las cuentas especificadas para aparecer en las actualizaciones (p. ej., cuenta 1 Y 2)
* `tokenAccounts`: expansión opcional de cuentas de tokens asociadas (ATA) (`balanceChanged`, `all` o `none`). Consulta [Monitorear una billetera, incluidas las transferencias de tokens](#monitorear-una-billetera-incluidas-las-transferencias-de-tokens) a continuación.

<Tip>
  Puedes incluir hasta 50,000 direcciones en los arreglos `accountInclude`, `accountExclude` e `accountRequired`.
</Tip>

### TransactionSubscribeOptions (Opcional)

* `commitment`: nivel de compromiso para obtener datos (`processed`, `confirmed` o `finalized`)
* `encoding`: formato de codificación de los datos devueltos (`base58`, `base64` o `jsonParsed`)
* `transactionDetails`: nivel de detalle de los datos devueltos (`full`, `signatures`, `accounts` e `none`)
* `showRewards`: indicador booleano que señala si los datos de recompensas deben incluirse en las actualizaciones
* `maxSupportedTransactionVersion`: especifica la versión más alta de las transacciones de las que quieres recibir actualizaciones. Establece el valor en `1` para recibir transacciones heredadas, v0 y v1. Consulta [Compatibilidad con transacciones v1](/docs/es/rpc/transaction-v1).

<Info>
  `maxSupportedTransactionVersion` es obligatorio para devolver las cuentas y los detalles completos de una transacción determinada (es decir, `transactionDetails: "accounts" | "full"`).
</Info>

## Ejemplo de suscripción a transacciones

En este ejemplo, nos suscribimos a transacciones que contienen la cuenta de Raydium `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8`.

Cuando ocurra una transacción que contenga la cuenta `675k...1Mp8` en el `accountKeys` de la transacción, recibiremos una notificación WSS.

Según las opciones de suscripción, la notificación de la transacción se enviará con el nivel de compromiso `processed`, la codificación `jsonParsed` y los detalles de transacción `full`, y mostrará las recompensas.

<CodeGroup>
  ```javascript theme={"system"}
  const WebSocket = require('ws');

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

  // Function to send a request to the WebSocket server
  function sendRequest(ws) {
      const request = {
          jsonrpc: "2.0",
          id: 420,
          method: "transactionSubscribe",
          params: [
              {
                  accountInclude: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"]
              },
              {
                  commitment: "processed",
                  encoding: "jsonParsed",
                  transactionDetails: "full",
                  showRewards: true,
                  maxSupportedTransactionVersion: 1
              }
          ]
      };
      ws.send(JSON.stringify(request));
  }

  // Function to send a ping to the WebSocket server
  function startPing(ws) {
      setInterval(() => {
          if (ws.readyState === WebSocket.OPEN) {
              ws.ping();
              console.log('Ping sent');
          }
      }, 30000); // Ping every 30 seconds
  }

  // Define WebSocket event handlers

  ws.on('open', function open() {
      console.log('WebSocket is open');
      sendRequest(ws);  // Send a request once the WebSocket is open
      startPing(ws);    // Start sending pings
  });

  ws.on('message', function incoming(data) {
      const messageStr = data.toString('utf8');
      try {
          const messageObj = JSON.parse(messageStr);
          console.log('Received:', messageObj);
      } catch (e) {
          console.error('Failed to parse JSON:', e);
      }
  });

  ws.on('error', function error(err) {
      console.error('WebSocket error:', err);
  });

  ws.on('close', function close() {
      console.log('WebSocket is closed');
  });
  ```
</CodeGroup>

### Notificación de ejemplo

<CodeGroup>
  ```json theme={"system"}
  {
      "jsonrpc": "2.0",
      "method": "transactionNotification",
      "params": {
          "subscription": 4743323479349712,
          "result": {
              "transaction": {
                  "transaction": [
                      "Ae6zfSExLsJ/E1+q0jI+3ueAtSoW+6HnuDohmuFwagUo2BU4OpkSdUKYNI1dJfMOonWvjaumf4Vv1ghn9f3Avg0BAAEDGycH0OcYRpfnPNuu0DBQxTYPWpmwHdXPjb8y2P200JgK3hGiC2JyC9qjTd2lrug7O4cvSRUVWgwohbbefNgKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0HcpwKokfYDDAJTaF/TWRFWm0Gz5/me17PRnnywHurMBAgIAAQwCAAAAoIYBAAAAAAA=",
                      "base64"
                  ],
                  "meta": {
                      "err": null,
                      "status": {
                          "Ok": null
                      },
                      "fee": 5000,
                      "preBalances": [
                          28279852264,
                          158122684,
                          1
                      ],
                      "postBalances": [
                          28279747264,
                          158222684,
                          1
                      ],
                      "innerInstructions": [],
                      "logMessages": [
                          "Program 11111111111111111111111111111111 invoke [1]",
                          "Program 11111111111111111111111111111111 success"
                      ],
                      "preTokenBalances": [],
                      "postTokenBalances": [],
                      "rewards": null,
                      "loadedAddresses": {
                          "writable": [],
                          "readonly": []
                      },
                      "computeUnitsConsumed": 0
                  }
              },
              "signature": "5moMXe6VW7L7aQZskcAkKGQ1y19qqUT1teQKBNAAmipzdxdqVLAdG47WrsByFYNJSAGa9TByv15oygnqYvP6Hn2p",
              "slot": 224341380,
              "transactionIndex": 42
          }
      }
  }
  ```
</CodeGroup>

## Monitorear una billetera, incluidas las transferencias de tokens

Cuando monitoreas una billetera con `accountInclude`, solo se detectan las transacciones en las que la clave pública de la billetera aparece directamente en las claves de cuenta. Un caso frecuente no se detecta: cuando alguien envía un token SPL (por ejemplo, USDC) a la billetera, la transferencia afecta a la **cuenta de token asociada (ATA)** de la billetera, no a su clave pública, por lo que una suscripción básica `accountInclude: [wallet]` nunca la detecta.

Configura el campo `tokenAccounts` para ampliar la detección, de modo que la cuenta monitoreada también coincida con transacciones en las que **posee** un saldo de tokens:

* `balanceChanged`: detecta cuando la billetera posee un saldo de tokens cuyo importe cambió (o cuya cuenta de token se cerró) en la transacción. Úsalo para "avísame cuando el dinero realmente se mueva". Esta es la opción más específica, de menor volumen y más común.
* `all`: detecta cualquier transacción que haga referencia a un saldo de tokens que posee la billetera, incluso si no cambió. Genera un mayor volumen.
* `none`: sin expansión. Equivale a omitir el campo (el valor predeterminado).

La detección se basa en el propietario: abarca cualquier cuenta de token que posea la billetera, incluidas las no canónicas, no solo la dirección ATA derivada. Un valor no válido devuelve el error JSON-RPC `-32602`. Las suscripciones que omiten `tokenAccounts` funcionan exactamente como antes. Para obtener una descripción completa de cómo funciona la expansión de ATA, consulta [Filtrado de cuentas de tokens (ATA) mediante WebSocket](/docs/es/rpc/websocket/token-account-filtering).

```javascript theme={"system"}
const ws = new WebSocket('wss://mainnet.helius-rpc.com/?api-key=<API_KEY>');

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'transactionSubscribe',
    params: [
      {
        accountInclude: ['<WALLET_PUBKEY>'],
        tokenAccounts: 'balanceChanged' // also match the wallet's ATAs
      },
      { commitment: 'confirmed', encoding: 'jsonParsed', maxSupportedTransactionVersion: 1 }
    ]
  }));
  setInterval(() => ws.ping(), 30_000);
});

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  const result = msg.params?.result;
  if (!result) return;
  // Token balances this wallet owns that changed in the tx
  const owned = (result.transaction.meta.postTokenBalances || [])
    .filter((b) => b.owner === '<WALLET_PUBKEY>');
  console.log(result.signature, owned);
});
```

## Monitorear nuevos DCA de Jupiter

Jupiter DCA, o promedio de costo en dólares, es una forma de programar operaciones recurrentes en Solana. Como estas órdenes programadas de compra y venta se registran en la blockchain, los traders pueden usar el método `transactionSubscribe` y [`getAsset`](/docs/es/api-reference/das/getasset) para detectar nuevas órdenes.

<CodeGroup>
  ```javascript theme={"system"}
  const WebSocket = require('ws');   
  const bs58      = require('bs58').default;

  /* ───────────────────── 1.  CONFIG ──────────────────────────── */
  const API_KEY   = process.env.HELIUS_API_KEY || (() => { throw new Error('Set HELIUS_API_KEY'); })();
  const HELIUS_WS  = `wss://mainnet.helius-rpc.com?api-key=${API_KEY}`;
  const HELIUS_RPC = `https://mainnet.helius-rpc.com/?api-key=${API_KEY}`;
  const DCA_PROGRAM_ID = 'DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M';

  /* ───────────────────── 2.  BINARY DECODER ──────────────────── */
  function decodeOpenDcaV2(base58Data) {
    const buf = Buffer.from(bs58.decode(base58Data));
    return {
      appIdx:    buf.readBigUInt64LE(8), // Application Index
      inAmount:  buf.readBigUInt64LE(16), // Input Amount
      perCycle:  buf.readBigUInt64LE(24), // Per Cycle
      interval:  buf.readBigUInt64LE(32) // Interval
    };
  }

  const TOKEN_META = new Map();   // mint → { symbol, decimals }
  /**
   * Fetch symbol & decimals for a mint once then cache.
   * Uses Helius getAsset DAS method: https://www.helius.dev/docs/api-reference/das/getasset
   */
  async function getMeta(mint) {
    if (TOKEN_META.has(mint)) return TOKEN_META.get(mint);

    const body = {
      jsonrpc: '2.0',
      id:      'meow',
      method:  'getAsset',
      params:  { id: mint, displayOptions: { showFungible: true } }
    };

    const { result } = await fetch(HELIUS_RPC, {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify(body)
    }).then(r => r.json());

    const tokenInfo = result.token_info || {};
    const metadata = { symbol: tokenInfo.symbol || '?', decimals: tokenInfo.decimals ?? 0 };
    TOKEN_META.set(mint, metadata);
    return metadata;
  }

  /* ───────────────────── 4.  PRETTY HELPERS ──────────────────── */
  function formatTimestamp(unixSeconds) {
      return new Date(Number(unixSeconds) * 1_000)
               .toISOString()
               .replace('T', ' ')
               .replace('.000Z', ' UTC');
  }
  function formatInterval(seconds) {
      if (seconds % 86_400 === 0) return `every ${seconds / 86_400}d`;
      if (seconds %  3_600 === 0) return `every ${seconds /  3_600}h`;
      if (seconds %     60 === 0) return `every ${seconds /     60}m`;
      return `every ${seconds}s`;
    }

    function formatAmount(raw, decimals, symbol) {
      const ui = Number(raw) / 10 ** decimals;
      return `${ui} ${symbol}`;
    }
  /* ───────────────────── 5.  WEBSOCKET SETUP ─────────────────── */
  const ws = new WebSocket(HELIUS_WS);

  ws.on('open', () => {
    ws.send(JSON.stringify({
      jsonrpc: '2.0',
      id:      1,
      method:  'transactionSubscribe',
      params: [
        { failed: false, accountInclude: [DCA_PROGRAM_ID] },
        {
          commitment: 'confirmed',
          encoding:   'jsonParsed',
          transactionDetails: 'full',
          maxSupportedTransactionVersion: 1
        }
      ]
    }));

    setInterval(() => ws.ping(), 10_000);
  });

  /* ───────────────────── 6.  MAIN MESSAGE HANDLER ────────────── */
  ws.on('message', async raw => {
    const payload = JSON.parse(raw);
    const result  = payload.params?.result;
    if (!result) return;

    // Look for the `OpenDcaV2` log message
    const logs = result.transaction.meta.logMessages || [];
    if (!logs.some(l => l.includes('OpenDcaV2'))) return;

    // loop through all instructions in the transaction to find the DCA instruction
    for (const ix of result.transaction.transaction.message.instructions) {
      if (ix.programId !== DCA_PROGRAM_ID) continue;

      try {
        // 1) decode binary payload
        const d = decodeOpenDcaV2(ix.data);

        // 2) fetch token symbols / decimals (cached)
        const [inMeta, outMeta] = await Promise.all([
          getMeta(ix.accounts[3]),   // input mint
          getMeta(ix.accounts[4])    // output mint
        ]);

        // 3) create a nice looking table
        console.table({
          user:        ix.accounts[2],
          pair:        `${inMeta.symbol} → ${outMeta.symbol}`,
          opened:      formatTimestamp(d.appIdx),
          'total in':  formatAmount(d.inAmount,  inMeta.decimals, inMeta.symbol),
          'per cycle': formatAmount(d.perCycle,  inMeta.decimals, inMeta.symbol),
          interval:    formatInterval(Number(d.interval))
        });
      } catch (e) {}
    }
  });

  ws.on('error', console.error);

  ws.on('close', () => process.exit(1));
  ```
</CodeGroup>

### Notificación de ejemplo

<Frame>
  <img src="https://mintcdn.com/helius/RGuN9Tphu9J_7kRM/images/enhanced-websockets-example-1.png?fit=max&auto=format&n=RGuN9Tphu9J_7kRM&q=85&s=0cbc0eb2c0eecf83b37217011cb9e3c7" alt="Terminal tables of new Jupiter DCA orders showing the user wallet, token pair, open time, total input, amount per cycle, and interval" width="566" height="622" data-path="images/enhanced-websockets-example-1.png" />
</Frame>

## Monitorear nuevos tokens de pump.fun

<CodeGroup>
  ```javascript theme={"system"}
  const WebSocket = require('ws');

  const KEY    = process.env.HELIUS_API_KEY ?? (() => { throw new Error('Set HELIUS_API_KEY'); })();
  const WS_URL = `wss://mainnet.helius-rpc.com?api-key=${KEY}`;
  const PUMP_FUN_PROG = '6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P';

  /* ────────── 2.  OPEN WEBSOCKET & SUBSCRIBE ──────────────────── */
  const ws = new WebSocket(WS_URL);

  ws.on('open', () => {
    ws.send(JSON.stringify({
      jsonrpc : '2.0',
      id      : 1,
      method  : 'transactionSubscribe',
      params  : [
        { failed:false, accountInclude:[PUMP_FUN_PROG] },
        { commitment:'confirmed', encoding:'jsonParsed',
          transactionDetails:'full', maxSupportedTransactionVersion:1 }
      ]
    }));
    // ping every 10 s so we don't get dropped
    setInterval(() => ws.ping(), 10_000);
  });

  /* ────────── 3.  MESSAGE HANDLER ─────────────────────────────── */
  ws.on('message', raw => {
    const payload = JSON.parse(raw);
    const result  = payload.params?.result;
    if (!result) return;

    const logs = result.transaction.meta.logMessages || [];
    // filter for the pump.fun "InitializeMint2" log
    if (!logs.some(l => l.includes('Instruction: InitializeMint2'))) return;

    const sig   = result.signature;    // transaction signature
    const keys  = result.transaction.transaction.message.accountKeys
                               .map(k => k.pubkey);
    //   keys[0] → creator wallet
    //   keys[1] → the new token
    console.table({
      tx:      sig,
      creator: keys[0],
      token:   keys[1]
    });
  });

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

### Notificación de ejemplo

<Frame>
  <img src="https://mintcdn.com/helius/RGuN9Tphu9J_7kRM/images/enhanced-websockets-example-2.png?fit=max&auto=format&n=RGuN9Tphu9J_7kRM&q=85&s=8febc28503381b0da3cd0f1bb40459cb" alt="Terminal tables of newly created pump.fun tokens showing the transaction signature, creator wallet, and token mint address" width="738" height="355" data-path="images/enhanced-websockets-example-2.png" />
</Frame>

## Administrar suscripciones

### Identificadores de suscripción

Cuando `transactionSubscribe` se ejecuta correctamente, el servidor devuelve un identificador de suscripción en el campo `result`. Es el mismo número que aparece en `params.subscription` en cada notificación de esa suscripción:

<CodeGroup>
  ```json Subscribe Response theme={"system"}
  {
    "jsonrpc": "2.0",
    "result": 4743323479349712,
    "id": 420
  }
  ```

  ```json Notification theme={"system"}
  {
    "jsonrpc": "2.0",
    "method": "transactionNotification",
    "params": {
      "subscription": 4743323479349712,
      "result": {}
    }
  }
  ```
</CodeGroup>

Guarda el identificador de suscripción de la respuesta. Lo necesitarás para cancelar la suscripción.

### Cancelar la suscripción

Para dejar de recibir notificaciones, llama a `transactionUnsubscribe` con el identificador de suscripción. Cada llamada a `transactionSubscribe` en la misma conexión crea una suscripción independiente con su propio identificador. Asegúrate de cancelar la suscripción antes de volver a suscribirte para evitar recibir notificaciones duplicadas.

<CodeGroup>
  ```json Request theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 421,
    "method": "transactionUnsubscribe",
    "params": [4743323479349712]
  }
  ```

  ```json Response theme={"system"}
  {
    "jsonrpc": "2.0",
    "result": true,
    "id": 421
  }
  ```
</CodeGroup>

En este ejemplo, nos suscribimos a las transacciones de Raydium, obtenemos el identificador de suscripción de la respuesta del servidor y, luego, cancelamos la suscripción con ese identificador. Es posible que algunos mensajes en tránsito sigan llegando brevemente después de llamar a `transactionUnsubscribe`. Este comportamiento es normal.

<CodeGroup>
  ```javascript theme={"system"}
  const WebSocket = require('ws');

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

  ws.on('open', () => {
      ws.send(JSON.stringify({
          jsonrpc: '2.0',
          id: 420,
          method: 'transactionSubscribe',
          params: [
              { accountInclude: ['675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'] },
              {
                  commitment: 'processed',
                  encoding: 'jsonParsed',
                  transactionDetails: 'full',
                  maxSupportedTransactionVersion: 1,
              },
          ],
      }));
      setInterval(() => ws.ping(), 30000);
  });

  ws.on('message', (data) => {
      const msg = JSON.parse(data.toString());

      // Capture the subscription ID from the subscribe response
      if (msg.id === 420 && msg.result !== undefined) {
          subscriptionId = msg.result;
          console.log('Subscribed, ID:', subscriptionId);
          return;
      }

      // Handle transaction notifications
      if (msg.method === 'transactionNotification') {
          console.log('Received:', msg.params.result.signature);
      }
  });

  function unsubscribe() {
      if (subscriptionId !== null) {
          ws.send(JSON.stringify({
              jsonrpc: '2.0',
              id: 421,
              method: 'transactionUnsubscribe',
              params: [subscriptionId],
          }));
          subscriptionId = null;
      }
  }
  ```
</CodeGroup>
