Quick Start

Transfer

Para handles signing and broadcasting in one call:
import 'package:para/para.dart';

final para = Para(apiKey: 'your-api-key');
final wallet = (await para.fetchWallets()).firstWhere((w) => w.type == 'EVM');

// Send ETH - Para signs and broadcasts
final result = await para.transfer(
  walletId: wallet.id!,
  to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  amount: '1000000000000000', // 0.001 ETH in wei
  chainId: '11155111', // Optional: Sepolia testnet (defaults to wallet's chain)
  rpcUrl: null, // Optional: override default RPC
);
print('Transaction sent: ${result.hash}');
print('From: ${result.from}, To: ${result.to}');
print('Amount: ${result.amount}, Chain: ${result.chainId}');

Advanced Control

Sign with Para, then broadcast yourself for custom gas/RPC settings:
// Step 1: Sign transaction with Para
final transaction = EVMTransaction(
  to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  value: '1000000000000000',
  gasLimit: '21000',
);

final result = await para.signTransaction(
  walletId: wallet.id!,
  transaction: transaction.toJson(),
  chainId: '11155111', // Sepolia testnet
);

// Step 2: Broadcast using your preferred library (e.g., web3dart)
// final txHash = await broadcastWithWeb3Dart(result.signature);

Common Operations

Send ETH

// Para handles everything - signing and broadcasting
final result = await para.transfer(
  walletId: wallet.id!,
  to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  amount: '1000000000000000', // 0.001 ETH in wei
  chainId: '11155111', // Optional: Sepolia testnet
  rpcUrl: null, // Optional: custom RPC URL
);
print('Transaction hash: ${result.hash}');
print('From: ${result.from}, To: ${result.to}, Chain: ${result.chainId}');

Sign Transaction

final transaction = EVMTransaction(
  to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  value: '1000000000000000',
  gasLimit: '21000',
  maxPriorityFeePerGas: '1000000000', // 1 Gwei
  maxFeePerGas: '3000000000', // 3 Gwei
  nonce: '0',
  chainId: '11155111', // Sepolia
  type: 2,
);

final result = await para.signTransaction(
  walletId: wallet.id!,
  transaction: transaction.toJson(),
  chainId: '11155111',
);
print('Signed: ${result.signature}');

Check Balance

// Native ETH balance
final ethBalance = await para.getBalance(walletId: wallet.id!);

// ERC-20 token balance
final tokenBalance = await para.getBalance(
  walletId: wallet.id!,
  token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
);

Sign Message

final message = 'Hello, Ethereum!';
final result = await para.signMessage(
  walletId: wallet.id!,
  message: message,
);
print('Signature: ${result.signature}');

Networks

Testnets

NetworkChain IDNative TokenDefault RPC
Sepolia11155111ETHhttps://ethereum-sepolia-rpc.publicnode.com
Polygon Mumbai80001MATIChttps://rpc-mumbai.maticvigil.com
Base Sepolia84532ETHhttps://sepolia.base.org

Mainnets

NetworkChain IDNative TokenDefault RPC
Ethereum1ETHhttps://eth.llamarpc.com
Polygon137MATIChttps://polygon-rpc.com
Base8453ETHhttps://mainnet.base.org
Arbitrum42161ETHhttps://arb1.arbitrum.io/rpc
Optimism10ETHhttps://mainnet.optimism.io

Complete Example

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

class EVMWalletView extends StatefulWidget {
  final Para para;
  final Wallet wallet;
  
  const EVMWalletView({required this.para, required this.wallet});
  
  @override
  State<EVMWalletView> createState() => _EVMWalletViewState();
}

class _EVMWalletViewState extends State<EVMWalletView> {
  bool _isLoading = false;
  String? _txHash;
  
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        children: [
          Text(
            widget.wallet.address ?? 'No address',
            style: TextStyle(fontFamily: 'monospace', fontSize: 12),
          ),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: _isLoading ? null : _sendETH,
            child: Text(_isLoading ? 'Sending...' : 'Send 0.001 ETH'),
          ),
          if (_txHash != null)
            Padding(
              padding: const EdgeInsets.only(top: 20),
              child: Text('Sent: $_txHash', style: TextStyle(fontSize: 12)),
            ),
        ],
      ),
    );
  }
  
  Future<void> _sendETH() async {
    setState(() => _isLoading = true);
    try {
      final result = await widget.para.transfer(
        walletId: widget.wallet.id!,
        to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
        amount: '1000000000000000',
        chainId: '11155111', // Optional: Sepolia testnet
        rpcUrl: null, // Optional: custom RPC
      );
      setState(() => _txHash = result.hash);
    } catch (e) {
      print('Error: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }
}

Smart Contract Interaction

// Call a contract function
final contractTransaction = EVMTransaction(
  to: '0x123abc...', // Contract address
  value: '0',
  gasLimit: '150000',
  maxPriorityFeePerGas: '1000000000',
  maxFeePerGas: '3000000000',
  nonce: '0',
  chainId: '11155111', // Sepolia testnet
  smartContractAbi: '''[{
    "inputs": [{"name":"num","type":"uint256"}],
    "name": "store",
    "type": "function"
  }]''',
  smartContractFunctionName: 'store',
  smartContractFunctionArgs: ['42'],
  type: 2,
);

final result = await para.signTransaction(
  walletId: wallet.id!,
  transaction: contractTransaction.toJson(),
  chainId: '11155111', // Sepolia testnet
);