Skip to content

Commit 1202e93

Browse files
authored
[LABS-293] Ensure wallet is synced for RPC TX endpoints (#20190)
* Ensure wallet is synced for RPC tx endpoints * Address flakes * more flakes * More flakes in DL tests
1 parent fcdb8e4 commit 1202e93

File tree

5 files changed

+34
-23
lines changed

5 files changed

+34
-23
lines changed

chia/_tests/core/data_layer/test_data_rpc.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
from chia.wallet.trading.offer import Offer as TradingOffer
7474
from chia.wallet.transaction_record import TransactionRecord
7575
from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
76-
from chia.wallet.wallet import Wallet
7776
from chia.wallet.wallet_node import WalletNode
7877
from chia.wallet.wallet_request_types import CheckOfferValidity, DLLatestSingleton
7978
from chia.wallet.wallet_rpc_api import WalletRpcApi
@@ -763,6 +762,7 @@ async def test_get_owned_stores(
763762
ph = await action_scope.get_puzzle_hash(wallet_node.wallet_state_manager)
764763
for i in range(num_blocks):
765764
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
765+
await full_node_api.wait_for_wallet_synced(wallet_node, timeout=30)
766766
funds = sum(
767767
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks)
768768
)
@@ -845,6 +845,11 @@ class OfferSetup:
845845
maker: StoreSetup
846846
taker: StoreSetup
847847
full_node_api: FullNodeSimulator
848+
wallet_nodes: list[WalletNode]
849+
850+
async def wait_for_wallets_synced(self, timeout: int = 30) -> None:
851+
for node in self.wallet_nodes:
852+
await self.full_node_api.wait_for_wallet_synced(wallet_node=node, timeout=timeout)
848853

849854

850855
@pytest.fixture(name="offer_setup")
@@ -857,16 +862,17 @@ async def offer_setup_fixture(
857862
[full_node_service], wallet_services, bt = two_wallet_nodes_services
858863
enable_batch_autoinsertion_settings = getattr(request, "param", (True, True))
859864
full_node_api = full_node_service._api
860-
wallets: list[Wallet] = []
865+
wallets: list[WalletNode] = []
861866
for wallet_service in wallet_services:
862867
wallet_node = wallet_service._node
863868
assert wallet_node.server is not None
864869
await wallet_node.server.start_client(PeerInfo(self_hostname, full_node_api.server.get_port()), None)
865870
assert wallet_node.wallet_state_manager is not None
866871
wallet = wallet_node.wallet_state_manager.main_wallet
867-
wallets.append(wallet)
872+
wallets.append(wallet_node)
868873

869874
await full_node_api.farm_blocks_to_wallet(count=1, wallet=wallet, timeout=60)
875+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=30)
870876

871877
async with contextlib.AsyncExitStack() as exit_stack:
872878
store_setups: list[StoreSetup] = []
@@ -951,6 +957,7 @@ async def offer_setup_fixture(
951957
data_rpc_client=taker.data_rpc_client,
952958
),
953959
full_node_api=full_node_api,
960+
wallet_nodes=wallets,
954961
)
955962

956963
maker.data_rpc_client.close()
@@ -1018,6 +1025,7 @@ async def populate_offer_setup(offer_setup: OfferSetup, count: int) -> OfferSetu
10181025
data_rpc_client=offer_setup.taker.data_rpc_client,
10191026
),
10201027
full_node_api=offer_setup.full_node_api,
1028+
wallet_nodes=offer_setup.wallet_nodes,
10211029
)
10221030

10231031

@@ -1843,6 +1851,7 @@ async def test_make_and_cancel_offer(offer_setup: OfferSetup, reference: MakeAnd
18431851
# due to differences in chain progression, the exact offer and trade id may differ from the reference
18441852
# assert maker_response == {"success": True, "offer": reference.make_offer_response}
18451853
assert maker_response["success"] is True
1854+
await offer_setup.wait_for_wallets_synced()
18461855

18471856
cancel_request = {
18481857
"trade_id": maker_response["offer"]["trade_id"],
@@ -1926,6 +1935,7 @@ async def test_make_and_cancel_offer_then_update(
19261935
# due to differences in chain progression, the exact offer and trade id may differ from the reference
19271936
# assert maker_response == {"success": True, "offer": reference.make_offer_response}
19281937
assert maker_response["success"] is True
1938+
await offer_setup.wait_for_wallets_synced()
19291939

19301940
cancel_request = {
19311941
"trade_id": maker_response["offer"]["trade_id"],
@@ -2015,6 +2025,7 @@ async def test_make_and_cancel_offer_not_secure_clears_pending_roots(
20152025
# due to differences in chain progression, the exact offer and trade id may differ from the reference
20162026
# assert maker_response == {"success": True, "offer": reference.make_offer_response}
20172027
assert maker_response["success"] is True
2028+
await offer_setup.wait_for_wallets_synced()
20182029

20192030
cancel_request = {
20202031
"trade_id": maker_response["offer"]["trade_id"],
@@ -2568,6 +2579,7 @@ async def populate_proof_setup(offer_setup: OfferSetup, count: int) -> OfferSetu
25682579
data_rpc_client=offer_setup.taker.data_rpc_client,
25692580
),
25702581
full_node_api=offer_setup.full_node_api,
2582+
wallet_nodes=offer_setup.wallet_nodes,
25712583
)
25722584

25732585

chia/_tests/pools/test_pool_rpc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ async def test_self_pooling_to_pooling(self, setup: Setup, fee: uint64, self_hos
839839
our_ph, "", uint32(0), f"{self_hostname}:5000", "new", "SELF_POOLING", fee
840840
)
841841
await full_node_api.wait_transaction_records_entered_mempool(records=[creation_tx])
842+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
842843
creation_tx_2: TransactionRecord = await client.create_new_pool_wallet(
843844
our_ph, "", uint32(0), f"{self_hostname}:5001", "new", "SELF_POOLING", fee
844845
)

chia/_tests/wallet/rpc/test_dl_wallet_rpc.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ async def test_wallet_make_transaction(
7777
calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks)
7878
)
7979

80+
await full_node_api.wait_for_wallet_synced(wallet_node)
8081
await time_out_assert(15, wallet.get_confirmed_balance, initial_funds)
8182
await time_out_assert(15, wallet.get_unconfirmed_balance, initial_funds)
8283

@@ -111,6 +112,7 @@ async def test_wallet_make_transaction(
111112
for i in range(5):
112113
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
113114
await asyncio.sleep(0.5)
115+
await full_node_api.wait_for_wallet_synced(wallet_node)
114116

115117
async def is_singleton_confirmed(rpc_client: WalletRpcClient, lid: bytes32) -> bool:
116118
rec = (await rpc_client.dl_latest_singleton(DLLatestSingleton(lid))).singleton
@@ -131,6 +133,7 @@ async def is_singleton_confirmed(rpc_client: WalletRpcClient, lid: bytes32) -> b
131133
for i in range(5):
132134
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
133135
await asyncio.sleep(0.5)
136+
await full_node_api.wait_for_wallet_synced(wallet_node)
134137

135138
new_singleton_record = (await client.dl_latest_singleton(DLLatestSingleton(launcher_id))).singleton
136139
assert new_singleton_record is not None
@@ -219,13 +222,15 @@ async def is_singleton_generation(rpc_client: WalletRpcClient, lid: bytes32, gen
219222
launcher_id_2 = (
220223
await client.create_new_dl(CreateNewDL(root=merkle_root, fee=uint64(50), push=True), DEFAULT_TX_CONFIG)
221224
).launcher_id
225+
await full_node_api.wait_for_wallet_synced(wallet_node)
222226
launcher_id_3 = (
223227
await client.create_new_dl(CreateNewDL(root=merkle_root, fee=uint64(50), push=True), DEFAULT_TX_CONFIG)
224228
).launcher_id
225229

226230
for i in range(5):
227231
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
228232
await asyncio.sleep(0.5)
233+
await full_node_api.wait_for_wallet_synced(wallet_node)
229234

230235
await time_out_assert(15, is_singleton_confirmed, True, client, launcher_id_2)
231236
await time_out_assert(15, is_singleton_confirmed, True, client, launcher_id_3)
@@ -248,6 +253,7 @@ async def is_singleton_generation(rpc_client: WalletRpcClient, lid: bytes32, gen
248253
for i in range(5):
249254
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
250255
await asyncio.sleep(0.5)
256+
await full_node_api.wait_for_wallet_synced(wallet_node)
251257

252258
await time_out_assert(15, is_singleton_confirmed, True, client, launcher_id)
253259
await time_out_assert(15, is_singleton_confirmed, True, client, launcher_id_2)
@@ -283,6 +289,7 @@ async def is_singleton_generation(rpc_client: WalletRpcClient, lid: bytes32, gen
283289
for i in range(5):
284290
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
285291
await asyncio.sleep(0.5)
292+
await full_node_api.wait_for_wallet_synced(wallet_node)
286293
additions = []
287294
for tx in txs:
288295
if tx.spend_bundle is not None:

chia/_tests/wallet/rpc/test_wallet_rpc.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,6 +2003,7 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment) -
20032003

20042004
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
20052005
await farm_transaction_block(full_node_api, wallet_1_node)
2006+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_1_node, timeout=20)
20062007

20072008
# Update metadata
20082009
with pytest.raises(ValueError, match="wallet id 1 is of type Wallet but type DIDWallet is required"):
@@ -2018,6 +2019,7 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment) -
20182019

20192020
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
20202021
await farm_transaction_block(full_node_api, wallet_1_node)
2022+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_1_node, timeout=20)
20212023

20222024
# Transfer DID
20232025
async with wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
@@ -2031,6 +2033,8 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment) -
20312033

20322034
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
20332035
await farm_transaction_block(full_node_api, wallet_1_node)
2036+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_1_node, timeout=20)
2037+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_2_node, timeout=20)
20342038

20352039
async def num_wallets() -> int:
20362040
return len(await wallet_2_node.wallet_state_manager.get_all_wallet_info_entries())
@@ -2058,6 +2062,8 @@ async def num_wallets() -> int:
20582062

20592063
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
20602064
await farm_transaction_block(full_node_api, wallet_2_node)
2065+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_1_node, timeout=20)
2066+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_2_node, timeout=20)
20612067

20622068
next_did_coin = await did_wallet_2.get_coin()
20632069
assert next_did_coin.parent_coin_info == last_did_coin.name()
@@ -2070,6 +2076,8 @@ async def num_wallets() -> int:
20702076

20712077
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1)
20722078
await farm_transaction_block(full_node_api, wallet_2_node)
2079+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_1_node, timeout=20)
2080+
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_2_node, timeout=20)
20732081

20742082
next_did_coin = await did_wallet_2.get_coin()
20752083
assert next_did_coin.parent_coin_info == last_did_coin.name()

chia/wallet/wallet_rpc_api.py

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ def _inner(func: RpcEndpoint) -> RpcEndpoint:
322322
async def rpc_endpoint(
323323
self: WalletRpcApi, request: dict[str, Any], *args: object, **kwargs: object
324324
) -> EndpointResult:
325+
if await self.service.wallet_state_manager.synced() is False:
326+
raise ValueError("Wallet needs to be fully synced before making transactions.")
327+
325328
assert self.service.logged_in_fingerprint is not None
326329
tx_config_loader: TXConfigLoader = TXConfigLoader.from_json_dict(request)
327330

@@ -1113,9 +1116,6 @@ async def create_new_wallet(
11131116
extra_conditions: tuple[Condition, ...] = tuple(),
11141117
) -> EndpointResult:
11151118
wallet_state_manager = self.service.wallet_state_manager
1116-
1117-
if await self.service.wallet_state_manager.synced() is False:
1118-
raise ValueError("Wallet needs to be fully synced.")
11191119
main_wallet = wallet_state_manager.main_wallet
11201120
fee = uint64(request.get("fee", 0))
11211121

@@ -1631,9 +1631,6 @@ async def send_transaction(
16311631
action_scope: WalletActionScope,
16321632
extra_conditions: tuple[Condition, ...] = tuple(),
16331633
) -> SendTransactionResponse:
1634-
if await self.service.wallet_state_manager.synced() is False:
1635-
raise ValueError("Wallet needs to be fully synced before sending transactions")
1636-
16371634
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=Wallet)
16381635

16391636
# TODO: Add support for multiple puzhash/amount/memo sets
@@ -2154,8 +2151,6 @@ async def cat_spend(
21542151
extra_conditions: tuple[Condition, ...] = tuple(),
21552152
hold_lock: bool = True,
21562153
) -> CATSpendResponse:
2157-
if await self.service.wallet_state_manager.synced() is False:
2158-
raise ValueError("Wallet needs to be fully synced.")
21592154
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=CATWallet)
21602155

21612156
amounts: list[uint64] = []
@@ -2860,8 +2855,6 @@ async def did_transfer_did(
28602855
action_scope: WalletActionScope,
28612856
extra_conditions: tuple[Condition, ...] = tuple(),
28622857
) -> DIDTransferDIDResponse:
2863-
if await self.service.wallet_state_manager.synced() is False:
2864-
raise ValueError("Wallet needs to be fully synced.")
28652858
did_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet)
28662859
puzzle_hash: bytes32 = decode_puzzle_hash(request.inner_address)
28672860
async with self.service.wallet_state_manager.lock:
@@ -3331,8 +3324,6 @@ async def nft_mint_bulk(
33313324
) -> NFTMintBulkResponse:
33323325
if action_scope.config.push:
33333326
raise ValueError("Automatic pushing of nft minting transactions not yet available") # pragma: no cover
3334-
if await self.service.wallet_state_manager.synced() is False:
3335-
raise ValueError("Wallet needs to be fully synced.")
33363327
nft_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=NFTWallet)
33373328
if request.royalty_address in {None, ""}:
33383329
royalty_puzhash = await action_scope.get_puzzle_hash(self.service.wallet_state_manager)
@@ -3610,9 +3601,6 @@ async def pw_join_pool(
36103601
) -> PWJoinPoolResponse:
36113602
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=PoolWallet)
36123603

3613-
if await self.service.wallet_state_manager.synced() is False:
3614-
raise ValueError("Wallet needs to be fully synced.")
3615-
36163604
pool_wallet_info: PoolWalletInfo = await wallet.get_current_state()
36173605
if (
36183606
pool_wallet_info.current.state == FARMING_TO_POOL.value
@@ -3652,9 +3640,6 @@ async def pw_self_pool(
36523640
# Then we transition to FARMING_TO_POOL or SELF_POOLING
36533641
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=PoolWallet)
36543642

3655-
if await self.service.wallet_state_manager.synced() is False:
3656-
raise ValueError("Wallet needs to be fully synced.")
3657-
36583643
total_fee = await wallet.self_pool(request.fee, action_scope)
36593644
# tx_endpoint will take care of filling in these default values
36603645
return PWSelfPoolResponse(
@@ -3674,8 +3659,6 @@ async def pw_absorb_rewards(
36743659
extra_conditions: tuple[Condition, ...] = tuple(),
36753660
) -> PWAbsorbRewardsResponse:
36763661
"""Perform a sweep of the p2_singleton rewards controlled by the pool wallet singleton"""
3677-
if await self.service.wallet_state_manager.synced() is False:
3678-
raise ValueError("Wallet needs to be fully synced before collecting rewards")
36793662
wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=PoolWallet)
36803663

36813664
assert isinstance(wallet, PoolWallet)

0 commit comments

Comments
 (0)