Pancakeswap live trades
This is a minimal example code for showing live swaps happening on PancakeSwap and all other Uniswap v2 compatible DEXes on Binance Smart Chain.
The example scripts reads the swap stream of PancakeSwap pools
Displays human readable price of swaps
The example event reading method is not robust as it does not deal with minor blockchain reorganisations. See other examples in the Tutorials section how to handle this.
Uses public BNB Chain JSON-RPC endpoint by default
The public JSON-RPC endpoint is not very performant, so you should get your own JSON-RPC node for production usage
To run:
python scripts/pancakeswap-live-swaps-minimal.py
Example output:
Swap at block:30,239,875 buy price:2.64193807 LEE/USDT in tx 0x0b51a9f0a0f50c493111c29e670a419f400daba03e63b9360c52dcf6a3b16c20
Swap at block:30,239,875 sell price:236.64745674 WBNB/USDT in tx 0x13b65557c777ec26a52dd2e025ac22f8382c62262af8838dc7ebd13b2711765d
Swap at block:30,239,875 buy price:0.00000039 JGB/USDT in tx 0x13b65557c777ec26a52dd2e025ac22f8382c62262af8838dc7ebd13b2711765d
Swap at block:30,239,875 sell price:0.00000043 JGB/USDT in tx 0x8b54bc21666463b533a42264c5b5cf9090d91e9bbdbc9d24b1cc757a128cf67b
Swap at block:30,239,876 buy price:70.20751754 L3/USDT in tx 0xe9dc7b06729f563de7bc7c4412586c54a3e8f774aace636320bff06583f77b33
Swap at block:30,239,876 buy price:70.20771432 L3/USDT in tx 0xec507565a1d8e330b717f64b63a1d1f75ca5fed14aeca76cc27981da528d515e
"""A minimal example of reading PancakeSwap live swaps.
- Reads the swap stream of PancakeSwap pools
- Displays human readable price of swaps
- *This event reader is not robust* as it does not deal with minor blockchain reorganisations.
See other examples in the Tutorials section how to handle this.
- Uses public BNB Chain JSON-RPC endpoint by default
To run:
.. code-block:: shell
python scripts/pancakeswap-live-swaps-minimal.py
Example output:
.. code-block: text
Swap block:30,238,558 tx:0x826a7b87f2155f90a2ce41a8c9eebc58532d36e2e707181e6471c0c29573a5ab sell price:0.00099721 Welle/USDT
Swap block:30,238,558 tx:0x5cf346e19501bcf8aa428409d016390528e840c29a7758a4ba10f795c60bb18a buy price:12.20856495 RWT/USDT
Swap block:30,238,558 tx:0x54e6edccaf39a753b732e2e9c09fa5220b373c1b5116016f0fb5b2796d1a3af5 sell price:240.90248007 WBNB/USDT
Swap block:30,238,559 tx:0xc0bb97210da2fda1348f00e9daec9dbdd23c1dac50e6b44296c8fe4810a861fb buy price:0.06722527 TEA/USDT
Swap block:30,238,559 tx:0x6df61a50ca1073a9698929873718b98cc2330c33b8225ddc5cd6cb66aac7fd63 buy price:0.07435398 TEA/USDT
Swap block:30,238,559 tx:0x0b2f2bd819bcc19bbdabe7fb799e057c46ec6c50328dcbd7928a503046ef7da2 sell price:0.07993185 TEA/USDT
Swap block:30,238,559 tx:0x0b2f2bd819bcc19bbdabe7fb799e057c46ec6c50328dcbd7928a503046ef7da2 sell price:0.07805091 TEA/USDT
"""
import os
import time
from functools import lru_cache
from web3 import HTTPProvider, Web3
from eth_defi.abi import get_contract
from eth_defi.chain import install_chain_middleware
from eth_defi.event_reader.filter import Filter
from eth_defi.event_reader.logresult import decode_log
from eth_defi.event_reader.reader import read_events, LogResult
from eth_defi.uniswap_v2.pair import fetch_pair_details, PairDetails
QUOTE_TOKENS = ["BUSD", "USDC", "USDT"]
@lru_cache(maxsize=100)
def fetch_pair_details_cached(web3: Web3, pair_address: str) -> PairDetails:
return fetch_pair_details(web3, pair_address)
def main():
json_rpc_url = os.environ.get("JSON_RPC_BINANCE", "https://bsc-dataseed.binance.org/")
web3 = Web3(HTTPProvider(json_rpc_url))
web3.middleware_onion.clear()
install_chain_middleware(web3)
# Read the prepackaged ABI files and set up event filter
# for any Uniswap v2 like pool on BNB Smart Chain (not just PancakeSwap).
#
# We use ABI files distributed by SushiSwap project.
#
Pair = get_contract(web3, "sushi/UniswapV2Pair.json")
filter = Filter.create_filter(address=None, event_types=[Pair.events.Swap])
next_block = web3.eth.block_number
print(f"Starting at block {next_block:,}")
# Keep reading events as they land
while True:
start = next_block
end = web3.eth.block_number
evt: LogResult
for evt in read_events(
web3,
start_block=start,
end_block=end,
filter=filter,
):
decoded = decode_log(evt)
# Swap() events are generated by UniswapV2Pool contracts
pair = fetch_pair_details_cached(web3, decoded["address"])
token0 = pair.token0
token1 = pair.token1
block_number = evt["blockNumber"]
# Determine the human-readable order of token tickers
if token0.symbol in QUOTE_TOKENS:
base = token1 # token
quote = token0 # stablecoin/BNB
base_amount = decoded["args"]["amount1Out"] - decoded["args"]["amount1In"]
quote_amount = decoded["args"]["amount0Out"] - decoded["args"]["amount0In"]
else:
base = token0 # stablecoin/BNB
quote = token1 # token
base_amount = decoded["args"]["amount0Out"] - decoded["args"]["amount0Out"]
quote_amount = decoded["args"]["amount1Out"] - decoded["args"]["amount1Out"]
# Calculate the price in Python Decimal class
if base_amount and quote_amount:
human_base_amount = base.convert_to_decimals(base_amount)
human_quote_amount = quote.convert_to_decimals(quote_amount)
price = human_quote_amount / human_base_amount
if human_quote_amount > 0:
# We define selling when the stablecoin amount increases
# in the swap
direction = "sell"
else:
direction = "buy"
price = abs(price)
print(f"Swap at block:{block_number:,} {direction} price:{price:,.8f} {base.symbol}/{quote.symbol} in tx {evt['transactionHash']}")
else:
# Swap() event from DEX that is not Uniswap v2 compatible
# print(f"Swap block:{block_number:,} tx:{evt['transactionHash']} could not decode")
pass
else:
# No event detected between these blocks
print(".")
next_block = end + 1
# Sleep is not an ideal way to loop through blocks
# and is here only for an example purpose
time.sleep(5)
if __name__ == "__main__":
main()