-
Notifications
You must be signed in to change notification settings - Fork 92
chore: Adapt custom_fee_royalty.py to be end-to-end #679 #694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,117 @@ | ||
| """ | ||
| Run with: | ||
| uv run examples/custom_royalty_fee.py | ||
| python examples/custom_royalty_fee.py | ||
| End-to-end example for creating a Non-Fungible Token (NFT) | ||
| with a custom royalty fee on the Hedera testnet. | ||
| """ | ||
| from hiero_sdk_python.tokens.custom_fixed_fee import CustomFixedFee | ||
| from hiero_sdk_python.tokens.custom_royalty_fee import CustomRoyaltyFee | ||
|
|
||
| import os | ||
| from dotenv import load_dotenv | ||
| from hiero_sdk_python.account.account_id import AccountId | ||
| from hiero_sdk_python.tokens.token_id import TokenId | ||
| from hiero_sdk_python.client.client import Client | ||
| from hiero_sdk_python.custom_fees.custom_royalty_fee import CustomRoyaltyFee | ||
| from hiero_sdk_python.token.token_create_transaction import TokenCreateTransaction | ||
| from hiero_sdk_python.token.token_info_query import TokenInfoQuery | ||
| from hiero_sdk_python.token.token_type import TokenType | ||
| from hiero_sdk_python.token.token_supply_type import TokenSupplyType | ||
| from hiero_sdk_python.key.key import Key | ||
| from hiero_sdk_python.hbar.hbar import Hbar | ||
|
|
||
| def set_up_client() -> Client: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. def setup_client(): |
||
| """ | ||
| Sets up and returns the Hedera client. | ||
| (Copied from other examples for consistency) | ||
| """ | ||
| load_dotenv() | ||
| try: | ||
| operator_id_str = os.environ["OPERATOR_ID"] | ||
| operator_key_str = os.environ["OPERATOR_KEY"] | ||
| except KeyError: | ||
| raise Exception("OPERATOR_ID and OPERATOR_KEY env variables must be set") | ||
|
|
||
| client = Client.for_testnet() | ||
| client.set_operator(AccountId.from_string(operator_id_str), Key.from_string(operator_key_str)) | ||
| return client | ||
|
|
||
| def custom_royalty_fee(): | ||
| fallback_fee = CustomFixedFee( | ||
| amount=50, | ||
| denominating_token_id=TokenId(0, 0, 789), | ||
| def create_token_with_fee(client: Client, fee: CustomRoyaltyFee) -> AccountId: | ||
| """ | ||
| Creates a new Non-Fungible Token (NFT) with a custom royalty fee. | ||
| Royalty fees can only be applied to NON_FUNGIBLE_UNIQUE token types. | ||
| """ | ||
| print("Creating a new NFT with a custom royalty fee...") | ||
|
|
||
| operator_id = client.operator_account_id | ||
| operator_key = client.operator_private_key | ||
|
|
||
| # Create the TokenCreateTransaction | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will all fail Search for any other TokenCreateTransaction example and notice they tend to use .set_token_name That's because if you look at the code for src/hiero_sdk_python/tokens/token_create_transaction.py but if you instead want to pass parameters directly (like your attempt), you need to pass it in the way the class allows, which would actually be: 1. Define your token parameterstoken_params = TokenParams( 2. Define your token keystoken_keys = TokenKeys( 3. Create the TokenCreateTransactiontx = TokenCreateTransaction(
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note we don't have functionality in token create for you to create a max_transaction_fee so that won't work either |
||
| tx = TokenCreateTransaction( | ||
| token_name="My Royalty NFT", | ||
| token_symbol="MRNFT", | ||
| token_type=TokenType.NON_FUNGIBLE_UNIQUE, | ||
| supply_type=TokenSupplyType.FINITE, | ||
| treasury_account_id=operator_id, | ||
| # Add the custom fee we defined | ||
| custom_fees=[fee], | ||
| admin_key=operator_key, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you do not need an admin key, i think |
||
| supply_key=operator_key, | ||
| max_supply=100, | ||
| # Set transaction fee | ||
| max_transaction_fee=Hbar(30) | ||
| ) | ||
|
|
||
| # Sign and execute | ||
| submitted_tx = tx.execute(client) | ||
| receipt = submitted_tx.get_receipt(client) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. get_receipt is not something we do we do more like this: |
||
| token_id = receipt.token_id | ||
|
|
||
| print(f"Successfully created token with ID: {token_id}") | ||
| return token_id | ||
|
|
||
| def query_token(client: Client, token_id: AccountId): | ||
| """ | ||
| Queries the token info to verify the custom fee. | ||
| """ | ||
| print(f"\nQuerying token {token_id} for custom fee verification...") | ||
|
|
||
| token_info = TokenInfoQuery().set_token_id(token_id).execute(client) | ||
|
|
||
| print(f"Found {len(token_info.custom_fees)} custom fees.") | ||
|
|
||
| if token_info.custom_fees: | ||
| # Access the first fee (we only added one) | ||
| fee = token_info.custom_fees[0] | ||
| if isinstance(fee, CustomRoyaltyFee): | ||
| print("Verified: CustomRoyaltyFee found.") | ||
| print(f" Numerator: {fee.numerator}") | ||
| print(f" Denominator: {fee.denominator}") | ||
| print(f" Fee Collector: {fee.fee_collector_account_id}") | ||
| else: | ||
| print(f"Verified: Found a fee, but it's not a Royalty Fee. Type: {type(fee)}") | ||
| else: | ||
| print("Error: No custom fees found on the token.") | ||
|
|
||
| def main(): | ||
| """ | ||
| Main function to orchestrate the end-to-end example. | ||
| """ | ||
| client = set_up_client() | ||
| operator_id = client.operator_account_id | ||
|
|
||
|
|
||
| # This will be a 10/100 (10%) royalty fee, paid to the operator's account | ||
| royalty_fee = CustomRoyaltyFee( | ||
| numerator=5, | ||
| numerator=10, | ||
| denominator=100, | ||
| fallback_fee=fallback_fee, | ||
| fee_collector_account_id=AccountId(0, 0, 456), | ||
| all_collectors_are_exempt=True, | ||
| fallback_fee=None, # No fallback fee for this example | ||
| fee_collector_account_id=operator_id | ||
| ) | ||
| print("\nCustomRoyaltyFee:") | ||
| print(f"Numerator: {royalty_fee.numerator}") | ||
| print(f"Denominator: {royalty_fee.denominator}") | ||
| print(f"Fallback Fee Amount: {royalty_fee.fallback_fee.amount if royalty_fee.fallback_fee is not None else 'None'}") | ||
| print(f"Fallback Fee Denominating Token ID: {royalty_fee.fallback_fee.denominating_token_id if royalty_fee.fallback_fee is not None else 'None'}") | ||
| print(f"Fee Collector Account ID: {royalty_fee.fee_collector_account_id}") | ||
| print(f"All Collectors Exempt: {royalty_fee.all_collectors_are_exempt}") | ||
|
|
||
| # Convert to protobuf | ||
| royalty_fee_proto = royalty_fee._to_proto() | ||
|
|
||
| print("Royalty Fee Protobuf:", royalty_fee_proto) | ||
|
|
||
| try: | ||
|
|
||
| token_id = create_token_with_fee(client, royalty_fee) | ||
|
|
||
|
|
||
| query_token(client, token_id) | ||
| except Exception as e: | ||
| print(f"\nAn error occurred: {e}") | ||
|
|
||
| if __name__ == "__main__": | ||
| custom_royalty_fee() | ||
| main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're missing some key imports that you are using, for example
import sys