Skip to content

Commit

Permalink
A Python tutorial to make a swap on Uniswap DEX or other DEX (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
miohtama authored Aug 16, 2023
1 parent ca29529 commit abb2c8d
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 16 deletions.
22 changes: 12 additions & 10 deletions docs/source/tutorials/index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.. meta::
:description: Python and Pandas examples for blockchain data research
:title: Web3 tutorials for Python

.. _tutorials:

Tutorials
=========
Expand All @@ -13,22 +15,21 @@ Examples include

* Performing ERC-20 token transfers

* Making swaps on Uniswap, Pancakeswap, others

* Data research with Jupyter Notebooks and Pandas

`For any questions please join to Discord chat <https://tradingstrategy.ai/community>`__.

Prerequisites
-------------

Make sure you know how to install packages (pip, poetry)
and use Python virtual environments.

To run the scripts you need to be able to understand
how Python packaging works and how to install additional modules.

Install the package with data addons:

.. code-block:: shell
- You need to know UNIX command line basics, like how to use environment variables.
Microsoft Windows is fine, but we do not test or write any instructions for it, so please
consult your local Windows expert for any Windows specific questions.

pip install "web3-ethereum-defi[data]"
- Make sure you know how to install packages (pip, poetry)
and use Python virtual environments. `See Github README for details <https://github.com/tradingstrategy-ai/web3-ethereum-defi>`__.

Example tutorials
-----------------
Expand All @@ -37,6 +38,7 @@ Example tutorials
:maxdepth: 1

transfer
make-uniswap-swap-in-python
multithread-reader
verify-node-integrity
live-price
Expand Down
2 changes: 2 additions & 0 deletions docs/source/tutorials/live-price.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,7 @@ Sample output:
Block 19,937,848 at 2022-07-28 06:16:16 current price:269.3162 WBNB/BUSD TWAP:269.3539 WBNB/BUSD
Oracle data updates: Counter({'created': 6, 'discarded': 1, 'reorgs': 0}), trades in TWAP buffer:144, oldest:2022-07-28 06:11:16, newest:2022-07-28 06:16:13
`For any questions please join to Discord chat <https://tradingstrategy.ai/community>`__.

.. literalinclude:: ../../../scripts/uniswap-v2-swaps-live.py
:language: python
2 changes: 2 additions & 0 deletions docs/source/tutorials/live-swap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ good free RPC nodes which makes running the example code easy.
the startup is a bit slow as the pair details cache
is warming up.

- `For any questions please join to Discord chat <https://tradingstrategy.ai/community>`__.

To run for Polygon (and QuickSwap):

.. code-block:: shell
Expand Down
54 changes: 54 additions & 0 deletions docs/source/tutorials/make-uniswap-swap-in-python.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.. meta::
:title: How to swap tokens on Uniswap and DEXes using Python
:description: Python token swap tutorial with slippage protection


Swap tokens on Uniswap v2 compatible DEXes
------------------------------------------

This is an simple example script to swap one token to another securely.
It works on any `Uniswap v2 compatible DEX <https://tradingstrategy.ai/glossary/uniswap>`__.
For this particular example, we use PancakeSwap on Binance Smart Chain,
but you can reconfigure the script for any Uniswap v2 compatible protocol
on any `EVM-compatible <https://tradingstrategy.ai/glossary/evm-compatible>`__ blockchain.
The script is set up to swap from BUSD to Binance-custodied ETH.

- First :ref:`Read tutorials section for required Python knowledge, version and how to install related packages <tutorials>`.
- In order to run this example script, you need to have
- Private key on BNB Smart Chain with BNB balance, `you can generate a private key on a command line using these instructions <https://ethereum.stackexchange.com/a/125699/620>`__.
- `Binance Smart Chain JSON-RPC node <https://docs.bnbchain.org/docs/rpc>`__. You can use public ones.
- BUSD balance (you can swap some BNB on BUSD manually by importing your private key to a wallet).
- Easy way to get few dollars worth of starting tokens is `Transak <https://global.transak.com/>`__. Buy popular tokens with debit card - Transak supports buying tokens natively for many blockchains.
- Easy way to to manually swap between BUSD/BNB/other native gas token is to import your private key to `Rabby desktop wallet <https://rabby.io/>`__ and use Rabby's built-in swap and trade aggregator function.

This script will

- Sets up a private key with BNB gas money

- Sets up a PancakeSwap instance

- Perform a swap from BUSD (`base token <https://tradingstrategy.ai/glossary/base-token>`__) to
Binance-custodied ETH (`quote token <https://tradingstrategy.ai/glossary/quote-token>`__) for any amount of tokens you enter

- `Uses slippage protection <https://tradingstrategy.ai/glossary/slippage>`__
for the swap so that you do not get exploited by `MEV bots <https://tradingstrategy.ai/glossary/mev>`__

- Wait for the transactions to complete and display the reason if the trade failed

To find tokens to trade you can use `Trading Strategy search <https://tradingstrategy.ai/search>`__
or `market data listings <https://tradingstrategy.ai/trading-view>`__.
`For any questions please join to Discord chat <https://tradingstrategy.ai/community>`__.

To run:

.. code-block:: shell
export JSON_RPC_BINANCE="https://bsc-dataseed.bnbchain.org"
export PRIVATE_KEY="your private key here"
python scripts/make-swap-on-pancake.py
Example script
~~~~~~~~~~~~~~

.. literalinclude:: ../../../scripts/make-swap-on-pancake.py
:language: python
8 changes: 5 additions & 3 deletions docs/source/tutorials/transfer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ You need

- Understanding how to operate command line and command line applications

`For any questions please join to Discord chat <https://tradingstrategy.ai/community>`__.

Set up
~~~~~~

Expand Down Expand Up @@ -59,7 +61,7 @@ Then create the following script:
from eth_defi.abi import get_deployed_contract
from eth_defi.token import fetch_erc20_details
from eth_defi.txmonitor import wait_transactions_to_complete
from eth_defi.confirmation import wait_transactions_to_complete
# What is the token we are transferring.
# Replace with your own token address.
Expand All @@ -84,7 +86,7 @@ Then create the following script:
print(f"Token details are {token_details}")
balance = erc_20.functions.balanceOf(account.address).call()
eth_balance = web3.eth.getBalance(account.address)
eth_balance = web3.eth.get_balance(account.address)
print(f"Your balance is: {token_details.convert_to_decimals(balance)} {token_details.symbol}")
print(f"Your have {eth_balance/(10**18)} ETH for gas fees")
Expand All @@ -99,7 +101,7 @@ Then create the following script:
except ValueError as e:
raise AssertionError(f"Not a good decimal amount: {decimal_amount}") from e
assert web3.isChecksumAddress(to_address), f"Not a valid address: {to_address}"
assert web3.is_checksum_address(to_address), f"Not a checksummed Ethereum address: {to_address}"
# Fat-fingering check
print(f"Confirm transferring {decimal_amount} {token_details.symbol} to {to_address}")
Expand Down
2 changes: 2 additions & 0 deletions eth_defi/confirmation.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ def wait_transactions_to_complete(
:param txs:
List of transaction hashes
:param confirmation_block_count:
How many blocks wait for the transaction receipt to settle.
Set to zero to return as soon as we see the first transaction receipt.
:return:
Map of transaction hashes -> receipt
"""
Expand Down
7 changes: 5 additions & 2 deletions eth_defi/uniswap_v2/swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from eth_typing import HexAddress
from web3.contract import Contract
from web3.contract.contract import ContractFunction

from eth_defi.uniswap_v2.deployment import FOREVER_DEADLINE, UniswapV2Deployment
from eth_defi.uniswap_v2.fees import estimate_buy_price, estimate_sell_price
Expand All @@ -21,7 +22,7 @@ def swap_with_slippage_protection(
amount_out: Optional[int] = None,
fee: int = 30,
deadline: int = FOREVER_DEADLINE,
) -> Callable:
) -> ContractFunction:
"""Helper function to prepare a swap from quote token to base token (buy base token with quote token)
with price estimation and slippage protection baked in.
Expand Down Expand Up @@ -97,10 +98,12 @@ def swap_with_slippage_protection(
:param amount_in:
How much of the quote token we want to pay, this has to be `None` if `amount_out` is specified.
Must be in raw quote token units.
:param amount_out:
How much of the base token we want to receive, this has to be `None` if `amount_in` is specified
Must be in raw base token units.
:param max_slippage:
Expand All @@ -113,7 +116,7 @@ def swap_with_slippage_protection(
Time limit of the swap transaction, by default = forever (no deadline)
:return:
Prepared swap function which can be used directly to build transaction
Bound ContractFunction that can be used to build a transaction
"""

assert fee > 0, "fee must be non-zero"
Expand Down
Loading

0 comments on commit abb2c8d

Please sign in to comment.