Skip to content

feat: add ContractCreateTransaction #198

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b9da071
feat: add ContractSelector class
Dosik13 Jul 18, 2025
0c71444
feat: add ContractFunctionParamters
Dosik13 Jul 18, 2025
e9336cb
feat: add ContractId class
Dosik13 Jul 18, 2025
8347e4b
test: add unit tests for contractId
Dosik13 Jul 18, 2025
ed66460
feat: export contract_id in transaction_receipt
Dosik13 Jul 18, 2025
176018f
feat: add ContractCreateTransaction class
Dosik13 Jul 18, 2025
0c37662
test: add unit tests for ContractCreateTransaction
Dosik13 Jul 18, 2025
76d1bfa
test: add integration tests forContractCreateTransaction
Dosik13 Jul 18, 2025
f995fac
docs: add ContractCreateTransaction in examples README
Dosik13 Jul 28, 2025
6a9fda6
docs: add contract create example
Dosik13 Jul 18, 2025
2f01c48
feat: add contract bytecode files (SimpleContract for basic testing, …
Dosik13 Jul 21, 2025
14574b7
feat: add contract bytecode loader utility and examples module initia…
Dosik13 Jul 21, 2025
bc6abbc
test: update ContractCreate integration tests to use contract utils a…
Dosik13 Jul 21, 2025
cbb5e89
chore: fix linting issues in contract utilities
Dosik13 Jul 21, 2025
0762866
docs: update contract create example
Dosik13 Jul 21, 2025
a94c714
docs: add contract create with constructor example
Dosik13 Jul 21, 2025
49d6d09
chore: address PR feedback for contract create
Dosik13 Jul 21, 2025
2857dc7
refactor: migrate ContractFunctionParameters to use eth-abi for param…
Dosik13 Jul 24, 2025
02ae3f3
feat: add type stub file for ContractFunctionParameters with eth-abi …
Dosik13 Jul 25, 2025
b8a17c6
docs: update examples
Dosik13 Jul 25, 2025
ad13d2b
docs: add contract creation example with direct bytecode usage
Dosik13 Jul 25, 2025
f893875
chore: address PR feedback
Dosik13 Jul 25, 2025
ea5a44a
fix: remove unnecessary added add_function() method from ContractFunc…
Dosik13 Jul 25, 2025
a0c55a2
feat: add ConstructorTestContract smart contract for testing Contract…
Dosik13 Jul 28, 2025
4673816
test: add integration tests for ContracFunctionParameters
Dosik13 Jul 28, 2025
2f957f1
chore: add ContractCreateTransaction and ContractFunctionParameters t…
Dosik13 Jul 29, 2025
11ae8a6
feat: add eth-abi dependency for contract parameter encoding
Dosik13 Jul 29, 2025
19b212b
fix: update ConstructorTestContract bytecode to match compiled version
Dosik13 Jul 29, 2025
acd1198
docs: add parameter order comments in contract test
Dosik13 Jul 29, 2025
010308c
docs: add more documentaton in contract utils
Dosik13 Jul 30, 2025
c3c581e
chore: address PR feedback
Dosik13 Jul 30, 2025
ee4b724
chore: address incorrect error raising
Dosik13 Jul 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ You can choose either syntax or even mix both styles in your projects.
- [Querying File Contents](#querying-file-contents)
- [Updating a File](#updating-a-file)
- [Deleting a File](#deleting-a-file)
- [Contract Transactions](#contract-transactions)
- [Creating a Contract](#creating-a-contract)
- [Miscellaneous Queries](#miscellaneous-queries)
- [Querying Transaction Record](#querying-transaction-record)

Expand Down Expand Up @@ -1043,6 +1045,106 @@ transaction.execute(client)

```

```

## Contract Transactions

### Creating a Contract

#### Pythonic Syntax:
```
# First, create a file with the contract bytecode
transaction = FileCreateTransaction(
keys=[operator_key.public_key()],
contents=contract_bytecode,
file_memo="Contract bytecode file"
).freeze_with(client)

transaction.sign(operator_key)
file_receipt = transaction.execute(client)

file_id = file_receipt.file_id

# Create constructor parameters if needed
constructor_params = ContractFunctionParameters().add_string("Hello, World!")

# Create the contract using bytecode from file
transaction = ContractCreateTransaction(
contract_params=ContractCreateParams(
bytecode_file_id=file_id,
gas=200000,
admin_key=admin_key,
initial_balance=100000000, # 1 HBAR in tinybars
parameters=constructor_params.to_bytes(),
contract_memo="My first smart contract"
)
).freeze_with(client)

transaction.sign(operator_key)
transaction.sign(admin_key)
transaction.execute(client)
```

#### Method Chaining:
```
# First, create a file with the contract bytecode
file_receipt = (
FileCreateTransaction()
.set_keys(operator_key.public_key())
.set_contents(contract_bytecode)
.set_file_memo("Contract bytecode file")
.freeze_with(client)
.sign(operator_key)
.execute(client)
)

file_id = file_receipt.file_id

# Create constructor parameters if needed
constructor_params = ContractFunctionParameters().add_string("Hello, World!")

# Create the contract using bytecode from file
transaction = (
ContractCreateTransaction()
.set_bytecode_file_id(file_id)
.set_gas(200000)
.set_admin_key(admin_key)
.set_initial_balance(100000000) # 1 HBAR in tinybars
.set_constructor_parameters(constructor_params)
.set_contract_memo("My first smart contract")
.freeze_with(client)
)

transaction.sign(operator_key)
transaction.sign(admin_key)
transaction.execute(client)
```

#### Creating a Contract with Direct Bytecode:
```
##### Convert hex bytecode to bytes
bytecode = bytes.fromhex(contract_bytecode_hex)

# Create constructor parameters if needed
constructor_params = ContractFunctionParameters().add_string("Hello, World!")

# Create the contract using bytecode directly
transaction = (
ContractCreateTransaction()
.set_bytecode(bytecode)
.set_gas(200000)
.set_admin_key(admin_key)
.set_initial_balance(100000000) # 1 HBAR in tinybars
.set_constructor_parameters(constructor_params)
.set_contract_memo("My first smart contract")
.freeze_with(client)
)

transaction.sign(operator_key)
transaction.sign(admin_key)
transaction.execute(client)
```

## Miscellaneous Queries

### Querying Transaction Record
Expand Down
101 changes: 101 additions & 0 deletions examples/contract_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""
Example demonstrating contract creation on the network.

This module shows how to create a smart contract by:
1. Setting up a client with operator credentials
2. Creating a file containing contract bytecode
3. Creating a contract using the file

Usage:
# Due to the way the script is structured, it must be run as a module
# from the project root directory

# Run from the project root directory
python -m examples.contract_create

"""

import os
import sys

from dotenv import load_dotenv

from hiero_sdk_python import AccountId, Client, Network, PrivateKey
from hiero_sdk_python.contract.contract_create_transaction import (
ContractCreateTransaction,
)
from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction
from hiero_sdk_python.response_code import ResponseCode

# Import the bytecode for a basic smart contract (SimpleContract.sol) that can be deployed
# The contract bytecode is pre-compiled from Solidity source code
from .contracts import SIMPLE_CONTRACT_BYTECODE

load_dotenv()


def setup_client():
"""Initialize and set up the client with operator account"""
network = Network(network="testnet")
client = Client(network)

operator_id = AccountId.from_string(os.getenv("OPERATOR_ID"))
operator_key = PrivateKey.from_string(os.getenv("OPERATOR_KEY"))
client.set_operator(operator_id, operator_key)

return client


def create_contract_file(client):
"""Create a file containing the contract bytecode"""
file_receipt = (
FileCreateTransaction()
.set_keys(client.operator_private_key.public_key())
.set_contents(SIMPLE_CONTRACT_BYTECODE)
.set_file_memo("Contract bytecode file")
.execute(client)
)

# Check if file creation was successful
if file_receipt.status != ResponseCode.SUCCESS:
print(
f"File creation failed with status: {ResponseCode(file_receipt.status).name}"
)
sys.exit(1)

return file_receipt.file_id


def contract_create():
"""
Demonstrates creating a contract on the network by:
1. Setting up client with operator account
2. Creating a file containing contract bytecode
3. Creating a contract using the file
"""
client = setup_client()

file_id = create_contract_file(client)

# Create contract using the file
receipt = (
ContractCreateTransaction()
.set_bytecode_file_id(file_id)
.set_gas(2000000) # 2M gas
.set_contract_memo("My first smart contract")
.execute(client)
)

# Check if contract creation was successful
if receipt.status != ResponseCode.SUCCESS:
print(
f"Contract creation failed with status: {ResponseCode(receipt.status).name}"
)
sys.exit(1)

contract_id = receipt.contract_id
print(f"Contract created successfully with ID: {contract_id}")


if __name__ == "__main__":
contract_create()
120 changes: 120 additions & 0 deletions examples/contract_create_constructor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
"""
Example demonstrating contract creation with constructor parameters on the network.

This module shows how to create a stateful smart contract by:
1. Setting up a client with operator credentials
2. Creating a file containing contract bytecode
3. Creating a contract using the file and constructor parameters

Usage:
# Due to the way the script is structured, it must be run as a module
# from the project root directory

# Run from the project root directory
python -m examples.contract_create_constructor

"""

import os
import sys

from dotenv import load_dotenv

from hiero_sdk_python import AccountId, Client, Network, PrivateKey
from hiero_sdk_python.contract.contract_create_transaction import (
ContractCreateTransaction,
)
from hiero_sdk_python.contract.contract_function_parameters import (
ContractFunctionParameters,
)
from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction
from hiero_sdk_python.response_code import ResponseCode

# Import the bytecode for a stateful smart contract (StatefulContract.sol) that can be deployed
# The contract bytecode is pre-compiled from Solidity source code
from .contracts import STATEFUL_CONTRACT_BYTECODE

load_dotenv()


def setup_client():
"""Initialize and set up the client with operator account"""
network = Network(network="testnet")
client = Client(network)

operator_id = AccountId.from_string(os.getenv("OPERATOR_ID"))
operator_key = PrivateKey.from_string(os.getenv("OPERATOR_KEY"))
client.set_operator(operator_id, operator_key)

return client


def create_contract_file(client):
"""Create a file containing the stateful contract bytecode"""
file_receipt = (
FileCreateTransaction()
.set_keys(client.operator_private_key.public_key())
.set_contents(STATEFUL_CONTRACT_BYTECODE)
.set_file_memo("Stateful contract bytecode file")
.execute(client)
)

# Check if file creation was successful
if file_receipt.status != ResponseCode.SUCCESS:
print(
f"File creation failed with status: {ResponseCode(file_receipt.status).name}"
)
sys.exit(1)

return file_receipt.file_id


def contract_create_constructor():
"""
Demonstrates creating a stateful contract with constructor parameters by:
1. Setting up client with operator account
2. Creating a file containing stateful contract bytecode
3. Creating a contract using the file with constructor parameters
"""
client = setup_client()

file_id = create_contract_file(client)

# Prepare constructor parameters for the stateful contract
# The contract's constructor expects a bytes32 parameter that will be stored
# We need to:
# 1. Convert our string message to UTF-8 bytes (encode)
# 2. Pass those bytes to add_bytes32() to properly format for the contract
# NOTE: If message exceeds 32 bytes, it will raise an error.
# If message is less than 32 bytes, it will be padded with zeros.
initial_message = "Initial message from constructor".encode("utf-8")

# Create ContractFunctionParameters object and add the bytes32 parameter
# This will be passed to setConstructorParameters() when creating the contract
constructor_params = ContractFunctionParameters().add_bytes32(initial_message)

# Create contract using the file with constructor parameters
receipt = (
ContractCreateTransaction()
.set_admin_key(client.operator_private_key.public_key())
.set_gas(2000000) # 2M gas
.set_bytecode_file_id(file_id)
.set_constructor_parameters(constructor_params)
.set_contract_memo("Stateful smart contract with constructor")
.execute(client)
)

# Check if contract creation was successful
if receipt.status != ResponseCode.SUCCESS:
print(
f"Contract creation failed with status: {ResponseCode(receipt.status).name}"
)
sys.exit(1)

contract_id = receipt.contract_id
print(f"Stateful contract created successfully with ID: {contract_id}")
print(f"Initial message set in constructor: '{initial_message.decode('utf-8')}'")


if __name__ == "__main__":
contract_create_constructor()
Loading