Skip to main content
Glama
iosService.tsโ€ข9.3 kB
// iOS-specific service for testing iOS integration patterns export class IOSService { // Simulate iOS Keychain operations async testKeychain(key: string, value: string): Promise<{ success: boolean; message: string; swiftCode: string; }> { const swiftCode = ` import Security import Foundation func saveToKeychain(key: String, value: Data) -> Bool { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key, kSecValueData as String: value, kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly ] // Delete any existing item SecItemDelete(query as CFDictionary) // Add new item let status = SecItemAdd(query as CFDictionary, nil) return status == errSecSuccess } func loadFromKeychain(key: String) -> Data? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: AnyObject? let status = SecItemCopyMatching(query as CFDictionary, &result) if status == errSecSuccess { return result as? Data } return nil } // Example usage with LDK seed let seedKey = "ldk_node_seed" let seed = Data(/* 32 bytes of entropy */) let saved = saveToKeychain(key: seedKey, value: seed) print("Seed saved: \\(saved)")`.trim(); return { success: true, message: `Keychain test for key '${key}' completed successfully`, swiftCode }; } // Simulate iOS background task async testBackgroundProcessing(): Promise<{ success: boolean; message: string; swiftCode: string; }> { const swiftCode = ` import BackgroundTasks import LightningDevKit class LightningBackgroundTask { static let taskIdentifier = "com.yourapp.lightning.sync" static func register() { BGTaskScheduler.shared.register( forTaskWithIdentifier: taskIdentifier, using: nil ) { task in self.handleBackgroundTask(task: task as! BGProcessingTask) } } static func schedule() { let request = BGProcessingTaskRequest(identifier: taskIdentifier) request.requiresNetworkConnectivity = true request.requiresExternalPower = false request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 minutes do { try BGTaskScheduler.shared.submit(request) } catch { print("Failed to schedule background task: \\(error)") } } static func handleBackgroundTask(task: BGProcessingTask) { // Schedule next task schedule() task.expirationHandler = { // Clean up if task expires task.setTaskCompleted(success: false) } // Perform Lightning sync Task { do { // Sync chain data await ldkManager.syncToTip() // Process pending events await ldkManager.processPendingEvents() // Persist state await ldkManager.persistState() task.setTaskCompleted(success: true) } catch { task.setTaskCompleted(success: false) } } } }`.trim(); return { success: true, message: 'Background processing test completed', swiftCode }; } // Simulate push notification setup async testPushNotification(): Promise<{ success: boolean; message: string; swiftCode: string; }> { const swiftCode = ` import UserNotifications import UIKit class LightningNotificationService { static func requestAuthorization() async -> Bool { do { let options: UNAuthorizationOptions = [.alert, .badge, .sound] let granted = try await UNUserNotificationCenter.current() .requestAuthorization(options: options) if granted { await MainActor.run { UIApplication.shared.registerForRemoteNotifications() } } return granted } catch { print("Notification authorization failed: \\(error)") return false } } static func notifyPaymentReceived(amountMsat: UInt64, description: String?) { let content = UNMutableNotificationContent() content.title = "Payment Received" content.body = "You received \\(amountMsat / 1000) sats" if let desc = description { content.subtitle = desc } content.sound = .default content.badge = 1 let request = UNNotificationRequest( identifier: UUID().uuidString, content: content, trigger: nil // Immediate delivery ) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("Failed to deliver notification: \\(error)") } } } static func handleIncomingPayment(paymentHash: String) { // Fetch payment details from LDK guard let payment = ldkManager.getPayment(hash: paymentHash) else { return } // Show notification notifyPaymentReceived( amountMsat: payment.amountMsat, description: payment.description ) // Update app badge Task { @MainActor in UIApplication.shared.applicationIconBadgeNumber += 1 } } }`.trim(); return { success: true, message: 'Push notification test completed', swiftCode }; } // Simulate biometric authentication async testBiometricAuth(): Promise<{ success: boolean; message: string; swiftCode: string; }> { const swiftCode = ` import LocalAuthentication import Security class BiometricLightningAuth { enum BiometricType { case none case touchID case faceID } static func getBiometricType() -> BiometricType { let context = LAContext() var error: NSError? guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else { return .none } switch context.biometryType { case .touchID: return .touchID case .faceID: return .faceID default: return .none } } static func authenticateForPayment(amount: UInt64) async -> Bool { let context = LAContext() context.localizedCancelTitle = "Cancel" let reason = "Authenticate to send \\(amount / 1000) sats" do { let success = try await context.evaluatePolicy( .deviceOwnerAuthenticationWithBiometrics, localizedReason: reason ) return success } catch { print("Biometric authentication failed: \\(error)") return false } } static func protectSeedWithBiometrics(seed: Data) throws -> Data { let context = LAContext() context.localizedReason = "Protect your Lightning wallet" let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: "ldk_protected_seed", kSecValueData as String: seed, kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAttrAccessControl as String: SecAccessControlCreateWithFlags( nil, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, .biometryCurrentSet, nil )! ] // Remove existing item SecItemDelete(query as CFDictionary) // Add with biometric protection let status = SecItemAdd(query as CFDictionary, nil) guard status == errSecSuccess else { throw NSError(domain: "BiometricAuth", code: Int(status)) } return seed } static func retrieveSeedWithBiometrics() async throws -> Data { let context = LAContext() context.localizedReason = "Access your Lightning wallet" let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: "ldk_protected_seed", kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne, kSecUseAuthenticationContext as String: context ] var result: AnyObject? let status = SecItemCopyMatching(query as CFDictionary, &result) guard status == errSecSuccess, let data = result as? Data else { throw NSError(domain: "BiometricAuth", code: Int(status)) } return data } }`.trim(); return { success: true, message: 'Biometric authentication test completed', swiftCode }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/StevenGeller/ldk-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server