Thank you for your interest in contributing to helius-go! This document provides guidelines and information for contributors.
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/helius-go.git - Create a branch:
git checkout -b feature/your-feature - Make your changes
- Run tests:
go test -cover ./... - Submit a pull request
- Go 1.21 or later
- golangci-lint (for linting)
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run with race detection
go test -race ./...
# Run specific test
go test -run TestValidateWebhookSignature ./...# Install golangci-lint
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
# Run linter
golangci-lint run- All API methods take
context.Contextas the first parameter
// Good
func (c *Client) GetAsset(ctx context.Context, id string) (*Asset, error)
// Bad
func (c *Client) GetAsset(id string) (*Asset, error)- Return custom
*APIErrorfor HTTP errors
if resp.StatusCode >= 400 {
return nil, &APIError{
StatusCode: resp.StatusCode,
Message: string(body),
Path: path,
}
}- Use functional options for configuration
client, err := helius.NewClient(apiKey,
helius.WithNetwork(helius.Devnet),
helius.WithTimeout(30*time.Second),
)- Minimum 80% code coverage required
- Use
httptest.Serverfor mocking HTTP responses - Table-driven tests for multiple cases
- Test both success and error paths
Example test structure:
func TestGetAsset(t *testing.T) {
t.Run("successful get", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(Asset{ID: "test-id"})
}))
defer server.Close()
client, _ := NewClient("test-key", WithAPIURL(server.URL))
asset, err := client.GetAsset(context.Background(), "test-id")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if asset.ID != "test-id" {
t.Errorf("ID = %s, want test-id", asset.ID)
}
})
t.Run("empty id returns error", func(t *testing.T) {
client, _ := NewClient("test-key")
_, err := client.GetAsset(context.Background(), "")
if err == nil {
t.Error("expected error for empty id")
}
})
}- All exported types and functions must have doc comments
- Include code examples in doc comments where helpful
- Use
// Example:blocks for usage examples
// GetAsset fetches a single asset by its ID (mint address).
//
// Example:
//
// asset, err := client.GetAsset(ctx, "mint-address")
// if err != nil {
// log.Fatal(err)
// }
// fmt.Println(asset.ID)
func (c *Client) GetAsset(ctx context.Context, id string) (*Asset, error)- Update documentation if needed
- Ensure all tests pass
- Ensure code coverage is at least 80%
- Update README.md if adding new features
- Wait for code review
When contributing to webhook-related code:
- Always use constant-time comparison for signature validation
- Never log secrets or API keys
- Test edge cases (empty strings, nil values)
- Never commit API keys or secrets
- Use environment variables for testing with real APIs
- Mark test functions that require real API access with build tags
Open an issue for questions or discussion about potential contributions.