Bloomr Documentation
website·Indexed 31 days ago
https://docs.bloomr.ioBloomr allows you to stream real-time data directly from the blockchain using JavaScript/TypeScript scripts. The platform provides tools for EVM interaction, including Solidity calls, ABI encoding/decoding, internal transaction traversal, and event log access. Data can be exported via Webhooks, Websockets, or polling. It features a compute-based pricing model using Compute Units (CUs) and supports custom script databases and address lists for tracking large numbers of contracts.
What's inside Bloomr
- Bloomr streams are created by writing JavaScript (specifically TypeScript) scripts that define the information you want to extract. These scripts are hosted and executed directly on Bloomr's infrastructure, removing the need for local development tools, server deployments, or DevOps configuration. Once a script is defined, the resulting data can be consumed via Bloomr's data streaming methods.
Overview of Bloomr for real-time blockchain data streaming
Bloomr is a service that allows developers to stream real-time data directly from EVM-compatible blockchains. Its architecture is designed to simplify the creation of real-time decentralized applications (dApps), often eliminating the need for a dedicated back-end even when implementing complex logic.Access Bloomr script runtime utility functions
Bloomr scripts are executed in a specific runtime environment that provides built-in utility functions. For developers using TypeScript, the environment's type definitions are provided in thebloomr-script.d.tsfile, which allows for type-safe development and autocompletion of the available runtime utilities.Understand the relationship between Solidity and the EVM
The Ethereum Virtual Machine (EVM) is a virtual machine that executes bytecode. While Solidity is the most common language used to write smart contracts, it is not the EVM itself; it is one of several languages (including Vyper and Huff) that compile into EVM bytecode. The EVM is agnostic to the source language. Solidity defines widely adopted conventions for calldata layout, return data layout, and log/event data and topics.Understand Bloomr script execution and filtering
Bloomr executes scripts in response to blockchain events. While scripts can be configured to run for all transactions across all blockchains, using filters allows you to specify the exact conditions under which a script should trigger. Because users pay for script execution time, implementing precise filters is critical for maintaining cost-efficient operations.Choose a method to consume Bloomr data streams
After setting up Bloomr scripts, you can retrieve the emitted data stream using one of three subscription methods: WebSockets for real-time streaming, Webhooks for push notifications, or manual polling for on-demand data retrieval.Interact with smart contracts via transactions
Calling a smart contract is done by sending a transaction to its address. A call can include a quantity of the native token (e.g., Ether) and
calldata. The contract returnsreturndataand a boolean indicating success or failure (failed calls revert all state changes).To call a specific Solidity function, the calldata must contain:
- The function signature (first 5 bytes).
- The function arguments encoded according to the ABI specification.
Identify function calls using decodeCall
Interfaces defined in an ABI expose adecodeCall()method. This is used to analyze calldata to determine which function is being called. It returnsnullif no match is found, or an object containing the methodname,signature, and decodedargs.const { MyInterface: { decodeCall } } = abi<MyAbi>` interface MyInterface { function myFn(uint256 fnArg) external returns (uint256); } `; const result = decodeCall('0xc92e77d2000000000000000000000000000000000000000000000000000000000000002a'); // Result: { name: "myFn", signature: "myFn(uint256)", args: { fnArg : 42n } }Call a smart contract interface
You can define an interface using theabitag and then instantiate it for a specific address using the.at()method to perform Solidity calls from within handlers.const { IERC20 } = abi<MyAbi>` interface IERC20 { function balanceOf(address owner) external view returns (uint256) } `; onTx(tx => { const token = IERC20.at(tx.to); console.log('balance of sender', token.balanceOf(tx.from)); })Define and call non-deployed utility contracts in Bloomr
Use thesoliditytag to define a Solidity contract and interfaces directly within a Bloomr script. Bloomr dynamically compiles these contracts, making them usable as if they were deployed on all blockchains. This is particularly useful for creating helpers that fetch complex on-chain information in the context of the current block.const { IERC20: { Transfer }, Main: { getTokenDetails }, } = solidity<GetTokenData>` pragma solidity ^0.8.15; interface IERC20 { event Transfer(address indexed from, address indexed to, uint256 value); function decimals() external view returns (uint256); function name() external view returns (string memory); } contract Main { function getTokenDetails(IERC20 token) public view returns (uint256 decimals, string memory name) { decimals = token.decimals(); name = token.name(); } } ` // The function getTokenDetails is now callable directly from JS const details = getTokenDetails(tokenAddress);Verify Bloomr webhook signatures
Bloomr signs every webhook message with a private key to ensure authenticity. To verify that an incoming HTTP POST request originated from Bloomr, you should check the message against the public key available in your webhook settings. The signature is provided in thex-signaturerequest header.// Define the public key (replace with the actual public key from your webhook settings) const PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- THE KEY HERE -----END PUBLIC KEY-----`; import express from "express"; import { createVerify } from "crypto"; const app = express(); app.use(express.json()); // To parse requests app.post("/", (req, res) => { const signature = req.headers["x-signature"]; if (!signature || typeof signature !== "string") { return res.status(400).send("Signature required"); } const verifier = createVerify("sha256"); verifier.update(JSON.stringify(req.body)); const isVerified = verifier.verify(PUBLIC_KEY, signature, "base64"); if (isVerified) { console.log("Verified"); // Process the webhook body } else { console.log("Verification failed"); return res.status(401).send("Invalid signature"); } }); const port = 8080; app.listen(port, () => { console.log(`Server listening on port ${port}`); });Manage and use Address Lists in Bloomr scripts
Address lists are collections of addresses or hashes that can be managed via the Bloomr admin panel and accessed within scripts. They are shared across all scripts and filters, allowing for inter-script communication. A key performance benefit is that checking if an address list contains a specific address is free (no cost/gas equivalent), even for lists containing millions of entries.const myList = getAddressList('my list name'); onTx(tx => { // Add an address to the list myList.add(tx.to); // Remove an address from the list myList.delete(tx.to); // Check if an address exists in the list (Free operation) if (myList.has(tx.to)) { // Execute logic } })