@@ -346,6 +346,12 @@ async def test_choose_x402_route_prefers_exact_when_gateway_is_unfunded():
346346 formatted_available = "0.00" ,
347347 )
348348 ),
349+ get_gateway_onchain_balance = AsyncMock (
350+ return_value = SimpleNamespace (
351+ available = 0 ,
352+ formatted_available = "0.00" ,
353+ )
354+ ),
349355 )
350356 x402_adapter = SimpleNamespace (
351357 _resolve_agent_network = lambda wallet_id , destination_chain : "eip155:84532"
@@ -385,6 +391,12 @@ async def test_choose_x402_route_keeps_gateway_when_it_is_the_only_option():
385391 formatted_available = "0.00" ,
386392 )
387393 ),
394+ get_gateway_onchain_balance = AsyncMock (
395+ return_value = SimpleNamespace (
396+ available = 0 ,
397+ formatted_available = "0.00" ,
398+ )
399+ ),
388400 )
389401 x402_adapter = SimpleNamespace (
390402 _resolve_agent_network = lambda wallet_id , destination_chain : "eip155:84532"
@@ -403,6 +415,52 @@ async def test_choose_x402_route_keeps_gateway_when_it_is_the_only_option():
403415 assert route ["gateway_ready" ] is False
404416
405417
418+ @pytest .mark .asyncio
419+ async def test_choose_x402_route_uses_onchain_fallback_when_api_balance_is_stale ():
420+ gateway_kind = SimpleNamespace (
421+ amount_atomic = 250000 ,
422+ is_gateway_batched = True ,
423+ get_amount_usdc = lambda : Decimal ("0.25" ),
424+ )
425+ requirements = SimpleNamespace (
426+ select_preferred_kind = lambda * , prefer_gateway , source_network : (
427+ gateway_kind if prefer_gateway else None
428+ )
429+ )
430+ client = SimpleNamespace (
431+ _nano_adapter = object (),
432+ get_gateway_balance = AsyncMock (
433+ return_value = SimpleNamespace (
434+ available = 0 ,
435+ formatted_available = "0.00" ,
436+ )
437+ ),
438+ get_gateway_onchain_balance = AsyncMock (
439+ return_value = SimpleNamespace (
440+ available = 300000 ,
441+ formatted_available = "0.30" ,
442+ )
443+ ),
444+ )
445+ x402_adapter = SimpleNamespace (
446+ _resolve_agent_network = lambda wallet_id , destination_chain : "eip155:84532"
447+ )
448+
449+ route = await _choose_x402_route (
450+ client = client ,
451+ wallet_id = "buyer-wallet" ,
452+ x402_adapter = x402_adapter ,
453+ requirements = requirements ,
454+ )
455+
456+ assert route ["selected_route" ] == "nanopayment"
457+ assert route ["payment_source" ] == "gateway_balance"
458+ assert route ["selected_kind" ] is gateway_kind
459+ assert route ["gateway_ready" ] is True
460+ assert route ["gateway_available_balance" ] == "0.30"
461+ assert route ["gateway_reason" ] == "Gateway on-chain balance is sufficient (API balance appears stale)"
462+
463+
406464@pytest .mark .asyncio
407465async def test_pay_route_inspects_url_even_when_amount_is_supplied (
408466 monkeypatch : pytest .MonkeyPatch ,
0 commit comments