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

# Send ETH Transactions

> Learn how to send ETH transactions with the Dynamic Swift SDK.

## Overview

This guide covers sending ETH transactions including transaction creation, signing, and sending with the Dynamic Swift SDK.

## Prerequisites

* Dynamic SDK initialized (see [Installation Guide](/swift/quickstart))
* User authenticated (see [Authentication Guide](/swift/authentication))
* Wallets available (see [Wallet Creation](/swift/wallet-creation))
* Network configured (see [Networks](/swift/wallets/general/network-management))

## Send ETH Transaction

```swift theme={"system"}
import DynamicSDKSwift
import SwiftBigInt

let sdk = DynamicSDK.instance()

func sendTransaction(wallet: BaseWallet, to: String, amountInEth: Double) async {
    do {
        // Get current gas price
        let chainId = 1 // Ethereum mainnet, or use your target chain
        let client = sdk.evm.createPublicClient(chainId: chainId)
        let gasPrice = try await client.getGasPrice()

        // Convert ETH to Wei (1 ETH = 10^18 Wei)
        let weiAmount = BigUInt(amountInEth * pow(10.0, 18.0))

        // Create transaction
        let transaction = EthereumTransaction(
            from: wallet.address,
            to: to,
            value: weiAmount,
            gas: BigUInt(21000),  // Standard ETH transfer
            maxFeePerGas: gasPrice * 2,
            maxPriorityFeePerGas: gasPrice
        )

        // Send transaction
        let txHash = try await sdk.evm.sendTransaction(
            transaction: transaction,
            wallet: wallet
        )

        print("Transaction sent!")
        print("Hash: \(txHash)")
    } catch {
        print("Transaction failed: \(error)")
    }
}
```

## Complete Send Transaction Example

```swift theme={"system"}
import SwiftUI
import DynamicSDKSwift
import SwiftBigInt

struct SendTransactionView: View {
    let wallet: BaseWallet

    @State private var recipient = ""
    @State private var amount = ""
    @State private var txHash: String?
    @State private var isLoading = false
    @State private var errorMessage: String?

    private let sdk = DynamicSDK.instance()

    var body: some View {
        VStack(spacing: 16) {
            TextField("Recipient address", text: $recipient)
                .textFieldStyle(.roundedBorder)
                .autocapitalization(.none)

            TextField("Amount (ETH)", text: $amount)
                .textFieldStyle(.roundedBorder)
                .keyboardType(.decimalPad)

            Button("Send Transaction") {
                sendTransaction()
            }
            .disabled(recipient.isEmpty || amount.isEmpty || isLoading)
            .buttonStyle(.borderedProminent)

            if isLoading {
                ProgressView("Sending...")
            }

            if let hash = txHash {
                VStack(alignment: .leading, spacing: 8) {
                    Text("Transaction Sent!")
                        .font(.headline)
                        .foregroundColor(.green)

                    Text("Hash: \(hash)")
                        .font(.system(.caption, design: .monospaced))
                        .lineLimit(2)

                    Button("Copy Hash") {
                        UIPasteboard.general.string = hash
                    }
                    .font(.caption)
                }
                .padding()
                .background(Color.green.opacity(0.1))
                .cornerRadius(8)
            }

            if let error = errorMessage {
                Text(error)
                    .foregroundColor(.red)
                    .font(.caption)
            }
        }
        .padding()
    }

    private func sendTransaction() {
        guard let amountDouble = Double(amount) else {
            errorMessage = "Invalid amount"
            return
        }

        isLoading = true
        errorMessage = nil
        txHash = nil

        Task { @MainActor in
            do {
                // Convert ETH to Wei (1 ETH = 10^18 Wei)
                let weiAmount = BigUInt(amountDouble * pow(10, 18))

                // Get gas price
                let chainId = 84532 // Base Sepolia - adjust as needed
                let client = sdk.evm.createPublicClient(chainId: chainId)
                let gasPrice = try await client.getGasPrice()

                // Create and send transaction
                let transaction = EthereumTransaction(
                    from: wallet.address,
                    to: recipient,
                    value: weiAmount,
                    gas: BigUInt(21000),
                    maxFeePerGas: gasPrice * 2,
                    maxPriorityFeePerGas: gasPrice
                )

                txHash = try await sdk.evm.sendTransaction(
                    transaction: transaction,
                    wallet: wallet
                )
            } catch {
                errorMessage = "Failed: \(error.localizedDescription)"
            }
            isLoading = false
        }
    }
}
```

## Sign Transaction (Without Sending)

To sign a transaction without broadcasting it, use `signEthereumTransaction`:

```swift theme={"system"}
import DynamicSDKSwift

let sdk = DynamicSDK.instance()

func signTransactionOnly(wallet: BaseWallet) async {
    do {
        let signedTx = try await sdk.wallets.signEthereumTransaction(
            wallet: wallet,
            to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bDd7",
            value: "0.001",
            gasLimit: "21000",
            maxPriorityFeePerGas: "2",
            maxFeePerGas: "50"
        )
        print("Signed transaction: \(signedTx)")
    } catch {
        print("Failed to sign: \(error)")
    }
}
```

## Best Practices

### 1. Always Get Current Gas Price

```swift theme={"system"}
let client = sdk.evm.createPublicClient(chainId: chainId)
let gasPrice = try await client.getGasPrice()

// Add buffer for price fluctuations
let maxFeePerGas = gasPrice * 2
```

### 2. Handle Transaction Errors

```swift theme={"system"}
do {
    let txHash = try await sdk.evm.sendTransaction(
        transaction: transaction,
        wallet: wallet
    )
} catch {
    // Common errors:
    // - Insufficient funds
    // - Gas price too low
    // - Invalid recipient address
    // - Network issues

    if error.localizedDescription.contains("insufficient") {
        showError("Insufficient funds for transaction")
    } else {
        showError("Transaction failed: \(error.localizedDescription)")
    }
}
```

### 3. Show Transaction Status

```swift theme={"system"}
struct TransactionStatusView: View {
    let txHash: String
    let chainId: Int

    var explorerUrl: String {
        // Map chain ID to block explorer
        switch chainId {
        case 1: return "https://etherscan.io/tx/\(txHash)"
        case 84532: return "https://sepolia.basescan.org/tx/\(txHash)"
        case 137: return "https://polygonscan.com/tx/\(txHash)"
        default: return ""
        }
    }

    var body: some View {
        VStack {
            Text("Transaction Submitted")
                .font(.headline)

            Text(txHash)
                .font(.caption)
                .lineLimit(1)
                .truncationMode(.middle)

            if !explorerUrl.isEmpty {
                Link("View on Explorer", destination: URL(string: explorerUrl)!)
                    .font(.caption)
            }
        }
    }
}
```

### 4. Confirm Before Sending

```swift theme={"system"}
struct ConfirmTransactionView: View {
    let recipient: String
    let amount: String
    let onConfirm: () -> Void
    let onCancel: () -> Void

    var body: some View {
        VStack(spacing: 16) {
            Text("Confirm Transaction")
                .font(.headline)

            VStack(alignment: .leading) {
                Text("To: \(recipient)")
                Text("Amount: \(amount) ETH")
            }
            .font(.caption)

            HStack {
                Button("Cancel", action: onCancel)
                    .buttonStyle(.bordered)

                Button("Confirm", action: onConfirm)
                    .buttonStyle(.borderedProminent)
            }
        }
        .padding()
    }
}
```

## Error Handling

### Common Transaction Errors

```swift theme={"system"}
do {
    let txHash = try await sdk.evm.sendTransaction(
        transaction: transaction,
        wallet: wallet
    )
} catch {
    let errorMessage: String
    let errorDesc = error.localizedDescription.lowercased()

    if errorDesc.contains("insufficient") {
        errorMessage = "Insufficient balance for this transaction"
    } else if errorDesc.contains("gas") {
        errorMessage = "Gas estimation failed. Try increasing gas limit."
    } else if errorDesc.contains("rejected") || errorDesc.contains("denied") {
        errorMessage = "Transaction was rejected"
    } else if errorDesc.contains("network") {
        errorMessage = "Network error. Please check your connection."
    } else {
        errorMessage = "Transaction failed. Please try again."
    }

    showAlert(errorMessage)
}
```

## Next Steps

* [ERC-20 Token Transfers](/swift/wallets/evm/erc20-transfers) - Send ERC-20 tokens
* [Smart Contract Interactions](/swift/wallets/evm/smart-contracts) - Interact with smart contracts
* [Gas Management](/swift/wallets/evm/gas-management) - Gas estimation and optimization
* [Message Signing](/swift/wallets/evm/message-signing) - Sign messages and typed data
