Skip to content

Commit

Permalink
add bsc integration tests for custom create
Browse files Browse the repository at this point in the history
add v3_pool_fees in create_custom() docstring

add create_custom in the readme
  • Loading branch information
Elnaril committed Nov 10, 2023
1 parent d2a9a22 commit 168a74e
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 1 deletion.
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pip install uniswap-smart-path
## Usage

The library exposes a class, `SmartPath` with a public method `get_swap_in_path()` that can be used to find the best path/price.
For performance's sake, it is asynchronous.
For performance's sake, it is asynchronous. Currently, it supports only the Ethereum blockchain.

```python
from uniswap_smart_path import SmartPath
Expand All @@ -68,6 +68,7 @@ smart_path = await SmartPath.create(rpc_endpoint=rpc_endpoint)

### V2 or V3 pools only
The factory method `SmartPath.create_v2_only()` can be used to create a `SmartPath` instance that will look for the best path in V2 pools only.
Currently, it supports only the Ethereum blockchain.

```python
from uniswap_smart_path import SmartPath
Expand All @@ -77,6 +78,7 @@ smart_path = await SmartPath.create_v2_only(rpc_endpoint=rpc_endpoint) # could
```

Same thing if you wish to look into V3 pools only, just use `SmartPath.create_v3_only()`
Currently, it supports only the Ethereum blockchain.

```python
from uniswap_smart_path import SmartPath
Expand All @@ -85,6 +87,26 @@ smart_path = await SmartPath.create_v3_only(rpc_endpoint=rpc_endpoint) # could

```

### Custom pools and blockchains
A custom SmartPath can be created with the factory method `SmartPath.create_custom()`

```python
from uniswap_smart_path import SmartPath

pivot_tokens = (wbnb_address, usdt_address, usdc_address, dai_address) # BSC addresses
v3_pool_fees = (100, 500, 2500, 10000) # Pancakeswap v3 fees

smart_path = await SmartPath.create_custom(
w3, # BSC AsyncWeb3 instance
pivot_tokens=pivot_tokens,
v3_pool_fees=v3_pool_fees,
v2_router=pancakeswapv2_address,
v2_factory=pancakeswapv2_factory,
v3_quoter=pancakeswapv3_quoter_address,
v3_factory=pancakeswapv3_factory,
)
```

## Result
Examples of output paths that you can use with the [UR codec](https://github.com/Elnaril/uniswap-universal-router-decoder) to encode a transaction.

Expand Down
134 changes: 134 additions & 0 deletions integration_tests/main_bsc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import asyncio
import logging
import os
from pprint import pp
import subprocess
import time

from uniswap_universal_router_decoder import RouterCodec
from web3 import AsyncWeb3

from uniswap_smart_path import SmartPath


web3_provider = os.environ['WEB3_HTTP_PROVIDER_URL_BSC_MAINNET']
w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider("http://127.0.0.1:8545", {"timeout": 40}))
chain_id = 1337
block_number = 33368277

smart_path = smart_path_v2_only = smart_path_v3_only = None

pancakeswapv2_address = AsyncWeb3.to_checksum_address("0x10ED43C718714eb63d5aA57B78B54704E256024E")
pancakeswapv2_factory = AsyncWeb3.to_checksum_address("0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73")
pancakeswapv3_quoter_address = AsyncWeb3.to_checksum_address("0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997")
pancakeswapv3_factory = AsyncWeb3.to_checksum_address("0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865")

wbnb_address = AsyncWeb3.to_checksum_address("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c")
usdc_address = AsyncWeb3.to_checksum_address("0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d")
usdt_address = AsyncWeb3.to_checksum_address("0x55d398326f99059fF775485246999027B3197955")
dai_address = AsyncWeb3.to_checksum_address("0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3")
uni_address = AsyncWeb3.to_checksum_address("0xBf5140A22578168FD562DCcF235E5D43A02ce9B1")

pivot_tokens = (wbnb_address, usdt_address, usdc_address, dai_address)
v3_pool_fees = (100, 500, 2500, 10000)


codec = RouterCodec()
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("web3").setLevel(logging.WARNING)
logging.getLogger("uniswap_smart_path._datastructures").setLevel(logging.WARNING)


def launch_ganache():
ganache_process = subprocess.Popen(
f"""ganache
--logging.quiet='true'
--fork.url='{web3_provider}'
--fork.blockNumber='{block_number}'
--miner.defaultGasPrice='15000000000'
""".replace("\n", " "),
shell=True,
)
time.sleep(3)
parent_id = ganache_process.pid
return parent_id


def kill_processes(parent_id):
processes = [str(parent_id), ]
pgrep_process = subprocess.run(
f"pgrep -P {parent_id}", shell=True, text=True, capture_output=True
).stdout.strip("\n")
children_ids = pgrep_process.split("\n") if len(pgrep_process) > 0 else []
processes.extend(children_ids)
subprocess.run(f"kill {' '.join(processes)}", shell=True, text=True, capture_output=True)


async def check_initialization():
assert await w3.eth.chain_id == chain_id # 1337
assert await w3.eth.block_number == block_number + 1
print(" => Initialization: OK")


async def get_uni_dai_path():
print(" => Getting UNI DAI path")
amount_in = 100 * 10**18
path = await smart_path.get_swap_in_path(amount_in, uni_address, dai_address) # noqa
pp(f"{path = }")
print(path[0]["estimate"])
assert path[0]["estimate"] == 399452796099215583034
print(" => UNI DAI path: OK")


async def get_wbnb_usdt_path():
print(" => Getting WBNB USDT path")
amount_in = 100 * 10**18
path = await smart_path.get_swap_in_path(amount_in, wbnb_address, usdt_address) # noqa
pp(f"{path = }")
print(path[0]["estimate"])
assert path[0]["estimate"] == 25260332135985986979008
print(" => WBNB USDT path: OK")


async def launch_integration_tests():
print("------------------------------------------")
print("| Launching integration tests |")
print("------------------------------------------")

global smart_path
smart_path = await SmartPath.create_custom(
w3,
pivot_tokens=pivot_tokens,
v3_pool_fees=v3_pool_fees,
v2_router=pancakeswapv2_address,
v2_factory=pancakeswapv2_factory,
v3_quoter=pancakeswapv3_quoter_address,
v3_factory=pancakeswapv3_factory,
)

await check_initialization()
await asyncio.sleep(2)
await get_uni_dai_path()
await asyncio.sleep(2)
await get_wbnb_usdt_path()
await asyncio.sleep(2)


def print_success_message():
print("------------------------------------------")
print("| Integration tests are successful !! :) |")
print("------------------------------------------")


def main():
ganache_pid = launch_ganache()
try:
loop = asyncio.get_event_loop()
loop.run_until_complete(launch_integration_tests())
print_success_message()
finally:
kill_processes(ganache_pid)


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions uniswap_smart_path/smart_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ async def create_custom(
to the following optional keyword arguments:
* pivot_tokens: Sequence[str] - addresses of the token used for multi-hop pools, like weth, usdc, usdt, dai, ...
* v3_pool_fees: tuple of v3 fees as basis point. eg: (100, 500, 3000, 10000)
* v2_router: str - v2 router address
* v2_factory: str - v2 factory address
* v3_quoter: str - v3 quoter address
Expand Down

0 comments on commit 168a74e

Please sign in to comment.