Skip to content

Commit 96d1356

Browse files
[CHIA-3388] Port test_cat_endpoints in test_wallet_rpc.py to WalletTestFramework and R-CATs (#19818)
* Port `test_cat_endpoints` to `WalletTestFramework` * Use mint_cat from cat tests * Add RCAT parametrization * Delete now unnecessary `from_zero` * Minor clarification. --------- Co-authored-by: Amine Khaldi <[email protected]>
1 parent 590317c commit 96d1356

File tree

2 files changed

+194
-84
lines changed

2 files changed

+194
-84
lines changed

chia/_tests/wallet/rpc/test_wallet_rpc.py

Lines changed: 192 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from chia._tests.environments.wallet import WalletStateTransition, WalletTestFramework
2121
from chia._tests.util.setup_nodes import SimulatorsAndWalletsServices
2222
from chia._tests.util.time_out_assert import time_out_assert, time_out_assert_not_none
23+
from chia._tests.wallet.cat_wallet.test_cat_wallet import mint_cat
2324
from chia._tests.wallet.test_wallet_coin_store import (
2425
get_coin_records_amount_filter_tests,
2526
get_coin_records_amount_range_tests,
@@ -69,6 +70,7 @@
6970
from chia.wallet.cat_wallet.cat_constants import DEFAULT_CATS
7071
from chia.wallet.cat_wallet.cat_utils import CAT_MOD, construct_cat_puzzle
7172
from chia.wallet.cat_wallet.cat_wallet import CATWallet
73+
from chia.wallet.cat_wallet.r_cat_wallet import RCATWallet
7274
from chia.wallet.conditions import (
7375
ConditionValidTimes,
7476
CreateCoinAnnouncement,
@@ -1077,23 +1079,34 @@ async def test_get_transaction_count(wallet_rpc_environment: WalletRpcTestEnviro
10771079
assert transaction_count == 0
10781080

10791081

1082+
@pytest.mark.parametrize(
1083+
"wallet_environments",
1084+
[
1085+
{
1086+
"num_environments": 2,
1087+
"blocks_needed": [1, 1],
1088+
}
1089+
],
1090+
indirect=True,
1091+
)
1092+
@pytest.mark.limit_consensus_modes(reason="irrelevant")
1093+
@pytest.mark.parametrize("wallet_type", [CATWallet, RCATWallet])
10801094
@pytest.mark.anyio
1081-
async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment) -> None:
1082-
env: WalletRpcTestEnvironment = wallet_rpc_environment
1083-
1084-
wallet_node: WalletNode = env.wallet_1.node
1085-
1086-
client: WalletRpcClient = env.wallet_1.rpc_client
1087-
client_2: WalletRpcClient = env.wallet_2.rpc_client
1088-
1089-
full_node_api: FullNodeSimulator = env.full_node.api
1090-
1091-
await generate_funds(full_node_api, env.wallet_1, 1)
1092-
await generate_funds(full_node_api, env.wallet_2, 1)
1093-
1095+
async def test_cat_endpoints(wallet_environments: WalletTestFramework, wallet_type: type[CATWallet]) -> None:
1096+
env_0 = wallet_environments.environments[0]
1097+
env_1 = wallet_environments.environments[1]
1098+
env_0.wallet_aliases = {
1099+
"xch": 1,
1100+
"cat0": 2,
1101+
"cat1": 3,
1102+
}
1103+
env_1.wallet_aliases = {
1104+
"xch": 1,
1105+
"cat0": 2,
1106+
}
10941107
# Test a deprecated path
10951108
with pytest.raises(ValueError, match="dropped"):
1096-
await client.fetch(
1109+
await env_0.rpc_client.fetch(
10971110
"create_new_wallet",
10981111
{
10991112
"wallet_type": "cat_wallet",
@@ -1102,136 +1115,232 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment) -
11021115
)
11031116

11041117
# Creates a CAT wallet with 100 mojos and a CAT with 20 mojos and fee=10
1105-
await client.create_new_cat_and_wallet(uint64(100), fee=uint64(10), test=True)
1106-
await time_out_assert(20, check_client_synced, True, client)
1107-
1108-
res = await client.create_new_cat_and_wallet(uint64(20), test=True)
1109-
assert res["success"]
1110-
cat_0_id = res["wallet_id"]
1111-
asset_id = bytes32.fromhex(res["asset_id"])
1112-
assert len(asset_id) > 0
1113-
1114-
await assert_wallet_types(client, {WalletType.STANDARD_WALLET: 1, WalletType.CAT: 2})
1115-
await assert_wallet_types(client_2, {WalletType.STANDARD_WALLET: 1})
1116-
1117-
bal_0 = await client.get_wallet_balance(cat_0_id)
1118-
assert bal_0["confirmed_wallet_balance"] == 0
1119-
assert bal_0["pending_coin_removal_count"] == 1
1120-
col = await client.get_cat_asset_id(cat_0_id)
1121-
assert col == asset_id
1122-
assert (await client.get_cat_name(cat_0_id)) == CATWallet.default_wallet_name_for_unknown_cat(asset_id.hex())
1123-
await client.set_cat_name(cat_0_id, "My cat")
1124-
assert (await client.get_cat_name(cat_0_id)) == "My cat"
1125-
result = await client.cat_asset_id_to_name(col)
1118+
await mint_cat(
1119+
wallet_environments,
1120+
env_0,
1121+
"xch",
1122+
"cat0",
1123+
uint64(100),
1124+
wallet_type,
1125+
"cat0",
1126+
)
1127+
await mint_cat(
1128+
wallet_environments,
1129+
env_0,
1130+
"xch",
1131+
"cat1",
1132+
uint64(20),
1133+
wallet_type,
1134+
"cat1",
1135+
)
1136+
1137+
cat_0_id = env_0.wallet_aliases["cat0"]
1138+
# The RPC response contains more than just the balance info but all the
1139+
# balance info should match. We're leveraging the `<=` operator to check
1140+
# for subset on `dict` `.items()`.
1141+
assert (
1142+
env_0.wallet_states[uint32(env_0.wallet_aliases["cat0"])].balance.to_json_dict().items()
1143+
<= (await env_0.rpc_client.get_wallet_balance(cat_0_id)).items()
1144+
)
1145+
asset_id = await env_0.rpc_client.get_cat_asset_id(cat_0_id)
1146+
assert (await env_0.rpc_client.get_cat_name(cat_0_id)) == wallet_type.default_wallet_name_for_unknown_cat(
1147+
asset_id.hex()
1148+
)
1149+
await env_0.rpc_client.set_cat_name(cat_0_id, "My cat")
1150+
assert (await env_0.rpc_client.get_cat_name(cat_0_id)) == "My cat"
1151+
result = await env_0.rpc_client.cat_asset_id_to_name(asset_id)
11261152
assert result is not None
11271153
wid, name = result
11281154
assert wid == cat_0_id
11291155
assert name == "My cat"
1130-
result = await client.cat_asset_id_to_name(bytes32.zeros)
1156+
result = await env_0.rpc_client.cat_asset_id_to_name(bytes32.zeros)
11311157
assert result is None
11321158
verified_asset_id = next(iter(DEFAULT_CATS.items()))[1]["asset_id"]
1133-
result = await client.cat_asset_id_to_name(bytes32.from_hexstr(verified_asset_id))
1159+
result = await env_0.rpc_client.cat_asset_id_to_name(bytes32.from_hexstr(verified_asset_id))
11341160
assert result is not None
11351161
should_be_none, name = result
11361162
assert should_be_none is None
11371163
assert name == next(iter(DEFAULT_CATS.items()))[1]["name"]
11381164

1139-
# make sure spend is in mempool before farming tx block
1140-
await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 2)
1141-
for i in range(5):
1142-
if check_mempool_spend_count(full_node_api, 0):
1143-
break
1144-
await farm_transaction_block(full_node_api, wallet_node)
1145-
1146-
# check that we farmed the transaction
1147-
assert check_mempool_spend_count(full_node_api, 0)
1148-
await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=5)
1149-
1150-
await time_out_assert(5, get_confirmed_balance, 20, client, cat_0_id)
1151-
bal_0 = await client.get_wallet_balance(cat_0_id)
1152-
assert bal_0["pending_coin_removal_count"] == 0
1153-
assert bal_0["unspent_coin_count"] == 1
1154-
11551165
# Creates a second wallet with the same CAT
1156-
res = await client_2.create_wallet_for_existing_cat(asset_id)
1166+
res = await env_1.rpc_client.create_wallet_for_existing_cat(asset_id)
11571167
assert res["success"]
11581168
cat_1_id = res["wallet_id"]
11591169
cat_1_asset_id = bytes.fromhex(res["asset_id"])
11601170
assert cat_1_asset_id == asset_id
11611171

1162-
await assert_wallet_types(client, {WalletType.STANDARD_WALLET: 1, WalletType.CAT: 2})
1163-
await assert_wallet_types(client_2, {WalletType.STANDARD_WALLET: 1, WalletType.CAT: 1})
1164-
1165-
await farm_transaction_block(full_node_api, wallet_node)
1166-
1167-
bal_1 = await client_2.get_wallet_balance(cat_1_id)
1168-
assert bal_1["confirmed_wallet_balance"] == 0
1172+
await wallet_environments.process_pending_states(
1173+
[
1174+
WalletStateTransition(),
1175+
WalletStateTransition(
1176+
pre_block_balance_updates={
1177+
"cat0": {
1178+
"init": True,
1179+
}
1180+
},
1181+
post_block_balance_updates={},
1182+
),
1183+
]
1184+
)
11691185

1170-
addr_0 = await client.get_next_address(cat_0_id, False)
1171-
addr_1 = await client_2.get_next_address(cat_1_id, False)
1186+
addr_0 = await env_0.rpc_client.get_next_address(cat_0_id, False)
1187+
addr_1 = await env_1.rpc_client.get_next_address(cat_1_id, False)
11721188

11731189
assert addr_0 != addr_1
11741190

11751191
# Test CAT spend without a fee
11761192
with pytest.raises(ValueError):
1177-
await client.cat_spend(
1193+
await env_0.rpc_client.cat_spend(
11781194
cat_0_id,
11791195
DEFAULT_TX_CONFIG.override(
1180-
excluded_coin_amounts=[uint64(20)],
1196+
excluded_coin_amounts=[uint64(100)],
11811197
excluded_coin_ids=[bytes32.zeros],
11821198
),
11831199
uint64(4),
11841200
addr_1,
11851201
uint64(0),
11861202
["the cat memo"],
11871203
)
1188-
tx_res = await client.cat_spend(cat_0_id, DEFAULT_TX_CONFIG, uint64(4), addr_1, uint64(0), ["the cat memo"])
1204+
tx_res = await env_0.rpc_client.cat_spend(
1205+
cat_0_id, wallet_environments.tx_config, uint64(4), addr_1, uint64(0), ["the cat memo"]
1206+
)
11891207

11901208
spend_bundle = tx_res.transaction.spend_bundle
11911209
assert spend_bundle is not None
11921210
assert uncurry_puzzle(spend_bundle.coin_spends[0].puzzle_reveal).mod == CAT_MOD
1193-
await farm_transaction(full_node_api, wallet_node, spend_bundle)
11941211

1195-
await farm_transaction_block(full_node_api, wallet_node)
1212+
await wallet_environments.process_pending_states(
1213+
[
1214+
WalletStateTransition(
1215+
pre_block_balance_updates={
1216+
"cat0": {
1217+
"unconfirmed_wallet_balance": -4,
1218+
"spendable_balance": -100,
1219+
"max_send_amount": -100,
1220+
"pending_change": 96,
1221+
"pending_coin_removal_count": 1,
1222+
}
1223+
},
1224+
post_block_balance_updates={
1225+
"cat0": {
1226+
"confirmed_wallet_balance": -4,
1227+
"spendable_balance": 96,
1228+
"max_send_amount": 96,
1229+
"pending_change": -96,
1230+
"pending_coin_removal_count": -1,
1231+
}
1232+
},
1233+
),
1234+
WalletStateTransition(
1235+
pre_block_balance_updates={},
1236+
post_block_balance_updates={
1237+
"cat0": {
1238+
"confirmed_wallet_balance": 4,
1239+
"unconfirmed_wallet_balance": 4,
1240+
"spendable_balance": 4,
1241+
"max_send_amount": 4,
1242+
"unspent_coin_count": 1,
1243+
}
1244+
},
1245+
),
1246+
]
1247+
)
11961248

11971249
# Test CAT spend with a fee
1198-
tx_res = await client.cat_spend(cat_0_id, DEFAULT_TX_CONFIG, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"])
1250+
tx_res = await env_0.rpc_client.cat_spend(
1251+
cat_0_id, wallet_environments.tx_config, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"]
1252+
)
11991253

12001254
spend_bundle = tx_res.transaction.spend_bundle
12011255
assert spend_bundle is not None
1202-
await farm_transaction(full_node_api, wallet_node, spend_bundle)
1256+
1257+
cat_spend_changes = [
1258+
WalletStateTransition(
1259+
pre_block_balance_updates={
1260+
"xch": {
1261+
"unconfirmed_wallet_balance": -5_000_000,
1262+
"<=#spendable_balance": -5_000_000,
1263+
"<=#max_send_amount": -5_000_000,
1264+
">=#pending_change": 1, # any amount increase
1265+
"unspent_coin_count": 0,
1266+
"pending_coin_removal_count": 1,
1267+
},
1268+
"cat0": {
1269+
"unconfirmed_wallet_balance": -1,
1270+
"<=#spendable_balance": -1,
1271+
"<=#max_send_amount": -1,
1272+
">=#pending_change": 1,
1273+
"pending_coin_removal_count": 1,
1274+
},
1275+
},
1276+
post_block_balance_updates={
1277+
"xch": {
1278+
"confirmed_wallet_balance": -5_000_000,
1279+
">=#spendable_balance": 1, # any amount increase
1280+
">=#max_send_amount": 1, # any amount increase
1281+
"<=#pending_change": -1, # any amount decrease
1282+
"unspent_coin_count": 0,
1283+
"pending_coin_removal_count": -1,
1284+
},
1285+
"cat0": {
1286+
"confirmed_wallet_balance": -1,
1287+
">=#spendable_balance": 1, # any amount increase
1288+
">=#max_send_amount": 1, # any amount increase
1289+
"<=#pending_change": -1, # any amount decrease
1290+
"pending_coin_removal_count": -1,
1291+
},
1292+
},
1293+
),
1294+
WalletStateTransition(
1295+
pre_block_balance_updates={},
1296+
post_block_balance_updates={
1297+
"cat0": {
1298+
"confirmed_wallet_balance": 1,
1299+
"unconfirmed_wallet_balance": 1,
1300+
"spendable_balance": 1,
1301+
"max_send_amount": 1,
1302+
"unspent_coin_count": 1,
1303+
},
1304+
},
1305+
),
1306+
]
1307+
await wallet_environments.process_pending_states(cat_spend_changes)
12031308

12041309
# Test CAT spend with a fee and pre-specified removals / coins
1205-
removals = await client.select_coins(
1206-
amount=uint64(2), wallet_id=cat_0_id, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
1310+
removals = await env_0.rpc_client.select_coins(
1311+
amount=uint64(2), wallet_id=cat_0_id, coin_selection_config=wallet_environments.tx_config.coin_selection_config
12071312
)
1208-
tx_res = await client.cat_spend(
1209-
cat_0_id, DEFAULT_TX_CONFIG, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"], removals=removals
1313+
tx_res = await env_0.rpc_client.cat_spend(
1314+
cat_0_id,
1315+
wallet_environments.tx_config,
1316+
uint64(1),
1317+
addr_1,
1318+
uint64(5_000_000),
1319+
["the cat memo"],
1320+
removals=removals,
12101321
)
12111322

12121323
spend_bundle = tx_res.transaction.spend_bundle
12131324
assert spend_bundle is not None
12141325
assert removals[0] in {removal for tx in tx_res.transactions for removal in tx.removals}
1215-
await farm_transaction(full_node_api, wallet_node, spend_bundle)
1326+
1327+
await wallet_environments.process_pending_states(cat_spend_changes)
12161328

12171329
# Test unacknowledged CAT
1218-
await wallet_node.wallet_state_manager.interested_store.add_unacknowledged_token(
1330+
await env_0.wallet_state_manager.interested_store.add_unacknowledged_token(
12191331
asset_id, "Unknown", uint32(10000), bytes32(b"\00" * 32)
12201332
)
1221-
cats = await client.get_stray_cats()
1333+
cats = await env_0.rpc_client.get_stray_cats()
12221334
assert len(cats) == 1
12231335

1224-
await time_out_assert(20, get_confirmed_balance, 14, client, cat_0_id)
1225-
await time_out_assert(20, get_confirmed_balance, 6, client_2, cat_1_id)
1226-
12271336
# Test CAT coin selection
1228-
selected_coins = await client.select_coins(
1229-
amount=1, wallet_id=cat_0_id, coin_selection_config=DEFAULT_COIN_SELECTION_CONFIG
1337+
selected_coins = await env_0.rpc_client.select_coins(
1338+
amount=1, wallet_id=cat_0_id, coin_selection_config=wallet_environments.tx_config.coin_selection_config
12301339
)
12311340
assert len(selected_coins) > 0
12321341

12331342
# Test get_cat_list
1234-
cat_list = (await client.get_cat_list()).cat_list
1343+
cat_list = (await env_0.rpc_client.get_cat_list()).cat_list
12351344
assert len(DEFAULT_CATS) == len(cat_list)
12361345
default_cats_set = {
12371346
DefaultCAT(asset_id=bytes32.from_hexstr(cat["asset_id"]), name=cat["name"], symbol=cat["symbol"])

chia/wallet/cat_wallet/r_cat_wallet.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ async def convert_to_revocable(
184184
replace_self.wallet_info = updated_wallet_info
185185

186186
cat_wallet.wallet_state_manager.wallets[cat_wallet.id()] = replace_self
187-
result = await cat_wallet.wallet_state_manager.create_more_puzzle_hashes(from_zero=True)
187+
await cat_wallet.wallet_state_manager.puzzle_store.delete_wallet(cat_wallet.id())
188+
result = await cat_wallet.wallet_state_manager.create_more_puzzle_hashes()
188189
await result.commit(cat_wallet.wallet_state_manager)
189190
return True
190191

0 commit comments

Comments
 (0)