Files

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

  1. Copy this template to create your smart contract:

    cp -r python /path/to/my-smart-contract
    cd /path/to/my-smart-contract
    
  2. Set up the environment:

    make setup
    source venv/bin/activate
    

    Or without make:

    python3 -m venv venv
    source venv/bin/activate
    pip install -r requirements.txt
    
  3. Generate the protobuf code:

    make proto
    
  4. 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"
    
  5. Implement your smart contract logic in process.py by modifying the process function.

  6. 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 the process function 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 process function via ProcessResult.error to 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]