> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Blockchain Integration

## EVM Operations (`sdk.evm`)

### createPublicClient

Create a public client for interacting with an EVM chain.

```dart theme={"system"}
EvmPublicClient createPublicClient({required int chainId})
```

#### Parameters

* **chainId** (int) - The chain ID (e.g., 1 for Ethereum mainnet, 137 for Polygon)

#### Returns

* **EvmPublicClient** - Public client for the chain

#### Example

```dart theme={"system"}
final sdk = DynamicSDK.instance;
final client = sdk.evm.createPublicClient(chainId: 1); // Ethereum mainnet
```

### getGasPrice

Get the current gas price for a chain.

```dart theme={"system"}
Future<GasPrice> getGasPrice()
```

#### Returns

* **GasPrice** - Current gas price information

#### Example

```dart theme={"system"}
final client = sdk.evm.createPublicClient(chainId: 1);

try {
  final gasPrice = await client.getGasPrice();
  print('Gas price: ${gasPrice.maxFeePerGas}');
} catch (e) {
  print('Failed to get gas price: $e');
}
```

### sendTransaction

Send a transaction on an EVM chain.

```dart theme={"system"}
Future<String> sendTransaction(BaseWallet wallet, EthereumTransaction transaction)
```

#### Parameters

* **wallet** (BaseWallet) - The wallet to send from
* **transaction** (EthereumTransaction) - Transaction details

#### Returns

* **String** - Transaction hash

#### Example

```dart theme={"system"}
final sdk = DynamicSDK.instance;

try {
  final transaction = EthereumTransaction(
    to: recipientAddress,
    value: '1000000000000000', // 0.001 ETH in Wei
    gasLimit: 21000,
  );
  final txHash = await sdk.evm.sendTransaction(wallet, transaction);
  print('Transaction sent: $txHash');
} catch (e) {
  print('Transaction failed: $e');
}
```

#### Complete Example with Gas Estimation

```dart theme={"system"}
class SendTransactionScreen extends StatefulWidget {
  final BaseWallet wallet;

  SendTransactionScreen({required this.wallet});

  @override
  _SendTransactionScreenState createState() => _SendTransactionScreenState();
}

class _SendTransactionScreenState extends State<SendTransactionScreen> {
  final sdk = DynamicSDK.instance;
  final recipientController = TextEditingController();
  final amountController = TextEditingController();
  bool isLoading = false;
  String? txHash;

  Future<void> sendTransaction() async {
    setState(() => isLoading = true);

    try {
      // Get current network
      final network = await sdk.wallets.getNetwork(widget.wallet);
      final chainId = network.chainId!;

      // Get gas price
      final client = sdk.evm.createPublicClient(chainId: chainId);
      final gasPrice = await client.getGasPrice();

      // Convert ETH to Wei (multiply by 10^18)
      final amount = double.parse(amountController.text);
      final weiAmount = (amount * 1e18).toStringAsFixed(0);

      // Create transaction
      final transaction = EthereumTransaction(
        to: recipientController.text,
        value: weiAmount,
        gasLimit: 21000,
        maxFeePerGas: gasPrice.maxFeePerGas,
        maxPriorityFeePerGas: gasPrice.maxPriorityFeePerGas,
      );

      // Send transaction
      final hash = await sdk.evm.sendTransaction(widget.wallet, transaction);

      setState(() {
        txHash = hash;
        isLoading = false;
      });

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Transaction sent: $hash')),
      );
    } catch (e) {
      setState(() => isLoading = false);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Transaction failed: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Send Transaction')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            TextField(
              controller: recipientController,
              decoration: InputDecoration(
                labelText: 'Recipient Address',
                hintText: '0x...',
              ),
            ),
            SizedBox(height: 16),
            TextField(
              controller: amountController,
              decoration: InputDecoration(
                labelText: 'Amount (ETH)',
                hintText: '0.001',
              ),
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            ),
            SizedBox(height: 24),
            ElevatedButton(
              onPressed: isLoading ? null : sendTransaction,
              child: isLoading
                  ? CircularProgressIndicator()
                  : Text('Send Transaction'),
            ),
            if (txHash != null) ...[
              SizedBox(height: 24),
              Text('Transaction Hash:'),
              SelectableText(
                txHash!,
                style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
              ),
            ],
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    recipientController.dispose();
    amountController.dispose();
    super.dispose();
  }
}
```

### signTransaction

Sign a transaction without sending it.

```dart theme={"system"}
Future<String> signTransaction(BaseWallet wallet, EthereumTransaction transaction)
```

#### Parameters

* **wallet** (BaseWallet) - The wallet to sign with
* **transaction** (EthereumTransaction) - Transaction to sign

#### Returns

* **String** - Signed transaction

#### Example

```dart theme={"system"}
try {
  final signedTx = await sdk.evm.signTransaction(wallet, transaction);
  print('Signed transaction: $signedTx');
} catch (e) {
  print('Failed to sign: $e');
}
```

### writeContract

Write to a smart contract (call a contract function).

```dart theme={"system"}
Future<String> writeContract(BaseWallet wallet, WriteContractInput input)
```

#### Parameters

* **wallet** (BaseWallet) - The wallet to call from
* **input** (WriteContractInput) - Contract call parameters

#### Returns

* **String** - Transaction hash

#### Example

```dart theme={"system"}
import 'package:web3dart/web3dart.dart';

final sdk = DynamicSDK.instance;

try {
  // ERC20 transfer example
  final input = WriteContractInput(
    address: tokenContractAddress,
    functionName: 'transfer',
    args: [recipientAddress, '1000000000000000000'], // 1 token with 18 decimals
    abi: [
      {
        'inputs': [
          {'name': 'recipient', 'type': 'address'},
          {'name': 'amount', 'type': 'uint256'},
        ],
        'name': 'transfer',
        'outputs': [
          {'name': '', 'type': 'bool'},
        ],
        'stateMutability': 'nonpayable',
        'type': 'function',
      },
    ],
  );

  final txHash = await sdk.evm.writeContract(wallet, input);
  print('Contract write successful: $txHash');
} catch (e) {
  print('Contract write failed: $e');
}
```

#### Complete ERC20 Token Transfer Example

```dart theme={"system"}
class TokenTransferScreen extends StatefulWidget {
  final BaseWallet wallet;

  TokenTransferScreen({required this.wallet});

  @override
  _TokenTransferScreenState createState() => _TokenTransferScreenState();
}

class _TokenTransferScreenState extends State<TokenTransferScreen> {
  final sdk = DynamicSDK.instance;
  final contractController = TextEditingController();
  final recipientController = TextEditingController();
  final amountController = TextEditingController();
  bool isLoading = false;
  String? txHash;

  // Standard ERC20 ABI (transfer function)
  static const erc20TransferAbi = [
    {
      'inputs': [
        {'name': 'recipient', 'type': 'address'},
        {'name': 'amount', 'type': 'uint256'},
      ],
      'name': 'transfer',
      'outputs': [
        {'name': '', 'type': 'bool'},
      ],
      'stateMutability': 'nonpayable',
      'type': 'function',
    },
  ];

  Future<void> transferTokens() async {
    setState(() => isLoading = true);

    try {
      // Convert amount to smallest unit (assuming 18 decimals)
      final amount = double.parse(amountController.text);
      final rawAmount = (amount * 1e18).toStringAsFixed(0);

      final input = WriteContractInput(
        address: contractController.text,
        functionName: 'transfer',
        args: [recipientController.text, rawAmount],
        abi: erc20TransferAbi,
      );

      final hash = await sdk.evm.writeContract(widget.wallet, input);

      setState(() {
        txHash = hash;
        isLoading = false;
      });

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Transfer successful: $hash')),
      );
    } catch (e) {
      setState(() => isLoading = false);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Transfer failed: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Transfer ERC20 Tokens')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            TextField(
              controller: contractController,
              decoration: InputDecoration(
                labelText: 'Token Contract Address',
                hintText: '0x...',
              ),
            ),
            SizedBox(height: 16),
            TextField(
              controller: recipientController,
              decoration: InputDecoration(
                labelText: 'Recipient Address',
                hintText: '0x...',
              ),
            ),
            SizedBox(height: 16),
            TextField(
              controller: amountController,
              decoration: InputDecoration(
                labelText: 'Amount',
                hintText: '1.0',
              ),
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            ),
            SizedBox(height: 24),
            ElevatedButton(
              onPressed: isLoading ? null : transferTokens,
              child: isLoading
                  ? CircularProgressIndicator()
                  : Text('Transfer Tokens'),
            ),
            if (txHash != null) ...[
              SizedBox(height: 24),
              Text('Transaction Hash:'),
              SelectableText(
                txHash!,
                style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
              ),
            ],
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    contractController.dispose();
    recipientController.dispose();
    amountController.dispose();
    super.dispose();
  }
}
```

## Solana Operations (`sdk.solana`)

### createConnection

Create a connection to a Solana network.

```dart theme={"system"}
SolanaConnection createConnection()
```

#### Returns

* **SolanaConnection** - Connection to the Solana network

#### Example

```dart theme={"system"}
final sdk = DynamicSDK.instance;
final connection = sdk.solana.createConnection();
```

### getLatestBlockhash

Get the latest blockhash for transaction creation.

```dart theme={"system"}
Future<BlockhashResult> getLatestBlockhash()
```

#### Returns

* **BlockhashResult** - Contains the blockhash and last valid block height

#### Example

```dart theme={"system"}
final connection = sdk.solana.createConnection();

try {
  final blockhashResult = await connection.getLatestBlockhash();
  final blockhash = blockhashResult.blockhash;
  print('Latest blockhash: $blockhash');
} catch (e) {
  print('Failed to get blockhash: $e');
}
```

### createSigner

Create a signer for signing Solana transactions.

```dart theme={"system"}
SolanaSigner createSigner(BaseWallet wallet)
```

#### Parameters

* **wallet** (BaseWallet) - The Solana wallet

#### Returns

* **SolanaSigner** - Signer for the wallet

#### Example

```dart theme={"system"}
final sdk = DynamicSDK.instance;
final signer = sdk.solana.createSigner(wallet);
```

### signMessage

Sign a message with a Solana wallet.

```dart theme={"system"}
Future<String> signMessage(String message)
```

#### Parameters

* **message** (String) - The message to sign

#### Returns

* **String** - The signature

#### Example

```dart theme={"system"}
final signer = sdk.solana.createSigner(wallet);

try {
  final signature = await signer.signMessage('Hello from Dynamic SDK!');
  print('Signature: $signature');
} catch (e) {
  print('Failed to sign message: $e');
}
```

### signEncodedTransaction

Sign a Solana transaction (base64 encoded).

```dart theme={"system"}
Future<String> signEncodedTransaction(String base64Transaction)
```

#### Parameters

* **base64Transaction** (String) - Base64 encoded transaction

#### Returns

* **String** - Signed transaction (base64 encoded)

#### Example

```dart theme={"system"}
final signer = sdk.solana.createSigner(wallet);

try {
  final signedTx = await signer.signEncodedTransaction(base64Transaction);
  print('Signed transaction: $signedTx');
} catch (e) {
  print('Failed to sign transaction: $e');
}
```

### signAndSendEncodedTransaction

Sign and send a Solana transaction.

```dart theme={"system"}
Future<String> signAndSendEncodedTransaction(String base64Transaction)
```

#### Parameters

* **base64Transaction** (String) - Base64 encoded transaction

#### Returns

* **String** - Transaction signature

#### Example

```dart theme={"system"}
final signer = sdk.solana.createSigner(wallet);

try {
  final signature = await signer.signAndSendEncodedTransaction(base64Transaction);
  print('Transaction sent: $signature');
} catch (e) {
  print('Transaction failed: $e');
}
```

### Complete Solana Transfer Example

```dart theme={"system"}
import 'package:solana/solana.dart';

class SolanaTransferScreen extends StatefulWidget {
  final BaseWallet wallet;

  SolanaTransferScreen({required this.wallet});

  @override
  _SolanaTransferScreenState createState() => _SolanaTransferScreenState();
}

class _SolanaTransferScreenState extends State<SolanaTransferScreen> {
  final sdk = DynamicSDK.instance;
  final recipientController = TextEditingController();
  final amountController = TextEditingController();
  bool isLoading = false;
  String? signature;

  Future<void> sendTransaction() async {
    setState(() => isLoading = true);

    try {
      // Create connection and signer
      final connection = sdk.solana.createConnection();
      final signer = sdk.solana.createSigner(widget.wallet);

      // Get latest blockhash
      final blockhashResult = await connection.getLatestBlockhash();

      // Convert SOL to lamports (multiply by 10^9)
      final amount = double.parse(amountController.text);
      final lamports = (amount * 1e9).toInt();

      // Create Solana client for transaction building
      final client = SolanaClient(
        rpcUrl: Uri.parse('https://api.mainnet-beta.solana.com'),
        websocketUrl: Uri.parse('wss://api.mainnet-beta.solana.com'),
      );

      // Create transfer instruction
      final fromPubkey = Ed25519HDPublicKey.fromBase58(widget.wallet.address);
      final toPubkey = Ed25519HDPublicKey.fromBase58(recipientController.text);

      final instruction = SystemInstruction.transfer(
        fundingAccount: fromPubkey,
        recipientAccount: toPubkey,
        lamports: lamports,
      );

      // Build transaction
      final message = Message(
        instructions: [instruction],
      );

      final compiledMessage = message.compile(
        recentBlockhash: blockhashResult.blockhash,
        feePayer: fromPubkey,
      );

      final transaction = SignedTx(
        compiledMessage: compiledMessage,
        signatures: [],
      );

      // Encode transaction to base64
      final base64Tx = base64Encode(transaction.encode());

      // Sign and send using Dynamic SDK
      final sig = await signer.signAndSendEncodedTransaction(base64Tx);

      setState(() {
        signature = sig;
        isLoading = false;
      });

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Transaction sent: $sig')),
      );
    } catch (e) {
      setState(() => isLoading = false);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Transaction failed: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Send Solana')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            TextField(
              controller: recipientController,
              decoration: InputDecoration(
                labelText: 'Recipient Address',
                hintText: 'Solana address...',
              ),
            ),
            SizedBox(height: 16),
            TextField(
              controller: amountController,
              decoration: InputDecoration(
                labelText: 'Amount (SOL)',
                hintText: '0.001',
              ),
              keyboardType: TextInputType.numberWithOptions(decimal: true),
            ),
            SizedBox(height: 24),
            ElevatedButton(
              onPressed: isLoading ? null : sendTransaction,
              child: isLoading
                  ? CircularProgressIndicator()
                  : Text('Send Transaction'),
            ),
            if (signature != null) ...[
              SizedBox(height: 24),
              Text('Transaction Signature:'),
              SelectableText(
                signature!,
                style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
              ),
            ],
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    recipientController.dispose();
    amountController.dispose();
    super.dispose();
  }
}
```

## Network Management (`sdk.networks`)

### Available Networks

Get lists of available EVM and Solana networks.

```dart theme={"system"}
List<GenericNetwork> get evm
List<GenericNetwork> get solana
```

#### Example

```dart theme={"system"}
final sdk = DynamicSDK.instance;

// Get all EVM networks
final evmNetworks = sdk.networks.evm;
for (final network in evmNetworks) {
  print('EVM Network: ${network.name}, Chain ID: ${network.chainId}');
}

// Get all Solana networks
final solanaNetworks = sdk.networks.solana;
for (final network in solanaNetworks) {
  print('Solana Network: ${network.name}, Network ID: ${network.networkId}');
}

// Find a specific network
final polygon = evmNetworks.firstWhere((n) => n.chainId == 137);
print('Found Polygon: ${polygon.name}');
```

### Network Selector Widget

```dart theme={"system"}
class NetworkSelector extends StatelessWidget {
  final String chainType; // 'EVM' or 'SOL'
  final Function(GenericNetwork) onNetworkSelected;
  final sdk = DynamicSDK.instance;

  NetworkSelector({
    required this.chainType,
    required this.onNetworkSelected,
  });

  @override
  Widget build(BuildContext context) {
    final networks = chainType == 'EVM'
        ? sdk.networks.evm
        : sdk.networks.solana;

    return DropdownButton<GenericNetwork>(
      hint: Text('Select Network'),
      items: networks.map((network) {
        return DropdownMenuItem(
          value: network,
          child: Text(network.name),
        );
      }).toList(),
      onChanged: (network) {
        if (network != null) {
          onNetworkSelected(network);
        }
      },
    );
  }
}
```

## Data Types

### EthereumTransaction

```dart theme={"system"}
class EthereumTransaction {
  final String to;                 // Recipient address
  final String value;              // Amount in Wei (as String)
  final int gasLimit;              // Gas limit
  final int? maxFeePerGas;         // Max fee per gas (optional)
  final int? maxPriorityFeePerGas; // Priority fee (optional)
  final String? data;              // Contract data (optional)
}
```

### WriteContractInput

```dart theme={"system"}
class WriteContractInput {
  final String address;                      // Contract address
  final String functionName;                 // Function to call
  final List<dynamic> args;                  // Function arguments
  final List<Map<String, dynamic>> abi;      // Contract ABI
}
```

### GasPrice

```dart theme={"system"}
class GasPrice {
  final int maxFeePerGas;
  final int maxPriorityFeePerGas;
}
```

### GenericNetwork

```dart theme={"system"}
class GenericNetwork {
  final String name;
  final int? chainId;      // For EVM networks
  final String? networkId; // For Solana networks
}
```

### BlockhashResult

```dart theme={"system"}
class BlockhashResult {
  final String blockhash;
  final int lastValidBlockHeight;
}
```

## Using web3dart for Advanced EVM Operations

The Dynamic SDK provides integration classes for using the `web3dart` package with Dynamic wallets.

### DynamicRpcService

Extends `RpcService` from web3dart to make RPC calls through the Dynamic SDK.

```dart theme={"system"}
class DynamicRpcService extends RpcService {
  final int chainId;
  final dynamic requestChannel;

  DynamicRpcService({
    required this.chainId,
    required this.requestChannel,
  });

  Future<RPCResponse> call(String function, [List? params]);
}
```

#### Example

```dart theme={"system"}
import 'package:web3dart/web3dart.dart';

final rpcService = DynamicRpcService(
  chainId: 1,
  requestChannel: wallet.requestChannel,
);

final response = await rpcService.call('eth_blockNumber');
```

### DynamicCredential

Implements `CredentialsWithKnownAddress` and `CustomTransactionSender` for signing messages and transactions with Dynamic wallets.

```dart theme={"system"}
class DynamicCredential extends CredentialsWithKnownAddress
    implements CustomTransactionSender {
  final dynamic requestChannel;
  final String address;

  DynamicCredential({
    required this.requestChannel,
    required String address,
  });

  Future<String> signMessage({required Uint8List payload});
  Future<String> sendTransaction(Transaction transaction);
}
```

#### Example

```dart theme={"system"}
import 'package:web3dart/web3dart.dart';

final credential = DynamicCredential(
  requestChannel: wallet.requestChannel,
  address: wallet.address,
);

// Sign a message
final signature = await credential.signMessage(
  payload: Uint8List.fromList(utf8.encode('Hello')),
);

// Send a transaction
final transaction = Transaction(
  to: EthereumAddress.fromHex('0x...'),
  value: EtherAmount.fromInt(EtherUnit.ether, 1),
);
final txHash = await credential.sendTransaction(transaction);
```

### Advanced Token Operations

For more complex EVM operations, you can use the `web3dart` package alongside the Dynamic SDK:

```dart theme={"system"}
import 'package:web3dart/web3dart.dart';
import 'package:http/http.dart' as http;

class AdvancedEvmOperations {
  final sdk = DynamicSDK.instance;

  Future<EtherAmount> getTokenBalance({
    required String tokenAddress,
    required String walletAddress,
    required String rpcUrl,
  }) async {
    final client = Web3Client(rpcUrl, http.Client());

    final contract = DeployedContract(
      ContractAbi.fromJson(erc20Abi, 'ERC20'),
      EthereumAddress.fromHex(tokenAddress),
    );

    final balanceFunction = contract.function('balanceOf');
    final balance = await client.call(
      contract: contract,
      function: balanceFunction,
      params: [EthereumAddress.fromHex(walletAddress)],
    );

    return EtherAmount.fromBigInt(EtherUnit.wei, balance.first);
  }
}
```

## Using solana package for Advanced Solana Operations

For complex Solana operations, use the `solana` package with Dynamic SDK:

```dart theme={"system"}
import 'package:solana/solana.dart';

class AdvancedSolanaOperations {
  final sdk = DynamicSDK.instance;

  Future<double> getTokenBalance({
    required String tokenMintAddress,
    required String walletAddress,
  }) async {
    final client = SolanaClient(
      rpcUrl: Uri.parse('https://api.mainnet-beta.solana.com'),
      websocketUrl: Uri.parse('wss://api.mainnet-beta.solana.com'),
    );

    final pubkey = Ed25519HDPublicKey.fromBase58(walletAddress);
    final balance = await client.rpcClient.getTokenAccountBalance(
      pubkey.toBase58(),
    );

    return balance.value.uiAmount ?? 0.0;
  }
}
```
