Skip to content

Usage

Note: The SDK must be initialized before use. On iOS, call AlphynSDK.register() in your AppDelegate (see Platform Setup). Then initialize the SDK from Dart in your main() function (see Initialization). All Dart APIs are available after initialization is complete.

import 'package:alphyn_sdk/alphyn_sdk.dart';
// Returns: Future<bool?>
// - true: SDK is successfully initialized and ready to use
// - false: SDK initialization failed or was not called
// - null: Initialization status cannot be determined
final isInitialized = await AlphynSdk.isInitialized();
if (isInitialized == true) {
print('✅ SDK initialized successfully');
// Output: ✅ SDK initialized successfully
} else {
print('❌ SDK not initialized');
}

Purpose: Verifies that the SDK was properly initialized on the native side. This should be the first call you make before using any other SDK functionality. Always check this status before attempting to retrieve device information or perform security scans.

Real Output Example:

[AlphynSdkManager] checkInitialization() called
[AlphynSdkManager] SDK initialization status: true
[ExampleApp] SDK initialized successfully
// Returns: Future<String>
// A unique identifier for the device, used for tracking and security verification
// This identifier is persistent across app sessions and is generated by the SDK
final deviceId = await AlphynSdk.getDeviceId();
print('Device ID: $deviceId');
// Output: Device ID: 817D56BE-0BC4-4CE4-8516-8F582EEBE0FC

Purpose: Retrieves a unique, persistent identifier for the device. This ID is essential for:

  • Device tracking across sessions
  • Security event correlation
  • Device fingerprinting
  • User verification processes
// Returns: Future<String>
// A cryptographic hash of the application binary
// Used to verify app integrity and detect tampering or modifications
final appHash = await AlphynSdk.getAppHash();
print('App Hash: $appHash');
// Output: App Hash: 64f3f5b47a856403dc48bfbaac0fcdb89f414f63dafb9c18e8b6d87f2a43caec

Purpose: Generates and returns a cryptographic hash of your application. This hash is critical for:

  • Detecting app tampering or unauthorized modifications
  • Verifying application integrity
  • Ensuring the app has not been repackaged or altered
  • Compliance and security auditing
// Returns: Future<String?>
// The most recent security scan result as a string
// Contains detailed information about the current security state of the device/app
// Returns null if no scan has been performed or SDK is not initialized
final scanResult = await AlphynSdk.getScanResult();
if (scanResult != null) {
print('Scan Result: $scanResult');
} else {
print('No scan result available');
}
// Example output: 'SIMULATOR_RUNTIME'
// or 'FRIDA_DETECTED'
// or null if no scan performed

Purpose: Retrieves the most current security scan results. This provides real-time information about:

  • Current security threats detected
  • Device security posture
  • Active security violations
  • Overall security status

Use this to make immediate security decisions (e.g., blocking features, logging out users).

// Returns: Future<List<String>>
// A list of specific security issues that triggered rejection or warnings
// Each string describes a distinct security concern detected
// getRejectReasons() returns a newline-separated string; split it into a list
final rejectReasonsRaw = await AlphynSdk.getRejectReasons();
final rejectReasons = rejectReasonsRaw.split('\n').where((line) => line.trim().isNotEmpty).toList();
print('Rejection Reasons: $rejectReasons');
// Example output:
// [
// 'DETECTION: COMMON_SUSPICIOUS_PATH Common suspicious file path accessible',
// 'DETECTION: SIMULATOR_ENVIRONMENT Simulator environment detected',
// 'DETECTION: SIMULATOR_RUNTIME Simulator runtime detected',
// 'DETECTION: DEBUGGER_SYSTEM_CHECK Debugger detected (system check)',
// 'DETECTION: FRIDA_DETECTED Frida traces detected',
// 'DETECTION: VPN_IN_USE VPN in use'
// ]
for (var reason in rejectReasons) {
print('Security Issue: $reason');
// Parse detection type and description
if (reason.startsWith('DETECTION:')) {
final parts = reason.substring(11).split(' ');
final detectionType = parts.first;
print(' Type: $detectionType');
}
}

Purpose: Returns a detailed list of all security violations or concerns detected during scanning. Each reason represents:

  • A specific security threat or risk factor
  • The type of violation (e.g., jailbreak, debugger, emulator)
  • Issues that may require app restrictions or user warnings

Use this to:

  • Display specific security warnings to users
  • Log detailed security events
  • Implement granular security policies based on threat types
// Returns: Future<DateTime?>
// The timestamp when the last security scan was completed
// Returns null if no scan has been performed yet
final lastScanDate = await AlphynSdk.getLastScanDate();
if (lastScanDate != null) {
print('Last Scan: ${lastScanDate.toIso8601String()}');
// Output: Last Scan: 2025-11-20T11:21:28.000Z
print('Time since last scan: ${DateTime.now().difference(lastScanDate)}');
// Output: Time since last scan: 0:00:02.456789
} else {
print('No scan performed yet');
}

Purpose: Provides the exact timestamp of the last completed security scan. Useful for:

  • Determining scan freshness
  • Calculating time intervals between scans
  • Triggering manual scans if too much time has passed
  • Audit logging and compliance reporting

signAction signs with a hardware-backed key that belongs to one enrolled user, so enrollForMfa(userId) must have run once on this device first, and userId below is your own identifier for the logged-in user. The PIN is optional. See MFA Transaction Signing for the full flow.

// Returns: Future<ActionVerificationResult>
// Verifies a high-risk action with the Alphyn backend
// Used for sensitive operations like payments, data transfers, etc.
final result = await AlphynSdk.signAction(
userId: userId,
actionLabel: 'payment_transfer',
context: {
'amount': '1000.00',
'currency': 'USD',
'recipient': '[email protected]',
'timestamp': DateTime.now().toIso8601String(),
},
);
if (result.success) {
print('✅ Action verified successfully');
print('Token: ${result.token}');
print('Expires at: ${result.expiresAtEpochMs != null ? DateTime.fromMillisecondsSinceEpoch(result.expiresAtEpochMs!) : 'N/A'}');
// Proceed with the high-risk action using the verification token
proceedWithAction(result.token!);
} else {
print('❌ Action verification failed');
print('Error Code: ${result.errorCode}');
print('Error Message: ${result.errorMessage}');
// Block the action or show error to user
showErrorToUser(result.errorMessage ?? 'Verification failed');
}

Purpose: Verifies high-risk actions with the Alphyn backend before execution. This provides an additional layer of security for sensitive operations by:

  • Validating the action context with the backend
  • Receiving a verification token for the action
  • Detecting suspicious patterns or unauthorized attempts
  • Enabling action-level security policies

Parameters:

  • actionLabel (required): A string identifier for the action type (e.g., 'payment_transfer', 'sensitive_data_access')
  • context (required): A map containing contextual information about the action. This is forwarded to the backend for verification.

Returns: Future<ActionVerificationResult> with the following properties:

  • success (bool): Whether the verification was successful
  • token (String?): Verification token if successful (use this to proceed with the action)
  • expiresAtEpochMs (int?): Token expiration timestamp in milliseconds since epoch
  • errorCode (String?): Error code if verification failed
  • errorMessage (String?): Human-readable error message if verification failed

Use Cases:

  • Payment transactions
  • Sensitive data transfers
  • Administrative operations
  • Account modifications
  • Any operation requiring additional verification

Example: Payment Verification

Future<void> processPayment({
required double amount,
required String recipient,
}) async {
// Verify the payment action before processing
final verification = await AlphynSdk.signAction(
userId: userId,
actionLabel: 'payment_transfer',
context: {
'amount': amount.toString(),
'currency': 'USD',
'recipient': recipient,
'timestamp': DateTime.now().toIso8601String(),
'user_id': currentUserId,
},
);
if (!verification.success) {
throw PaymentException(
'Payment verification failed: ${verification.errorMessage}',
);
}
// Use the verification token when processing the payment
await paymentService.transfer(
amount: amount,
recipient: recipient,
verificationToken: verification.token!,
);
}
// Returns: Future<List<String>>
// A comprehensive list of all risk factors detected across all scans
// Includes cumulative security concerns, not just current threats
final riskFactors = await AlphynSdk.getAllRiskFactors();
print('Total Risk Factors: ${riskFactors.length}');
// Example output:
// [
// 'COMMON_SUSPICIOUS_PATH',
// 'SIMULATOR_ENVIRONMENT',
// 'SIMULATOR_RUNTIME',
// 'DEBUGGER_SYSTEM_CHECK',
// 'DEBUGGER_PROCESS_CHECK',
// 'DEBUGGER_EXCEPTION_CHECK',
// 'VPN_IN_USE',
// 'FRIDA_DETECTED',
// 'FRIDA_SERVER_RUNNING'
// ]
for (var factor in riskFactors) {
print('Risk Factor: $factor');
}

Purpose: Returns a complete list of all security risk factors detected. This includes:

  • Historical security issues
  • Cumulative risk assessment data
  • All threat categories identified
  • Device security profile information

Use this for:

  • Comprehensive security reporting
  • Risk scoring and analysis
  • Security dashboards
  • Historical threat tracking
// Returns: Future<List<String>>
// A list of all scan results, optionally filtered by date range
// Each string represents a complete scan report from a specific time
// Get all scan results (no filter)
final allResults = await AlphynSdk.getAllScanResults();
// Get scan results from the last 7 days
final lastWeek = DateTime.now().subtract(Duration(days: 7));
final recentResults = await AlphynSdk.getAllScanResults(
startEpochMs: lastWeek.millisecondsSinceEpoch,
endEpochMs: DateTime.now().millisecondsSinceEpoch,
);
print('Total scans: ${allResults.length}');
print('Recent scans (7 days): ${recentResults.length}');
// Example output:
// [
// 'ScanResult(date: 2025-11-20 11:21:29 +0000, detections: ["Detection: COMMON_SUSPICIOUS_PATH Severity: HIGH", "Detection: SIMULATOR_RUNTIME Severity: CRITICAL"])',
// 'ScanResult(date: 2025-11-20 11:21:30 +0000, detections: ["Detection: FRIDA_DETECTED, FRIDA_SERVER_RUNNING Severity: CRITICAL"])'
// ]
// Parse scan results
for (var scanResult in recentResults) {
print('Scan: $scanResult');
// Extract date and detections from the string
if (scanResult.contains('date:')) {
// Parse the scan result string as needed
}
}

Purpose: Retrieves historical scan data with optional date range filtering. This allows you to:

  • Analyze security trends over time
  • Generate historical security reports
  • Track security improvements or degradation
  • Export scan history for compliance
  • Filter scans by specific time periods

Parameters:

  • startEpochMs (optional): Beginning of the date range in milliseconds since epoch (inclusive)
  • endEpochMs (optional): End of the date range in milliseconds since epoch (inclusive)
  • If both omitted: Returns all available scan results
// Returns: Future<void>
// Updates the scan interval in seconds
await AlphynSdk.setInterval(60.0); // Set to 60 seconds
print('Scan interval updated to 60 seconds');

Purpose: Updates the interval between automatic security scans. This allows you to:

  • Adjust scan frequency based on app state
  • Balance between security coverage and performance
  • Reduce battery usage when appropriate

Parameters:

  • intervalSeconds (required): The new interval in seconds (must be greater than 8)

Note: The interval must be greater than 8 seconds. Attempting to set a lower value will result in an error.

// Returns: Future<List<String>>
// A list of security modules loaded by the SDK
final modules = await AlphynSdk.getModules();
print('Loaded modules: ${modules.length}');
for (var module in modules) {
print('Module: $module');
}
// Example output: ['NetworkSecurity', 'DeviceIntegrity', 'AppVerification']

Purpose: Retrieves the list of security modules currently loaded by the SDK. This provides:

  • Visibility into which security checks are active
  • Debugging information for troubleshooting
  • Verification that expected modules are loaded

Use this for:

  • Security auditing
  • Diagnostics and troubleshooting
  • Verifying SDK configuration

The SDK provides a stream-based security event listener that works on both Android and iOS. This allows you to receive real-time security events from the native SDK in a reactive, Flutter-friendly way.

The securityEvents() method returns a Stream<AlphynCallbackResult> that emits security events from the native SDK. This works on both Android and iOS.

import 'package:alphyn_sdk/alphyn_sdk.dart';
import 'dart:async';
// Subscribe to security events
final subscription = AlphynSdk.securityEvents().listen(
(event) {
print('Event Type: ${event.originalEventType}');
print('Operation: ${event.operationType}');
print('Result: ${event.operationResult}');
print('Message: ${event.message}');
print('Details: ${event.details}');
// Handle different event types
switch (event.originalEventType) {
case AlphynEventType.threatDetected:
print('🚨 Threat detected!');
handleThreat(event);
break;
case AlphynEventType.scanSuccess:
print('✅ Scan completed successfully');
break;
case AlphynEventType.initComplete:
print('✅ SDK initialized');
break;
case AlphynEventType.networkError:
print('⚠️ Network error occurred');
break;
default:
print('Event: ${event.originalEventType}');
}
},
onError: (error) {
print('Error in security events stream: $error');
},
);
// Don't forget to cancel the subscription when done
// subscription.cancel();

Key Points:

  • Works on both Android and iOS
  • Automatically set up when you first access the stream
  • Multiple subscribers can listen to the same stream
  • Events are emitted on the main thread
  • Always cancel subscriptions in dispose() to prevent memory leaks
import 'package:flutter/material.dart';
import 'package:alphyn_sdk/alphyn_sdk.dart';
import 'dart:async';
class SecurityMonitor extends StatefulWidget {
@override
_SecurityMonitorState createState() => _SecurityMonitorState();
}
class _SecurityMonitorState extends State<SecurityMonitor> {
StreamSubscription<AlphynCallbackResult>? _subscription;
List<AlphynCallbackResult> _events = [];
@override
void initState() {
super.initState();
_setupListener();
}
void _setupListener() {
// Subscribe to security events stream
_subscription = AlphynSdk.securityEvents().listen(
(event) {
setState(() {
_events.insert(0, event); // Add to beginning
// Keep only last 50 events
if (_events.length > 50) {
_events = _events.take(50).toList();
}
});
},
onError: (error) {
print('Security events error: $error');
},
);
}
@override
void dispose() {
_subscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Security Monitor')),
body: ListView.builder(
itemCount: _events.length,
itemBuilder: (context, index) {
final event = _events[index];
return ListTile(
title: Text(event.originalEventType.name),
subtitle: Text(event.message),
trailing: Icon(
event.operationResult == OperationResult.success
? Icons.check_circle
: Icons.error,
color: event.operationResult == OperationResult.success
? Colors.green
: Colors.red,
),
);
},
),
);
}
}

Events are of type AlphynCallbackResult with the following properties:

  • operationType: The type of operation (OperationType.initialization, OperationType.securityScan, etc.)
  • operationResult: The result (OperationResult.success, OperationResult.failure, OperationResult.threatDetected)
  • originalEventType: The specific event type (AlphynEventType.initComplete, AlphynEventType.threatDetected, etc.)
  • message: Human-readable message
  • details: Additional details

The SDK emits various event types through the stream:

Initialization Events:

  • initComplete - SDK initialization completed successfully
  • initFailed - SDK initialization failed
  • firstInit - First-time initialization
  • invalidAppKey - Invalid application key provided

Security Events:

  • threatDetected - Security threat identified
  • secureDevice - Device verified as secure
  • scanSuccess - Security scan completed successfully
  • scanResponse - Scan results are available
  • scanFailed - Security scan failed
  • riskFactorDetected - Risk factor detected during scan

Network Events:

  • networkInit - Network initialization
  • networkMtls - Mutual TLS connection established
  • jwtAuthSuccess - JWT authentication successful
  • networkError - Network connectivity error
  • authFailed - Authentication failed
  • requestFailed - API request failed

Storage Events:

  • keystoreSuccess - Keystore operation successful
  • keystoreFailed - Keystore operation failed
  • keyExchangeSuccess - Key exchange completed
  • keysFoundStorage - Existing keys found in storage
  • keysCreatedNew - New keys created

Other Events:

  • invalidDateOrTime - Invalid date/time detected
  • callbackSuccess - Callback operation successful
  • callbackFailed - Callback operation failed
  1. Always cancel subscriptions in dispose() to prevent memory leaks
  2. Handle errors in the stream’s onError callback
  3. Filter events based on your needs (e.g., only listen to threat events)
  4. Update UI safely by checking mounted before calling setState()
  5. Limit event history to prevent memory issues (keep only last N events)
  • securityEvents() - Returns a Stream<AlphynCallbackResult> that emits security events from the native SDK. Works on both Android and iOS.
import 'package:flutter/material.dart';
import 'package:alphyn_sdk/alphyn_sdk.dart';
import 'dart:async';
class SecurityScreen extends StatefulWidget {
@override
_SecurityScreenState createState() => _SecurityScreenState();
}
class _SecurityScreenState extends State<SecurityScreen> {
bool _isInitialized = false;
String _deviceId = '';
String _appHash = '';
List<String> _scanResults = [];
List<AlphynCallbackResult> _securityEvents = [];
StreamSubscription<AlphynCallbackResult>? _eventSubscription;
@override
void initState() {
super.initState();
_initializeSdk();
_setupSecurityListener();
}
@override
void dispose() {
_eventSubscription?.cancel();
super.dispose();
}
Future<void> _initializeSdk() async {
try {
// Check initialization status (SDK is initialized natively)
final initialized = await AlphynSdk.isInitialized();
if (initialized == true) {
setState(() {
_isInitialized = true;
});
// Load device information
await _loadDeviceInfo();
// Perform security scan
await _performScan();
}
} catch (e) {
print('SDK check failed: $e');
}
}
void _setupSecurityListener() {
// Subscribe to security events stream
_eventSubscription = AlphynSdk.securityEvents().listen(
(event) {
setState(() {
_securityEvents.insert(0, event);
if (_securityEvents.length > 50) {
_securityEvents = _securityEvents.take(50).toList();
}
});
},
onError: (error) {
print('Security events error: $error');
},
);
}
Future<void> _loadDeviceInfo() async {
final deviceId = await AlphynSdk.getDeviceId();
final appHash = await AlphynSdk.getAppHash();
setState(() {
_deviceId = deviceId;
_appHash = appHash;
});
}
Future<void> _performScan() async {
final scanResult = await AlphynSdk.getScanResult();
// getRejectReasons() returns a newline-separated string; split it into a list
final rejectReasonsRaw = await AlphynSdk.getRejectReasons();
final rejectReasons = rejectReasonsRaw.split('\n').where((line) => line.trim().isNotEmpty).toList();
setState(() {
_scanResults = [];
if (scanResult != null && scanResult.isNotEmpty) {
_scanResults.add(scanResult);
}
if (rejectReasons.isNotEmpty) {
_scanResults.addAll(rejectReasons);
}
});
}
Future<void> _verifyTestAction() async {
try {
final result = await AlphynSdk.signAction(
userId: userId,
actionLabel: 'test_action',
context: {
'timestamp': DateTime.now().toIso8601String(),
'source': 'example_app',
},
);
if (result.success) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Action verified! Token: ${result.token}')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Verification failed: ${result.errorMessage}')),
);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Security Dashboard')),
body: _isInitialized
? SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Device ID: $_deviceId', style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Text('App Hash: $_appHash', style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 16),
Text('Scan Results:', style: TextStyle(fontWeight: FontWeight.bold)),
..._scanResults.map((result) => Padding(
padding: EdgeInsets.only(left: 16, top: 4),
child: Text(result),
)),
SizedBox(height: 16),
ElevatedButton(
onPressed: _verifyTestAction,
child: Text('Verify Test Action'),
),
SizedBox(height: 16),
Text('Security Events (${_securityEvents.length}):', style: TextStyle(fontWeight: FontWeight.bold)),
..._securityEvents.take(10).map((event) => Padding(
padding: EdgeInsets.only(left: 16, top: 4),
child: Text('${event.originalEventType.name}: ${event.message}'),
)),
],
),
)
: Center(child: CircularProgressIndicator()),
);
}
}