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/react inside a small companion webapp loaded in a webview_flutter WebView, 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).