Zellular SDK
Dependencies
To use zellular SDK, you’ll need to install the MCL native library. Follow these steps:
sudo apt install libgmp3-dev
wget https://github.com/herumi/mcl/archive/refs/tags/v1.93.zip
unzip v1.93.zip
cd mcl-1.93
mkdir build
cd build
cmake ..
make
make install
Installation
Install the zelluar SDK via pip:
pip install zellular
Usage
Network Architectures
Zellular supports multiple network architectures:
EigenlayerNetwork: For interacting with Zellular deployed on EigenLayer.
StaticNetwork: For local testing or proof-of-authority deployments with a fixed set of operators.
Setting Up With EigenLayer Network
from zellular import Zellular, EigenlayerNetwork
network = EigenlayerNetwork(
subgraph_url="https://api.studio.thegraph.com/query/95922/avs-subgraph/version/latest",
threshold_percent=67
)
app_name = "simple_app"
zellular = Zellular(app_name, network)
Setting Up With Static Network
import json
from zellular import Zellular, StaticNetwork
with open("nodes.json") as f:
nodes_data = json.load(f)
network = StaticNetwork(nodes_data, threshold_percent=67)
app_name = "simple_app"
zellular = Zellular(app_name, network)
Active Operators and Gateway Selection
You can optionally specify a gateway
parameter to connect to a specific operator, or let Zellular select one automatically.
from zellular import Zellular, EigenlayerNetwork
network = EigenlayerNetwork(
subgraph_url="https://api.studio.thegraph.com/query/95922/avs-subgraph/version/latest",
threshold_percent=67
)
zellular_auto = Zellular("simple_app", network)
custom_gateway = "http://your-custom-operator:6001"
zellular_custom = Zellular("simple_app", network, gateway=custom_gateway)
Manually Fetch Active Operators:
import asyncio
from pprint import pprint
from zellular import Zellular, EigenlayerNetwork
network = EigenlayerNetwork(
subgraph_url="https://api.studio.thegraph.com/query/95922/avs-subgraph/version/latest",
threshold_percent=67
)
zellular = Zellular("simple_app", network)
active_operators = asyncio.run(zellular.get_active_operators("simple_app"))
pprint(active_operators)
if active_operators:
random_operator = active_operators[0]
print(f"Selected operator: {random_operator.socket}")
Active operator selection helps:
Find healthy nodes for your application
Ensure operators are running the latest version
Ensure up-to-date consensus state
Posting Transactions
Zellular sequences transactions in batches:
import time
from uuid import uuid4
from zellular import Zellular, EigenlayerNetwork
network = EigenlayerNetwork(
subgraph_url="https://api.studio.thegraph.com/query/95922/avs-subgraph/version/latest",
threshold_percent=67
)
app_name = "simple_app"
zellular = Zellular(app_name, network)
t = int(time.time())
txs = [{"operation": "foo", "tx_id": str(uuid4()), "t": t} for _ in range(5)]
index = zellular.send(txs, blocking=True)
Note
You can add your app to the Zellular test network using:
curl -X POST https://www.zellular.xyz/testnet/apps -H "Content-Type: application/json" -d '{"app_name": "your-app-name"}'
Fetching and Verifying Transactions
Zellular allows trustless reading of finalized transactions using aggregated BLS signatures.
import json
from zellular import Zellular, EigenlayerNetwork
network = EigenlayerNetwork(
subgraph_url="https://api.studio.thegraph.com/query/95922/avs-subgraph/version/latest",
threshold_percent=67
)
app_name = "simple_app"
zellular = Zellular(app_name, network)
for batch, index in zellular.batches(after=0):
txs = json.loads(batch)
for i, tx in enumerate(txs):
print(index, i, tx)
Example output:
app: simple_app, index: 1, result: True
app: simple_app, index: 2, result: True
583 0 {'tx_id': '7eaa...2101', 'operation': 'foo', 't': 1725363009}
...
To start reading from the latest finalized batch:
index = zellular.get_last_finalized()["index"]
for batch, index in zellular.batches(after=index):
...