TypeScript Smart Contract Template
A TypeScript/JavaScript-based smart contract client for Dragonchain Prime that connects via gRPC.
Prerequisites
- Node.js 18 or later
- npm
Quick Start
-
Copy this template to create your smart contract:
cp -r typescript /path/to/my-smart-contract cd /path/to/my-smart-contract -
Install dependencies:
npm install -
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
src/process.tsby modifying theprocessTransactionfunction. -
Build and run:
npm run build npm start -- --config config.yamlOr run in development mode:
npm run dev -- --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 processTransaction function in src/process.ts:
export async function processTransaction(
txJson: string,
envVars: Record<string, string>,
secrets: Record<string, string>
): Promise<ProcessResult> {
// Parse the transaction
const tx: Transaction = JSON.parse(txJson);
// Access transaction data
const txnId = tx.header.txn_id;
const txnType = tx.header.txn_type;
const payload = tx.payload;
// Access environment variables
const scName = envVars["SMART_CONTRACT_NAME"];
const dcId = envVars["DRAGONCHAIN_ID"];
// Access secrets
const mySecret = secrets["SC_SECRET_MY_SECRET"];
// Implement your logic here
const result = {
status: "success",
data: "your result data",
};
return {
data: result,
outputToChain: true, // Set to true to persist result on chain
};
}
Transaction Structure
The Transaction interface in src/process.ts matches the Dragonchain transaction format:
interface Transaction {
version: string;
header: TransactionHeader;
payload: Record<string, unknown>;
}
interface TransactionHeader {
tag: string;
dc_id: string;
txn_id: string;
block_id: string;
txn_type: string;
timestamp: string;
invoker: string;
}
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 object with keys prefixed by SC_SECRET_.
Project Structure
.
├── src/
│ ├── main.ts # Client infrastructure (do not modify)
│ └── process.ts # Your smart contract logic (modify this)
├── proto/
│ └── remote_sc.proto # gRPC service definition
├── config.yaml # Configuration file
├── package.json # Node.js dependencies
├── tsconfig.json # TypeScript configuration
├── Makefile # Build commands
└── README.md # This file
File Descriptions
src/process.ts- Contains theprocessTransactionfunction where you implement your smart contract logic. This is the only file you need to modify for most use cases.src/main.ts- Contains the gRPC client infrastructure, connection handling, and worker pool. You typically don't need to modify this file.
NPM Scripts
npm install # Install dependencies
npm run build # Compile TypeScript to JavaScript
npm start # Run the compiled application
npm run dev # Run with ts-node (development)
npm run proto # Generate TypeScript types from proto
npm run clean # Remove build artifacts
npm run lint # Lint the code
npm run format # Format code with prettier
Make Commands
make setup # Install dependencies
make proto # Generate TypeScript types from proto
make build # Build TypeScript
make run # Build and run
make dev # Run in development mode
make clean # Remove build artifacts
make lint # Lint code
make format # Format code
Concurrent Processing
The client uses async/await with a concurrency limit to process multiple transactions simultaneously. The number of concurrent workers is configurable via num_workers in the config file.
Error Handling
- Return errors from the
processTransactionfunction 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 node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
CMD ["node", "dist/main.js", "--config", "config.yaml"]
Using with JavaScript
If you prefer plain JavaScript instead of TypeScript:
- Write your code in
src/process.jsinstead ofsrc/process.ts - Skip the build step and run directly:
node src/main.js --config config.yaml
License
[Your License Here]