fix / gateway use unified /trading endpoints and stop masking Gateway errors - #193
Merged
Conversation
… errors
GatewayClient:
- swaps go through Gateway's unified /trading/swap/{quote,execute} instead of
/connectors/{c}/router/*, which 404'd for clmm-only connectors (meteora,
orca) and doubled the path for typed values like "jupiter/router"
- normalize_swap_connector(): bare router connectors (jupiter, 0x, uniswap,
pancakeswap) get /router appended, everything else /clmm; typed values
pass through
- CLMM ops go through unified /trading/clmm/* with the schema Gateway
actually expects (chainNetwork, walletAddress, percentageToRemove)
- add GatewayError + check_gateway_error() for the {"error","status"} dict
_request returns on non-OK responses
Callers:
- /gateway/swap/quote no longer renders a Gateway 404 as a 200 quote with
price "0" — Gateway errors propagate with their real status code
- _refresh_position_data no longer closes DB positions when
positions-owned returns a Gateway error
- transaction poller treats Gateway HTTP errors as transient instead of
recording them as on-chain FAILED
- gecko price source no longer caches an empty token map on Gateway errors
- slippage_pct=0 was dropped as falsy everywhere; use `is not None`
Adds contract tests pinning paths/payload keys and error propagation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ko4KsGwUaHjqiRTYon31Li
…n AllConnectorSettings Gateway network connectors (e.g. 'solana-mainnet-beta') are only enumerated into hummingbot's AllConnectorSettings by GatewayHttpClient's status monitor, which reads /config/chains when Gateway comes online. That monitor is started by the standalone client's TradingCore but was never started here, so Gateway networks were absent from AllConnectorSettings until a connector for one happened to be constructed on demand. Start the monitor in the app lifespan (and stop it on shutdown). Newly added chains (e.g. unichain, robinhoodchain) now enumerate without first deploying a bot on them, and the monitor picks up Gateway coming online later. Startup is unaffected when Gateway is unreachable — the monitor pings in the background and simply stays offline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lur3b8AWCGzTQq3cG6kjxr
Contributor
|
Commit e1dd9af
Start HAPI using
|
… it until mTLS certs exist On a fresh install the monitor started by e1dd9af pinged Gateway every 2s before anything had populated Security.secrets_manager (it was only set lazily on first connector creation), so each ping crashed building the mTLS client with "AttributeError: 'NoneType' object has no attribute 'password'". - Log master_account in during lifespan startup, before the GatewayHttpClient singleton is created, so Security.secrets_manager is always set (and a wrong CONFIG_PASSWORD now fails startup with a clear error instead of surfacing later as decrypt failures). - When Gateway is secured (https) but the shared mTLS certs haven't been generated yet (fresh install, Gateway never started), defer the monitor instead of letting every ping fail loudly on the missing cert files. GatewayService.start() starts it right after generating the certs (start_monitor is a no-op when already running). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
Commit 8758059
Test in progress:
|
Contributor
Author
|
Try testing the case where the Gateway container is already running when
the user starts the Hummingbot API, as well as when it's not running and
the user starts it with the Hummingbot API.
GET /connectors/ should work in both cases
…On Mon, Jul 20, 2026 at 8:38 AM Ralph Comia ***@***.***> wrote:
*rapcmia* left a comment (hummingbot/hummingbot-api#193)
<#193 (comment)>
Commit 8758059
<8758059>
Start HAPI using make deploy failed due to AttributeError: 'NoneType'
object has no attribute 'password' ❌
- Reported issue on password has been fixed ✅
- Start Gateway through hummingbot-api without restarting the API ✅
- Confirm GET /connectors/ eventually includes solana-mainnet-beta and
the other configured Gateway networks. ✅
curl -s -u admin1:admin2 http://localhost:8000/gateway/chains |
jq '[.chains[] | .chain as $chain | .networks[] | "\($chain)-\(.)"]'
curl -s -u admin1:admin2 http://localhost:8000/connectors/ |
jq '[.[] | select(startswith("ethereum-") or startswith("solana-"))]'
Both commands returned the same 11 networks:
[
"ethereum-arbitrum",
"ethereum-avalanche",
"ethereum-base",
"ethereum-bsc",
"ethereum-celo",
"ethereum-mainnet",
"ethereum-optimism",
"ethereum-polygon",
"ethereum-sepolia",
"solana-devnet",
"solana-mainnet-beta"
]
- The network IDs generated from GET /gateway/chains exactly matched
the Gateway network IDs returned by GET /connectors
- All 11 networks are avail;able, including solana-mainnet-beta and
soalna-devnet
- Run the two developer test files and record the stated 32 passing
tests. ✅
- Test a valid Jupiter quote, slippage_pct: 0, and a invalid
connector.
#### Valid jupiter quote
curl -s -u admin1:admin2 -H 'Content-Type: application/json' -X POST http://localhost:8000/gateway/swap/quote -d '{
"connector": "jupiter",
"network": "solana-mainnet-beta",
"trading_pair": "SOL-USDC",
"side": "SELL",
"amount": 0.01,
"slippage_pct": 1.0
}' | jq
{
"base": "SOL",
"quote": "USDC",
"price": "76.9555",
"amount": "0.01",
"amount_in": "0.01",
"amount_out": "0.769555",
"expected_amount": "0.769555",
"slippage_pct": "1.0",
"gas_estimate": null
}
#### Jupiter quote with zero slippage
curl -s -u admin1:admin2 -H 'Content-Type: application/json' -X POST http://localhost:8000/gateway/swap/quote -d '{
"connector": "jupiter",
"network": "solana-mainnet-beta",
"trading_pair": "SOL-USDC",
"side": "SELL",
"amount": 0.01,
"slippage_pct": 0
}' | jq
{
"base": "SOL",
"quote": "USDC",
"price": "76.9525",
"amount": "0.01",
"amount_in": "0.01",
"amount_out": "0.769525",
"expected_amount": "0.769525",
"slippage_pct": "0",
"gas_estimate": null
}
#### Invalid conenctor error body
curl -s -u admin1:admin2 -H 'Content-Type: application/json' -X POST http://localhost:8000/gateway/swap/quote -d '{
"connector": "bogus",
"network": "solana-mainnet-beta",
"trading_pair": "SOL-USDC",
"side": "SELL",
"amount": 0.01,
"slippage_pct": 1.0
}' | jq
{
"detail": "Gateway error getting swap quote: Failed to get swap quote: Unsupported chain: bogus. Supported chains: ethereum, solana"
}
- The Jupiter requests confirmed unified swap quoting works with or
without slippage value ok
- Invalid connector response kept Gateway real error and non-200
status instead of successful zero-price quote
------------------------------
Test in progress:
- Test a read-only CLMM request and error propagation for an unknown
position.
- Test with hbot/8377, complete the Gateway OrderExecutor,
mint-address token, invalid-network, and CEX regression checks
—
Reply to this email directly, view it on GitHub
<#193?email_source=notifications&email_token=AANWHVUS5G6FRAF2VO35SG35FY4HLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBSGQYTAMRTG44KM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#issuecomment-5024102378>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANWHVWEJDYJMSXNHJU4CCL5FY4HLAVCNFSNUABFKJSXA33TNF2G64TZHM3TGMBXGUZTQNZWHNEXG43VMU5TIOBYGAYDKOJZGY3KC5QC>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Contributor
|
PR update:
Test a read-only CLMM request and error propagation for an unknown position. ✅
Test with hbot/8377, complete the Gateway OrderExecutor, mint-address token, invalid-network, and CEX regression checks ✅
Invalid gateway network fails without creating or registering an executor ✅
Regression tests on CEX using OrderExecutor ✅
|
rapcmia
approved these changes
Jul 21, 2026
rapcmia
left a comment
Contributor
There was a problem hiding this comment.
- Gateway startup, restart, and connector-network lifecycle checks.
- All 11 configured Ethereum and Solana networks appeared in /connectors/.
- Developer tests: 32 passed with 8 warnings.
- Jupiter quote, zero-slippage, and invalid-connector error propagation.
- Read-only CLMM request and unknown-position add/remove liquidity errors.
- Solana Gateway OrderExecutor market sell with non-zero fill and wallet update.
- Jupiter swap using a mint-address token.
- Invalid-network rejection without creating or registering an executor.
- Gate.io CEX regression:
- Successful BTC-USDT market buy and sell.
- Oversized order terminated with INSUFFICIENT_BALANCE.
- No order ID, fills, fees, balance change, active order, or running executor.
- Manually confirmed no order appeared in Gate.io exchange history.
A Gateway network such as 'solana-mainnet-beta' can exist twice in the account-state pipeline: as a unified Gateway trading connector and as a Gateway wallet fetched by _update_gateway_balances. Both wrote the same accounts_state[account]['solana-mainnet-beta'] key, and since connector results are applied after the gather, the connector view always won. That view is much narrower: gateway_base.update_balances() only queries Gateway for the tokens of the connector's trading pairs plus the native currency, so wallet tokens the connector doesn't trade disappear from portfolio state, and mint-address trading pairs report mint addresses instead of symbols. Skip Gateway connectors in the per-connector balance pass so the full wallet snapshot is the single source of truth for those keys, and mirror it onto non-master accounts holding the same connector (they trade the same Gateway default wallet) so their state doesn't go stale. Verified against a live Gateway: portfolio state now returns all seven wallet tokens with symbols, matching POST /chains/solana/balances; on the previous code the same setup returned four. Fixes #195 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
An audit of every Gateway route used by hummingbot-api (against Gateway
core-2.9/feat-robinhood-chainrunning on mTLS 15888) found the swap and CLMM paths pointing at routes that don't exist, plus a class of bugs where Gateway's error responses were silently treated as data.GatewayClient
/trading/swap/{quote,execute}instead of/connectors/{c}/router/*. The old path 404'd for clmm-only connectors (meteora, orca, pancakeswap-sol) and doubled the segment for typed values (jupiter/router→.../router/router/quote-swap).normalize_swap_connector(): bare router connectors (jupiter, 0x, uniswap, pancakeswap) get/routerappended, everything else/clmm; already-typed values (meteora/clmm,raydium/amm) pass through./trading/clmm/*with the schema Gateway actually expects:chainNetwork,walletAddress,percentageToRemove(the legacy/clmm/liquidity/*paths andaddress/percentagekeys don't exist on Gateway).GatewayError+check_gateway_error()for the{"error", "status"}dict_requestreturns on non-OK responses.Error propagation fixes
/gateway/swap/quoteno longer renders a Gateway 404 as a 200 quote withprice: "0"— Gateway errors propagate with their real status code and message._refresh_position_datano longer closes positions in the DB when positions-owned returns a Gateway error (only when the position is genuinely absent from a valid response).slippage_pct=0was dropped as falsy and replaced with the 1.0 default in several places; now usesis not None.Gateway connector discovery
main.py) and stop it on shutdown.GatewayHttpClient's monitor reads/config/chainswhen Gateway comes online and registers each network connector (e.g.solana-mainnet-beta,ethereum-mainnet, and newly added chains likeethereum-unichain) into hummingbot'sAllConnectorSettings. That monitor is started by the standalone client'sTradingCorebut was never started here, so Gateway networks were absent fromAllConnectorSettingsuntil a connector for one happened to be constructed on demand. Startup is unaffected when Gateway is unreachable — the monitor pings in the background and simply stays offline.Test plan
pytest test/test_gateway_client_contract.py test/test_gateway_error_masking.py— 32 tests pinning the paths, payload keys, and error behavior (all passing).meteora/clmmand barejupiterquotes return real prices; a bogus connector returns Gateway's real error instead of price 0; CLMM remove-liquidity hits/trading/clmm/removeand propagates Gateway's 404 for an unknown position;slippage_pct: 0round-trips as"0".GET /connectors/lists all Gateway networks from/config/chains; with Gateway unreachable the API still boots (200, no networks, no traceback) and picks them up on the next successful poll; clean shutdown stops the monitor without hanging.QA — test this PR together with hummingbot #8377
These two PRs are the paired Gateway fix: #193 (this PR) fixes hummingbot-api's own Gateway REST layer + connector discovery; hummingbot #8377 makes the in-process
OrderExecutorwork on Gateway swaps (order sizing, skipping the BudgetChecker, unified/trading/swap/*routes, andAllConnectorSettingsregistration on connector start). Test them together so the fullPOST /executors/→ Gateway path is exercised.Setup
mainnet-betaand a swap router (e.g. Jupiter). Add a funded Solana wallet (a few USD of SOL for the swap + gas is enough) and set it as the default. ConfirmGET http://localhost:15888/config/chainslistssolana.git checkout fix/gateway-unified-endpoints docker compose up emqx postgres -d uvicorn main:app --reload # GATEWAY_URL in .env points at Gateway (default http://localhost:15888)1. Connector discovery (this PR)
GET /connectors/→ the Gateway networks (solana-mainnet-beta,ethereum-mainnet, …) appear in the list. Ondevelopmentthey're absent (the monitor never runs), so this is the before/after.2. Swap quote + error masking (this PR)
POST /gateway/swap/quotewith{ "connector": "jupiter", "network": "solana-mainnet-beta", "trading_pair": "SOL-USDC", "side": "SELL", "amount": 0.01, "slippage_pct": 1.0 }→ a real price, not0.connector→ Gateway's real error propagates with its status, not a 200price: "0".3. End-to-end OrderExecutor on Gateway (needs #8377)
Deploy a swap executor.
connector_nameis the Gateway network idsolana-mainnet-beta(notjupiter/jupiter/router— the unifiedGatewayconnector resolves the swap provider and default wallet itself):RUNNING, sizes the order, submits through the unified/trading/swap/executeroute, and fills on-chain (GET /executors/{id}→POSITION_HOLDwith a non-zerofilled_amount_quote); verify the SOL→USDC balance change on-chain.on_startwithInvalid connector. solana-mainnet-beta does not exist in AllConnectorSettings— this is exactly what #8377 fixes.developmentit crashes inget_order_size_quantumwithKeyError; with #8377 it quantizes to 6 decimals and submits.4. Bad input + regression
connector_name(e.g.solana-typo-net) → the deploy fails fast with HTTP 500Unknown network …atstart_network, no executor is left running, and the bad name is not registered inAllConnectorSettings.order_executor(e.g.binancepaper trade) and confirm the standardBudgetCheckerbalance validation still behaves as before.🤖 Generated with Claude Code
https://claude.ai/code/session_01Ko4KsGwUaHjqiRTYon31Li