mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-09-05 02:24:21 -05:00
Merge pull request #37 from Chia-Network/paninaro.cli_nft_offer_royalties
Update `chia wallet take_offer` to show NFT royalties
This commit is contained in:
@@ -20,6 +20,7 @@ from chia.util.config import load_config
|
||||
from chia.util.default_root import DEFAULT_ROOT_PATH
|
||||
from chia.util.ints import uint16, uint32, uint64, uint128
|
||||
from chia.wallet.did_wallet.did_info import DID_HRP
|
||||
from chia.wallet.nft_wallet.nft_puzzles import NFT_METADATA_UPDATER_PUZZLE_HASH
|
||||
from chia.wallet.nft_wallet.nft_info import NFT_HRP, NFTInfo
|
||||
from chia.wallet.trade_record import TradeRecord
|
||||
from chia.wallet.trading.offer import Offer
|
||||
@@ -515,16 +516,50 @@ async def take_offer(args: dict, wallet_client: WalletRpcClient, fingerprint: in
|
||||
print("Please enter a valid offer file or hex blob")
|
||||
return
|
||||
|
||||
offered, requested, _ = offer.summary()
|
||||
offered, requested, driver_dict = offer.summary()
|
||||
cat_name_resolver = wallet_client.cat_asset_id_to_name
|
||||
print("Summary:")
|
||||
print(" OFFERED:")
|
||||
await print_offer_summary(cat_name_resolver, offered)
|
||||
print(" REQUESTED:")
|
||||
await print_offer_summary(cat_name_resolver, requested)
|
||||
|
||||
print()
|
||||
|
||||
nft_coin_id: Optional[bytes32] = nft_coin_id_from_offer(driver_dict)
|
||||
nft_royalty_percentage: int = (
|
||||
0 if nft_coin_id is None else await get_nft_royalty_percentage(nft_coin_id, wallet_client)
|
||||
)
|
||||
nft_total_amount_requested_str: Optional[str] = None
|
||||
if nft_royalty_percentage > 0:
|
||||
print("NFT Royalty Fee:")
|
||||
nft_royalty_asset_id, nft_royalty_amount, nft_total_amount_requested = calculate_nft_royalty_amount(
|
||||
offered, requested, nft_coin_id, nft_royalty_percentage
|
||||
)
|
||||
nft_royalty_currency: str = "Unknown CAT"
|
||||
if nft_royalty_asset_id == "xch":
|
||||
nft_royalty_currency = "XCH"
|
||||
else:
|
||||
result = await cat_name_resolver(bytes32.fromhex(nft_royalty_asset_id))
|
||||
if result is not None:
|
||||
nft_royalty_currency = result[1]
|
||||
|
||||
nft_royalty_divisor = units["chia"] if nft_royalty_asset_id == "xch" else units["cat"]
|
||||
nft_total_amount_requested_str = (
|
||||
f"{Decimal(nft_total_amount_requested) / nft_royalty_divisor} {nft_royalty_currency}"
|
||||
)
|
||||
print(
|
||||
f" {Decimal(nft_royalty_amount) / nft_royalty_divisor} {nft_royalty_currency} "
|
||||
f"({nft_royalty_amount} mojos)"
|
||||
)
|
||||
|
||||
print(f"Included Fees: {Decimal(offer.bundle.fees()) / units['chia']}")
|
||||
|
||||
if nft_total_amount_requested_str is not None:
|
||||
print(f"Total Amount Requested: {nft_total_amount_requested_str}")
|
||||
|
||||
if not examine_only:
|
||||
print()
|
||||
confirmation = input("Would you like to take this offer? (y/n): ")
|
||||
if confirmation in ["y", "yes"]:
|
||||
trade_record = await wallet_client.take_offer(offer, fee=fee)
|
||||
@@ -929,3 +964,44 @@ async def get_nft_info(args: Dict, wallet_client: WalletRpcClient, fingerprint:
|
||||
print_nft_info(nft_info)
|
||||
except Exception as e:
|
||||
print(f"Failed to get NFT info: {e}")
|
||||
|
||||
|
||||
async def get_nft_royalty_percentage(nft_coin_id: bytes32, wallet_client: WalletRpcClient) -> int:
|
||||
info = NFTInfo.from_json_dict((await wallet_client.get_nft_info(nft_coin_id.hex()))["nft_info"])
|
||||
return info.royalty_percentage
|
||||
|
||||
|
||||
def calculate_nft_royalty_amount(
|
||||
offered: Dict[str, Any], requested: Dict[str, Any], nft_coin_id: bytes32, nft_royalty_percentage: int
|
||||
) -> Tuple[str, int, int]:
|
||||
nft_asset_id = nft_coin_id.hex()
|
||||
amount_dict: Dict[str, Any] = requested if nft_asset_id in offered else offered
|
||||
amounts: List[Tuple[str, int]] = list(amount_dict.items())
|
||||
|
||||
if len(amounts) != 1 or not isinstance(amounts[0][1], int):
|
||||
raise ValueError("Royalty enabled NFTs only support offering/requesting one NFT for one currency")
|
||||
|
||||
royalty_amount: uint64 = uint64(amounts[0][1] * nft_royalty_percentage / 10000)
|
||||
royalty_asset_id = amounts[0][0]
|
||||
total_amount_requested = (requested[royalty_asset_id] if amount_dict == requested else 0) + royalty_amount
|
||||
return royalty_asset_id, royalty_amount, total_amount_requested
|
||||
|
||||
|
||||
def driver_dict_asset_is_nft(driver_dict: Dict[str, Any], asset_id: str) -> bool:
|
||||
asset_dict: Dict[str, Any] = driver_dict[asset_id]
|
||||
if asset_dict.get("type") == "singleton":
|
||||
updater_hash_hexstr: Optional[str] = asset_dict.get("also", {}).get("updater_hash")
|
||||
try:
|
||||
updater_hash = bytes32.from_hexstr(updater_hash_hexstr)
|
||||
return updater_hash == NFT_METADATA_UPDATER_PUZZLE_HASH
|
||||
except ValueError:
|
||||
# Failed to construct bytes32 from updater_hash_hexstr
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def nft_coin_id_from_offer(driver_dict: Dict[str, Any]) -> Optional[bytes32]:
|
||||
nft_asset_id: Optional[str] = next(
|
||||
(key for key in driver_dict.keys() if driver_dict_asset_is_nft(driver_dict, key)), None
|
||||
)
|
||||
return bytes32.fromhex(nft_asset_id) if nft_asset_id is not None else None
|
||||
|
||||
@@ -20,6 +20,7 @@ LAUNCHER_PUZZLE_HASH = LAUNCHER_PUZZLE.get_tree_hash()
|
||||
SINGLETON_MOD_HASH = SINGLETON_TOP_LAYER_MOD.get_tree_hash()
|
||||
NFT_STATE_LAYER_MOD_HASH = NFT_STATE_LAYER_MOD.get_tree_hash()
|
||||
NFT_METADATA_UPDATER = load_clvm("nft_metadata_updater_default.clvm")
|
||||
NFT_METADATA_UPDATER_PUZZLE_HASH = NFT_METADATA_UPDATER.get_tree_hash()
|
||||
NFT_OWNERSHIP_LAYER = load_clvm("nft_ownership_layer.clvm")
|
||||
NFT_TRANSFER_PROGRAM_DEFAULT = load_clvm("nft_ownership_transfer_program_one_way_claim_with_royalties.clvm")
|
||||
STANDARD_PUZZLE_MOD = load_clvm("p2_delegated_puzzle_or_hidden_puzzle.clvm")
|
||||
|
||||
Reference in New Issue
Block a user