mobile_proof_plugin 0.1.1
mobile_proof_plugin: ^0.1.1 copied to clipboard
Flutter plugin for TLSN-based mobile proofs with WebView capture and custom MPC provider flows.
example/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mobile_proof_plugin/mobile_proof_plugin.dart';
void main() {
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'mobile_proof_plugin example',
theme: ThemeData(
colorSchemeSeed: const Color(0xFF2563EB),
useMaterial3: true,
),
home: const ExampleHomePage(),
);
}
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({super.key});
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
static const String _providerRegistryAssetPath =
'packages/mobile_proof_plugin/assets/providers.json';
final TextEditingController _verifierUrlController = TextEditingController(
text: 'http://10.0.2.2:7047',
);
bool _running = false;
String _status = 'Ready';
@override
void dispose() {
_verifierUrlController.dispose();
super.dispose();
}
Future<void> _runProof() async {
final verifierUrl = Uri.tryParse(_verifierUrlController.text.trim());
if (verifierUrl == null) {
setState(() {
_status = 'Invalid verifier URL';
});
return;
}
setState(() {
_running = true;
_status = 'Starting provider flow...';
});
final client = MobileProofClient(bridge: MethodChannelNativeBridge());
final StreamSubscription<SessionProgress> progressSub =
client.subscribeProgress().listen((progress) {
if (!mounted) return;
setState(() {
_status = '[${progress.phase.name}] ${progress.message}';
});
});
try {
await client.attestProvider(
context: context,
providerId: 'kaggle.current_user.v1',
providerRegistryAssetPath: _providerRegistryAssetPath,
transportConfig: TransportConfig(
deploymentMode: DeploymentMode.hosted,
verifierUrl: verifierUrl,
trustedNotaryKeys: const <String>[
// Replace with production notary keys.
'REPLACE_WITH_BASE64_NOTARY_PUBLIC_KEY'
],
enforceNativeCore: false,
enableLogging: true,
),
);
if (!mounted) return;
setState(() {
_status = 'Proof generated successfully';
});
} on ProofException catch (error) {
if (!mounted) return;
setState(() {
_status = 'Proof failed: [${error.code.name}] ${error.message}';
});
} finally {
await progressSub.cancel();
await client.dispose();
if (mounted) {
setState(() {
_running = false;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('mobile_proof_plugin')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField(
controller: _verifierUrlController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Verifier URL',
),
),
const SizedBox(height: 12),
FilledButton(
onPressed: _running ? null : _runProof,
child: Text(_running ? 'Running...' : 'Run Provider Attestation'),
),
const SizedBox(height: 12),
Text('Status: $_status'),
],
),
),
);
}
}