Solana Streams
Beta

Solana blockchain data
delivered to you

Streams provides near real-time delivery of raw Solana data and sequential backfills pushed directly to your destination.

Backfilling
Streaming historical blocks...

Solana Mainnet

  • Filtered payload

  • Raw payload

    Backfilling
    Indexing Solana transaction...

    Solana Mainnet

    • Filtered payload

    • Raw payload

      Live
      Monitoring accounts...

      Solana Mainnet

      • Filtered payload

      • Raw payload

        Tools to turn raw data into your data

        • 01
        • 02
        • 03
        • 04
        • 05
        • 06
        • 07
        • 08
        • 09
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
          function main(data) {
          try {
          var data = data.streamData;
          const addresses = [
          "O8gFLKB5MbQAFEhE0hjZ4a6BDPv4bcIr5RyWHzyHE6lf",
          "qEXih0ktFgGMZ8QFvRkZJwHEwsBRuWkoejlDHvyDvsKJ",
          "vy66nKHXLDkhpIE4Euz3uMLG5SWID8aFfY5XbgmSrl5z"
          ];
          var addressSet = new Set(addresses.map(address => address.toLowerCase()));
          var paddedAddressSet = new Set(addresses.map(address => '0x' + address.toLowerCase().slice(2).padStart(64, '0')));
          var matchingTransactions = [];
          var matchingReceipts = [];
          data.block.transactions.forEach(transaction => {
          let transactionMatches = (transaction.from && addressSet.has(transaction.from.toLowerCase())) ||
          (transaction.to && addressSet.has(transaction.to.toLowerCase()));
          if (transactionMatches) {
          matchingTransactions.push(transaction);
          }
          });
          data.receipts.forEach(receipt => {
          let receiptMatches = receipt.logs && receipt.logs.some(log =>
          log.topics && log.topics.length > 1 &&
          (paddedAddressSet.has(log.topics[1]) || (log.topics.length > 2 && paddedAddressSet.has(log.topics[2])))
          );
          if (receiptMatches) {
          matchingReceipts.push(receipt);
          }
          });
          if (matchingTransactions.length === 0 && matchingReceipts.length === 0) {
          return null;
          }
          return {
          transactions: matchingTransactions,
          receipts: matchingReceipts
          };
          } catch (e) {
          return {error: e.message};
          }
          }
        Raw payload
        Shape
        Needs transformation
        Size
        20.2MB
        Filtered payload
        Shape
        Valid payload shape
        Size
        1.2MB

        New!

        Filter and Transform your data exactly how you want, cut out what you don't, and optimize costs.

        BETA

        Key-Value Store lets you target and access dynamic lists and sets, updatable from anywhere natively within streams and API.

        walletStore
        <List>
        • 01
        • 02
        • 03
        • 04
        • 05
        • 06
        • 07
        • 08
        • 09
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
          function main(data) {
          var matchingTransactions = [];
          function checkAddress(address) {
          let result = qnContainsListItem("walletStore", address);
          return result;
          }
          data.streamData.block.transactions.forEach(transaction => {
          let transactionMatches = (transaction.from && checkAddress(transaction.from)) ||
          (transaction.to && checkAddress(transaction.to));
          if (transactionMatches) {
          matchingTransactions.push(transaction);
          }
          });
          return matchingTransactions;
          }

        Filters and Key-Value Store usage on Solana Streams increases the delay from the chain tip. For real-time Solana data, we recommend our Yellowstone Geyser gRPC Add-on.

        We focus on infrastructure,
        so you can focus on innovation

        PostgreSQL
        Amazon S3
        Webhook
        Snowflake
        Coming soon
        Coming soon
        Coming soon
        Coming soon
        Coming soon

        Guaranteed delivery to your Webhook, S3 Bucket, Snowflake or Postgres.

        OR

        Use Functions to enrich, process, and run custom code on our scalable serverless platform, enabling workflow creation without additional services.

        • Filtered payload

          • 01
          • 02
          • 03
          • 04
          • 05
          • 06
          • 07
          • 08
          • 09
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
            function main(data) {
            try {
            var data = data.streamData;
            const addresses = [
            "O8gFLKB5MbQAFEhE0hjZ4a6BDPv4bcIr5RyWHzyHE6lf",
            "qEXih0ktFgGMZ8QFvRkZJwHEwsBRuWkoejlDHvyDvsKJ",
            "vy66nKHXLDkhpIE4Euz3uMLG5SWID8aFfY5XbgmSrl5z"
            ];
            var addressSet = new Set(addresses.map(address => address.toLowerCase()));
            var paddedAddressSet = new Set(addresses.map(address => '0x' + address.toLowerCase().slice(2).padStart(64, '0')));
            var matchingTransactions = [];
            var matchingReceipts = [];
            data.block.transactions.forEach(transaction => {
            let transactionMatches = (transaction.from && addressSet.has(transaction.from.toLowerCase())) ||
            (transaction.to && addressSet.has(transaction.to.toLowerCase()));
            if (transactionMatches) {
            matchingTransactions.push(transaction);
            }
            });
            data.receipts.forEach(receipt => {
            let receiptMatches = receipt.logs && receipt.logs.some(log =>
            log.topics && log.topics.length > 1 &&
            (paddedAddressSet.has(log.topics[1]) || (log.topics.length > 2 && paddedAddressSet.has(log.topics[2])))
            );
            if (receiptMatches) {
            matchingReceipts.push(receipt);
            }
            });
            if (matchingTransactions.length === 0 && matchingReceipts.length === 0) {
            return null;
            }
            return {
            transactions: matchingTransactions,
            receipts: matchingReceipts
            };
            } catch (e) {
            return {error: e.message};
            }
            }
        • Filtered payload

          • 01
          • 02
          • 03
          • 04
          • 05
          • 06
          • 07
          • 08
          • 09
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
            function main(data) {
            var matchingTransactions = [];
            function checkAddress(address) {
            let result = qnContainsListItem("walletStore", address);
            return result;
            }
            data.streamData.block.transactions.forEach(transaction => {
            let transactionMatches = (transaction.from && checkAddress(transaction.from)) ||
            (transaction.to && checkAddress(transaction.to));
            if (transactionMatches) {
            matchingTransactions.push(transaction);
            }
            });
            return matchingTransactions;
            }
        • Filtered payload

          • 01
          • 02
          • 03
          • 04
          • 05
          • 06
          • 07
          • 08
          • 09
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
            function main(data) {
            try {
            var data = data.streamData;
            const addresses = [
            "O8gFLKB5MbQAFEhE0hjZ4a6BDPv4bcIr5RyWHzyHE6lf",
            "qEXih0ktFgGMZ8QFvRkZJwHEwsBRuWkoejlDHvyDvsKJ",
            "vy66nKHXLDkhpIE4Euz3uMLG5SWID8aFfY5XbgmSrl5z"
            ];
            var addressSet = new Set(addresses.map(address => address.toLowerCase()));
            var paddedAddressSet = new Set(addresses.map(address => '0x' + address.toLowerCase().slice(2).padStart(64, '0')));
            var matchingTransactions = [];
            var matchingReceipts = [];
            data.block.transactions.forEach(transaction => {
            let transactionMatches = (transaction.from && addressSet.has(transaction.from.toLowerCase())) ||
            (transaction.to && addressSet.has(transaction.to.toLowerCase()));
            if (transactionMatches) {
            matchingTransactions.push(transaction);
            }
            });
            data.receipts.forEach(receipt => {
            let receiptMatches = receipt.logs && receipt.logs.some(log =>
            log.topics && log.topics.length > 1 &&
            (paddedAddressSet.has(log.topics[1]) || (log.topics.length > 2 && paddedAddressSet.has(log.topics[2])))
            );
            if (receiptMatches) {
            matchingReceipts.push(receipt);
            }
            });
            if (matchingTransactions.length === 0 && matchingReceipts.length === 0) {
            return null;
            }
            return {
            transactions: matchingTransactions,
            receipts: matchingReceipts
            };
            } catch (e) {
            return {error: e.message};
            }
            }

        "The outstanding real-time performance helps us deliver the freshest analytics to our users – key to maintaining our competitive edge in the industry."

        Nirmal

        Head of Engineering

        Scalable, serverless, simple. See for yourself in seconds.

        Create a free Stream

        60% Cheaper

        Experience substantial savings compared to conventional methods when handling the same load by using more efficient resource utilization.

        7x Faster

        Achieve faster backfill speeds over traditional backfilling techniques, significantly reducing the time required for data synchronization.

        ~80hrs Saved

        Drastically reduce data engineering hours with automatic routing to your data warehouses, streamlining your workflows in seconds.