Official iOS SDK for LicenseChain - Secure license management for iOS applications.
- π Secure Authentication - User registration, login, and session management
- π License Management - Create, validate, update, and revoke licenses
- π‘οΈ Hardware ID Validation - Prevent license sharing and unauthorized access
- π Webhook Support - Real-time license events and notifications
- π Analytics Integration - Track license usage and performance metrics
- β‘ High Performance - Optimized for iOS runtime
- π Async Operations - Non-blocking HTTP requests and data processing
- π οΈ Easy Integration - Simple API with comprehensive documentation
Add to your Podfile
:
pod 'LicenseChain', '~> 1.0'
Then run:
pod install
Add to your Package.swift
:
dependencies: [
.package(url: "https://github.com/LicenseChain/LicenseChain-iOS-SDK.git", from: "1.0.0")
]
- Download the latest release from GitHub Releases
- Add the framework to your Xcode project
- Link the framework in your target's "Frameworks and Libraries"
import LicenseChain
class ViewController: UIViewController {
private var licenseClient: LicenseChainClient!
override func viewDidLoad() {
super.viewDidLoad()
// Initialize the client
let config = LicenseChainConfig(
apiKey: "your-api-key",
appName: "your-app-name",
version: "1.0.0"
)
licenseClient = LicenseChainClient(config: config)
// Connect to LicenseChain
Task {
do {
try await licenseClient.connect()
print("Connected to LicenseChain successfully!")
} catch {
print("Failed to connect: \(error.localizedDescription)")
}
}
}
}
// Register a new user
Task {
do {
let user = try await licenseClient.register(
username: "username",
password: "password",
email: "email@example.com"
)
print("User registered successfully! ID: \(user.id)")
} catch {
print("Registration failed: \(error.localizedDescription)")
}
}
// Login existing user
Task {
do {
let user = try await licenseClient.login(
username: "username",
password: "password"
)
print("User logged in successfully! Session ID: \(user.sessionId)")
} catch {
print("Login failed: \(error.localizedDescription)")
}
}
// Validate a license
Task {
do {
let license = try await licenseClient.validateLicense("LICENSE-KEY-HERE")
print("License is valid!")
print("License Key: \(license.key)")
print("Status: \(license.status)")
print("Expires: \(license.expires)")
print("Features: \(license.features.joined(separator: ", "))")
print("User: \(license.user)")
} catch {
print("License validation failed: \(error.localizedDescription)")
}
}
// Get user's licenses
Task {
do {
let licenses = try await licenseClient.getUserLicenses()
print("Found \(licenses.count) licenses:")
for (index, license) in licenses.enumerated() {
print(" \(index + 1). \(license.key) - \(license.status) (Expires: \(license.expires))")
}
} catch {
print("Failed to get licenses: \(error.localizedDescription)")
}
}
// Get hardware ID (automatically generated)
let hardwareId = licenseClient.getHardwareId()
print("Hardware ID: \(hardwareId)")
// Validate hardware ID with license
Task {
do {
let isValid = try await licenseClient.validateHardwareId(
licenseKey: "LICENSE-KEY-HERE",
hardwareId: hardwareId
)
if isValid {
print("Hardware ID is valid for this license!")
} else {
print("Hardware ID is not valid for this license.")
}
} catch {
print("Hardware ID validation failed: \(error.localizedDescription)")
}
}
// Set up webhook handler
licenseClient.setWebhookHandler { event, data in
print("Webhook received: \(event)")
switch event {
case "license.created":
print("New license created: \(data["licenseKey"] ?? "")")
case "license.updated":
print("License updated: \(data["licenseKey"] ?? "")")
case "license.revoked":
print("License revoked: \(data["licenseKey"] ?? "")")
default:
break
}
}
// Start webhook listener
Task {
do {
try await licenseClient.startWebhookListener()
print("Webhook listener started successfully!")
} catch {
print("Failed to start webhook listener: \(error.localizedDescription)")
}
}
let config = LicenseChainConfig(
apiKey: "your-api-key",
appName: "your-app-name",
version: "1.0.0",
baseUrl: "https://api.licensechain.app" // Optional
)
let client = LicenseChainClient(config: config)
// Connect to LicenseChain
func connect() async throws
// Disconnect from LicenseChain
func disconnect() async throws
// Check connection status
var isConnected: Bool { get }
// Register a new user
func register(username: String, password: String, email: String) async throws -> User
// Login existing user
func login(username: String, password: String) async throws -> User
// Logout current user
func logout() async throws
// Get current user info
func getCurrentUser() async throws -> User
// Validate a license
func validateLicense(_ licenseKey: String) async throws -> License
// Get user's licenses
func getUserLicenses() async throws -> [License]
// Create a new license
func createLicense(userId: String, features: [String], expires: String) async throws -> License
// Update a license
func updateLicense(_ licenseKey: String, updates: [String: Any]) async throws -> License
// Revoke a license
func revokeLicense(_ licenseKey: String) async throws
// Extend a license
func extendLicense(_ licenseKey: String, days: Int) async throws -> License
// Get hardware ID
func getHardwareId() -> String
// Validate hardware ID
func validateHardwareId(licenseKey: String, hardwareId: String) async throws -> Bool
// Bind hardware ID to license
func bindHardwareId(licenseKey: String, hardwareId: String) async throws
// Set webhook handler
func setWebhookHandler(_ handler: @escaping (String, [String: String]) -> Void)
// Start webhook listener
func startWebhookListener() async throws
// Stop webhook listener
func stopWebhookListener() async throws
// Track event
func trackEvent(_ eventName: String, properties: [String: Any]) async throws
// Get analytics data
func getAnalytics(timeRange: String) async throws -> Analytics
Add required permissions to your Info.plist
:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
For production, configure ATS properly:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>api.licensechain.app</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
</dict>
</dict>
</dict>
Set these in your build settings or through your build process:
// In your app configuration
let apiKey = Bundle.main.object(forInfoDictionaryKey: "LICENSECHAIN_API_KEY") as? String ?? ""
let appName = Bundle.main.object(forInfoDictionaryKey: "LICENSECHAIN_APP_NAME") as? String ?? ""
let version = Bundle.main.object(forInfoDictionaryKey: "LICENSECHAIN_APP_VERSION") as? String ?? ""
let config = LicenseChainConfig(
apiKey: "your-api-key",
appName: "your-app-name",
version: "1.0.0",
baseUrl: "https://api.licensechain.app",
timeout: 30, // Request timeout in seconds
retries: 3, // Number of retry attempts
debug: false, // Enable debug logging
userAgent: "MyApp/1.0.0" // Custom user agent
)
The SDK automatically generates and manages hardware IDs to prevent license sharing:
// Hardware ID is automatically generated and stored
let hardwareId = licenseClient.getHardwareId()
// Validate against license
let isValid = try await licenseClient.validateHardwareId(licenseKey: licenseKey, hardwareId: hardwareId)
- All API requests use HTTPS
- API keys are securely stored and transmitted
- Session tokens are automatically managed
- Webhook signatures are verified
- Real-time license validation
- Hardware ID binding
- Expiration checking
- Feature-based access control
// Track custom events
Task {
do {
try await licenseClient.trackEvent("app.started", properties: [
"level": 1,
"playerCount": 10
])
} catch {
print("Failed to track event: \(error.localizedDescription)")
}
}
// Track license events
Task {
do {
try await licenseClient.trackEvent("license.validated", properties: [
"licenseKey": "LICENSE-KEY",
"features": "premium,unlimited"
])
} catch {
print("Failed to track event: \(error.localizedDescription)")
}
}
// Get performance metrics
Task {
do {
let metrics = try await licenseClient.getPerformanceMetrics()
print("API Response Time: \(metrics.averageResponseTime)ms")
print("Success Rate: \(metrics.successRate * 100)%")
print("Error Count: \(metrics.errorCount)")
} catch {
print("Failed to get metrics: \(error.localizedDescription)")
}
}
do {
let license = try await licenseClient.validateLicense("invalid-key")
} catch let error as InvalidLicenseError {
print("License key is invalid")
} catch let error as ExpiredLicenseError {
print("License has expired")
} catch let error as NetworkError {
print("Network connection failed: \(error.localizedDescription)")
} catch let error as LicenseChainError {
print("LicenseChain error: \(error.localizedDescription)")
} catch {
print("Unknown error: \(error.localizedDescription)")
}
// Automatic retry for network errors
let config = LicenseChainConfig(
apiKey: "your-api-key",
appName: "your-app-name",
version: "1.0.0",
retries: 3, // Retry up to 3 times
timeout: 30 // Wait 30 seconds for each request
)
// Example test
func testValidateLicense() async throws {
let client = LicenseChainClient(config: testConfig)
let license = try await client.validateLicense("test-license-key")
XCTAssertTrue(license.isValid)
}
// Test with real API
func testIntegration() async throws {
let client = LicenseChainClient(config: realConfig)
try await client.connect()
let licenses = try await client.getUserLicenses()
XCTAssertNotNil(licenses)
}
See the Examples/
directory for complete examples:
BasicUsageViewController.swift
- Basic SDK usageAdvancedFeaturesViewController.swift
- Advanced features and configurationWebhookIntegrationViewController.swift
- Webhook handling
We welcome contributions! Please see our Contributing Guide for details.
- Clone the repository
- Install Xcode 13 or later
- Install iOS 12.0 or later
- Build:
xcodebuild -scheme LicenseChain build
- Test:
xcodebuild -scheme LicenseChain test
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: https://docs.licensechain.app/ios
- Issues: GitHub Issues
- Discord: LicenseChain Discord
- Email: support@licensechain.app
Made with β€οΈ for the iOS community