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

# Blockchain Integration

## EVM Operations (`sdk.web3dart`)

### createPublicClient

Create a public client for interacting with an EVM chain.

```dart theme={"system"}
external Web3Client createPublicClient({required int chainId});
```

#### Parameters

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

#### Returns

* **Web3Client**: Public client for the chain (from the `web3dart` package)

#### Example

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

final sdk = DynamicSDK.instance;
final client = sdk.web3dart.createPublicClient(chainId: 1); // Ethereum mainnet
```

### getGasPrice

Get the current gas price for a chain.

```dart theme={"system"}
external Future<EtherAmount> getGasPrice();
```

#### Returns

* **EtherAmount**: Current gas price in wei (from the `web3dart` package)

#### Example

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

final client = DynamicSDK.instance.web3dart.createPublicClient(chainId: 1);

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

### sendTransaction

Send a transaction on an EVM chain.

```dart theme={"system"}
external Future<String> sendTransaction({
  required Transaction transaction,
  required BaseWallet wallet,
});
```

#### Parameters

* **transaction** (Transaction): Transaction details (from the `web3dart` package)
* **wallet** (BaseWallet): The wallet to send from

#### Returns

* **String**: Transaction hash

#### Example

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

final sdk = DynamicSDK.instance;

try {
  final transaction = Transaction(
    to: EthereumAddress.fromHex(recipientAddress),
    value: EtherAmount.fromBigInt(EtherUnit.wei, BigInt.parse('1000000000000000')), // 0.001 ETH
    maxGas: 21000,
  );
  final txHash = await sdk.web3dart.sendTransaction(
    transaction: transaction,
    wallet: wallet,
  );
  print('Transaction sent: $txHash');
} catch (e) {
  print('Transaction failed: $e');
}
```

#### Complete Example with Gas Estimation

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

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(wallet: widget.wallet);
      final chainId = network.intValue()!;

      // Get gas price
      final client = sdk.web3dart.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).toInt();

      // Create transaction
      final transaction = Transaction(
        to: EthereumAddress.fromHex(recipientController.text),
        value: EtherAmount.fromBigInt(EtherUnit.wei, BigInt.from(weiAmount)),
        maxGas: 21000,
        maxFeePerGas: gasPrice,
      );

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

      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();
  }
}
```

### signEthereumTransaction

Sign a transaction without sending it. Only works with embedded wallets.

```dart theme={"system"}
external Future<String> signEthereumTransaction({
  required String walletId,
  required Transaction transaction,
});
```

#### Parameters

* **walletId** (String): The ID of the embedded wallet to sign with
* **transaction** (Transaction): Transaction to sign (from the `web3dart` package)

#### Returns

* **String**: Signed transaction

#### Example

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

try {
  final signedTx = await sdk.wallets.signEthereumTransaction(
    walletId: wallet.id,
    transaction: 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"}
external Future<String> writeContract({
  required BaseWallet wallet,
  required 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:dynamic_sdk/dynamic_sdk.dart';
import 'package:dynamic_sdk_web3dart/dynamic_sdk_web3dart.dart';
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.web3dart.writeContract(wallet: wallet, input: input);
  print('Contract write successful: $txHash');
} catch (e) {
  print('Contract write failed: $e');
}
```

#### Complete ERC20 Token Transfer Example

```dart theme={"system"}
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:dynamic_sdk_web3dart/dynamic_sdk_web3dart.dart';
import 'package:flutter/material.dart';

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.web3dart.writeContract(wallet: widget.wallet, input: 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"}
external Connection createConnection();
```

#### Returns

* **Connection**: Connection to the Solana network (from the `solana_web3_latest` package)

#### Example

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

final sdk = DynamicSDK.instance;
final connection = sdk.solana.createConnection();
```

### getLatestBlockhash

Get the latest blockhash for transaction creation.

```dart theme={"system"}
external Future<BlockhashWithExpiryBlockHeight> getLatestBlockhash();
```

#### Returns

* **BlockhashWithExpiryBlockHeight**: Contains the blockhash and last valid block height

#### Example

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

final connection = DynamicSDK.instance.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"}
external DynamicSolanaSigner createSigner({
  required BaseWallet wallet,
});
```

#### Parameters

* **wallet** (BaseWallet): The Solana wallet

#### Returns

* **DynamicSolanaSigner**: Signer for the wallet

#### Example

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

final sdk = DynamicSDK.instance;
final signer = sdk.solana.createSigner(wallet: wallet);
```

### signMessage

Sign a message with a Solana wallet.

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

#### Parameters

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

#### Returns

* **String**: The signature

#### Example

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

final signer = DynamicSDK.instance.solana.createSigner(wallet: wallet);

try {
  final signature = await signer.signMessage(message: '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"}
external Future<String> signEncodedTransaction({
  required String base64Transaction,
});
```

#### Parameters

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

#### Returns

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

#### Example

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

final signer = DynamicSDK.instance.solana.createSigner(wallet: wallet);

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

### signAndSendEncodedTransaction

Sign and send a Solana transaction.

```dart theme={"system"}
import 'package:dynamic_sdk_solana/src/dynamic_solana_signer.dart';

external Future<String> signAndSendEncodedTransaction({
  required String base64Transaction,
  SolanaTransactionType transactionType = SolanaTransactionType.versioned,
  SolanaSponsorshipMode? sponsorshipMode,
});
```

#### Parameters

* **base64Transaction** (String): Base64 encoded transaction
* **transactionType** (SolanaTransactionType): Transaction type, defaults to `versioned`
* **sponsorshipMode** (SolanaSponsorshipMode?): Overrides the project's SVM gas sponsorship for this transaction. `auto` follows the project setting, `off` always pays the fee from the wallet, `required` fails when sponsorship is unavailable.

#### Returns

* **String**: Transaction signature

#### Example

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

final signer = DynamicSDK.instance.solana.createSigner(wallet: wallet);

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

### Complete Solana Transfer Example

```dart theme={"system"}
import 'dart:convert';

import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:dynamic_sdk_solana/dynamic_sdk_solana.dart';
import 'package:flutter/material.dart';
import 'package:solana/encoder.dart';
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(wallet: 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 = transaction.encode();

      // Sign and send using Dynamic SDK
      final sig = await signer.signAndSendEncodedTransaction(
        base64Transaction: 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"}
final evmNetworks = sdk.networks.evm;       // List<GenericNetwork>
final solanaNetworks = sdk.networks.solana; // List<GenericNetwork>
```

#### 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"}
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:flutter/material.dart';

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

### Transaction and EtherAmount

EVM transactions and amounts use the [`web3dart`](https://pub.dev/packages/web3dart) `Transaction`, `EthereumAddress`, and `EtherAmount` types.

### 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<dynamic> abi;      // Contract ABI
  final BigInt? value;          // Optional Ether value to send
  final BigInt? gas;            // Optional gas limit
}
```

### GenericNetwork

```dart theme={"system"}
class GenericNetwork {
  final String name;
  final dynamic chainId;        // int for EVM networks
  final dynamic networkId;      // String for Solana networks
  final List<String> rpcUrls;
}
```

### BlockhashWithExpiryBlockHeight

Returned by `connection.getLatestBlockhash()` (from the `solana_web3_latest` package).

```dart theme={"system"}
class BlockhashWithExpiryBlockHeight {
  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.

### Gas Sponsorship

The `sdk.web3dart` extension exposes EVM gas sponsorship. See [EVM Gas Sponsorship](https://docs.dynamic.xyz/docs/flutter/wallets/evm/gas-sponsorship.md).

```dart theme={"system"}
external Future<bool> isGasSponsorshipEnabled();

external Future<String> sendSponsoredTransaction({
  required List<EvmSponsoredCall> calls,
  required BaseWallet wallet,
});

external Future<BigInt> erc20Allowance({
  required String token,
  required String owner,
  required String spender,
  required int chainId,
});
```

#### Example

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

final txHash = await DynamicSDK.instance.web3dart.sendSponsoredTransaction(
  calls: [
    EvmSponsoredCall(
      target: recipientAddress,
      data: '0x',
      value: '1000000000000000',
    ),
  ],
  wallet: wallet,
);
```

### DynamicRpcService

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

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

abstract class DynamicRpcService extends RpcService {
  final int chainId;

  DynamicRpcService({required this.chainId}) : super('');

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

#### Example

You do not need to construct `DynamicRpcService` yourself — `sdk.web3dart.createPublicClient` builds it internally. Use the returned `Web3Client` for RPC calls:

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

final client = DynamicSDK.instance.web3dart.createPublicClient(chainId: 1);
final blockNumber = await client.getBlockNumber();
```

### 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 double.tryParse(balance.value.uiAmountString ?? '') ?? 0.0;
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.