Skip to main content

Multicall batching middleware for asynchronous scripts using web3.py

Project description

Dank Mids

PyPI Monthly Downloads

Dank Mids is a EVM RPC batching library that helps reduce the number of HTTP requests to a node, saving time and resources. It automatically collects eth_call calls into multicalls and bundles all RPC calls together in jsonrpc batch calls.

tl;dr: its fast as fuck.

image

The goal of this tool is to reduce the workload on RPC nodes and allow users to make calls to their preferred node more efficiently. This optimization is especially useful for developers writing scripts that perform large-scale blockchain analysis, as it can save development time and resources.

Why is Dank so fast?

There are a number of optimizations that went into making Dank the fastest way to pull rpc data to Python.

  1. Implemented (mostly) in C.
  2. Bypasses the default formatters in web3.py
  3. JSON encoding and decoding is handled by msgspec. All responses are decoded to specialized msgspec.Struct objects defined in the evmspec library.
  4. We use my C-compiled faster-eth-abi and faster-eth-utils instead of the original python implementations eth-abi and eth-utils.
  5. Responses are decoded on a JIT (just-in-time) basis, meaning individual task cancellation works as expected even when response data is received as part of a larger batch.
  6. more stuff I'll write down later...

Batching Flow

This diagram shows how requests move from user calls into Dank Mids queues, then through batch execution and response spoofing.

flowchart TD
    A[User code<br/>await w3.eth.call / other RPC] --> B[DankMiddlewareController.__call__]

    B -->|eth_call| C[eth_call request]
    B -->|other RPC| D[RPCRequest]

    C -->|multicall compatible| E[pending_eth_calls<br/>block to Multicall]
    C -->|no multicall| D
    D --> F[pending_rpc_calls<br/>JSONRPCBatch queue]

    E --> G[RPCRequest.get_response<br/>triggers execute_batch when needed]
    F --> G

    G --> H[DankMiddlewareController.execute_batch]
    H --> I[DankBatch<br/>multicalls + rpc_calls]
    I --> J[DankBatch.coroutines]

    J -->|large multicall| K[Multicall.get_response]
    J -->|small multicall split| L[JSONRPCBatch]
    J -->|rpc calls| L

    K --> M[_requester.post<br/>eth_call to multicall contract]
    M --> N[Multicall.spoof_response<br/>split results to eth_call futures]

    L --> O[JSONRPCBatch.post<br/>build JSON-RPC batch payload]
    O --> P[_requester.post batch<br/>+ decode responses]
    P --> Q[JSONRPCBatch.spoof_response<br/>match by id, resolve futures]

    N --> R[User awaiters resolve]
    Q --> R

Notes:

  • Batches can start early when the queue is full (_Batch.append -> controller.early_start).
  • Otherwise, the first waiter to need results will trigger execute_batch from RPCRequest.get_response.

Installation

To install Dank Mids, use pip:

pip install dank-mids

Development and Contributing

This repository uses pre-commit for local commit-time checks. Setup and usage instructions live in CONTRIBUTING.md.

Benchmark

We've included a benchmark script that compares the time it takes to fetch the pool tokens (token0 and token1) for each pool on Sushiswap on Ethereum mainnet. To run it, first install the repo with uv sync and then run the benchmark with uv run brownie run examples/benchmark.

Running 'examples/benchmark.py::main'...
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4213/4213 [08:50<00:00,  7.95it/s]
brownie sync end: 2025-04-14 21:21:35.531099
brownie sync took: 0:08:50.212665
brownie 4 threads start: 2025-04-14 21:21:35.548373
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4213/4213 [08:31<00:00,  8.23it/s]
brownie 4 threads end: 2025-04-14 21:30:08.065397
brownie 4 threads took: 0:08:32.517024
brownie 16 threads start: 2025-04-14 21:30:08.086342
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4213/4213 [08:26<00:00,  8.32it/s]
brownie 16 threads end: 2025-04-14 21:38:38.141635
brownie 16 threads took: 0:08:30.055293
dank start: 2025-04-14 21:38:38.161024
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4213/4213 [00:55<00:00, 75.49it/s]
dank end: 2025-04-14 21:39:33.982835
dank took: 0:00:55.821811

As you can see, dank_mids allowed us to save 7 minutes and 34 seconds vs brownie with 16 threads. That's an 89% reduction in runtime, or about 9x as fast as brownie!

Usage with web3.py

The primary function you need to use Dank Mids is setup_dank_w3_from_sync. This function takes a sync Web3 instance and wraps it for async use. If using dank_mids with eth-brownie, you can just import the premade dank_web3 object as well

Example usage of Dank Mids with web3py:

from dank_mids.helpers import setup_dank_w3_from_sync
dank_web3 = setup_dank_w3_from_sync(w3)
# OR
from dank_mids import dank_web3

# Then:
random_block = await dank_web3.eth.get_block(123)

Usage with eth-brownie

Usage with ape

  • COMING SOON: Dank Mids will also work with ape.

Observability (Retry Events)

Dank Mids exposes a retry observer API for capturing retry decisions, plus a stats observer for collector metrics. Internal emit points are deferred to a follow-up PR. For the full explanation and examples (structured logging, Prometheus, Sentry/Stats), see docs/retry_observer.rst.

Testimonials

Yearn big brain Tonkers Kuma had this to say:

image

Notes

You can also set DANK_MIDS_DEMO_MODE=True to see a visual representation of the batching in real time on your console.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dank_mids-4.20.210.tar.gz (184.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

dank_mids-4.20.210-cp313-cp313-win_amd64.whl (877.8 kB view details)

Uploaded CPython 3.13Windows x86-64

dank_mids-4.20.210-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

dank_mids-4.20.210-cp313-cp313-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

dank_mids-4.20.210-cp312-cp312-win_amd64.whl (876.7 kB view details)

Uploaded CPython 3.12Windows x86-64

dank_mids-4.20.210-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

dank_mids-4.20.210-cp312-cp312-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

dank_mids-4.20.210-cp311-cp311-win_amd64.whl (869.6 kB view details)

Uploaded CPython 3.11Windows x86-64

dank_mids-4.20.210-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

dank_mids-4.20.210-cp311-cp311-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

dank_mids-4.20.210-cp310-cp310-win_amd64.whl (870.1 kB view details)

Uploaded CPython 3.10Windows x86-64

dank_mids-4.20.210-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

dank_mids-4.20.210-cp310-cp310-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file dank_mids-4.20.210.tar.gz.

File metadata

  • Download URL: dank_mids-4.20.210.tar.gz
  • Upload date:
  • Size: 184.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dank_mids-4.20.210.tar.gz
Algorithm Hash digest
SHA256 08ae9621121218d1c0af7e99efa77488b17507ca92f0b7372bb5bf43b1b981dc
MD5 d968f3a7855be17c1a62d1e444bea052
BLAKE2b-256 dd59ac9ba05bc7427966e231bcc2fc5df74f4acb0292926ad51be6ad4220576b

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 81db9fcd1ceea034e726343c7d227e939e8824ee1fb79c2c64b4b580ab3a47ac
MD5 e5c372fc22322f7d92efbc8900bcb219
BLAKE2b-256 7b0c0cde4a8279553e8b32f4548b2b9d4601e58fec1d7ae77eed51e344777f87

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4e3941f75465460c18b891e4d4a8240519e7ab1212714f53dc8dd8d81d01519a
MD5 c7a1187533621679feaff89e84c83dd8
BLAKE2b-256 54c09e1c4ddb7db3f7e36a80ad0e1e805ed33bd34ab005314d879a18e7e15af5

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c1a889ee59d47548075484753e000cbe35b2e2e46405c0c9b1c7c8c7045d65b0
MD5 544aaccd514fca32773bdb12edaa6f9d
BLAKE2b-256 793e80a9d7a00b42005528e37f85d6e3233bb0dd93f10050fa421227c0b04d9e

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 542b78a55ba2316b3040aadd3cd7ce7e957c5239daa11ff7cc4d300dc9334166
MD5 c6fea54e810e0a48cb79920dde1310b1
BLAKE2b-256 6c13cc2827b5926c10f6479cca8eb04df9f45f9cfdc7dd508a070efb86b4033e

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 22fba69ece9c9d5bb3a2a432639c8ac594d71c933a6b42d842bd746a6f35ca1c
MD5 dbdbcbf0cd1515f0520171b79bb4a6f3
BLAKE2b-256 af4ab9d5a9dd6f97588b5567b7696fe58b2681a65a2e8f54662ffaa0396de80a

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 be2079d342972b2d5bba2cf19a9ca768b0b0ed281aab6244b0f6efc6df2b99dc
MD5 171cede903b3b1d525427d7275f240d4
BLAKE2b-256 13fd09a516bfbadfcd005b9638ee136a5edf52b1032d2a702fa230a6e0ee9087

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 fbf7e4e79a169936a19b184d44e32876c278a97d4dc9d90cf99857c0ede7b376
MD5 cd623d883f3473f0d6e8f175a6a1fab4
BLAKE2b-256 77b0c1d4fee12390abe34f7353267d5d0285c88337a478c6fb0f7971c7abfe75

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b3fe5f93e312d65a488dbc4e16a2a9c9861971c99bb55d0f83985eba40ba0c31
MD5 3fe32ec6a906174213ea7d5b52872f7d
BLAKE2b-256 5d4b5f31fcf6ee7b6229cced4054488f19ef646cb725758834a22ce7c4cee667

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 80aa3868b163304c027876921907f215517d156e7e77d6e220acfcded0cd2b39
MD5 a481f57ef19e5136195ad678ee7d3687
BLAKE2b-256 9d7451ffe706a1232780a0e01f3fc25d88d93a29169868b5b97142fb2e5b4053

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 486c104f873def4d3f852afb67e6e07eddb9b7212a79e2d7515ea32a8c59c0fe
MD5 6c71b24ca32c217b9aaefc7a38a0bb80
BLAKE2b-256 1faf7b342513cf243fdd50aa1b2ce6918effcde8c287d6bb597402bf30559e87

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1b441dd3fe0663772dceb9e05401341eda63a5a3964109ee909bcf8e0b23c627
MD5 dce143d666353c6c41e76fae8df7616e
BLAKE2b-256 871c08db71cda9df7cba815973943a32d6d6dffdada5fad389e77bcedf534222

See more details on using hashes here.

File details

Details for the file dank_mids-4.20.210-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dank_mids-4.20.210-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 32d087478e255c545c866cd03d3956a00e13e6c35ab079671dd4ce5619a739b5
MD5 06073bb6685448cf17e002375bdfa359
BLAKE2b-256 719385df8621f474923bd1e1c22158a592c0df586f32be5b85cc207ce4e0aed5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page