Skip to content

Smart Contracts Transactions Trackers

About

The service detects smart contract transactions in EVM compatible netwworks, decodes inputs and sends messages with all transaction details to secured RabbitMQ queue.

The queue is perstistant and accessible only for you. Every tracker has own queue. You can consume messages from queue any time when you need. The messages will not be lost.

You can use track smart contracts in networks for which we have own nodes. If we do not support your network then you can use own nodes.

The plans and limits details can be found here.

Getting started

Registration

The email and password is only required to register the account. We will send the email with confirmation link to confirm your email.

The trial plan will be activated right after the email confirmation. The plan will be active during first 14 days from this moment.

You can start to add your first tracker right after login.

Tracker for Built-In Networks

If your smart contract is in the list of networks for which we have our nodes, then you can add tracker here. In this case you will need to provide tracker name and smart contract address. Other fields are optional.

Once tracker is created you can find out all tracker details, by clicking on the tracker name on the Trackers for Built-In Networks page.

The tracker will start txs detections once it will be activated. You can do that be setting the Active check box while tracker creation or editing process.

The tracker will start txs detection from the latest block in the network.

Tracker for Own Nodes

If smart contract is deployed in the network for what we do not have our nodes, then you can use your own node.

The process of adding tracker for own node is almost the same as for trackers for built-in networks.

You also will need to provide the url to your node and period for new block check. The service will validate the node RPC accesibility while adding the tracker.

The period for new block check is in seconds and defines how freaquently the service will check for the new block in your node RPC. It is recommended to set this value less then everage time for the new block inclusion in your network. For example, if it is 12 secs, then block check period can be set to 10 secs.

ABI file

If you will provide the API file of the smart contract that is used in tracker, then the service will decode transactions inputs and include them in RabbitMQ messages.

If the function that is used in detected transaction if not found in the ABI file or was failed to decode the inputs, then decoded inputs will not be added to RabbitMQ messages.

Limits

Max Trackers

The maximum amount of trackers that you can have according to the selected plan.

Max Detected Transactions

Defines the maximum number of transactions that can be detected by every tracker on daily basis. You will get an email with notification if the number of detected txs will be close to 80% of the limit.

The tracker will be automatically disactivated if this limit will be encreased in more then 2 days during 1 month. This will provide enough timeslot for you to be able to change the subscription and will not stop the transactions detections.

Max Queue Size

Defines the maximum number of messages that the tracker queue can persist. If this number will be increased the tracker will be disactivated.

Tracker Disactivation

If tracker was disactivated (manually or automatically) and when it will be activated again it will start transaction detection from the latest block in the network and not from latest synced block. In other words the transactions that were included the network during the period when the tracker was not active will not be detected.

RabbitMQ

The queue is persistant and your messages will not be lost, even if your consumer will be down for some time. The transactions are added to queue with same sequense as they included to blockchain. If the transaction processing sequence is important for you, consume messages from queue one by one.

Connection Details

The RabbitMQ connection details can be found in Tracker details screen under the "RabbitMQ" tab:

RabbitMQ Connection Details

Message Details

{
    "Type": "EIP-1559", // "Legacy" or "EIP-1559"
    "Status": "Success", // "Success" or "Failed"
    "BlockNumber": 5687517,
    "BlockUtc": "2024-04-13T07:13:48Z",
    "TransactionHash": "0x9a8d35df6f3c9e7bd09beaafa02de482d95d0c26bf8cdb74ef15186f9a4c82b3",
    "TransactionIndex": 66,
    "Nonce": "0",
    "GasPrice": "1500433760",
    "GasLimit": "273363",
    "MaxFeePerGas": "1500539271",
    "MaxPriorityFeePerGas": "1500000000",
    "GasUsed": "179649",
    "CumulativeGasUsed": "7135532",
    "EffectiveGasPrice": "1500433760",
    "From": "0xdc2c6350962e0C420700856343D09819c57F97E4",
    "To": "0xaB260022803e6735a81256604d73115D663c6b82",
    "V": "0x1",
    "R": "0xadb99d3f345dd575f62b9fa53571128f8336826ee3b819b3a1f68caa73b11edc",
    "S": "0x59a473ab9308e41bdafe64b80e8e36fb6bd6ca0224739d033cc5dc49b19489ed",
    "Value": "4661526122423083",
    "Input": "0x30abda3f000000000000000000000000dc2c6350962e0c420700856343d09819c57f97e4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010539b4e15432b00000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000012aa678cb881add0237a98e92161e4fc8e8d809071b7b9bf6e7921592b05281900000000000000000000000000000000000000000000000000000000661a3ea100000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000201baa355d2acecc5ea75f1391e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000e0e10000000000000000000000000000000000000000000000000000000000000041bf0b8d0b144ed5513fb5fc9894019b3f729f004dc9b41efa4d7bb9d959979ead1e63fecce12809a4f64467f2425590290f570beafe92c2692aa37867ce06d4071b00000000000000000000000000000000000000000000000000000000000000",
    "FunctionHash": "0x30abda3f",
    "FunctionName": "buyKeysWithPayment",
    "Inputs": {
        "keysSubject": "0xdc2c6350962e0C420700856343D09819c57F97E4",
        "amount": "1",
        "paymentToken": "0x0000000000000000000000000000000000000000",
        "paymentAmount": "4595526122423083",
        "itemIds": [
            "40701809041840400404105000991006"
        ],
        "itemMaxUsers": [
            "57569"
        ],
        "nonce": "8442709949208181651685561496865447168896291973020413678905330572984236451865",
        "deadline": "1712996001",
        "signature": "bf0b8d0b144ed5513fb5fc9894019b3f729f004dc9b41efa4d7bb9d959979ead1e63fecce12809a4f64467f2425590290f570beafe92c2692aa37867ce06d4071b"
    },
    "Logs": [
        {
            "LogIndex": 75,
            "Address": "0x20574d9ccf7b029cc8b18fb4749d61def10f65bf",
            "Data": "0x0000000000000000000000000000000000000000000000000000022ecb25c0000000000000000000000000000000000000000000d720655ed296671373d80000",
            "Topics": [
                "0x6c07ee05dcf262f13abf9d87b846ee789d2f90fe991d495acd7d7fc109ee1f55"
            ]
        },
        {
            "LogIndex": 76,
            "Address": "0xab260022803e6735a81256604d73115d663c6b82",
            "Data": "0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000003691d6afc000000000000000000000000000000000000000000000000000000001a3185c5000000000000000000000000000000000000000000000000000000001a3185c5000000000000000000000000000000000000000000000000000000000000000000112aa678cb881add0237a98e92161e4fc8e8d809071b7b9bf6e7921592b0528190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000",
            "Topics": [
                "0xb400e306993fb63a4ea13da81d56e7ea20a340634136fb0e03d97564eda2f2b7",
                "0x000000000000000000000000dc2c6350962e0c420700856343d09819c57f97e4",
                "0x000000000000000000000000dc2c6350962e0c420700856343d09819c57f97e4"
            ]
        }
    ]
}
  "ContractTx": {
    "type": "object",
    "properties": {
      "type": {
        "type": "string",
        "nullable": true
      },
      "status": {
        "type": "string",
        "nullable": true
      },
      "blockNumber": {
        "type": "integer",
        "format": "int64",
        "nullable": true
      },
      "blockUtc": {
        "type": "string",
        "format": "date-time",
        "nullable": true
      },
      "transactionHash": {
        "type": "string",
        "nullable": true
      },
      "transactionIndex": {
        "type": "integer",
        "format": "int64",
        "nullable": true
      },
      "nonce": {
        "type": "string",
        "nullable": true
      },
      "gasPrice": {
        "type": "string",
        "nullable": true
      },
      "gasLimit": {
        "type": "string",
        "nullable": true
      },
      "maxFeePerGas": {
        "type": "string",
        "nullable": true
      },
      "maxPriorityFeePerGas": {
        "type": "string",
        "nullable": true
      },
      "gasUsed": {
        "type": "string",
        "nullable": true
      },
      "cumulativeGasUsed": {
        "type": "string",
        "nullable": true
      },
      "effectiveGasPrice": {
        "type": "string",
        "nullable": true
      },
      "from": {
        "type": "string",
        "nullable": true
      },
      "to": {
        "type": "string",
        "nullable": true
      },
      "v": {
        "type": "string",
        "nullable": true
      },
      "r": {
        "type": "string",
        "nullable": true
      },
      "s": {
        "type": "string",
        "nullable": true
      },
      "value": {
        "type": "string",
        "nullable": true
      },
      "input": {
        "type": "string",
        "nullable": true
      },
      "functionHash": {
        "type": "string",
        "nullable": true
      },
      "functionName": {
        "type": "string",
        "nullable": true
      },
      "inputs": {
        "type": "object",
        "additionalProperties": {
          "nullable": true
        },
        "nullable": true
      },
      "logs": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/ContractTxLog"
        },
        "nullable": true
      }
    },
    "additionalProperties": false
  },
  "ContractTxLog": {
    "type": "object",
    "properties": {
      "logIndex": {
        "type": "integer",
        "format": "int64",
        "nullable": true
      },
      "address": {
        "type": "string",
        "nullable": true
      },
      "data": {
        "type": "string",
        "nullable": true
      },
      "topics": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "nullable": true
      }
    },
    "additionalProperties": false
  }

Consumer Samples

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;

var connectionString = "connection-string";
var queue = "queue-name";

Console.WriteLine("Connect to queue");

var factory = new ConnectionFactory
{
    Uri = new Uri(connectionString)
};

using (var connection = factory.CreateConnection())
{
    using (var channel = connection.CreateModel())
    {
        channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

        Console.WriteLine("Waiting for messages.");

        var consumer = new EventingBasicConsumer(channel);
        consumer.Received += (model, ea) =>
        {
            byte[] body = ea.Body.ToArray();
            var message = Encoding.UTF8.GetString(body);

            Console.WriteLine(message);

            channel.BasicAck(ea.DeliveryTag, false);
        };

        channel.BasicConsume(queue: queue,
            autoAck: false,
            consumer: consumer);

        Console.WriteLine("Press [enter] to exit.");
        Console.ReadLine();
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

public class RabbitMQConsumer {

    private final static String CONNECTION_STRING = "connection-string";
    private final static String QUEUE_NAME = "queue-name";        

    public static void main(String[] args) throws IOException, TimeoutException {
        System.out.println("Connect to queue");

        ConnectionFactory factory = new ConnectionFactory();
        factory.setUri(CONNECTION_STRING);

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.basicQos(0, 1, false);

        System.out.println("Waiting for messages.");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(message);
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        };

        channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> { });

        System.out.println("Press [enter] to exit.");
        System.in.read();
        channel.close();
        connection.close();
    }
}
import pika
import sys

connection_string = "connection-string"
queue_name = "queue-name"

print("Connect to queue")

parameters = pika.URLParameters(connection_string)
connection = pika.BlockingConnection(parameters)
channel = connection.channel()

channel.basic_qos(prefetch_count=1)
print("Waiting for messages.")

def callback(ch, method, properties, body):
    print(body.decode('utf-8'))
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_consume(queue=queue_name, on_message_callback=callback)

try:
    print("Press [Ctrl+C] to exit.")
    channel.start_consuming()
except KeyboardInterrupt:
    print("Closing connection.")
    channel.stop_consuming()

connection.close()