> ## 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.

# SVM Gas Sponsorship

> Automatically sponsor Solana transaction fees for your users with Dynamic's built-in gas sponsorship feature.

## Overview

SVM Gas Sponsorship is Dynamic's built-in feature that automatically sponsors Solana (SVM) transaction fees for your users. When enabled, Dynamic handles all the complexity of fee sponsorship behind the scenes, allowing your users to transact without needing SOL for gas fees.

When enabled, Dynamic automatically replaces the fee payer in Solana transactions with a sponsored account, so your users don't need SOL for gas.

<Note>
  SVM Gas Sponsorship is available exclusively for **V3 MPC embedded wallets**. It works automatically once enabled - no code changes required.
</Note>

## Prerequisites

* Dynamic SDK initialized (see [Quickstart](/flutter/quickstart))
* User authenticated (see [Authentication](/flutter/authentication))
* Solana wallet available (see [Wallet Creation](/flutter/wallet-creation))
* V3 MPC embedded wallets configured in the dashboard

## Enabling SVM Gas Sponsorship

1. Go to the [Dynamic Dashboard](https://app.dynamic.xyz)
2. Navigate to **Settings** > **Embedded Wallets**
3. Ensure Solana (SOL) is enabled in your chain configurations
4. Toggle on **SVM Gas Sponsorship**

<Note>
  The SVM Gas Sponsorship toggle only appears when Solana is enabled in your chain configurations and you're using V3 MPC wallets.
</Note>

## How It Works

Once enabled, gas sponsorship is applied automatically to all transactions from your users' embedded wallets. Your code remains unchanged:

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

final sdk = DynamicSDK.instance;

Future<String> sendSOLGasless({
  required BaseWallet wallet,
  required String recipientAddress,
  required double amount,
}) async {
  final signer = sdk.solana.createSigner(wallet: wallet);
  final connection = sdk.solana.createConnection();

  final fromPubKey = Pubkey.fromString(wallet.address);
  final toPubKey = Pubkey.fromString(recipientAddress);

  final BlockhashWithExpiryBlockHeight recentBlockhash =
      await connection.getLatestBlockhash();

  // Create transaction - sponsorship is handled automatically
  final transaction = Transaction.v0(
    payer: fromPubKey,
    recentBlockhash: recentBlockhash.blockhash,
    instructions: [
      SystemProgram.transfer(
        fromPubkey: fromPubKey,
        toPubkey: toPubKey,
        lamports: solToLamports(amount),
      ),
    ],
  );

  // Sign and send - gas fees are sponsored automatically
  final signature = await signer.signAndSendTransaction(
    transaction: transaction,
  );

  return signature;
}

int solToLamports(double sol) {
  return (sol * 1e9).toInt();
}
```

### Transaction Flow

When your application sends a transaction:

1. **Transaction Creation**: Your app creates a standard Solana transaction
2. **Automatic Sponsorship**: The SDK intercepts the transaction before signing
3. **Backend Processing**: The transaction is sent to Dynamic's backend
4. **Sponsorship Processing**: Dynamic sponsors the transaction
5. **Fee Payer Replacement**: The transaction's fee payer is replaced with Dynamic's sponsored account
6. **User Signing**: The sponsored transaction is returned for the user to sign
7. **Broadcast**: The fully signed transaction is sent to the Solana network

## Limitations

### Wallet Requirements

* **Embedded wallets only**: Sponsorship only works with Dynamic's MPC embedded wallets
* **V3 wallets required**: Must be using V3 MPC wallet configuration
* **Not for external wallets**: External wallets (Phantom, Solflare, etc.) are not supported

### Transaction Constraints

* **Transaction size**: Maximum 2KB for the base64-encoded transaction
* **Already-signed transactions**: Transactions that are already signed will not be sponsored
* **Single transaction**: Each transaction is sponsored individually (no batching)

### Fallback Behavior

If sponsorship fails, the SDK will fall back to using the original transaction, which requires the user to have SOL for gas fees.

<Warning>
  When sponsorship fails, the transaction will proceed without sponsorship. Ensure your UX handles cases where users may need SOL for gas fees as a fallback.
</Warning>

## Checking Sponsorship Status

You can check if gas sponsorship is enabled in your project settings:

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

bool checkSponsorshipEnabled() {
  return sdk.projectSettings?.sdk?.embeddedWallets?.svmGasSponsorshipEnabled ?? false;
}
```

## Error Handling

```dart theme={"system"}
enum SolanaTransactionResult {
  success,
  insufficientBalance,
  sponsorshipFailed,
  error,
}

class TransactionResponse {
  final SolanaTransactionResult result;
  final String? signature;
  final String? errorMessage;

  TransactionResponse({
    required this.result,
    this.signature,
    this.errorMessage,
  });
}

Future<TransactionResponse> sendTransactionWithFallback({
  required BaseWallet wallet,
  required String recipient,
  required double amount,
}) async {
  try {
    // Attempt transaction - sponsorship applied automatically if enabled
    final signature = await sendSOLGasless(
      wallet: wallet,
      recipientAddress: recipient,
      amount: amount,
    );
    return TransactionResponse(
      result: SolanaTransactionResult.success,
      signature: signature,
    );
  } catch (e) {
    final errorDesc = e.toString().toLowerCase();

    if (errorDesc.contains('insufficient') || errorDesc.contains('balance')) {
      return TransactionResponse(
        result: SolanaTransactionResult.insufficientBalance,
        errorMessage: 'Insufficient balance for transaction',
      );
    } else if (errorDesc.contains('sponsor')) {
      return TransactionResponse(
        result: SolanaTransactionResult.sponsorshipFailed,
        errorMessage: 'Gas sponsorship failed, SOL required for fees',
      );
    } else {
      return TransactionResponse(
        result: SolanaTransactionResult.error,
        errorMessage: e.toString(),
      );
    }
  }
}

// Usage in Widget
void _handleSendTransaction() async {
  final response = await sendTransactionWithFallback(
    wallet: widget.wallet,
    recipient: _recipientController.text,
    amount: double.parse(_amountController.text),
  );

  setState(() {
    switch (response.result) {
      case SolanaTransactionResult.success:
        signature = response.signature;
        error = null;
        break;
      case SolanaTransactionResult.insufficientBalance:
      case SolanaTransactionResult.sponsorshipFailed:
      case SolanaTransactionResult.error:
        signature = null;
        error = response.errorMessage;
        break;
    }
  });
}
```

## Complete Example Widget

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

class GaslessSendWidget extends StatefulWidget {
  final BaseWallet wallet;

  const GaslessSendWidget({Key? key, required this.wallet}) : super(key: key);

  @override
  State<GaslessSendWidget> createState() => _GaslessSendWidgetState();
}

class _GaslessSendWidgetState extends State<GaslessSendWidget> {
  final sdk = DynamicSDK.instance;
  final _recipientController = TextEditingController();
  final _amountController = TextEditingController();

  String? signature;
  bool isLoading = false;
  String? error;

  bool get sponsorshipEnabled =>
      sdk.projectSettings?.sdk?.embeddedWallets?.svmGasSponsorshipEnabled ?? false;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          // Show sponsorship status
          Container(
            padding: const EdgeInsets.all(8),
            decoration: BoxDecoration(
              color: sponsorshipEnabled
                  ? Colors.green.withOpacity(0.1)
                  : Colors.orange.withOpacity(0.1),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Row(
              children: [
                Icon(
                  sponsorshipEnabled ? Icons.check_circle : Icons.info,
                  color: sponsorshipEnabled ? Colors.green : Colors.orange,
                  size: 16,
                ),
                const SizedBox(width: 8),
                Text(
                  sponsorshipEnabled
                      ? 'Gas fees are sponsored'
                      : 'Gas sponsorship not enabled',
                  style: TextStyle(
                    color: sponsorshipEnabled ? Colors.green : Colors.orange,
                    fontSize: 12,
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 16),
          TextField(
            controller: _recipientController,
            decoration: const InputDecoration(
              labelText: 'Recipient Address',
              border: OutlineInputBorder(),
            ),
          ),
          const SizedBox(height: 16),
          TextField(
            controller: _amountController,
            decoration: const InputDecoration(
              labelText: 'Amount (SOL)',
              border: OutlineInputBorder(),
            ),
            keyboardType: const TextInputType.numberWithOptions(decimal: true),
          ),
          const SizedBox(height: 16),
          ElevatedButton(
            onPressed: isLoading ? null : _sendTransaction,
            child: isLoading
                ? const SizedBox(
                    height: 20,
                    width: 20,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  )
                : Text(sponsorshipEnabled ? 'Send SOL (Gasless)' : 'Send SOL'),
          ),
          if (signature != null) ...[
            const SizedBox(height: 16),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.green.withOpacity(0.1),
                borderRadius: BorderRadius.circular(8),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    'Success!',
                    style: TextStyle(
                      color: Colors.green,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    signature!,
                    style: const TextStyle(fontSize: 12),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                  ),
                ],
              ),
            ),
          ],
          if (error != null) ...[
            const SizedBox(height: 16),
            Text(
              error!,
              style: const TextStyle(color: Colors.red, fontSize: 12),
            ),
          ],
        ],
      ),
    );
  }

  Future<void> _sendTransaction() async {
    // Implementation as shown in error handling section
  }

  @override
  void dispose() {
    _recipientController.dispose();
    _amountController.dispose();
    super.dispose();
  }
}
```

## Best Practices

1. **Don't assume sponsorship**: Build your UI to handle cases where sponsorship might not be available
2. **Show transaction status**: Provide feedback during the sponsorship and signing process
3. **Test in Sandbox first**: Verify sponsorship works in your Sandbox environment before going live
4. **Monitor usage**: Keep an eye on sponsorship usage in your dashboard

## Next Steps

* [Solana Connection](/flutter/wallets/solana/connection) - Connection setup
* [Send Solana Transactions](/flutter/wallets/solana/send-transactions) - Full transaction guide
* [Sign Solana Messages](/flutter/wallets/solana/message-signing) - Sign messages
