Skip to content

Commit

Permalink
TokenTypeClass
Browse files Browse the repository at this point in the history
  • Loading branch information
exploreriii committed Jan 16, 2025
1 parent d2f2ce3 commit f658537
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ balance = ( CryptoGetAccountBalanceQuery() .set_account_id(some_account_id) .exe
```

### Creating a Token
You can choose to create either a fungible (common) or non-fungible (unique) token. Use the `TokenType` class to specify which type.

#### Pythonic Syntax:
```
Expand All @@ -177,6 +178,7 @@ transaction = TokenCreateTransaction(
token_symbol="EXT",
decimals=2,
initial_supply=1000,
token_type=TokenType(TokenType.FUNGIBLE_COMMON), # or TokenType.NON_FUNGIBLE_UNIQUE
treasury_account_id=operator_id,
admin_key=admin_key
).freeze_with(client)
Expand All @@ -194,6 +196,7 @@ transaction = (
.set_token_symbol("EXT")
.set_decimals(2)
.set_initial_supply(1000)
.set_token_type(TokenType(TokenType.FUNGIBLE_COMMON)) # or NON_FUNGIBLE_UNIQUE
.set_treasury_account_id(operator_id)
.set_admin_key(admin_key) # Optional to create a token. Necessary for Token Delete or Update.
.freeze_with(client)
Expand Down
4 changes: 4 additions & 0 deletions examples/token_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from hedera_sdk_python.tokens.token_create_transaction import TokenCreateTransaction
from hedera_sdk_python.client.network import Network
from cryptography.hazmat.primitives import serialization
from hedera_sdk_python.token.token_type import TokenType

load_dotenv()

Expand All @@ -21,13 +22,16 @@ def create_token():

client.set_operator(operator_id, operator_key)

chosen_token_type = TokenType(TokenType.FUNGIBLE_COMMON) # or TokenType.NON_FUNGIBLE_UNIQUE

transaction = (
TokenCreateTransaction()
.set_token_name("MyToken")
.set_token_symbol("MTK")
.set_decimals(2)
.set_initial_supply(10)
.set_treasury_account_id(operator_id)
.set_token_type(chosen_token_type) #Optional
.set_admin_key(admin_key)
.freeze_with(client)
.sign(operator_key)
Expand Down
85 changes: 85 additions & 0 deletions src/hedera_sdk_python/tokens/token_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from hedera_sdk_python.hapi.services import basic_types_pb2

class TokenType:
"""
Represents the type of a Hedera token.
This class mirrors the enum defined in Hedera's protobufs:
0: FUNGIBLE_COMMON
1: NON_FUNGIBLE_UNIQUE
"""
FUNGIBLE_COMMON = 0
NON_FUNGIBLE_UNIQUE = 1

def __init__(self, token_type=FUNGIBLE_COMMON):
"""
Initializes a TokenType instance with:
TokenType.FUNGIBLE_COMMON or TokenType.NON_FUNGIBLE_UNIQUE.
"""
if token_type not in (self.FUNGIBLE_COMMON, self.NON_FUNGIBLE_UNIQUE):
raise ValueError(f"Invalid TokenType value: {token_type}")
self._token_type = token_type

@classmethod
def from_proto(cls, token_type_proto):
"""
Creates a TokenType instance from the integer value in the protobuf enum.
Args:
token_type_proto (int): The integer value corresponding to the TokenType.
Returns:
TokenType: A TokenType instance matching the protobuf value.
"""
if token_type_proto == basic_types_pb2.TokenType.FUNGIBLE_COMMON:
return cls(cls.FUNGIBLE_COMMON)
elif token_type_proto == basic_types_pb2.TokenType.NON_FUNGIBLE_UNIQUE:
return cls(cls.NON_FUNGIBLE_UNIQUE)
else:
raise ValueError(f"Unknown TokenType proto value: {token_type_proto}")

def to_proto(self):
"""
Converts this TokenType instance into its protobuf enum integer.
Returns:
int: The integer value corresponding to the Hedera protobuf enum.
"""
if self._token_type == self.FUNGIBLE_COMMON:
return basic_types_pb2.TokenType.FUNGIBLE_COMMON
else:
return basic_types_pb2.TokenType.NON_FUNGIBLE_UNIQUE


@classmethod
def from_string(cls, token_type_str):
"""
Parses a string like "FUNGIBLE_COMMON" or "NON_FUNGIBLE_UNIQUE"
and returns a TokenType instance.
Args:
token_type_str (str): A string describing the token type.
Returns:
TokenType: A TokenType instance.
Raises:
ValueError: If the provided string doesn't match known token types.
"""
token_type_str = token_type_str.strip().upper()
if token_type_str == "FUNGIBLE_COMMON":
return cls(cls.FUNGIBLE_COMMON)
elif token_type_str == "NON_FUNGIBLE_UNIQUE":
return cls(cls.NON_FUNGIBLE_UNIQUE)
else:
raise ValueError(f"Invalid token type string: {token_type_str}")

def __str__(self):
"""
Returns a human-readable string for this TokenType. For example:
'FUNGIBLE_COMMON' or 'NON_FUNGIBLE_UNIQUE'.
"""
if self._token_type == self.FUNGIBLE_COMMON:
return "FUNGIBLE_COMMON"
else:
return "NON_FUNGIBLE_UNIQUE"

2 changes: 2 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from hedera_sdk_python.consensus.topic_id import TopicId
from hedera_sdk_python.query.topic_info_query import TopicInfoQuery
from hedera_sdk_python.query.account_balance_query import CryptoGetAccountBalanceQuery
from hedera_sdk_python.tokens.token_type import TokenType

load_dotenv()

Expand Down Expand Up @@ -70,6 +71,7 @@ def create_token(client, operator_id, admin_key):
decimals=2,
initial_supply=1000,
treasury_account_id=operator_id,
token_type=TokenType(TokenType.FUNGIBLE_COMMON),
admin_key=admin_key
)
transaction.freeze_with(client)
Expand Down
103 changes: 103 additions & 0 deletions tests/test_token_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import pytest
from hedera_sdk_python.hapi.services import basic_types_pb2
from hedera_sdk_python.tokens.token_type import TokenType

def test_default_init():
"""
Test the default, a TokenType with FUNGIBLE_COMMON.
"""
token_type = TokenType()
assert token_type._token_type == TokenType.FUNGIBLE_COMMON

def test_init_fungible():
"""
Test initializing a TokenType as FUNGIBLE_COMMON.
"""
token_type = TokenType(TokenType.FUNGIBLE_COMMON)
assert token_type._token_type == TokenType.FUNGIBLE_COMMON

def test_init_non_fungible():
"""
Test initializing a TokenType as NON_FUNGIBLE_UNIQUE.
"""
token_type = TokenType(TokenType.NON_FUNGIBLE_UNIQUE)
assert token_type._token_type == TokenType.NON_FUNGIBLE_UNIQUE

def test_init_invalid():
"""
Test that initializing a TokenType with an invalid value raises a ValueError.
"""
with pytest.raises(ValueError, match="Invalid TokenType value"):
TokenType(2) # Not 0 or 1

def test_from_proto_fungible():
"""
Test creating a TokenType instance from the protobuf enum (FUNGIBLE_COMMON).
"""
token_type = TokenType.from_proto(basic_types_pb2.TokenType.FUNGIBLE_COMMON)
assert token_type._token_type == TokenType.FUNGIBLE_COMMON

def test_from_proto_non_fungible():
"""
Test creating a TokenType instance from the protobuf enum (NON_FUNGIBLE_UNIQUE).
"""
token_type = TokenType.from_proto(basic_types_pb2.TokenType.NON_FUNGIBLE_UNIQUE)
assert token_type._token_type == TokenType.NON_FUNGIBLE_UNIQUE

def test_from_proto_invalid():
"""
Test that from_proto with an invalid protobuf value raises a ValueError.
"""
with pytest.raises(ValueError, match="Unknown TokenType proto value"):
TokenType.from_proto(2)

def test_to_proto_fungible():
"""
Test converting a TokenType(FUNGIBLE_COMMON) to its protobuf enum integer.
"""
token_type = TokenType(TokenType.FUNGIBLE_COMMON)
proto_value = token_type.to_proto()
assert proto_value == basic_types_pb2.TokenType.FUNGIBLE_COMMON

def test_to_proto_non_fungible():
"""
Test converting a TokenType(NON_FUNGIBLE_UNIQUE) to its protobuf enum integer.
"""
token_type = TokenType(TokenType.NON_FUNGIBLE_UNIQUE)
proto_value = token_type.to_proto()
assert proto_value == basic_types_pb2.TokenType.NON_FUNGIBLE_UNIQUE

def test_from_string_fungible():
"""
Test parsing a string 'FUNGIBLE_COMMON' into a TokenType.
"""
token_type = TokenType.from_string("FUNGIBLE_COMMON")
assert token_type._token_type == TokenType.FUNGIBLE_COMMON

def test_from_string_non_fungible():
"""
Test parsing a string 'NON_FUNGIBLE_UNIQUE' into a TokenType.
"""
token_type = TokenType.from_string("NON_FUNGIBLE_UNIQUE")
assert token_type._token_type == TokenType.NON_FUNGIBLE_UNIQUE

def test_from_string_invalid():
"""
Test that from_string with an unknown string raises a ValueError.
"""
with pytest.raises(ValueError, match="Invalid token type string"):
TokenType.from_string("unknown_type")

def test_str_fungible():
"""
Test string representation of a TokenType(FUNGIBLE_COMMON).
"""
token_type = TokenType(TokenType.FUNGIBLE_COMMON)
assert str(token_type) == "FUNGIBLE_COMMON"

def test_str_non_fungible():
"""
Test string representation of a TokenType(NON_FUNGIBLE_UNIQUE).
"""
token_type = TokenType(TokenType.NON_FUNGIBLE_UNIQUE)
assert str(token_type) == "NON_FUNGIBLE_UNIQUE"

0 comments on commit f658537

Please sign in to comment.