Skip to content

test: switching mainnet rpc for CI tests - #483

Closed
liquid-8 wants to merge 39 commits into
uniswap-python:dev/v4-finfrom
liquid-8:uni_v4_final
Closed

liquid-8 wants to merge 39 commits into
uniswap-python:dev/v4-finfrom
liquid-8:uni_v4_final

Conversation

@liquid-8

Copy link
Copy Markdown
Member

No description provided.

liquid-8 and others added 30 commits July 28, 2026 11:20
* v4 support pre-alpha

* v4 support pre-alpha

* Revert "v4 support pre-alpha"

This reverts commit fa75632.

* Revert "v4 support pre-alpha"

This reverts commit de63ce4.

* Update __init__.py

* Add files via upload

* Add Uniswap4 to module exports

* Delete uniswap/uniswap-v4 directory

* Add files via upload

* Refactor uniswap4.py by removing unused imports

Removed unused imports and cleaned up code formatting.

* Add files via upload

Pool manager contract ABI

* Delete uniswap/configs/evmuniV4_permit2.ini

Deleted due to naming fix

* Delete uniswap/configs/evmuniV4_chains.ini

Deleted due to naming fix

* Delete uniswap/configs/evmuniV4_quoter.ini

Deleted due to naming fix

* Delete uniswap/configs/evmuniV4_router.ini

Deleted due to naming fix

* Delete uniswap/configs/evmuniV4_stateview.ini

Deleted due to naming fix

* Add files via upload

Naming fix

* Add files via upload

Liquidity pools list management class added, UniswapV4 improvements.

* Delete uniswap/uni4base.py

refactor

* Delete uniswap/configs/chains.ini

refactor

* Delete uniswap/configs directory

refactor

* Beta

refactoring+bug fixes

* Add files via upload

* Add files via upload

* Delete uniswap/v4pools.py

moved to util

* Delete uniswap/v4types.py

moved to types

* Delete uniswap/v4constants.py

moved to constants

* Add files via upload

Structure refactoring; fixes; StateView contract support added

* Formmating fixes, naming fixes

* fix constants

* Fix util

* technical commit

* Technical fixes

* pre-commit formatter/linter

* fix pyproject.toml

* ci: update GitHub Actions to supported versions

* ci: fix python version output quoting in workflow

* build(deps): update poetry.lock

* typecheck fixes

* review fixes

* poetry.lock update

* more typecheck fixes

* more typecheck

* get_token fix

* PositionDescriptor support; PositionManager read methods support; misc

* fixes

* PositionManager full support; PoolManager full support; contracts-related methods naming improvement.

* fixes

* review fixes

* extra fix

* poetry.lock fix

* v4 test prototype

* Update uniswap/uniswap4.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update tests/v4tests.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix

* tech commit

* tech fix

* fix(ci): replace rate-limited Infura with public RPC (uniswap-python#431)

* fix(ci): replace rate-limited Infura with public RPC and fix type errors

- Switch PROVIDER_MAINNET fallback from Infura to ethereum.publicnode.com
  (Infura public key was hitting "Too Many Requests" rate limits)
- Add dev/v4 and dev/v4-fin branches to CI triggers
- Fix mypy errors: use str() for bytes fallback in token name/symbol
  decode, add type: ignore for web3 get_logs attribute

Co-authored-by: Bob <bob@superuserlabs.org>

* fix(ci): switch Arbitrum RPC and resolve mypy warning

* fix(ci): stop push runs from preferring stale mainnet secret (uniswap-python#432)

* Added multi-hop quotes support

* review fixes

* Checks improvements, small logic fix, multi-hop tests added

* Added multi-hop swaps support; added market pricing functions similar to main class; removed hardcoded zero values regarding hooks; impoved pool data fetching process;  misc improvement

* review fix

* typecheck fix

* Improved exceptions handling; get_logs() glitch fix

* Added swap tests; added liquidity read functions; added liquidity tests

* typo fix

* Fixes: get_poolkeys_sublist() - addresses comparison; estimate_price_impact() - route param removed;  decode_position_info() - imcorrect input value handling

* Fix: decode_position_info() - truncated poolID decoding

* Add get_position_value() and get_minted_token_id(); related tests; tick math improved; misc

* get_amounts_for_liquidity_by_ticks() refactoring; review suggestions added

* typecheck glitch fix

* typo

* typo

* get_sqrt_ratio_at_tick() moved to util.py as it is shared with v3;  get_minted_token_id() refactoring to support multiple mints

* review suggestion

* review suggestion

* Add liquidity management methods; add router commands and pool actions constants

* quick self-fix

* typos

* typos

* Changed direct contract call methods naming to improve usability

* typo

* Improve log processing in fetch_poolkey_data(); typos fixed

* Add fetch_poolkey_data()  reconnect functionality

* Change fetch_poolkey_data(): param/var renamed and docstring changed for better clarity; tests exceptions handling improved slightly.

* Add universal router prerequisites

* quick fix

* Add universal router support

* Review fixes

* review suggestions

* Review suggestions

* Review suggestions

* Fixed custom recipient' logic in swaps; fixed ABIs constants.

* review fixes

* Removed custom recipent in swaps; tests added.

* quick fix

* misc fixes

* Switch from ganachr to foundry-anvil for v4 tests

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* Add custom transactions' nonce; custom delay time within approve(); universal router' commands and actions ABIs clarified

* fix

* ABI fix

* fix

* Add more v4 tests

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* Add more tests

* fix

* Add liquidity tests

* fix

* Add swap tests

* fix

* fix

* fix

* fix

* Add fetch pool data test

* Add the rest of pool data tests

* Add liquidity postions management tests.

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* Add StateView and PositionDescriptor tests; liquidity tests reorg.

* fix

* fix

* fix

* fix

* Add Universal_router_execute() tests

* fix

* fix

* Add positive slippage collection

* Fix comments

* Fix positive slippage recipient

* Minor fixes.

* Fix

* RC

* fix

* Docstrings clarification, comments on universal_router_execute() usage

* fix

* Fix position_manager_permit2_single()

* Fix constructor network handling

* fix

* Docstrings clarification

* fix

* Add testnets, minor constructor improvements

* Docstrings clarification

* Add router v2.1.1 support; add X Layer, Tempo, Robinhood networks support; removes Blast and testnets support.

* fix

* abi fix for multihop swap

* fix

* fix

* tests fix

* fix singlehop swaps abi, method and tests

* unversal router execute() test fix

* Add ReservesLens support

* draft fixes

* getPoolTVLBatch fix

* getPoolTVLBatch params refactoring

* docstring clarification

* Fix ruff versions clownshow; docstring clarificatiom

---------

Co-authored-by: Erik Bjäreholt <erik@bjareho.lt>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Bob <bob@superuserlabs.org>
…ts list (uniswap-python#470)

- Remove "Want to help implement v4?" callout (v4 shipped in uniswap-python#418)
- Add Uniswap v4 (as of v0.8.0, beta) to the Supports section with
  a brief feature list (swaps, quoting, liquidity, pool cache service)
…niswap-python#471)

* docs: add v4 narrative guide and fill examples page with v2/v3 snippets

- docs/v4.rst: new page covering PoolKey concept, connecting Uniswap4,
  spot price, quoting (exact-in/out, single-hop and multi-hop), price
  impact estimation, making swaps, pool discovery, and full liquidity
  lifecycle (create pool, mint, read, collect, decrease, burn)
- docs/examples.rst: was empty ('No examples here yet!'); now has v2 and
  v3 examples for prices, swaps, multi-hop, and liquidity management
- docs/index.rst: add v4 to the toctree

* test(v4): add runnable example tests against Anvil mainnet fork

Five example test classes covering the most common v4 workflows:
  - TestExampleSpotPrice: get_token_token_spot_price (reads sqrtPriceX96)
  - TestExampleQuote: get_price_input / get_price_output (single-hop and
    2-hop ETH→USDC→USDT route via the on-chain Quoter)
  - TestExamplePriceImpact: estimate_price_impact (small vs large trade)
  - TestExampleStateView: stateview_get_slot0 / stateview_get_liquidity
  - TestExamplePoolDiscovery: V4pools.fetch_poolkey_data / get_poolkeys_sublist

These serve as executable documentation (mirror of docs/v4.rst) and run
in CI as part of the UNISWAP_VERSION=4 matrix job.

Port 10997 is used so this file can run in parallel with test_uniswap4.py
(which occupies 10998).

* fix(tests): add missing hooks arg to stateview_get_slot0/liquidity calls

* fix(docs): correct API mismatches flagged by Greptile review

- docs/v4.rst: fix position lifecycle — get_position_info has no 'liquidity'
  key; use position_manager_get_position_liquidity() instead.
  get_position_value requires token decimals. collect_fees, decrease_liquidity,
  and burn_position all require pool_key as first arg plus amount*_min args.
- docs/v4.rst: add missing hooks=ZERO_HOOK to stateview_get_slot0 and
  stateview_get_liquidity calls (both methods require hooks with no default).
- docs/examples.rst: remove unsupported route= kwarg from v3 make_trade call;
  show two sequential single-hop trades instead.
- docs/examples.rst: fix misleading v2 comment ("ETH → USDC → WBTC"); v2
  routes through WETH automatically, not USDC.
- tests/test_v4_examples.py: bound pool discovery scan with last_block to
  avoid scanning from deployment to chain tip (thousands of RPC calls).

* fix(tests): avoid archive RPC in pool discovery example

* fix(docs): make routed swaps executable

* fix(docs): remove full liquidity before burn_position
…python#472)

* refactor(tests): replace ganache with anvil for v1-v3 tests

Ganache is an npm-maintained tool that has fallen behind foundry's anvil in
maintenance and compatibility. Anvil is already used for v4 tests (test_uniswap4.py)
and is installed via the foundry-toolchain GitHub Action in CI.

- Replace GanacheInstance with AnvilInstance in tests/test_uniswap.py
- Swap the ganache fixture for an anvil fixture (same port 10999, Foundry's
  default test mnemonic account uniswap-python#9 instead of ganache's --wallet.seed account)
- Remove `npm install -g ganache@7.5.0` and Node setup from CI workflow
- Update README to reference Anvil/Foundry instead of ganache-cli

* docs: make Foundry install work in fresh shells

* docs: invoke foundryup from installed path

* docs: add Foundry binaries to current PATH

* fix(tests): pre-populate gas before build_transaction to fix v1 InvalidJump

web3.py calls eth_estimateGas internally during build_transaction when no
gas field is present in tx_params. Anvil's strict EVM rejects this for Vyper
v1 exchange contracts with EVM error InvalidJump (computed jump tables used
by old Vyper don't pass strict JUMPDEST validation during simulation).

The existing use_estimate_gas=False path set a 250k gas fallback AFTER
build_transaction had already made — and failed — the estimateGas call.

Fix: pre-populate gas in tx_params before calling build_transaction when
use_estimate_gas=False, so web3's internal estimate is never triggered.

* test: xfail v1 token-to-ETH cases incompatible with Anvil revm

Anvil's revm enforces strict JUMPDEST validation, which rejects the
computed jump tables used by old Vyper-compiled Uniswap v1 exchange
contracts in the tokenToEth code path (EvmError: InvalidJump). Ganache
was more permissive and executed these without error.

The ETH-to-token direction works fine; only token-to-ETH triggers
the incompatibility. Mark the two failing test cases as xfail so CI
is green while keeping the test coverage visible.

* test: try 500k gas fallback for v1 token-to-ETH, remove xfail

liquid-8 observed out-of-gas in the e792149 CI run rather than a hard
InvalidJump at execution. Raise the no-estimate-gas fallback from 250k
to 500k — the same direction that resolved similar v4 gas issues — and
remove the xfail marks so CI validates the fix directly.

If this run still fails, the root cause is confirmed as an EVM bytecode
incompatibility rather than insufficient gas, and the xfail approach
is the right interim.

* test: re-add xfail for v1 token-to-ETH (Anvil revm InvalidJump)

500k gas still hits InvalidJump — it's not a gas issue. Anvil's strict
revm rejects the non-standard JUMP patterns in Uniswap v1 Vyper 0.1.x
bytecode; Ganache was permissive about these. Gas increase cannot fix
this class of failure.

xfail on `client.version == 1 and output_token == ETH_ADDRESS` in both
test_make_trade and test_make_trade_output, with an explicit reason
string pointing at the deprecation track.
 uniswap-python#363) (uniswap-python#459)

* fix: avoid duplicate WETH in swap path when input/output is WETH (closes uniswap-python#363)

* fix: also avoid duplicate WETH in _token_to_token_swap_output (closes uniswap-python#363)

* fix: use is_same_address() for WETH comparison in _token_to_token_swap_output

Raw == fails when input_token/output_token is bytes or lowercase hex,
falling through to the wrong 3-hop path. Consistent with the rest of
the codebase (line 746 and the v3 path use is_same_address).

* Update uniswap/uniswap.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: botbikamordehai2-sketch <mbotbika9@gmail.com>
Co-authored-by: Yohan K <72107640+liquid-8@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…uniswap-python#473)

* build(deps): bump Python to 3.12, drop typed_ast and ruff-replaced linters

- Require Python ^3.12 (from ^3.7.2)
- Drop typing-extensions: Concatenate/ParamSpec now in stdlib typing (3.10+)
- Drop black and flake8: superseded by ruff (already in pre-commit config)
- Bump pytest ^6 → ^8, Sphinx * → ^9 (requires Python 3.12)
- Unpin pydata-sphinx-theme (sphinx-book-theme#711 long resolved)
- Drop allow-prereleases on web3 (stable 6.x line is sufficient)
- Loosen click ^8.0.3 → ^8
- Update build backend: poetry.masonry.api → poetry.core.masonry.api
- CI: test and typecheck jobs now use Python 3.12
- Move [tool.ruff] → [tool.ruff.lint] (deprecation fix)
- Silence unused _token_two variable (second-token approval was never wired up)

Note: web3 7.x upgrade deferred (major async-first rewrite, breaking API changes).

* ci: fix Poetry 2.x compat and bump docs to Python 3.12

- Remove deprecated 'installer.modern-installation' setting (removed in Poetry 2.0)
- Bump docs.yml from Python 3.8 to 3.12 to match the new package floor
  (Python 3.8 + cytoolz 0.12.1 failed to build via Cython under PEP 517)

* fix(makefile): replace flake8/black with ruff lint/format targets

flake8 and black were removed as direct dependencies in the Python 3.12 dep bump;
the Makefile still referenced them. Ruff already handles both roles.

* fix(deps): add explicit floors for Python 3.12-incompatible Cython packages

cytoolz 0.12.1, frozenlist 1.3.3, yarl 1.8.2, and multidict 6.0.4 all
declare python-versions=>=3.6 but have no pre-built cp312 wheels, causing
Cython compilation failures when installing under Python 3.12.

Add explicit minimum constraints in pyproject.toml so poetry resolves to
versions that ship cp312 wheels:
- cytoolz >=0.12.3  (locked to 1.1.0)
- frozenlist >=1.5.0  (locked to 1.8.0)
- multidict >=6.0.5  (locked to 6.7.1)
- yarl >=1.10.0  (locked to 1.24.5)

propcache 0.5.2 added as a new transitive dep from yarl 1.24.5.

* fix(deps): add aiohttp floor to unblock Python 3.12 CI

aiohttp 3.8.4 (transitive via web3) has no cp312 wheels and fails
to build from source on Python 3.12 — PyLongObject.ob_digit was
removed in 3.12. Added aiohttp = ">=3.9.0" (first release with
cp312 wheels) as a direct dependency constraint; poetry re-locked
to 3.14.3 which ships cp312 wheels.

This fixes all 6 failing CI jobs (build + 4 test matrix + typecheck).

* fix(deps): pin setuptools<82 and bump doc theme versions for Python 3.12 CI

Two independent CI failures after the Python 3.12 bump:

- Test/typecheck jobs: eth-keyfile (pulled in via web3->eth-account) still
  imports pkg_resources, which setuptools dropped starting in 82.0.0 (last
  shipped in 81.0.0). eth-account>=0.12 fixes this upstream but requires
  hexbytes>=1.2.0, which conflicts with web3 6.x's hexbytes<0.4.0 pin — that
  needs the (deliberately deferred) web3 7.x migration. Pin setuptools<82 as
  a stopgap; also floor typing-extensions>=4.12.0, since 4.5.0 crashes under
  Python 3.12.13's stricter TypeVar base-class check (docs build failure).

- Docs build: sphinx-book-theme was resolving to 0.0.11 (a 2020-era release,
  incompatible with Sphinx 9's theme API — missing 'get_edit_url'). Floor it
  to ^1.1, which also pulls a compatible pydata-sphinx-theme (0.20.0).
  Along the way, Sphinx 9 hard-fails on the old implicit-%s extlinks caption
  format ("issue #" -> "issue #%s").

Verified locally: full install, docs build (make html), pytest collection
(250 tests), and mypy --pretty all pass in an isolated poetry venv.

* fix(deps): add ruff as explicit dev dependency

Makefile lint/format targets call `poetry run ruff` but ruff was
absent from [tool.poetry.dev-dependencies]. A fresh `poetry install`
would succeed without it, making `make lint` fail immediately.

Lock file regenerated with Poetry 2.3.2 / Python 3.12.3.
Replaces the stale 'Support our continued work' Gitcoin CTA with a
Funding section covering the Uniswap Grants Program grant (v3, 2021),
community Gitcoin donations, and Superuser Labs' sponsorship of
continued development including the v4 work.
…p-python#475)

lru-dict 1.1.8 ships no wheels for recent Python and its source fails
to compile under modern clang (incompatible-function-pointer-types on
the popitem method table; amitdev/lru-dict#76), breaking
'poetry install' on Python 3.13. 1.2.0 contains the fix and stays
within web3 6.x's 'lru-dict <1.3.0' constraint.
Adds: multihops in v3; async v2,v3, v4
@codecov

codecov Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.89161% with 333 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.20%. Comparing base (a9490e1) to head (ecd51a3).
⚠️ Report is 34 commits behind head on dev/v4-fin.

Files with missing lines Patch % Lines
uniswap/asyncuniswap.py 71.69% 229 Missing ⚠️
uniswap/uniswap.py 67.17% 43 Missing ⚠️
uniswap/util.py 67.42% 43 Missing ⚠️
uniswap/uniswap4.py 73.46% 13 Missing ⚠️
uniswap/decorators.py 20.00% 4 Missing ⚠️
uniswap/tokens.py 80.00% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff               @@
##           dev/v4-fin     #483      +/-   ##
==============================================
- Coverage       73.97%   70.20%   -3.78%     
==============================================
  Files              12       14       +2     
  Lines            2309     4282    +1973     
==============================================
+ Hits             1708     3006    +1298     
- Misses            601     1276     +675     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@greptile-apps

greptile-apps Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 0/5

[High impact] Upgrades Python version, dependencies, and test infrastructure.

This PR should not merge until the trade regressions and async client failures are fixed.

Findings

  1. P1 Token trades lose automatic approval ▶
  2. P1 V1 price requests fail ▶
  3. P1 Async setup uses another connection ▶
  4. P1 Concurrent transactions reuse a nonce ▶
  5. P1 V1 async approval cannot encode ▶
  6. P1 Async tests skip asset purchases ▶
  7. P1 Routed swaps lose ETH handling ▶
  8. P2 V3 example finds no pool ▶
  9. P2 Mint example uses wrong keywords ▶
  10. P2 Discovery example cannot start ▶
  11. P2 Mint example exceeds its budgets ▶
  12. P2 Caching option does nothing ▶

Summary

This PR changes the CI mainnet RPC and also adds async clients, v3 routed swaps, new examples, and dependency upgrades.

  • Callers can await Uniswap trades, quotes, and pool lookups.
  • Synchronous v1–v3 quotes and trades can follow token routes.
  • The synchronous v4 client keeps working with the updated Web3 interface.
  • CI tests use Anvil and Python 3.12.
  • The guides show how to use Uniswap v2, v3, and v4.
  • Shared helpers and examples use updated Python and Web3 APIs.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Caller[Python caller] --> Sync[Uniswap and Uniswap4]
  Caller --> Async[AsyncUniswap and AsyncUniswap4]
  Sync --> Quote[Single-pool or routed quote]
  Async --> Quote
  Quote --> Bound[Apply slippage limit]
  Bound --> Tx[Build and sign transaction]
  Tx --> RPC[Web3 connection]
  RPC --> Chain[Uniswap contracts]
  CI[Python 3.12 CI] --> Fork[Anvil mainnet fork]
  Fork --> Sync
  Fork --> Async
Loading

Reviews (1) · Last reviewed commit: "test: switching mainnet rpc for tests" · Reviewed by Greptile

Comment thread uniswap/uniswap.py

# ------ Make Trade ----------------------------------------------------------------
@check_approval
def make_trade(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Token trades lose automatic approval

Removing check_approval means make_trade and make_trade_output submit ERC-20 swaps without checking or granting allowance. Wallets that have not already approved the router now get reverted trades. Restore the approval step; the new tests hide this regression by approving tokens first.

Knowledge Base Used: Uniswap V1–V3 client operations

Comment thread uniswap/uniswap.py
Comment on lines +230 to 233
if is_same_address(token0, ETH_ADDRESS) and self.version == 2:
return self._get_eth_token_input_price(token1, Wei(qty), fee)
elif token1 == ETH_ADDRESS:
elif is_same_address(token1, ETH_ADDRESS) and self.version == 2:
return self._get_token_eth_input_price(token0, qty, fee)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 V1 price requests fail

The new version == 2 condition excludes v1 from both ETH quote paths. A v1 ETH/token quote now converts ETH to WETH and enters _get_token_token_input_price or _get_token_token_output_price, which does not support v1. Both public price methods therefore fail for supported pairs. Keep v1 on its exchange quote path.

Knowledge Base Used: Uniswap V1–V3 client operations

Comment thread uniswap/asyncuniswap.py
Comment on lines +117 to +127
if not provider:
provider = os.environ["PROVIDER"]
if web3:
self.w3 = web3
else:
# Initialize web3. Extra provider for testing.
self.w3 = AsyncWeb3(
AsyncWeb3.AsyncHTTPProvider(provider, request_kwargs={"timeout": 60})
)
tmp_w3 = Web3(Web3.HTTPProvider(provider, request_kwargs={"timeout": 60}))
self.netid = int(tmp_w3.net.version)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Async setup uses another connection

Both async constructors require PROVIDER even when the caller supplies web3. They then read the chain and starting nonce from a separate synchronous HTTP connection. Passing only web3 raises KeyError; if PROVIDER points to another chain, the clients select the wrong contracts and nonce. Read these values from the supplied AsyncWeb3 through an async initialization step.

Comment thread uniswap/asyncuniswap4.py
Comment on lines +3469 to +3471
"nonce": Nonce(max(self.last_nonce, 0))
if custom_nonce is None
else custom_nonce,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Concurrent transactions reuse a nonce

Two writes started together on either async client can both read the same last_nonce. _build_and_send_tx updates it only after awaiting transaction submission, so the calls can build transactions with the same nonce. One transaction then gets rejected or replaces the other. Reserve each nonce before yielding, or lock the transaction build-and-send path.

Comment thread uniswap/asyncuniswap.py
Comment on lines +1486 to +1490
contract_addr = (
self._exchange_address_from_token(token)
if self.version == 1
else self.router_address
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 V1 async approval cannot encode

For v1, AsyncUniswap.approve calls _exchange_address_from_token without await. It passes the resulting coroutine as the ERC-20 spender address, so Web3 cannot encode the approval call. Await the exchange lookup before building the transaction.

Suggested change
contract_addr = (
self._exchange_address_from_token(token)
if self.version == 1
else self.router_address
)
contract_addr = (
await self._exchange_address_from_token(token)
if self.version == 1
else self.router_address
)

Comment thread docs/examples.rst
Comment on lines +174 to +175
# Get the pool contract instance
pool = uni.get_pool_instance(ETH, USDC, fee=500)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 V3 example finds no pool

The liquidity example passes the zero-address ETH marker to get_pool_instance, which sends the addresses directly to getPool. V3 pools use WETH, so the lookup returns no pool. Use WETH and explain that the wallet needs wrapped ETH. Also put USDC in amount_0 and WETH in amount_1 to match the pool's token order.

Knowledge Base Used: Uniswap V1–V3 client operations

Comment thread docs/examples.rst
Comment on lines +183 to +184
amount0=ONE_ETH // 10,
amount1=340 * 10**6,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Mint example uses wrong keywords

mint_liquidity takes amount_0 and amount_1, not amount0 and amount1. Even after fixing the pool lookup, these keywords raise TypeError. Use the actual parameter names so readers can run the documented call.

Suggested change
amount0=ONE_ETH // 10,
amount1=340 * 10**6,
amount_0=ONE_ETH // 10,
amount_1=340 * 10**6,

Comment thread docs/v4.rst
pools = V4pools(w3)

# Scan the chain (slow on first run — save to disk for reuse)
pools.fetch_poolkey_data(chunk_size=2000)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Discovery example cannot start

fetch_poolkey_data(chunk_size=2000) omits the required first_block argument, so it raises TypeError before fetching anything. Supply the mainnet starting block, such as 21688329, used by the tests.

Suggested change
pools.fetch_poolkey_data(chunk_size=2000)
pools.fetch_poolkey_data(first_block=21688329, chunk_size=2000)

Comment thread docs/v4.rst
Comment on lines +329 to +339
tx = uni.mint_position(
pool_key=pool_key,
tick_lower=-887270, # near minimum tick
tick_upper=887270, # near maximum tick (full range)
liquidity=10**18, # amount of liquidity to provide
amount0=ONE_ETH // 10, # max ETH to spend
amount1=340 * 10**6, # max USDC to spend
)

# Retrieve the ERC-721 token ID(s) minted by this transaction
token_ids = uni.get_minted_token_id(tx.hex())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Mint example exceeds its budgets

At the preceding 3400 USDC/ETH price, full-range liquidity=10**18 needs roughly 17,150 ETH and 58 million USDC, not 0.1 ETH and 340 USDC. The documented transaction therefore reverts. Calculate liquidity with get_liquidity_for_amounts_by_ticks from the actual price and budgets. Approve USDC for the position manager, and wait for the mint receipt before reading its token ID.

Knowledge Base Used: Uniswap V4 client operations

Comment thread uniswap/uniswap.py
if enable_caching:
self.w3.middleware_onion.inject(_get_eth_simple_cache_middleware(), layer=0)

self.netid = int(self.w3.net.version)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Caching option does nothing

enable_caching is still accepted and documented, but the code that enabled caching has been removed. Passing True now silently does nothing, leaving callers with extra RPC calls. Restore supported caching or remove the option and explain the change.

@liquid-8 liquid-8 closed this Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants