mirror of
https://github.com/sonr-io/common.git
synced 2026-01-11 20:08:57 +00:00
main
Sonr Common Package
The common package provides high-level, simplified interfaces for IPFS and WebAuthn functionality, designed for easy integration into external libraries and applications within the Sonr network.
Features
- IPFS Integration: Simple, high-level API for storing and retrieving data from IPFS
- WebAuthn Support: Comprehensive WebAuthn credential management and verification
- Helper Functions: Convenient wrapper functions that abstract complexity
- Well-Tested: Comprehensive test coverage with unit and integration tests
- Production-Ready: Battle-tested implementations with proper error handling
Table of Contents
Installation
go get github.com/sonr-io/common
Quick Start
IPFS Example
package main
import (
"fmt"
"github.com/sonr-io/common"
)
func main() {
// Check if IPFS daemon is running
if !common.IsIPFSDaemonRunning() {
panic("IPFS daemon is not running")
}
// Store data
data := []byte("Hello, IPFS!")
cid, err := common.StoreData(data)
if err != nil {
panic(err)
}
fmt.Printf("Stored data with CID: %s\n", cid)
// Retrieve data
retrieved, err := common.RetrieveData(cid)
if err != nil {
panic(err)
}
fmt.Printf("Retrieved: %s\n", string(retrieved))
}
WebAuthn Example
package main
import (
"fmt"
"github.com/sonr-io/common"
)
func main() {
// Generate a challenge for WebAuthn ceremony
challenge, err := common.NewChallenge()
if err != nil {
panic(err)
}
fmt.Printf("Challenge: %s\n", challenge)
// Verify origin
origin := "https://example.com"
allowedOrigins := []string{"https://example.com", "https://app.example.com"}
if err := common.VerifyOrigin(origin, allowedOrigins); err != nil {
panic(err)
}
fmt.Println("Origin verified successfully!")
}
IPFS Module
The IPFS module (ipfs/) provides a high-level interface for interacting with IPFS nodes.
Core Functions
Client Management
// Create a new IPFS client
client, err := common.NewIPFSClient()
// Or use the panic version for critical scenarios
client := common.MustGetIPFSClient()
// Check if daemon is running
if common.IsIPFSDaemonRunning() {
// Daemon is available
}
Data Storage
// Store raw bytes
cid, err := common.StoreData([]byte("data"))
// Store a file with metadata
cid, err := common.StoreFile("document.txt", fileData)
// Store multiple files as a folder
files := map[string][]byte{
"file1.txt": []byte("content 1"),
"file2.txt": []byte("content 2"),
}
cid, err := common.StoreFolder(files)
Data Retrieval
// Retrieve data by CID
data, err := common.RetrieveData("QmXxx...")
// Using client directly for advanced operations
client, _ := common.NewIPFSClient()
exists, err := client.Exists("QmXxx...")
entries, err := client.Ls("QmXxx...")
Advanced IPFS Usage
import "github.com/sonr-io/common/ipfs"
client, _ := ipfs.GetClient()
// Pin content
err := client.Pin("QmXxx...", "my-important-data")
// Unpin content
err := client.Unpin("QmXxx...")
// Check if pinned
pinned, err := client.IsPinned("ipns-name")
// Get node status
status, err := client.NodeStatus()
fmt.Printf("Peer ID: %s\n", status.PeerID)
fmt.Printf("Connected Peers: %d\n", status.ConnectedPeers)
WebAuthn Module
The WebAuthn module (webauthn/) provides comprehensive support for WebAuthn authentication.
Challenge Generation
// Generate a cryptographic challenge (32 bytes, base64url encoded)
challenge, err := common.NewChallenge()
// Get the standard challenge length
length := common.ChallengeLength() // Returns 32
Origin Verification
// Verify origin against allowed list
allowedOrigins := []string{
"https://example.com",
"https://app.example.com:8080",
}
err := common.VerifyOrigin("https://example.com", allowedOrigins)
Base64 URL Encoding
// Encode data to URL-safe base64 (no padding)
encoded := common.EncodeBase64URL([]byte("data"))
// Decode URL-safe base64
decoded, err := common.DecodeBase64URL(encoded)
Credential Management
Credential Creation (Registration)
// Unmarshal credential creation response from client
credData := []byte(`{"id":"...","type":"public-key",...}`)
credResponse, err := common.UnmarshalCredentialCreation(credData)
// Parse and validate credential creation
parsedCred, err := common.ParseCredentialCreation(credData)
// Marshal credential for storage
jsonData, err := common.MarshalCredentialCreation(credResponse)
Credential Assertion (Authentication)
// Unmarshal assertion response from client
assertionData := []byte(`{"id":"...","type":"public-key",...}`)
assertionResponse, err := common.UnmarshalCredentialAssertion(assertionData)
// Parse and validate assertion
parsedAssertion, err := common.ParseCredentialAssertion(assertionData)
// Marshal assertion for storage
jsonData, err := common.MarshalCredentialAssertion(assertionResponse)
Advanced WebAuthn Usage
import "github.com/sonr-io/common/webauthn"
// Create registration options
options := &webauthn.PublicKeyCredentialCreationOptions{
RelyingParty: webauthn.RelyingPartyEntity{
Name: "Example Corp",
ID: "example.com",
},
User: webauthn.UserEntity{
ID: []byte("user-id"),
Name: "user@example.com",
DisplayName: "User Name",
},
Challenge: challenge,
Parameters: []webauthn.CredentialParameter{
{Type: webauthn.PublicKeyCredentialType, Algorithm: -7}, // ES256
},
}
// Verify credential creation
clientDataHash, err := parsedCred.Verify(
storedChallenge,
verifyUser,
verifyUserPresence,
relyingPartyID,
rpOrigins,
rpTopOrigins,
rpTopOriginsVerify,
metadataProvider,
credParams,
)
// Verify credential assertion
err = parsedAssertion.Verify(
storedChallenge,
relyingPartyID,
rpOrigins,
rpTopOrigins,
rpTopOriginsVerify,
appID,
verifyUser,
verifyUserPresence,
credentialPublicKey,
)
Helper Functions
IPFS Helpers
| Function | Description |
|---|---|
NewIPFSClient() |
Create IPFS client with detailed error messages |
MustGetIPFSClient() |
Panic version for critical initialization |
StoreData(data) |
Store raw bytes and return CID |
RetrieveData(cid) |
Retrieve content by CID |
IsIPFSDaemonRunning() |
Check if IPFS daemon is accessible |
StoreFile(name, data) |
Store file with metadata |
StoreFolder(files) |
Store multiple files as a folder |
WebAuthn Helpers
| Function | Description |
|---|---|
NewChallenge() |
Generate 32-byte cryptographic challenge |
ChallengeLength() |
Get standard challenge length (32) |
VerifyOrigin(origin, allowed) |
Verify origin against allowed list |
EncodeBase64URL(data) |
Encode to URL-safe base64 |
DecodeBase64URL(encoded) |
Decode URL-safe base64 |
UnmarshalCredentialCreation(data) |
Parse credential creation response |
MarshalCredentialCreation(ccr) |
Serialize credential creation |
ParseCredentialCreation(data) |
Parse and validate creation response |
UnmarshalCredentialAssertion(data) |
Parse assertion response |
MarshalCredentialAssertion(car) |
Serialize assertion response |
ParseCredentialAssertion(data) |
Parse and validate assertion |
Testing
The package includes a comprehensive Makefile for testing and development tasks.
Available Make Targets
# Run all tests
make test
# Run tests for specific modules
make test-ipfs
make test-webauthn
# Generate coverage reports
make coverage # Show coverage summary
make coverage-ipfs # IPFS module coverage
make coverage-webauthn # WebAuthn module coverage
make coverage-all # HTML coverage report
# Code quality
make fmt # Format code
make vet # Run go vet
make lint # Run golangci-lint
# Performance
make bench # Run benchmarks
make test-race # Run tests with race detector
# Maintenance
make clean # Clean test cache and coverage files
make deps # Install dependencies
# Quick check
make check # Run fmt, vet, and test
Running Tests Manually
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run specific tests
go test -v -run TestNewChallenge
# Run benchmarks
go test -bench=. -benchmem ./...
Test Coverage
Current test coverage:
- Common package: 49.4%
- WebAuthn module: Comprehensive (50+ tests)
- IPFS module: Core functionality tested
Examples
Complete IPFS Example
package main
import (
"fmt"
"log"
"github.com/sonr-io/common"
"github.com/sonr-io/common/ipfs"
)
func main() {
// Check daemon availability
if !common.IsIPFSDaemonRunning() {
log.Fatal("IPFS daemon is not running. Start it with: ipfs daemon")
}
// Get client for advanced operations
client, err := common.NewIPFSClient()
if err != nil {
log.Fatal(err)
}
// Store a file
fileData := []byte("This is my important document")
cid, err := common.StoreFile("document.txt", fileData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Stored file with CID: %s\n", cid)
// Pin the content
if err := client.Pin(cid, "important-document"); err != nil {
log.Fatal(err)
}
fmt.Println("Content pinned successfully")
// Check if content exists
exists, err := client.Exists(cid)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Content exists: %v\n", exists)
// Get node status
status, err := client.NodeStatus()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Node Status:\n")
fmt.Printf(" Peer ID: %s\n", status.PeerID)
fmt.Printf(" Connected Peers: %d\n", status.ConnectedPeers)
fmt.Printf(" Version: %s\n", status.Version)
// Store multiple files as a folder
folder := map[string][]byte{
"readme.md": []byte("# Project\nThis is a test project"),
"main.go": []byte("package main\n\nfunc main() {}"),
"config.yml": []byte("port: 8080\nhost: localhost"),
}
folderCID, err := common.StoreFolder(folder)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Stored folder with CID: %s\n", folderCID)
// List folder contents
entries, err := client.Ls(folderCID)
if err != nil {
log.Fatal(err)
}
fmt.Println("Folder contents:")
for _, entry := range entries {
fmt.Printf(" - %s\n", entry)
}
}
Complete WebAuthn Example
package main
import (
"fmt"
"log"
"github.com/sonr-io/common"
"github.com/sonr-io/common/webauthn"
)
func main() {
// Generate challenge for registration
challenge, err := common.NewChallenge()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Registration Challenge: %s\n", challenge)
// Verify request origin
origin := "https://example.com"
allowedOrigins := []string{
"https://example.com",
"https://app.example.com",
}
if err := common.VerifyOrigin(origin, allowedOrigins); err != nil {
log.Fatalf("Origin verification failed: %v", err)
}
fmt.Println("Origin verified!")
// Simulate receiving credential creation response from client
// In a real scenario, this would come from the browser
credentialJSON := []byte(`{
"id": "base64-credential-id",
"type": "public-key",
"rawId": "base64-raw-id",
"response": {
"clientDataJSON": "base64-client-data",
"attestationObject": "base64-attestation"
}
}`)
// Parse credential creation response
credResponse, err := common.UnmarshalCredentialCreation(credentialJSON)
if err != nil {
log.Printf("Parse error (expected in demo): %v", err)
}
// For authentication, generate a new challenge
authChallenge, err := common.NewChallenge()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Authentication Challenge: %s\n", authChallenge)
// Encode/decode example
secretData := []byte("secret-session-data")
encoded := common.EncodeBase64URL(secretData)
fmt.Printf("Encoded: %s\n", encoded)
decoded, err := common.DecodeBase64URL(encoded)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Decoded: %s\n", string(decoded))
// Challenge length validation
expectedLength := common.ChallengeLength()
fmt.Printf("Expected challenge length: %d bytes\n", expectedLength)
}
Module Structure
common/
common.go # Helper functions and simplified API
common_test.go # Comprehensive test suite
Makefile # Testing and development tasks
README.md # This file
go.mod # Go module definition
ipfs/ # IPFS module
client.go # IPFS client implementation
file.go # File operations
folder.go # Folder operations
webauthn/ # WebAuthn module
client.go # WebAuthn client operations
credential.go # Credential types
assertion.go # Authentication assertions
attestation.go # Registration attestation
challenge.go # Challenge generation
base64.go # Base64 URL encoding
decoder.go # JSON decoding utilities
... # Additional WebAuthn components
Requirements
- Go 1.25 or higher
- IPFS daemon running (for IPFS operations)
- Dependencies managed via
go.mod
Contributing
We welcome contributions! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Test your changes (
make test) - Format your code (
make fmt) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Workflow
# Install dependencies
make deps
# Run tests during development
make test
# Check code quality
make check
# Generate coverage report
make coverage-all
# Run benchmarks
make bench
License
This project is part of the Sonr network. See the LICENSE file for details.
Support
For issues, questions, or contributions, please visit:
- GitHub: https://github.com/sonr-io/common
- Documentation: https://docs.sonr.io
Acknowledgments
- Built on Kubo for IPFS functionality
- WebAuthn implementation based on W3C WebAuthn specification
Description
Languages
Go
99.3%
Makefile
0.7%