web3_webview 1.0.14 copy "web3_webview: ^1.0.14" to clipboard
web3_webview: ^1.0.14 copied to clipboard

web3_webview is a powerful bridge between a DApp running inside a WebView and your Flutter application, enabling secure and seamless two-way communication between them

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:web3_webview/web3_webview.dart';

/// Example app for `web3_webview` – 3 modes: read-only, privateKey, external signer.
///
/// Loads `privateKey` from secure storage in production – here placeholders.
/// Do NOT hardcode keys in real apps.
void main() => runApp(const ExampleApp());

/// Root widget with tab demo for 3 modes + dark preview.
class ExampleApp extends StatefulWidget {
  const ExampleApp({super.key});
  @override
  State<ExampleApp> createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  ThemeMode _mode = ThemeMode.light;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'web3_webview example',
      theme: ThemeData(
          useMaterial3: true,
          brightness: Brightness.light,
          colorSchemeSeed: const Color(0xFF6366F1)),
      darkTheme: ThemeData(
          useMaterial3: true,
          brightness: Brightness.dark,
          colorSchemeSeed: const Color(0xFF818CF8)),
      themeMode: _mode,
      home: ExampleHome(
        isDark: _mode == ThemeMode.dark,
        onToggleDark: () => setState(() =>
            _mode = _mode == ThemeMode.dark ? ThemeMode.light : ThemeMode.dark),
      ),
    );
  }
}

class ExampleHome extends StatefulWidget {
  final bool isDark;
  final VoidCallback onToggleDark;
  const ExampleHome(
      {super.key, required this.isDark, required this.onToggleDark});
  @override
  State<ExampleHome> createState() => _ExampleHomeState();
}

class _ExampleHomeState extends State<ExampleHome> {
  int _index = 0;

  static final NetworkConfig _eth = NetworkConfig(
    chainId: '0x1',
    chainName: 'Ethereum Mainnet',
    nativeCurrency: NativeCurrency(name: 'Ether', symbol: 'ETH', decimals: 18),
    rpcUrls: ['https://mainnet.infura.io/v3/YOUR_KEY'],
    blockExplorerUrls: ['https://etherscan.io'],
  );

  // Premium themes – auto dark via system, plus custom dark override
  WalletDialogTheme get _lightTheme =>
      WalletDialogTheme(primaryColor: const Color(0xFF6366F1));
  WalletDialogTheme get _darkTheme =>
      WalletDialogTheme.dark(primaryColor: const Color(0xFF818CF8));

  // Fully custom UI – replace any dialog with your own widget (branding, layout, no code fork)
  WalletDialogBuilders get _customBuilders => WalletDialogBuilders(
        connect: (ctx,
            {required address,
            required host,
            required appName,
            required controller,
            required theme}) async {
          // Example: branded confirm with AlertDialog – you can use any widget
          return showDialog<bool>(
            context: ctx,
            barrierDismissible: false,
            builder: (c) => AlertDialog(
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(16)),
              title: Text('$appName muốn kết nối', style: theme.headerStyle),
              content: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text('Host: $host', style: theme.captionStyle),
                    const SizedBox(height: 8),
                    Text(
                        'Wallet: ${address.substring(0, 8)}...${address.substring(address.length - 6)}',
                        style: theme.valueStyle
                            .copyWith(fontFamily: 'monospace', fontSize: 12)),
                    const SizedBox(height: 12),
                    Text('Bạn có tin tưởng site này không?',
                        style: theme.captionStyle),
                  ]),
              actions: [
                TextButton(
                    onPressed: () => Navigator.pop(c, false),
                    child: const Text('Từ chối')),
                FilledButton(
                    onPressed: () => Navigator.pop(c, true),
                    style: FilledButton.styleFrom(
                        backgroundColor: theme.primaryColor),
                    child: const Text('Kết nối')),
              ],
            ),
          );
        },
        sign: (ctx,
            {required message,
            required address,
            required host,
            required controller,
            required theme}) async {
          return showDialog<bool>(
            context: ctx,
            builder: (c) => AlertDialog(
              title: const Text('Yêu cầu ký'),
              content: SingleChildScrollView(
                  child: Text(message,
                      style: const TextStyle(
                          fontFamily: 'monospace', fontSize: 12))),
              actions: [
                TextButton(
                    onPressed: () => Navigator.pop(c, false),
                    child: const Text('Hủy')),
                FilledButton(
                    onPressed: () => Navigator.pop(c, true),
                    child: const Text('Ký')),
              ],
            ),
          );
        },
        transaction: (ctx,
            {required txParams,
            required host,
            required controller,
            required theme}) async {
          final to = txParams['to']?.toString() ?? '—';
          final value = txParams['value']?.toString() ?? '0';
          return showDialog<bool>(
            context: ctx,
            builder: (c) => AlertDialog(
              title: const Text('Xác nhận giao dịch'),
              content: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text('Host: $host', style: theme.captionStyle),
                    const SizedBox(height: 8),
                    Text('To: $to',
                        style: theme.valueStyle
                            .copyWith(fontSize: 12, fontFamily: 'monospace')),
                    const SizedBox(height: 4),
                    Text('Value: $value', style: theme.valueStyle),
                  ]),
              actions: [
                TextButton(
                    onPressed: () => Navigator.pop(c, false),
                    child: const Text('Từ chối')),
                FilledButton(
                    onPressed: () => Navigator.pop(c, true),
                    child: const Text('Gửi')),
              ],
            ),
          );
        },
      );

  // Demo private key – NEVER hardcode in production, load from secure storage
  static const _demoPk =
      '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('web3_webview 1.0.11 • premium + dark'),
        actions: [
          IconButton(
            tooltip: widget.isDark ? 'Light mode' : 'Dark mode',
            icon: Icon(widget.isDark
                ? Icons.light_mode_rounded
                : Icons.dark_mode_rounded),
            onPressed: widget.onToggleDark,
          ),
        ],
      ),
      body: IndexedStack(
        index: _index,
        children: [
          // 1. Read-only – no privateKey/signer, DApp still loads (auto dark)
          Web3WebView(
            web3WalletConfig: Web3WalletConfig(
              currentNetwork: _eth,
              supportNetworks: [_eth],
              name: 'Read-only Demo',
              id: 'com.example.readonly',
              dialogTheme: _lightTheme,
              darkDialogTheme: _darkTheme,
              onError: (m, p, msg) => debugPrint('read-only onError $m: $msg'),
            ),
            initialUrlRequest: URLRequest(
                url: WebUri('https://metamask.github.io/test-dapp/')),
            onPermissionRequest: (c, r) async => PermissionResponse(
              resources: r.resources,
              action: PermissionResponseAction.DENY,
            ),
          ),
          // 2. Local private key – same themes, premium cards adapt to dark
          Web3WebView(
            web3WalletConfig: Web3WalletConfig(
              privateKey: _demoPk,
              currentNetwork: _eth,
              supportNetworks: [_eth],
              name: 'PrivateKey Demo',
              id: 'com.example.privatekey',
              dialogTheme: _lightTheme,
              darkDialogTheme: _darkTheme,
              onError: (m, p, msg) => debugPrint('pk onError $m: $msg'),
            ),
            initialUrlRequest: URLRequest(
                url: WebUri('https://metamask.github.io/test-dapp/')),
            onPermissionRequest: (c, r) async => PermissionResponse(
              resources: r.resources,
              action: PermissionResponseAction.DENY,
            ),
          ),
          // 3. External signer (WalletConnect etc.) – dark auto
          Web3WebView(
            web3WalletConfig: Web3WalletConfig(
              signer: DemoSigner('0x1111111111111111111111111111111111111111'),
              currentNetwork: _eth,
              supportNetworks: [_eth],
              name: 'External Signer Demo',
              id: 'com.example.signer',
              dialogTheme: _lightTheme,
              darkDialogTheme: _darkTheme,
            ),
            initialUrlRequest: URLRequest(
                url: WebUri('https://metamask.github.io/test-dapp/')),
            onPermissionRequest: (c, r) async => PermissionResponse(
              resources: r.resources,
              action: PermissionResponseAction.DENY,
            ),
          ),
          // 4. Custom UI – override dialog completely to match your brand
          Web3WebView(
            web3WalletConfig: Web3WalletConfig(
              privateKey: _demoPk,
              currentNetwork: _eth,
              supportNetworks: [_eth],
              name: 'Custom UI Demo',
              id: 'com.example.custom',
              dialogTheme: _lightTheme,
              darkDialogTheme: _darkTheme,
              dialogBuilders: _customBuilders, // <-- your builders
              onError: (m, p, msg) => debugPrint('custom onError $m: $msg'),
            ),
            initialUrlRequest: URLRequest(
                url: WebUri('https://metamask.github.io/test-dapp/')),
            onPermissionRequest: (c, r) async => PermissionResponse(
              resources: r.resources,
              action: PermissionResponseAction.DENY,
            ),
          ),
        ],
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: _index,
        onDestinationSelected: (i) => setState(() => _index = i),
        destinations: const [
          NavigationDestination(
              icon: Icon(Icons.visibility), label: 'Read-only'),
          NavigationDestination(icon: Icon(Icons.key), label: 'PrivateKey'),
          NavigationDestination(icon: Icon(Icons.wallet), label: 'Signer'),
          NavigationDestination(
              icon: Icon(Icons.brush_rounded), label: 'Custom'),
        ],
      ),
    );
  }
}

/// Minimal external signer demo – replace with WalletConnect / enclave logic.
class DemoSigner extends Web3Signer {
  @override
  final String address;
  DemoSigner(this.address);

  @override
  Future<String> signMessage(
      String method, String from, dynamic message, String password) async {
    // TODO: delegate to WalletConnect, show your own UI, then return 0x signature
    throw WalletException('DemoSigner: implement signMessage', code: 4200);
  }

  @override
  Future<String> sendTransaction(Map<String, dynamic> txParams) async {
    // TODO: delegate to WalletConnect
    throw WalletException('DemoSigner: implement sendTransaction', code: 4200);
  }
}
7
likes
150
points
62
downloads

Documentation

API reference

Publisher

verified publisherdatit309.is-a.dev

Weekly Downloads

web3_webview is a powerful bridge between a DApp running inside a WebView and your Flutter application, enabling secure and seamless two-way communication between them

Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

crypto, eip55, flutter, flutter_inappwebview, hex, http, intl, modal_bottom_sheet, uuid, web3dart

More

Packages that depend on web3_webview