mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-20 16:08:51 +03:00
Make tests pass for takers
This commit is contained in:
parent
2a1322adbc
commit
7ee3f8845b
@ -863,11 +863,11 @@ class NFTWallet:
|
||||
if len(offer_dict) != 2 or (amounts[0] > 0 == amounts[1] > 0):
|
||||
raise ValueError("Royalty enabled NFTs only support offering/requesting one NFT for one currency")
|
||||
|
||||
offered_asset_id = list(offer_dict.items())[0][0]
|
||||
if offered_asset_id is None:
|
||||
first_asset_id = list(offer_dict.items())[0][0]
|
||||
if first_asset_id is None:
|
||||
nft: bool = False
|
||||
else:
|
||||
nft = driver_dict[offered_asset_id].check_type(
|
||||
nft = driver_dict[first_asset_id].check_type(
|
||||
[
|
||||
AssetType.SINGLETON.value,
|
||||
AssetType.METADATA.value,
|
||||
@ -876,8 +876,14 @@ class NFTWallet:
|
||||
)
|
||||
|
||||
offered: bool = list(offer_dict.items())[0][1] < 0
|
||||
if offered:
|
||||
offered_asset_id: Optional[bytes32] = first_asset_id
|
||||
requested_asset_id: Optional[bytes32] = list(offer_dict.items())[1][0]
|
||||
else:
|
||||
offered_asset_id = list(offer_dict.items())[1][0]
|
||||
requested_asset_id = first_asset_id
|
||||
|
||||
if nft and offered:
|
||||
if nft == offered:
|
||||
assert offered_asset_id is not None # hello mypy
|
||||
wallet = await wallet_state_manager.get_wallet_for_asset_id(offered_asset_id.hex())
|
||||
p2_ph = await wallet_state_manager.main_wallet.get_new_puzzlehash()
|
||||
@ -905,12 +911,8 @@ class NFTWallet:
|
||||
transaction_bundles: List[SpendBundle] = [tx.spend_bundle for tx in txs if tx.spend_bundle is not None]
|
||||
total_spend_bundle = SpendBundle.aggregate(transaction_bundles)
|
||||
|
||||
# Clear the owner field in the driver dict
|
||||
driver_dict[offered_asset_id].info["also"]["also"]["owner"] = "()"
|
||||
|
||||
return Offer(notarized_payments, total_spend_bundle, driver_dict)
|
||||
else:
|
||||
requested_asset_id: Optional[bytes32] = list(offer_dict.items())[0][0]
|
||||
assert isinstance(requested_asset_id, bytes32)
|
||||
requested_info = driver_dict[requested_asset_id]
|
||||
transfer_info = requested_info.also().also() # type: ignore
|
||||
@ -921,7 +923,6 @@ class NFTWallet:
|
||||
requested_payments: Dict[Optional[bytes32], List[Payment]] = {
|
||||
requested_asset_id: [Payment(p2_ph, uint64(offer_dict[requested_asset_id]), [p2_ph])]
|
||||
}
|
||||
offered_asset_id = list(offer_dict.items())[1][0]
|
||||
offered_amount = uint64(abs(offer_dict[offered_asset_id]))
|
||||
royalty_amount = uint64(offered_amount * royalty_percentage / 10000)
|
||||
if offered_amount == royalty_amount:
|
||||
@ -941,6 +942,17 @@ class NFTWallet:
|
||||
|
||||
notarized_payments = Offer.notarize_payments(requested_payments, pmt_coins)
|
||||
announcements_to_assert = Offer.calculate_announcements(notarized_payments, driver_dict)
|
||||
# Calculate the royalty announcement separately
|
||||
announcements_to_assert.extend(
|
||||
Offer.calculate_announcements(
|
||||
{
|
||||
offered_asset_id: [
|
||||
NotarizedPayment(royalty_address, royalty_amount, [royalty_address], requested_asset_id)
|
||||
]
|
||||
},
|
||||
driver_dict,
|
||||
)
|
||||
)
|
||||
|
||||
if wallet.type() == WalletType.STANDARD_WALLET:
|
||||
tx = await wallet.generate_signed_transaction(
|
||||
@ -973,7 +985,7 @@ class NFTWallet:
|
||||
assert royalty_coin
|
||||
# make the royalty payment solution
|
||||
# ((nft_launcher_id . ((ROYALTY_ADDRESS, royalty_amount, (ROYALTY_ADDRESS)))))
|
||||
royalty_sol = Program.to([[offered_asset_id, [royalty_address, royalty_amount, [royalty_address]]]])
|
||||
royalty_sol = Program.to([[requested_asset_id, [royalty_address, royalty_amount, [royalty_address]]]])
|
||||
royalty_spend = SpendBundle([CoinSpend(royalty_coin, OFFER_MOD, royalty_sol)], G2Element())
|
||||
|
||||
total_spend_bundle = SpendBundle.aggregate([txn_spend_bundle, royalty_spend])
|
||||
|
@ -540,13 +540,16 @@ class TradeManager:
|
||||
removal_dict.setdefault(wallet_id, [])
|
||||
removal_dict[wallet_id].append(removal)
|
||||
|
||||
all_removals: List[bytes32] = [r.name() for removals in removal_dict.values() for r in removals]
|
||||
|
||||
for wid, grouped_removals in removal_dict.items():
|
||||
wallet = self.wallet_state_manager.wallets[wid]
|
||||
to_puzzle_hash = bytes32([1] * 32) # We use all zeros to be clear not to send here
|
||||
removal_tree_hash = Program.to([coin_as_list(rem) for rem in grouped_removals]).get_tree_hash()
|
||||
# We also need to calculate the sent amount
|
||||
removed: int = sum(c.amount for c in grouped_removals)
|
||||
change_coins: List[Coin] = addition_dict[wid] if wid in addition_dict else []
|
||||
potential_change_coins: List[Coin] = addition_dict[wid] if wid in addition_dict else []
|
||||
change_coins: List[Coin] = [c for c in potential_change_coins if c.parent_coin_info in all_removals]
|
||||
change_amount: int = sum(c.amount for c in change_coins)
|
||||
sent_amount: int = removed - change_amount
|
||||
txs.append(
|
||||
@ -573,38 +576,34 @@ class TradeManager:
|
||||
return txs
|
||||
|
||||
async def respond_to_offer(self, offer: Offer, fee=uint64(0)) -> Tuple[bool, Optional[TradeRecord], Optional[str]]:
|
||||
potential_special_offer: Optional[Offer] = await self.check_for_special_offer_taking(offer, fee=fee)
|
||||
if potential_special_offer is not None:
|
||||
complete_offer: Offer = potential_special_offer
|
||||
else:
|
||||
take_offer_dict: Dict[Union[bytes32, int], int] = {}
|
||||
arbitrage: Dict[Optional[bytes32], int] = offer.arbitrage()
|
||||
for asset_id, amount in arbitrage.items():
|
||||
if asset_id is None:
|
||||
wallet = self.wallet_state_manager.main_wallet
|
||||
key: Union[bytes32, int] = int(wallet.id())
|
||||
take_offer_dict: Dict[Union[bytes32, int], int] = {}
|
||||
arbitrage: Dict[Optional[bytes32], int] = offer.arbitrage()
|
||||
for asset_id, amount in arbitrage.items():
|
||||
if asset_id is None:
|
||||
wallet = self.wallet_state_manager.main_wallet
|
||||
key: Union[bytes32, int] = int(wallet.id())
|
||||
else:
|
||||
# ATTENTION: new wallets
|
||||
wallet = await self.wallet_state_manager.get_wallet_for_asset_id(asset_id.hex())
|
||||
if wallet is None and amount < 0:
|
||||
return False, None, f"Do not have a wallet for asset ID: {asset_id} to fulfill offer"
|
||||
elif wallet is None or wallet.type() == WalletType.NFT:
|
||||
key = asset_id
|
||||
else:
|
||||
# ATTENTION: new wallets
|
||||
wallet = await self.wallet_state_manager.get_wallet_for_asset_id(asset_id.hex())
|
||||
if wallet is None and amount < 0:
|
||||
return False, None, f"Do not have a wallet for asset ID: {asset_id} to fulfill offer"
|
||||
elif wallet is None or wallet.type() == WalletType.NFT:
|
||||
key = asset_id
|
||||
else:
|
||||
key = int(wallet.id())
|
||||
take_offer_dict[key] = amount
|
||||
key = int(wallet.id())
|
||||
take_offer_dict[key] = amount
|
||||
|
||||
# First we validate that all of the coins in this offer exist
|
||||
valid: bool = await self.check_offer_validity(offer)
|
||||
if not valid:
|
||||
return False, None, "This offer is no longer valid"
|
||||
# First we validate that all of the coins in this offer exist
|
||||
valid: bool = await self.check_offer_validity(offer)
|
||||
if not valid:
|
||||
return False, None, "This offer is no longer valid"
|
||||
|
||||
success, take_offer, error = await self._create_offer_for_ids(take_offer_dict, offer.driver_dict, fee=fee)
|
||||
if not success or take_offer is None:
|
||||
return False, None, error
|
||||
success, take_offer, error = await self._create_offer_for_ids(take_offer_dict, offer.driver_dict, fee=fee)
|
||||
if not success or take_offer is None:
|
||||
return False, None, error
|
||||
|
||||
complete_offer = Offer.aggregate([offer, take_offer])
|
||||
assert complete_offer.is_valid()
|
||||
complete_offer = Offer.aggregate([offer, take_offer])
|
||||
assert complete_offer.is_valid()
|
||||
|
||||
final_spend_bundle: SpendBundle = complete_offer.to_valid_spend()
|
||||
|
||||
|
@ -146,7 +146,7 @@ class Offer:
|
||||
|
||||
parent_puzzle: Program = parent_spend.puzzle_reveal.to_program()
|
||||
parent_solution: Program = parent_spend.solution.to_program()
|
||||
additions: List[Coin] = parent_spend.additions()
|
||||
additions: List[Coin] = [a for a in parent_spend.additions() if a not in self.bundle.removals()]
|
||||
|
||||
puzzle_driver = match_puzzle(parent_puzzle)
|
||||
if puzzle_driver is not None:
|
||||
@ -167,7 +167,7 @@ class Offer:
|
||||
a
|
||||
for a in additions_w_amount
|
||||
if a.puzzle_hash
|
||||
== construct_puzzle(puzzle_driver, OFFER_HASH).get_tree_hash(OFFER_HASH)
|
||||
== construct_puzzle(puzzle_driver, OFFER_HASH).get_tree_hash(OFFER_HASH) # type: ignore
|
||||
]
|
||||
if len(additions_w_amount_and_puzhash) == 1:
|
||||
coins_for_this_spend.append(additions_w_amount_and_puzhash[0])
|
||||
|
@ -23,6 +23,7 @@ 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
|
||||
from chia.wallet.puzzle_drivers import PuzzleInfo
|
||||
from chia.wallet.trading.offer import Offer
|
||||
from chia.wallet.util.compute_memos import compute_memos
|
||||
|
||||
# from chia.wallet.util.wallet_types import WalletType
|
||||
@ -145,7 +146,7 @@ async def test_nft_offer_sell_nft(two_wallet_nodes: Any, trusted: Any) -> None:
|
||||
|
||||
# maker create offer: NFT for xch
|
||||
trade_manager_maker = wallet_maker.wallet_state_manager.trade_manager
|
||||
# trade_manager_taker = wallet_taker.wallet_state_manager.trade_manager
|
||||
trade_manager_taker = wallet_taker.wallet_state_manager.trade_manager
|
||||
|
||||
coins_maker = nft_wallet_maker.nft_wallet_info.my_nft_coins
|
||||
assert len(coins_maker) == 1
|
||||
@ -170,6 +171,17 @@ async def test_nft_offer_sell_nft(two_wallet_nodes: Any, trusted: Any) -> None:
|
||||
assert error is None
|
||||
assert trade_make is not None
|
||||
|
||||
success, trade_take, error = await trade_manager_taker.respond_to_offer(
|
||||
Offer.from_bytes(trade_make.offer), fee=uint64(1)
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
assert error is None
|
||||
assert success is True
|
||||
assert trade_take is not None
|
||||
|
||||
for _ in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_maker))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"trusted",
|
||||
@ -275,7 +287,7 @@ async def test_nft_offer_request_nft(two_wallet_nodes: Any, trusted: Any) -> Non
|
||||
|
||||
# maker create offer: NFT for xch
|
||||
trade_manager_maker = wallet_maker.wallet_state_manager.trade_manager
|
||||
# trade_manager_taker = wallet_taker.wallet_state_manager.trade_manager
|
||||
trade_manager_taker = wallet_taker.wallet_state_manager.trade_manager
|
||||
|
||||
coins_maker = nft_wallet_maker.nft_wallet_info.my_nft_coins
|
||||
assert len(coins_maker) == 0
|
||||
@ -299,3 +311,14 @@ async def test_nft_offer_request_nft(two_wallet_nodes: Any, trusted: Any) -> Non
|
||||
assert success is True
|
||||
assert error is None
|
||||
assert trade_make is not None
|
||||
|
||||
success, trade_take, error = await trade_manager_taker.respond_to_offer(
|
||||
Offer.from_bytes(trade_make.offer), fee=uint64(1)
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
assert error is None
|
||||
assert success is True
|
||||
assert trade_take is not None
|
||||
|
||||
for _ in range(1, num_blocks):
|
||||
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_maker))
|
||||
|
Loading…
Reference in New Issue
Block a user