193 lines
5.4 KiB
Markdown
Executable File
193 lines
5.4 KiB
Markdown
Executable File
# Go Smart Contract Template
|
|
|
|
A Go-based smart contract client for Dragonchain Prime that connects via gRPC.
|
|
|
|
## Prerequisites
|
|
|
|
- Go 1.21 or later
|
|
- Protocol Buffers compiler (`protoc`)
|
|
- Go protobuf plugins
|
|
|
|
### Installing Tools
|
|
|
|
```bash
|
|
# Install protoc (Ubuntu/Debian)
|
|
sudo apt install -y protobuf-compiler
|
|
|
|
# Install protoc (macOS)
|
|
brew install protobuf
|
|
|
|
# Install Go protobuf plugins
|
|
make tools
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
1. **Copy this template** to create your smart contract:
|
|
```bash
|
|
cp -r go /path/to/my-smart-contract
|
|
cd /path/to/my-smart-contract
|
|
```
|
|
|
|
2. **Initialize your Go module and update package names**:
|
|
```bash
|
|
go mod init github.com/your-org/your-project
|
|
make fix-package-name
|
|
```
|
|
|
|
3. **Generate the protobuf code**:
|
|
```bash
|
|
make proto
|
|
```
|
|
|
|
4. **Configure your connection** by editing `config.yaml`:
|
|
```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.go` by modifying the `Process` function.
|
|
|
|
6. **Build and run**:
|
|
```bash
|
|
make build
|
|
./smart-contract -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.go`:
|
|
|
|
```go
|
|
func Process(ctx context.Context, txJSON string, envVars, secrets map[string]string) ProcessResult {
|
|
// Parse the transaction
|
|
var tx Transaction
|
|
if err := json.Unmarshal([]byte(txJSON), &tx); err != nil {
|
|
return ProcessResult{Error: fmt.Errorf("failed to parse transaction: %w", err)}
|
|
}
|
|
|
|
// Access transaction data
|
|
txnId := tx.Header.TxnId
|
|
txnType := tx.Header.TxnType
|
|
payload := tx.Payload
|
|
|
|
// Access environment variables
|
|
scName := envVars["SMART_CONTRACT_NAME"]
|
|
dcID := envVars["DRAGONCHAIN_ID"]
|
|
|
|
// Access secrets
|
|
mySecret := secrets["SC_SECRET_MY_SECRET"]
|
|
|
|
// Implement your logic here
|
|
result := map[string]any{
|
|
"status": "success",
|
|
"data": "your result data",
|
|
}
|
|
|
|
return ProcessResult{
|
|
Data: result,
|
|
OutputToChain: true, // Set to true to persist result on chain
|
|
Error: nil,
|
|
}
|
|
}
|
|
```
|
|
|
|
### Transaction Structure
|
|
|
|
The `Transaction` struct in `process.go` matches the Dragonchain transaction format:
|
|
|
|
```go
|
|
type Transaction struct {
|
|
Version string `json:"version"`
|
|
Header TransactionHeader `json:"header"`
|
|
Payload map[string]any `json:"payload"`
|
|
}
|
|
|
|
type TransactionHeader struct {
|
|
Tag string `json:"tag"`
|
|
DcId string `json:"dc_id"`
|
|
TxnId string `json:"txn_id"`
|
|
BlockId string `json:"block_id"`
|
|
TxnType string `json:"txn_type"`
|
|
Timestamp string `json:"timestamp"`
|
|
Invoker string `json:"invoker"`
|
|
}
|
|
```
|
|
|
|
### 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` map with keys prefixed by `SC_SECRET_`.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
.
|
|
├── main.go # Client infrastructure (do not modify)
|
|
├── process.go # Your smart contract logic (modify this)
|
|
├── proto/
|
|
│ └── remote_sc.proto # gRPC service definition
|
|
├── config.yaml # Configuration file
|
|
├── go.mod # Go module definition
|
|
├── Makefile # Build commands
|
|
└── README.md # This file
|
|
```
|
|
|
|
### File Descriptions
|
|
|
|
- **`process.go`** - 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.go`** - Contains the gRPC client infrastructure, connection handling, and worker pool. You typically don't need to modify this file.
|
|
|
|
## Make Commands
|
|
|
|
```bash
|
|
make proto # Generate Go code from proto files
|
|
make build # Build the binary
|
|
make run # Run with default config
|
|
make test # Run tests
|
|
make clean # Remove build artifacts
|
|
make tools # Install required tools
|
|
make deps # Download dependencies
|
|
make fix-package-name # Update package name based on go.mod
|
|
```
|
|
|
|
## Concurrent Processing
|
|
|
|
The client uses a worker pool pattern 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 to report failures to the server
|
|
- The client automatically handles reconnection on connection failures
|
|
- Logs are captured and sent back with the response
|
|
|
|
## License
|
|
|
|
[Your License Here]
|