Skip to main content

ConseilPy

PyPI version Build Status Made With License: MIT

Python toolkit for Conseil blockchain indexer

Installation

Python 3.6+ required

$ pip install conseil

Usage

ConseilPy is a lot like Sqlalchemy, so if you're familiar with it, you can easily cook queries.

It's time to cook

Quickstart

Get top 5 delegators by balance

from conseil import conseil

Account = conseil.tezos.alphanet.accounts
Account.query(Account.acccount_id, Account.balance) \
    .filter(Account.script.is_(None), 
            Account.account_id.startswith('KT1')) \
    .order_by(Account.balance.desc()) \
    .limit(5) \
    .all()

See more examples

Client initialization

If using a default conseil client is not an option you can instantiate it yourself:

from conseil.api import ConseilApi
from conseil.core import Client

conseil = Client(ConseilApi(
    api_key='<API_KEY>',
    api_host='<API_HOST>',
    api_version=2
))

Exploring database schema

Conseil metadata has the following tree structure:
platform / network / entity / attribute / value

So you can simply access any node by name:

>>> from conseil import conseil
>>> print(conseil.tezos.alphanet.operations.kind.transaction)
transaction

Autocompletion Shift + Tab and docstrings are available in Jupyter:

>>> conseil
Path
metadata/platforms

Platforms
.tezos

>>> conseil.tezos.alphanet
Path
metadata/tezos/alphanet/entities

Entities
.accounts
.balance_updates
.ballots
.blocks
.delegates
.fees
.operation_groups
.operations
.proposals
.rolls

Alternatively you can check full SQL schema

Selecting fields

Conseil doesn't support joins at the moment so you can request attributes for a single entity only.

from conseil import conseil

c = conseil.tezos.alphanet

# select all fields
c.query(c.accounts)
c.accounts.query()

# select specific fields
c.query(c.accounts.balance, c.accounts.account_id)
c.accounts.query(c.accounts.balance, c.accounts.account_id)

# select single field
c.accounts.balance.query()

Filtering results

Conseil receives a conjunction of predicates, which can be inverted by one, but not together. Predicate syntax is similar to Sqlalchemy, but has less operations.

from conseil import conseil
from conseil.core import not_

Account = conseil.tezos.alphanet.accounts
Account.query() \
    .filter(not_(Account.account_id.startswith('tz')),
            Account.script.is_(None),
            Account.balance > 0)

Here is a full list of supported operations:

Conseil operation Filter Inversed
in x.in_(a, b, ...) x.notin_(a, b, ...)
between x.between(a, b) not_(x.between(a, b))
like x.like(a) x.notlike(a)
lt x < a x >= a
gt x > a x <= a
eq x == a x != a
startsWith x.startswith(a) not_(x.startsWith(a))
endsWith x.endswith(a) not_(x.endswith(a))
isnull x.is_(None) x.isnot(None)

You can also use filter_by for simple queries:

from conseil import conseil

conseil.tezos.alphanet.accounts.query() \
    .filter_by(account_id='tzkt')

Data aggregation

This is an important concept to understand. In Conseil you specify which columns will be aggregated and the rest of them are used in GROUP BY clause. Here is an example:

from conseil import conseil

Block = conseil.tezos.alphanet.blocks
Block.query(Block.baker, Block.level.count(), Block.timestamp.max())  
# will be compiled to SELECT baker, COUNT(level), MAX(timestamp) FROM blocks GROUP BY baker

Additionally, you can specify HAVING predicates if you want to filter results by aggregated column:

from conseil import conseil

Block = conseil.tezos.alphanet.blocks
Block.query(Block.baker, Block.level.count()) \
    .having(Block.level.count() > 1)  # you have to specify aggregation function here as well

Here is the list of supported aggregation functions:

  • count
  • sum
  • avg
  • min
  • max

If you want to group by some fields but not include them in the result use group_by method:

from conseil import conseil

Block = conseil.tezos.alphanet.blocks
Block.query(Block.level.count()) \
	.group_by(Block.baker)

Sorting and limiting results

This is similar to Sqlalchemy as well, you can specify one or multiple sort columns with optional descending modifier.

from conseil import conseil

Account = conseil.tezos.alphanet.accounts
Account.query() \
    .order_by(Account.balance.desc(), Account.account_id) \
    .limit(20)

You can sort by aggregated column too:

from conseil import conseil

Operation = conseil.tezos.alphanet.operations
Operation.query(Operation.source, Operation.amount.avg()) \
    .order_by(Operation.amount.avg().desc()) \
    .limit(50)

Query preview

So you have cooked a simple query and want to see the resulting Conseil request body.

from conseil import conseil

Account = conseil.tezos.alphanet.accounts
query = Account.query() \
    .order_by(Account.balance.desc()) \
    .limit(1)

Then you can simply:

>>> query
Path
data/tezos/alphanet/accounts

Query
{"aggregation": [],
 "fields": [],
 "limit": 1,
 "orderBy": [{"direction": "desc", "field": "balance"}],
 "output": "json",
 "predicates": []}

Execution

It's time to submit our query and get some data.

from conseil import conseil

Account = conseil.tezos.alphanet.accounts

Return multiple rows

query = Account.query()

query.all()  # will return List[dict] (default output type)
query.all(output='csv')  # will return string (csv)

Return single row

query = Account.query() \
	.filter_by(account_id='tzkt')

query.one()  # will fail if there is no account with such id or there are many
query.one_or_none()  # will handle the exception and return None

Return scalar

query = Account.balance.query() \
	.order_by(Account.balance.desc()) \
    .limit(1)

query.scalar()  # will return single numeric value

Return vector

query = Operation.query(Operation.timestamp) \
    .filter_by(source='tzkt')
    
query.vector()  # will return flat list of timestamps

Precision

Conseil allows to specify numeric column precision. In order to use this functionality use decimal type. For example:

from conseil import conseil
from decimal import Decimal

Account = conseil.tezos.alphanet.accounts
Account.query(Account.balance) \
    .filter(Account.balance > Decimal('0.1'), 
            Account.balance < Decimal('0.01'))  # precision will be 2 (max)

Renaming fields

You can change names of requested fields in the resulting json/csv:

from conseil import conseil

Account = conseil.tezos.alphanet.accounts
Account.query(Account.account_id.label('address'))

Metadata

Release files for conseil 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for conseil 0.1.4
File Size Uploaded Provenance
conseil-0.1.4.tar.gz 12.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for conseil 0.1.4
File Interpreter ABI Platform
conseil-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 23.1 kB

Release files / conseil-0.1.4.tar.gz

Download URL conseil-0.1.4.tar.gz
Size 12.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a3b2b6de5003c18c66090bdff2e7f27914e79373df716d2314ab3244623d8333
BLAKE2b-256 checksum
How to use checksums
3343f5b0746c979748144b9226b6f42bb70e7f3f2f6801744ce8aeb7014d1672
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/0.12.17 CPython/3.7.0 Linux/4.15.0-54-generic

Release files / conseil-0.1.4-py3-none-any.whl

Download URL conseil-0.1.4-py3-none-any.whl
Size 10.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c87d0cd0104086535d70574ab70acb0a995ddf4889da747b1738e081235f9c0f
BLAKE2b-256 checksum
How to use checksums
f7767da787c8f2a62a1bde6d06720499c090c5672c6ce39f08c3597dcf5d75c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/0.12.17 CPython/3.7.0 Linux/4.15.0-54-generic

Security for conseil 0.1.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page