Python Smart Contract Template
A Python-based smart contract client for Dragonchain Prime that connects via gRPC.
Prerequisites
- Python 3.10 or later
- pip
Quick Start
-
Copy this template to create your smart contract:
cp -r python /path/to/my-smart-contract cd /path/to/my-smart-contract -
Set up the environment:
make setup source venv/bin/activateOr without make:
python3 -m venv venv source venv/bin/activate pip install -r requirements.txt -
Generate the protobuf code:
make proto -
Configure your connection by editing
config.yaml:server_address: "your-dragonchain-server:50051" smart_contract_id: "your-smart-contract-id" api_key: "your-api-key" -
Implement your smart contract logic in
process.pyby modifying theprocessfunction. -
Run:
python main.py --config config.yaml
Configuration
| Field | Description | Default |
|---|---|---|
server_address |
gRPC server address | Required |
smart_contract_id |
Your smart contract ID | Required |
api_key |
API key for authentication | Required |
use_tls |
Enable TLS encryption | false |
tls_cert_path |
Path to TLS certificate | - |
num_workers |
Concurrent transaction processors | 10 |
reconnect_delay_seconds |
Delay between reconnection attempts | 5 |
max_reconnect_attempts |
Max reconnect attempts (0 = infinite) | 0 |
Implementing Your Smart Contract
Edit the process function in process.py:
def process(
tx_json: str,
env_vars: dict[str, str],
secrets: dict[str, str],
) -> ProcessResult:
# Parse the transaction
tx = Transaction.from_json(tx_json)
# Access transaction data
txn_id = tx.header.txn_id
txn_type = tx.header.txn_type
payload = tx.payload
# Access environment variables
sc_name = env_vars.get("SMART_CONTRACT_NAME")
dc_id = env_vars.get("DRAGONCHAIN_ID")
# Access secrets
my_secret = secrets.get("SC_SECRET_MY_SECRET")
# Implement your logic here
result = {
"status": "success",
"data": "your result data",
}
return ProcessResult(
data=result,
output_to_chain=True, # Set to True to persist result on chain
error=None,
)
Transaction Structure
The Transaction class in process.py matches the Dragonchain transaction format:
@dataclass
class Transaction:
version: str
header: TransactionHeader
payload: dict[str, Any]
@dataclass
class TransactionHeader:
tag: str
dc_id: str
txn_id: str
block_id: str
txn_type: str
timestamp: str
invoker: str
Available Environment Variables
| Variable | Description |
|---|---|
TZ |
Timezone |
ENVIRONMENT |
Deployment environment |
INTERNAL_ID |
Internal identifier |
DRAGONCHAIN_ID |
Dragonchain ID |
DRAGONCHAIN_ENDPOINT |
Dragonchain API endpoint |
SMART_CONTRACT_ID |
This smart contract's ID |
SMART_CONTRACT_NAME |
This smart contract's name |
SC_ENV_* |
Custom environment variables |
Secrets
Secrets are provided in the secrets dict with keys prefixed by SC_SECRET_.
Project Structure
.
├── main.py # Client infrastructure (do not modify)
├── process.py # Your smart contract logic (modify this)
├── proto/
│ └── remote_sc.proto # gRPC service definition
├── config.yaml # Configuration file
├── requirements.txt # Python dependencies
├── Makefile # Build commands
└── README.md # This file
File Descriptions
process.py- Contains theprocessfunction where you implement your smart contract logic. This is the only file you need to modify for most use cases.main.py- Contains the gRPC client infrastructure, connection handling, and worker pool. You typically don't need to modify this file.
Make Commands
make setup # Create venv and install dependencies
make proto # Generate Python code from proto files
make run # Run with default config
make test # Run tests
make clean # Remove generated files and venv
make deps # Install dependencies (no venv)
make format # Format code with black and isort
Concurrent Processing
The client uses a thread pool to process multiple transactions concurrently. The number of workers is configurable via num_workers in the config file.
Error Handling
- Return errors from the
processfunction viaProcessResult.errorto report failures - The client automatically handles reconnection on connection failures
- Logs are captured and sent back with the response
Docker
Example Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python -m grpc_tools.protoc \
-I./proto \
--python_out=. \
--grpc_python_out=. \
proto/remote_sc.proto
CMD ["python", "main.py", "--config", "config.yaml"]
License
[Your License Here]