pollar_flutter
Unofficial Flutter SDK for Pollar — OAuth/email login, custodial Stellar wallets, and USDC/XLM payments — for apps built on Boundless / Pollar.
Why a WebView bridge? Pollar's official SDK (
@pollar/core,@pollar/react) is JS/TS-only as of this writing — there's no published Flutter/Dart SDK, and no documented REST contract for login, wallet creation, or transaction signing (only a secret-key backend API for funding wallets, creating users, and verifying tokens — see Pollar's Server API docs). This package runs@pollar/reactinside a small companion webapp loaded in awebview_flutterWebView, and exposes it to Dart as a normal async API. Pollar's own pre-built modals (login, send, receive, history) render as real UI inside that WebView, so you get Pollar's actual OAuth flow and branded UI, not a reimplementation.
Setup (two parts)
1. Deploy the bridge webapp. It's in bridge-webapp/ in this
repository — a tiny Next.js app, one npx vercel away from a URL:
cd bridge-webapp
npm install
npx vercel
2. Add this package to your Flutter app:
dependencies:
pollar_flutter: ^0.1.0
import 'package:pollar_flutter/pollar_flutter.dart';
final pollar = PollarController(
bridgeUrl: 'https://your-bridge.vercel.app', // from step 1
apiKey: 'pub_testnet_xxxxxxxxxxxxxxxxxxxx', // dashboard.pollar.xyz — PUBLISHABLE key only
);
Mount the WebView somewhere in your widget tree (it can be tiny/offscreen most of the time, but needs real space when a modal is open):
Expanded(child: PollarView(controller: pollar))
Usage
// Login — opens Pollar's own branded login modal (Google / GitHub / email OTP)
await pollar.openLoginModal();
// React to auth changes
pollar.authState.listen((state) {
if (state.isAuthenticated) {
print('Wallet: ${state.wallet?.address}');
}
});
// Send a payment (headless — no modal needed once signed in)
final outcome = await pollar.sendPayment(
destination: 'GDESTINATION...',
amount: '10.00',
asset: const PollarAsset.credit(code: 'USDC', issuer: 'GA5Z...'),
);
if (outcome.isSuccess) {
print('Sent! ${outcome.hash}');
}
// Or use Pollar's pre-built send UI instead
await pollar.openSendModal();
// Balances & history
await pollar.refreshBalance();
final history = await pollar.fetchTxHistory(limit: 20);
See example/lib/main.dart for a full working screen.
What's covered
| Area | Methods |
|---|---|
| Login | openLoginModal(), login(), beginEmailLogin() / sendEmailCode() / verifyEmailCode(), logout() |
| Wallet | getWallet(), authState stream, setNetwork() |
| Payments | runTx(), sendPayment(), buildTx() / signAndSubmitTx(), openSendModal() |
| Balances | refreshBalance(), getWalletBalance(), walletBalanceState stream |
| History | fetchTxHistory(), openTxHistoryModal() |
| Trustlines | setTrustline() |
| KYC (Deferred mode) | getKycProviders(), getKycStatus(), startKyc() |
| Anything else | call(method, params) — generic escape hatch to any bridge handler |
Not covered yet: Swap, Earn, Ramps, Sessions, Smart Wallets (passkeys — those
need a native passkey ceremony, not just a WebView). PRs welcome — extend
Bridge.tsx's handlers map and add a matching method in
PollarController.
Funding wallets server-side (Deferred mode)
POST /v1/wallets/fund and the other secret-key Server API endpoints must
run on your backend, never in the Flutter app — see
Pollar's Server API docs.
This package intentionally doesn't wrap them.
Limitations
- Requires network + the bridge webapp to be reachable. There's no offline mode.
- OAuth popups inside a WebView can be inconsistent across Android / iOS WebView implementations. Test both platforms before your demo; email OTP login is the most reliable headless fallback.
- Passkey / smart wallets (
C...addresses) need a native WebAuthn ceremony that a plain WebView can't always provide — not wrapped here. - This is a community package, not built or endorsed by Pollar / Boundless.
License
MIT
Libraries
- pollar_flutter
- Unofficial Flutter SDK for Pollar (https://pollar.xyz).