pollar_flutter 0.1.0
pollar_flutter: ^0.1.0 copied to clipboard
Unofficial Flutter SDK for Pollar (https://pollar.xyz) — wallet onboarding and USDC/Stellar payments via a WebView bridge to @pollar/react, since Pollar's SDK is currently JS/TS-only.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:pollar_flutter/pollar_flutter.dart';
import 'screens/pay_freelancer_screen.dart';
// Replace with your deployed bridge-webapp URL and your Pollar
// PUBLISHABLE key (never the secret key) from dashboard.pollar.xyz.
const bridgeUrl = "https://workpay-five.vercel.app";
const pollarPublishableKey = 'pub_testnet_5f0a5c2785e0a53161c7354470f4c15c';
void main() => runApp(const DemoApp());
class DemoApp extends StatelessWidget {
const DemoApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: HomeScreen());
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late final PollarController pollar;
bool authenticated = false;
PollarWallet? wallet;
String status = 'Loading Pollar…';
@override
void initState() {
super.initState();
pollar = PollarController(bridgeUrl: bridgeUrl, apiKey: pollarPublishableKey);
pollar.onReady.listen((_) => setState(() => status = 'Ready'));
pollar.authState.listen((state) {
setState(() {
authenticated = state.isAuthenticated;
wallet = state.wallet;
});
});
pollar.transactionState.listen((state) {
setState(() => status = 'Transaction: ${state['step'] ?? state['status']}');
});
}
@override
void dispose() {
pollar.dispose();
super.dispose();
}
Future<void> _sendTestPayment() async {
if (wallet?.address == null) return;
setState(() => status = 'Sending…');
final outcome = await pollar.sendPayment(
destination: 'GDLDQRDWQP34XK5JWU6YTCELK42GCNZIRCPKAPFBUV4YO2BFWHD3GGBY',
amount: '1.00',
// Testnet USDC issuer — replace with the asset configured in your
// Dashboard (Treasury → Tokens & Trustlines).
asset: const PollarAsset.credit(
code: 'USDC',
issuer: 'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5'),
);
setState(() {
status = outcome.isSuccess
? 'Sent! hash=${outcome.hash}'
: 'Failed: ${outcome.details ?? outcome.resultCode}';
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Pollar + Flutter demo')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(status),
const SizedBox(height: 8),
Text(authenticated
? 'Wallet: ${wallet?.address ?? '—'} (${wallet?.custody})'
: 'Not signed in'),
const SizedBox(height: 16),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
ElevatedButton(
onPressed: () => pollar.openLoginModal(),
child: const Text('Sign in (Pollar modal)'),
),
if (authenticated) ...[
ElevatedButton(
onPressed: _sendTestPayment,
child: const Text('Send 1 USDC (headless runTx)'),
),
ElevatedButton(
onPressed: () => pollar.openSendModal(),
child: const Text('Send (Pollar modal)'),
),
ElevatedButton(
onPressed: () => pollar.openReceiveModal(),
child: const Text('Receive (Pollar modal)'),
),
ElevatedButton(
onPressed: () => pollar.openTxHistoryModal(),
child: const Text('History (Pollar modal)'),
),
ElevatedButton(
onPressed: () => pollar.logout(),
child: const Text('Log out'),
),
ElevatedButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => PayFreelancerScreen(pollar: pollar),
),
),
style: ElevatedButton.styleFrom(backgroundColor: Colors.indigo),
child: const Text(
'Open: Pay Freelancer (real UI)',
style: TextStyle(color: Colors.white),
),
),
],
],
),
],
),
),
// The WebView must be mounted for the bridge to work, and needs
// real screen space whenever a Pollar modal is open (login,
// send, receive, history). Keeping it small still works — the
// modal renders as a fixed overlay inside the WebView's own
// viewport, so give it enough room to be usable.
const Divider(height: 1),
Expanded(child: PollarView(controller: pollar)),
],
),
);
}
}