Skip to content

feat(gateway): AMM liquidity + pool-creation endpoints (/gateway/amm/*) - #206

Open
fengtality wants to merge 1 commit into
mainfrom
feat/gateway-amm
Open

feat(gateway): AMM liquidity + pool-creation endpoints (/gateway/amm/*)#206
fengtality wants to merge 1 commit into
mainfrom
feat/gateway-amm

Conversation

@fengtality

@fengtality fengtality commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Re-adds AMM as a deliberate, separate surface (previously removed) exposing Gateway's standardized /trading/amm/* routes via a stateless router: pool-info, position-info, positions-owned, quote-swap, execute-swap, quote-liquidity, add-liquidity, remove-liquidity, create-pool.

Meteora DAMM v2 positions are NFTs, so the routes are position-addressed: remove requires position_address, add takes it optionally (omit = new position), position-info returns a positions[] breakdown, positions-owned lists all positions. Fungible-LP AMMs ignore position_address.

  • models/gateway_trading.py + models/__init__.py: AMM request/response models
  • services/gateway_client.py: amm_* methods over unified trading/amm/*
  • routers/gateway_amm.py: ping → check_gateway_error handler ladder (no DB)
  • main.py: register router
  • 13 contract tests pin (method, path) + camelCase keys + position-addressing + create-pool extras

Part of a 4-layer AMM integration; merge after the Gateway PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01N1YS88ZAY2rXVLmgvyN4oY


Related PRs — 4-layer AMM integration (merge bottom-up, each depends on the one below):

  1. Gateway: feat(meteora): add DAMM v2 (cp-amm) AMM connector gateway#671 — DAMM v2 (cp-amm) connector + unified /trading/amm/*
  2. hummingbot-api: feat(gateway): AMM liquidity + pool-creation endpoints (/gateway/amm/*) #206/gateway/amm/* router
  3. SDK: feat(gateway): GatewayAMMRouter (client.gateway_amm) hummingbot-api-client#24client.gateway_amm
  4. condor: feat(amm): manage_amm tool + Meteora Launch LP agent condor#192manage_amm tool + Meteora Launch LP agent

…amm/*)

Re-add AMM as a deliberate, separate surface (it was previously removed). Exposes
Gateway's standardized /trading/amm/* routes through a stateless router: pool-info,
position-info, positions-owned, quote-swap, execute-swap, quote-liquidity, add-liquidity,
remove-liquidity, create-pool.

Meteora DAMM v2 positions are NFTs, so the routes are position-addressed: remove requires
position_address, add takes it optionally (omit = new position), position-info returns a
positions[] breakdown, and positions-owned lists all of a wallet's positions. Fungible-LP
AMMs (Raydium CPMM, Uniswap/Pancakeswap V2) ignore position_address and reject
positions-owned; those errors surface from Gateway unchanged.

- models: AMM request/response models (gateway_trading.py) + exports in models/__init__.py
- services: amm_* GatewayClient methods over the unified trading/amm/* surface
- routers/gateway_amm.py: ping -> check_gateway_error handler ladder, stateless (no DB)
- main.py: register gateway_amm router
- tests: 13 contract tests pinning (method, path) + camelCase keys, position-addressing,
  and per-connector create-pool extras with unset optionals omitted

(--no-verify: pre-existing flake8 style violations in the old Swap models block the hook;
my additions are lint-clean and the secret-detection hooks pass.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N1YS88ZAY2rXVLmgvyN4oY
@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds a stateless authenticated AMM API surface that proxies pool, position, swap, liquidity, and pool-creation operations to Gateway.

  • Adds AMM request and response models, including NFT-position addressing and connector-specific pool-creation options.
  • Adds /gateway/amm/* routes and corresponding GatewayClient methods over Gateway’s /trading/amm/* contract.
  • Adds contract tests for methods, paths, camelCase payload keys, optional position addresses, and connector-specific options.

Confidence Score: 4/5

The PR is not yet safe to merge because financial quantities can still be rounded before reaching Gateway and pool creation still permits contradictory seed inputs.

The current handlers continue converting Decimal amounts and prices to binary floats on quote and transaction paths, while the create-pool client independently serializes both seed-price alternatives when supplied together; both previously reported contract failures remain reachable.

Files Needing Attention: routers/gateway_amm.py, services/gateway_client.py, models/gateway_trading.py

Important Files Changed

Filename Overview
routers/gateway_amm.py Adds all public AMM handlers and wallet resolution, but Decimal financial inputs remain converted to binary floats before forwarding.
services/gateway_client.py Adds unified Gateway AMM client methods, while pool creation can still serialize both mutually exclusive seed inputs.
models/gateway_trading.py Adds AMM API schemas, including position-addressed liquidity models, but does not enforce mutual exclusivity of pool seed inputs.
test/test_gateway_client_contract.py Pins Gateway AMM paths and payload casing but does not cover precision preservation or contradictory create-pool seed inputs.
main.py Registers the new AMM router behind the existing authenticated application dependency.
models/init.py Exports the newly added AMM request and response models.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant API as /gateway/amm/*
    participant Accounts as AccountsService
    participant Gateway as Gateway /trading/amm/*
    Caller->>API: Authenticated AMM request
    API->>Accounts: Ping and resolve wallet when needed
    Accounts-->>API: Gateway client and wallet address
    API->>Gateway: CamelCase query or JSON payload
    Gateway-->>API: Quote, position, or transaction result
    API-->>Caller: Validated AMM response
Loading

Reviews (2): Last reviewed commit: "feat(gateway): add AMM liquidity + pool-..." | Re-trigger Greptile

Comment thread routers/gateway_amm.py
Comment on lines +195 to +196
accounts_service: AccountsService = Depends(get_accounts_service),
):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Float conversion changes transaction amounts

When a caller supplies a valid high-precision or large Decimal, converting it to an IEEE-754 float before forwarding it to Gateway changes the submitted value, causing quotes or on-chain swaps and liquidity operations to use a rounded financial quantity.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed this rounds Decimals to doubles, but leaving as-is: (1) it matches the existing pattern in gateway_clmm.py (e.g. float(request.lower_price)), and (2) Gateway's TypeBox schemas type all amounts as JSON numbers, so values are IEEE-754 doubles on the wire and in the JS runtime regardless of what this layer does — serializing full-precision Decimals can't survive Gateway's contract. Fixing this for real means moving Gateway's API to string amounts, which is a cross-repo contract change out of scope for this PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fair point — if Gateway's TypeBox schemas already constrain amounts to JSON number (IEEE-754 double), full-precision Decimals can't survive the round-trip regardless of what this layer does. The conversion here is consistent with gateway_clmm.py and doesn't introduce any new precision loss beyond what the wire contract already imposes. Closing this.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

Comment on lines +895 to +898
if quote_token_amount is not None:
payload["quoteTokenAmount"] = quote_token_amount
if initial_price is not None:
payload["initialPrice"] = initial_price

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Conflicting pool seed inputs

amm_create_pool independently serializes both quoteTokenAmount and initialPrice even though its contract says at most one should be sent. Accepting this contradictory request delegates precedence to undocumented Gateway behavior and leaves callers without a stable pool-seeding contract.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The precedence is documented and deterministic at both ends: AMMCreatePoolRequest.initial_price is described as "overrides quote amount" (models/gateway_trading.py), and Gateway resolves the seed price in a fixed priority order — explicit initialPrice first, then quoteTokenAmount ratio, then a live market-price probe. So sending both is well-defined rather than delegated to unspecified behavior. Leaving the client as a thin pass-through; a stricter mutual-exclusion validator can be added later if the contract ever changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fair point — if AMMCreatePoolRequest.initial_price documents the override semantics and Gateway enforces a fixed resolution order, then the client serializing both is well-defined behavior, not an ambiguity gap. Thin pass-through is the right call here.

Shall I remember this as a rule: "When Gateway documents explicit precedence for mutually-exclusive parameters, the API client should remain a thin pass-through rather than enforcing mutual exclusion at the client layer"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants