[CHIA-3391] Port test_nft*offers.py to be parametrized with R-CATs (#19842)

* Port `test_nft_offer_nft_for_cat`

* Port `test_nft_offer_nft0_and_xch_for_cat`

* Forgot to delete an unnecessary state process

* Port `test_nft_offer_sell_nft_for_cat`

* Port `test_nft_offer_request_nft_for_cat`

* Port `test_complex_nft_offer`

* Fix a new issue in complex test

* Minor change.

---------

Co-authored-by: Amine Khaldi <amine.khaldi@reactos.org>
This commit is contained in:
Matt Hauff
2025-08-07 10:47:53 -07:00
committed by GitHub
co-authored by Amine Khaldi
parent 43fb664831
commit b6db8529e8
2 changed files with 141 additions and 231 deletions
@@ -9,8 +9,10 @@ from chia_rs.sized_ints import uint16, uint32, uint64
from chia._tests.environments.wallet import WalletStateTransition, WalletTestFramework
from chia._tests.util.time_out_assert import time_out_assert
from chia._tests.wallet.cat_wallet.test_cat_wallet import mint_cat
from chia.types.blockchain_format.program import Program
from chia.wallet.cat_wallet.cat_wallet import CATWallet
from chia.wallet.cat_wallet.r_cat_wallet import RCATWallet
from chia.wallet.did_wallet.did_wallet import DIDWallet
from chia.wallet.nft_wallet.nft_wallet import NFTWallet
from chia.wallet.outer_puzzles import create_asset_id, match_puzzle
@@ -777,8 +779,11 @@ async def test_nft_offer_sell_did_to_did(wallet_environments: WalletTestFramewor
@pytest.mark.limit_consensus_modes
@pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
@pytest.mark.parametrize("zero_royalties", [True, False])
@pytest.mark.parametrize("wallet_type", [CATWallet, RCATWallet])
@pytest.mark.anyio
async def test_nft_offer_sell_nft_for_cat(wallet_environments: WalletTestFramework, zero_royalties: bool) -> None:
async def test_nft_offer_sell_nft_for_cat(
wallet_environments: WalletTestFramework, zero_royalties: bool, wallet_type: type[CATWallet]
) -> None:
env_maker = wallet_environments.environments[0]
env_taker = wallet_environments.environments[1]
wallet_maker = env_maker.xch_wallet
@@ -910,46 +915,24 @@ async def test_nft_offer_sell_nft_for_cat(wallet_environments: WalletTestFramewo
# Create new CAT and wallets for maker and taker
# Trade them between maker and taker to ensure multiple coins for each cat
cats_to_mint = 100000
cats_to_mint = uint64(100000)
cats_to_trade = uint64(10000)
async with wallet_maker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_maker = await CATWallet.create_new_cat_wallet(
env_maker.wallet_state_manager,
wallet_maker,
{"identifier": "genesis_by_id"},
uint64(cats_to_mint),
action_scope,
)
await wallet_environments.process_pending_states(
[
WalletStateTransition(
pre_block_balance_updates={
"xch": {
"set_remainder": True,
},
"cat": {
"init": True,
"set_remainder": True,
},
},
post_block_balance_updates={
"xch": {
"set_remainder": True,
},
"cat": {
"set_remainder": True,
},
},
),
WalletStateTransition(),
]
cat_wallet_maker = await mint_cat(
wallet_environments,
env_maker,
"xch",
"cat",
cats_to_mint,
wallet_type,
"cat",
)
cat_wallet_taker: CATWallet = await CATWallet.get_or_create_wallet_for_cat(
env_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
if wallet_type is RCATWallet:
extra_args: Any = (bytes32.zeros,)
else:
extra_args = tuple()
cat_wallet_taker: CATWallet = await wallet_type.get_or_create_wallet_for_cat(
env_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id(), *extra_args
)
await env_taker.change_balances({"cat": {"init": True}})
@@ -1120,8 +1103,11 @@ async def test_nft_offer_sell_nft_for_cat(wallet_environments: WalletTestFramewo
@pytest.mark.limit_consensus_modes
@pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
@pytest.mark.parametrize("test_change", [True, False])
@pytest.mark.parametrize("wallet_type", [CATWallet, RCATWallet])
@pytest.mark.anyio
async def test_nft_offer_request_nft_for_cat(wallet_environments: WalletTestFramework, test_change: bool) -> None:
async def test_nft_offer_request_nft_for_cat(
wallet_environments: WalletTestFramework, test_change: bool, wallet_type: type[CATWallet]
) -> None:
env_maker = wallet_environments.environments[0]
env_taker = wallet_environments.environments[1]
wallet_maker = env_maker.xch_wallet
@@ -1255,46 +1241,24 @@ async def test_nft_offer_request_nft_for_cat(wallet_environments: WalletTestFram
# Create new CAT and wallets for maker and taker
# Trade them between maker and taker to ensure multiple coins for each cat
cats_to_mint = 100000
cats_to_mint = uint64(100000)
cats_to_trade = uint64(20000)
async with wallet_maker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_maker = await CATWallet.create_new_cat_wallet(
env_maker.wallet_state_manager,
wallet_maker,
{"identifier": "genesis_by_id"},
uint64(cats_to_mint),
action_scope,
)
await wallet_environments.process_pending_states(
[
WalletStateTransition(
pre_block_balance_updates={
"xch": {
"set_remainder": True,
},
"cat": {
"init": True,
"set_remainder": True,
},
},
post_block_balance_updates={
"xch": {
"set_remainder": True,
},
"cat": {
"set_remainder": True,
},
},
),
WalletStateTransition(),
]
cat_wallet_maker = await mint_cat(
wallet_environments,
env_maker,
"xch",
"cat",
cats_to_mint,
wallet_type,
"cat",
)
await CATWallet.get_or_create_wallet_for_cat(
env_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
if wallet_type is RCATWallet:
extra_args: Any = (bytes32.zeros,)
else:
extra_args = tuple()
await wallet_type.get_or_create_wallet_for_cat(
env_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id(), *extra_args
)
await env_taker.change_balances({"cat": {"init": True}})
@@ -1690,8 +1654,11 @@ async def test_nft_offer_sell_cancel(wallet_environments: WalletTestFramework) -
[{"num_environments": 2, "blocks_needed": [3, 3], "config_overrides": {"automatically_add_unknown_cats": True}}],
indirect=True,
)
@pytest.mark.parametrize("wallet_type", [CATWallet, RCATWallet])
@pytest.mark.anyio
async def test_complex_nft_offer(wallet_environments: WalletTestFramework, royalty_pts: tuple[int, int, int]) -> None:
async def test_complex_nft_offer(
wallet_environments: WalletTestFramework, royalty_pts: tuple[int, int, int], wallet_type: type[CATWallet]
) -> None:
"""
This test is going to create an offer where the maker offers 1 NFT and 1 CAT for 2 NFTs, an XCH and a CAT
"""
@@ -1729,20 +1696,24 @@ async def test_complex_nft_offer(wallet_environments: WalletTestFramework, royal
ph_taker = await action_scope.get_puzzle_hash(wallet_taker.wallet_state_manager)
CAT_AMOUNT = uint64(100000000)
async with wallet_maker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_maker = await CATWallet.create_new_cat_wallet(
wsm_maker, wallet_maker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, action_scope
)
async with wallet_taker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_taker = await CATWallet.create_new_cat_wallet(
wsm_taker, wallet_taker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, action_scope
)
await env_maker.change_balances({"cat_maker": {"init": True}})
await env_taker.change_balances({"cat_taker": {"init": True}})
cat_wallet_maker = await mint_cat(
wallet_environments,
env_maker,
"xch",
"cat_maker",
CAT_AMOUNT,
wallet_type,
"cat_maker",
)
cat_wallet_taker = await mint_cat(
wallet_environments,
env_taker,
"xch",
"cat_taker",
CAT_AMOUNT,
wallet_type,
"cat_taker",
)
# We'll need these later
basic_nft_wallet_maker = await NFTWallet.create_new_nft_wallet(wsm_maker, wallet_maker, name="NFT WALLET MAKER")
@@ -2025,6 +1996,11 @@ async def test_complex_nft_offer(wallet_environments: WalletTestFramework, royal
{
"type": "CAT",
"tail": "0x" + cat_wallet_taker.get_asset_id(),
**(
{}
if wallet_type is CATWallet
else {"also": {"type": "revocation layer", "hidden_puzzle_hash": "0x" + bytes32.zeros.hex()}}
),
}
),
}
@@ -2090,7 +2066,8 @@ async def test_complex_nft_offer(wallet_environments: WalletTestFramework, royal
+ taker_royalty_summary[nft_to_offer_asset_id_taker_2][0]["amount"]
)
xch_coins = int(XCH_REQUESTED / 1_750_000_000_000) + 2
# in the zero royalty case, exact change ends up being selected which complicates things a bit
xch_coins = int(XCH_REQUESTED / 1_750_000_000_000) + 2 - (1 if royalty_basis_pts_maker == 0 else 0)
fee_coins = int(FEE / 1_750_000_000_000) + 1 if FEE > 1_750_000_000_000 else 1
await wallet_environments.process_pending_states(
[
@@ -2151,7 +2128,7 @@ async def test_complex_nft_offer(wallet_environments: WalletTestFramework, royal
"unconfirmed_wallet_balance": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
"<=#spendable_balance": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
"<=#max_send_amount": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
">=#pending_change": 1,
">=#pending_change": 0,
"pending_coin_removal_count": xch_coins + fee_coins,
},
"cat_taker": {
@@ -2173,9 +2150,9 @@ async def test_complex_nft_offer(wallet_environments: WalletTestFramework, royal
post_block_balance_updates={
"xch": {
"confirmed_wallet_balance": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
">=#spendable_balance": 1,
">=#max_send_amount": 1,
"<=#pending_change": -1,
">=#spendable_balance": 0,
">=#max_send_amount": 0,
"<=#pending_change": 0,
"pending_coin_removal_count": -fee_coins - xch_coins,
# Parametrizations make unspent_coin_count too complicated
"set_remainder": True,
+68 -135
View File
@@ -5,11 +5,14 @@ from typing import Optional, Union
import pytest
from chia_rs.sized_bytes import bytes32
from chia_rs.sized_ints import uint64
from typing_extensions import Any
from chia._tests.environments.wallet import WalletStateTransition, WalletTestFramework
from chia._tests.util.time_out_assert import time_out_assert
from chia._tests.wallet.cat_wallet.test_cat_wallet import mint_cat
from chia.types.blockchain_format.program import Program
from chia.wallet.cat_wallet.cat_wallet import CATWallet
from chia.wallet.cat_wallet.r_cat_wallet import RCATWallet
from chia.wallet.nft_wallet.nft_wallet import NFTWallet
from chia.wallet.outer_puzzles import create_asset_id, match_puzzle
from chia.wallet.puzzle_drivers import PuzzleInfo
@@ -696,8 +699,9 @@ async def test_nft_offer_with_metadata_update(wallet_environments: WalletTestFra
@pytest.mark.limit_consensus_modes(reason="irrelevant")
@pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
@pytest.mark.parametrize("wallet_type", [CATWallet, RCATWallet])
@pytest.mark.anyio
async def test_nft_offer_nft_for_cat(wallet_environments: WalletTestFramework) -> None:
async def test_nft_offer_nft_for_cat(wallet_environments: WalletTestFramework, wallet_type: type[CATWallet]) -> None:
env_0 = wallet_environments.environments[0]
env_1 = wallet_environments.environments[1]
wallet_maker = env_0.xch_wallet
@@ -785,73 +789,42 @@ async def test_nft_offer_nft_for_cat(wallet_environments: WalletTestFramework) -
assert await nft_wallet_taker.get_nft_count() == 0
# Create two new CATs and wallets for maker and taker
cats_to_mint = 10000
async with wallet_maker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_maker = await CATWallet.create_new_cat_wallet(
env_0.wallet_state_manager,
wallet_maker,
{"identifier": "genesis_by_id"},
uint64(cats_to_mint),
action_scope,
)
async with wallet_taker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_taker = await CATWallet.create_new_cat_wallet(
env_1.wallet_state_manager,
wallet_taker,
{"identifier": "genesis_by_id"},
uint64(cats_to_mint),
action_scope,
)
# mostly set_remainder here as minting CATs is tested elsewhere
await wallet_environments.process_pending_states(
[
WalletStateTransition(
pre_block_balance_updates={
"xch": {"set_remainder": True},
"maker cat": {
"init": True,
"set_remainder": True,
},
},
post_block_balance_updates={
"xch": {"set_remainder": True},
"maker cat": {
"set_remainder": True,
},
},
),
WalletStateTransition(
pre_block_balance_updates={
"xch": {"set_remainder": True},
"taker cat": {
"init": True,
"set_remainder": True,
},
},
post_block_balance_updates={
"xch": {"set_remainder": True},
"taker cat": {
"set_remainder": True,
},
},
),
]
cats_to_mint = uint64(10000)
cat_wallet_maker = await mint_cat(
wallet_environments,
env_0,
"xch",
"maker cat",
cats_to_mint,
wallet_type,
"maker cat",
)
wallet_maker_for_taker_cat: CATWallet = await CATWallet.get_or_create_wallet_for_cat(
env_0.wallet_state_manager, wallet_maker, cat_wallet_taker.get_asset_id()
cat_wallet_taker = await mint_cat(
wallet_environments,
env_1,
"xch",
"taker cat",
cats_to_mint,
wallet_type,
"taker cat",
)
await CATWallet.get_or_create_wallet_for_cat(
env_1.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
if wallet_type is RCATWallet:
extra_args: Any = (bytes32.zeros,)
else:
extra_args = tuple()
wallet_maker_for_taker_cat: CATWallet = await wallet_type.get_or_create_wallet_for_cat(
env_0.wallet_state_manager, wallet_maker, cat_wallet_taker.get_asset_id(), *extra_args
)
await wallet_type.get_or_create_wallet_for_cat(
env_1.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id(), *extra_args
)
await env_0.change_balances({"taker cat": {"init": True}})
await env_1.change_balances({"maker cat": {"init": True}})
# MAKE FIRST TRADE: 1 NFT for 10 taker cats
nft_to_offer = coins_maker[0]
nft_info: Optional[PuzzleInfo] = match_puzzle(uncurry_puzzle(nft_to_offer.full_puzzle))
@@ -902,9 +875,7 @@ async def test_nft_offer_nft_for_cat(wallet_environments: WalletTestFramework) -
"<=#max_send_amount": -maker_fee,
"pending_coin_removal_count": 1,
},
"taker cat": {
"init": True,
},
"taker cat": {},
"nft": {
"pending_coin_removal_count": 1,
},
@@ -940,9 +911,7 @@ async def test_nft_offer_nft_for_cat(wallet_environments: WalletTestFramework) -
">=#pending_change": 1,
"pending_coin_removal_count": 1,
},
"maker cat": {
"init": True,
},
"maker cat": {},
"taker cat": {
"unconfirmed_wallet_balance": -taker_cat_offered,
"<=#spendable_balance": -taker_cat_offered,
@@ -1367,8 +1336,11 @@ async def test_nft_offer_nft_for_nft(wallet_environments: WalletTestFramework) -
@pytest.mark.limit_consensus_modes(reason="irrelevant")
@pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
@pytest.mark.parametrize("wallet_type", [CATWallet, RCATWallet])
@pytest.mark.anyio
async def test_nft_offer_nft0_and_xch_for_cat(wallet_environments: WalletTestFramework) -> None:
async def test_nft_offer_nft0_and_xch_for_cat(
wallet_environments: WalletTestFramework, wallet_type: type[CATWallet]
) -> None:
env_0 = wallet_environments.environments[0]
env_1 = wallet_environments.environments[1]
wallet_maker = env_0.xch_wallet
@@ -1456,80 +1428,41 @@ async def test_nft_offer_nft0_and_xch_for_cat(wallet_environments: WalletTestFra
assert await nft_wallet_taker.get_nft_count() == 0
# Create two new CATs and wallets for maker and taker
cats_to_mint = 10000
async with wallet_maker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_maker = await CATWallet.create_new_cat_wallet(
env_0.wallet_state_manager,
wallet_maker,
{"identifier": "genesis_by_id"},
uint64(cats_to_mint),
action_scope,
)
cats_to_mint = uint64(10000)
cat_wallet_maker = await mint_cat(
wallet_environments,
env_0,
"xch",
"maker cat",
cats_to_mint,
CATWallet,
"maker cat",
)
async with wallet_taker.wallet_state_manager.new_action_scope(
wallet_environments.tx_config, push=True
) as action_scope:
cat_wallet_taker = await CATWallet.create_new_cat_wallet(
env_1.wallet_state_manager,
wallet_taker,
{"identifier": "genesis_by_id"},
uint64(cats_to_mint),
action_scope,
)
cat_wallet_taker = await mint_cat(
wallet_environments,
env_1,
"xch",
"taker cat",
cats_to_mint,
CATWallet,
"taker cat",
)
if wallet_type is RCATWallet:
extra_args: Any = (bytes32.zeros,)
else:
extra_args = tuple()
wallet_maker_for_taker_cat: CATWallet = await CATWallet.get_or_create_wallet_for_cat(
env_0.wallet_state_manager, wallet_maker, cat_wallet_taker.get_asset_id()
env_0.wallet_state_manager, wallet_maker, cat_wallet_taker.get_asset_id(), *extra_args
)
await CATWallet.get_or_create_wallet_for_cat(
env_1.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
env_1.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id(), *extra_args
)
# mostly set_remainder here as minting CATs is tested elsewhere
await wallet_environments.process_pending_states(
[
WalletStateTransition(
pre_block_balance_updates={
"xch": {"set_remainder": True},
"maker cat": {
"init": True,
"set_remainder": True,
},
"taker cat": {
"init": True,
"set_remainder": True,
},
},
post_block_balance_updates={
"xch": {"set_remainder": True},
"maker cat": {
"set_remainder": True,
},
},
),
WalletStateTransition(
pre_block_balance_updates={
"xch": {"set_remainder": True},
"maker cat": {
"init": True,
"set_remainder": True,
},
"taker cat": {
"init": True,
"set_remainder": True,
},
},
post_block_balance_updates={
"xch": {"set_remainder": True},
"taker cat": {
"set_remainder": True,
},
},
),
]
)
await env_0.change_balances({"taker cat": {"init": True}})
await env_1.change_balances({"maker cat": {"init": True}})
# MAKE FIRST TRADE: 1 NFT for 10 taker cats
nft_to_offer = coins_maker[0]