Skip to content

Commit fb371c6

Browse files
authored
Merge pull request #35 from exploreriii/TokenMintTransaction
Token mint transaction
2 parents 09959b4 + c719b08 commit fb371c6

13 files changed

+681
-11
lines changed

README.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This is a Python SDK for interacting with the Hedera Hashgraph platform. It allows developers to:
44

5-
- Manage Token Transactions like Create, Associate, Dissociate, Transfer & Delete
5+
- Manage Token Transactions like Create, Mint Fungible, Mint Non-Fungible, Associate, Dissociate, Transfer & Delete
66
- Manage Consensus Transactions like Topic Create, Update, Delete
77
- Submit Topic Messages
88
- Query Account Balance, Transaction Receipts, Topic Infos and Messages
@@ -19,6 +19,8 @@ This is a Python SDK for interacting with the Hedera Hashgraph platform. It allo
1919
- [Creating an Account](#creating-an-account)
2020
- [Querying Account Balance](#querying-account-balance)
2121
- [Creating a Token](#creating-a-token)
22+
- [Minting a Fungible Token](#minting-a-fungible-token)
23+
- [Minting a Non-Fungible Token](#minting-a-non-fungible-token)
2224
- [Associating a Token](#associating-a-token)
2325
- [Dissociating a Token](#dissociating-a-token)
2426
- [Transferring Tokens](#transferring-tokens)
@@ -112,6 +114,7 @@ Create a .env file in the root of your project with the following (replace with
112114
OPERATOR_ID=0.0.1234xx
113115
OPERATOR_KEY=302e020100300506032b657004220420...
114116
ADMIN_KEY=302a300506032b65700321009308ecfdf...
117+
SUPPLY_KEY =302a300506032b6570032100c5e4af5..."
115118
RECIPIENT_ID=0.0.789xx
116119
TOKEN_ID=0.0.100xx
117120
TOPIC_ID=0.0.200xx
@@ -143,6 +146,7 @@ New Account Public Key: 8f444e36e8926def492adxxx...
143146
Token creation successful. Token ID: 0.0.5025xxx
144147
Token association successful.
145148
Token dissociation successful.
149+
Token minting successful.
146150
Token transfer successful.
147151
Token deletion successful.
148152
Topic creation successful.
@@ -215,6 +219,7 @@ transaction = TokenCreateTransaction(
215219
initial_supply=1000,
216220
treasury_account_id=operator_id,
217221
admin_key=admin_key
222+
supply_key=supply_key
218223
).freeze_with(client)
219224
220225
transaction.sign(admin_key)
@@ -232,6 +237,7 @@ transaction = (
232237
.set_initial_supply(1000)
233238
.set_treasury_account_id(operator_id)
234239
.set_admin_key(admin_key) # Optional to create a token. Necessary for Token Delete or Update.
240+
.set_supply_key(supply_key) # Optional to change token supply. Necessary for Token Mint or Burn.
235241
.freeze_with(client)
236242
)
237243
@@ -240,6 +246,59 @@ transaction = (
240246
transaction.execute(client)
241247
```
242248

249+
250+
### Minting a Fungible Token
251+
252+
#### Pythonic Syntax:
253+
```
254+
transaction = TokenMintTransaction(
255+
token_id=token_id,
256+
amount=amount, # lowest denomination, must be positive and not zero
257+
).freeze_with(client)
258+
259+
transaction.sign(operator_key)
260+
transaction.sign(supply_key)
261+
transaction.execute(client)
262+
```
263+
#### Method Chaining:
264+
```
265+
transaction = (
266+
TokenMintTransaction()
267+
.set_token_id(token_id)
268+
.set_amount(amount) # lowest denomination, must be positive and not zero
269+
.freeze_with(client)
270+
)
271+
transaction.sign(operator_key)
272+
transaction.sign(admin_key)
273+
transaction.execute(client)
274+
```
275+
276+
### Minting a Non-Fungible Token
277+
278+
#### Pythonic Syntax:
279+
```
280+
transaction = TokenMintTransaction(
281+
token_id=token_id,
282+
metadata=metadata # Bytes for non-fungible tokens (NFTs)
283+
).freeze_with(client)
284+
285+
transaction.sign(operator_key)
286+
transaction.sign(supply_key)
287+
transaction.execute(client)
288+
```
289+
#### Method Chaining:
290+
```
291+
transaction = (
292+
TokenMintTransaction()
293+
.set_token_id(token_id)
294+
.set_metadata(metadata) # Bytes for non-fungible tokens (NFTs)
295+
.freeze_with(client)
296+
)
297+
transaction.sign(operator_key)
298+
transaction.sign(admin_key)
299+
transaction.execute(client)
300+
```
301+
243302
### Associating a Token
244303

245304
#### Pythonic Syntax:

examples/token_create.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ def create_token():
1919
operator_id = AccountId.from_string(os.getenv('OPERATOR_ID'))
2020
operator_key = PrivateKey.from_string(os.getenv('OPERATOR_KEY'))
2121
admin_key = PrivateKey.from_string(os.getenv('ADMIN_KEY'))
22+
supply_key = PrivateKey.from_string(os.getenv('ADMIN_KEY')) #Optional
2223

24+
2325
client.set_operator(operator_id, operator_key)
2426

2527
transaction = (
@@ -30,6 +32,7 @@ def create_token():
3032
.set_initial_supply(10)
3133
.set_treasury_account_id(operator_id)
3234
.set_admin_key(admin_key)
35+
.set_supply_key(supply_key)
3336
.freeze_with(client)
3437
.sign(operator_key)
3538
.sign(admin_key)

examples/token_mint_fungible.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import os
2+
import sys
3+
from dotenv import load_dotenv
4+
5+
from hedera_sdk_python import (
6+
Client,
7+
AccountId,
8+
PrivateKey,
9+
TokenMintTransaction,
10+
Network,
11+
TokenId,
12+
)
13+
14+
load_dotenv()
15+
16+
def fungible_token_mint():
17+
"""
18+
Mint fungible tokens to increase the total supply of the token.
19+
The new supply must be lower than 2^63-1 (within the range that can be safely stored in a signed 64-bit integer).
20+
21+
Loads environment variables for OPERATOR_ID, OPERATOR_KEY, SUPPLY_KEY, TOKEN_ID.
22+
Creates and signs a TokenMintTransaction for a fungible token.
23+
Submits the transaction and prints the result.
24+
"""
25+
26+
network = Network(network='testnet')
27+
client = Client(network)
28+
29+
payer_id = AccountId.from_string(os.getenv('OPERATOR_ID'))
30+
payer_key = PrivateKey.from_string(os.getenv('OPERATOR_KEY'))
31+
supply_key = PrivateKey.from_string(os.getenv('SUPPLY_KEY'))
32+
token_id = TokenId.from_string(os.getenv('TOKEN_ID'))
33+
34+
client.set_operator(payer_id, payer_key)
35+
36+
# Example: If the token has 2 decimals, "20000" here means 200.00 tokens minted.
37+
transaction = (
38+
TokenMintTransaction()
39+
.set_token_id(token_id)
40+
.set_amount(20000) # Positive, non-zero amount to mint in lowest denomination
41+
.freeze_with(client)
42+
.sign(payer_key)
43+
.sign(supply_key)
44+
)
45+
46+
try:
47+
receipt = transaction.execute(client)
48+
if receipt and receipt.tokenId:
49+
print(f"Fungible token minting successful")
50+
else:
51+
print(f"Fungible token minting failed")
52+
sys.exit(1)
53+
except Exception as e:
54+
print(f"Fungible token minting failed: {str(e)}")
55+
sys.exit(1)
56+
57+
58+
if __name__ == "__main__":
59+
fungible_token_mint()

examples/token_mint_non_fungible.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import os
2+
import sys
3+
import json
4+
from dotenv import load_dotenv
5+
6+
from hedera_sdk_python import (
7+
Client,
8+
AccountId,
9+
PrivateKey,
10+
TokenMintTransaction,
11+
Network,
12+
TokenId,
13+
)
14+
15+
load_dotenv()
16+
17+
def nft_token_mint(metadata):
18+
"""
19+
Minting a non-fungible token creates new NFTs for the token ID by providing metadata as a list of byte arrays.
20+
21+
Loads environment variables for OPERATOR_ID, OPERATOR_KEY, SUPPLY_KEY, TOKEN_ID.
22+
Creates and signs a TokenMintTransaction for a NON_FUNGIBLE_UNIQUE token.
23+
Submits the transaction and prints the result.
24+
"""
25+
26+
network = Network(network='testnet')
27+
client = Client(network)
28+
29+
payer_id = AccountId.from_string(os.getenv('OPERATOR_ID'))
30+
payer_key = PrivateKey.from_string(os.getenv('OPERATOR_KEY'))
31+
supply_key = PrivateKey.from_string(os.getenv('SUPPLY_KEY'))
32+
token_id = TokenId.from_string(os.getenv('TOKEN_ID'))
33+
34+
client.set_operator(payer_id, payer_key)
35+
36+
transaction = (
37+
TokenMintTransaction()
38+
.set_token_id(token_id)
39+
.set_metadata(metadata) # Mandatory single or list of byte array metadata for NFTs each up to 100 bytes e.g. b"A"
40+
.freeze_with(client)
41+
.sign(payer_key)
42+
.sign(supply_key)
43+
44+
)
45+
46+
try:
47+
receipt = transaction.execute(client)
48+
if receipt and receipt.tokenId:
49+
print(f"NFT minting successful")
50+
else:
51+
print(f"NFT minting failed")
52+
sys.exit(1)
53+
except Exception as e:
54+
print(f"NFT minting failed: {str(e)}")
55+
sys.exit(1)
56+
57+
58+
def load_metadata_from_json(file_path):
59+
"""
60+
Loads NFT metadata from a JSON file to use in the transaction.
61+
:param file_path: Path to the JSON file containing metadata.
62+
:return: List of byte arrays representing NFT metadata.
63+
"""
64+
try:
65+
with open(file_path, 'r') as file:
66+
metadata = json.load(file)
67+
if not isinstance(metadata, list):
68+
raise ValueError("Metadata JSON must be a list of strings.")
69+
# Convert each metadata string to bytes
70+
return [m.encode('utf-8') for m in metadata]
71+
except Exception as e:
72+
print(f"Failed to load metadata from JSON: {str(e)}")
73+
sys.exit(1)
74+
75+
if __name__ == "__main__":
76+
metadata = load_metadata_from_json("nft_metadata.json")
77+
nft_token_mint(metadata)
78+

src/hedera_sdk_python/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from .tokens.token_associate_transaction import TokenAssociateTransaction
1616
from .tokens.token_dissociate_transaction import TokenDissociateTransaction
1717
from .tokens.token_delete_transaction import TokenDeleteTransaction
18+
from .tokens.token_mint_transaction import TokenMintTransaction
1819
from .tokens.token_id import TokenId
1920

2021
# Transaction
@@ -62,6 +63,7 @@
6263
"TokenAssociateTransaction",
6364
"TokenDissociateTransaction",
6465
"TokenDeleteTransaction",
66+
"TokenMintTransaction",
6567
"TokenId",
6668

6769
# Transaction

src/hedera_sdk_python/client/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def __init__(self, network=None):
3232
if network is None:
3333
network = Network()
3434
self.network = network
35-
35+
3636
self.channel = None
3737
self.token_stub = None
3838
self.crypto_stub = None

src/hedera_sdk_python/tokens/token_create_transaction.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class TokenCreateTransaction(Transaction):
1515
"""
1616

1717
def __init__(self, token_name=None, token_symbol=None, decimals=None, initial_supply=None,
18-
treasury_account_id=None, admin_key=None):
18+
treasury_account_id=None, admin_key=None, supply_key=None):
1919
"""
2020
Initializes a new TokenCreateTransaction instance with optional keyword arguments.
2121
@@ -26,6 +26,8 @@ def __init__(self, token_name=None, token_symbol=None, decimals=None, initial_su
2626
initial_supply (int, optional): The initial supply of the token.
2727
treasury_account_id (AccountId, optional): The treasury account ID.
2828
admin_key (PrivateKey, optional): The admin key for the token.
29+
supply_key (PrivateKey, optional): The supply key for the token.
30+
2931
"""
3032
super().__init__()
3133
self.token_name = token_name
@@ -34,6 +36,7 @@ def __init__(self, token_name=None, token_symbol=None, decimals=None, initial_su
3436
self.initial_supply = initial_supply
3537
self.treasury_account_id = treasury_account_id
3638
self.admin_key = admin_key
39+
self.supply_key = supply_key
3740

3841
self._default_transaction_fee = 3_000_000_000
3942

@@ -67,6 +70,11 @@ def set_admin_key(self, admin_key):
6770
self.admin_key = admin_key
6871
return self
6972

73+
def set_supply_key(self, supply_key):
74+
self._require_not_frozen()
75+
self.supply_key = supply_key
76+
return self
77+
7078
def build_transaction_body(self):
7179
"""
7280
Builds and returns the protobuf transaction body for token creation.
@@ -91,13 +99,19 @@ def build_transaction_body(self):
9199
admin_public_key_bytes = self.admin_key.public_key().to_bytes_raw()
92100
admin_key_proto = basic_types_pb2.Key(ed25519=admin_public_key_bytes)
93101

102+
supply_key_proto = None
103+
if self.supply_key:
104+
supply_public_key_bytes = self.supply_key.public_key().to_bytes_raw()
105+
supply_key_proto = basic_types_pb2.Key(ed25519=supply_public_key_bytes)
106+
94107
token_create_body = token_create_pb2.TokenCreateTransactionBody(
95108
name=self.token_name,
96109
symbol=self.token_symbol,
97110
decimals=self.decimals,
98111
initialSupply=self.initial_supply,
99112
treasury=self.treasury_account_id.to_proto(),
100-
adminKey=admin_key_proto
113+
adminKey=admin_key_proto,
114+
supplyKey=supply_key_proto
101115
)
102116

103117
transaction_body = self.build_base_transaction_body()

0 commit comments

Comments
 (0)