> ## 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 EVM Transactions

> Sign and broadcast EIP-1559 EVM transactions in a single call with Dynamic's Java SDK

## Overview

`DynamicEvmWalletClient::sendTransaction` signs an EIP-1559 transaction with the MPC ceremony **and** broadcasts the result via JSON-RPC in one call. Returns the transaction hash as a `0x`-prefixed hex string.

`sendTransaction` is the recommended path for most apps. Reach for [`signTransaction`](/java/evm/sign-transaction) only if you need the signed RLP out-of-band — co-signing, custom relayers, or assembling the raw tx yourself.

## Prerequisites

* [Created an EVM wallet](/java/evm/create-wallet)
* A JSON-RPC endpoint for the target chain

## Sign + Broadcast in One Call

```java theme={"system"}
import java.math.BigInteger;
import xyz.dynamic.waas.evm.EvmTransaction;
import xyz.dynamic.waas.evm.opts.SendTransactionOpts;

EvmTransaction tx = EvmTransaction.builder()
    .chainId(11155111L)                                  // Sepolia
    .nonce(BigInteger.ZERO)
    .maxFeePerGas(new BigInteger("10000000000"))
    .maxPriorityFeePerGas(new BigInteger("1000000000"))
    .gasLimit(new BigInteger("21000"))
    .to("0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB")
    .value(BigInteger.ZERO)
    .data("0x")
    .build();

String txHash = client.sendTransaction(SendTransactionOpts.builder()
    .transaction(tx)
    .walletProperties(walletProperties)
    .externalServerKeyShares(externalServerKeyShares)
    .rpcUrl("https://sepolia.infura.io/v3/<your-key>")
    .build()
).join();

System.out.println("Submitted tx: " + txHash);
System.out.println("Explorer: https://sepolia.etherscan.io/tx/" + txHash);
```

A fresh JSON-RPC client is constructed per call. For high-throughput scenarios, compose [`signTransaction`](/java/evm/sign-transaction) with your own pooled `Web3j` instance instead.

## Broadcast a Pre-Signed Transaction

When the transaction is signed **elsewhere** — for example on a client via the embedded wallet — and the server only needs to relay it, use the static `EvmRpc.sendRawTransaction`. It broadcasts an already-signed transaction via `eth_sendRawTransaction` with **no wallet, MPC ceremony, or key shares** required — just the serialized signed transaction and an RPC URL:

```java theme={"system"}
import xyz.dynamic.waas.evm.EvmRpc;

// `signedRlpHex` is the 0x-prefixed signed transaction produced by the signer —
// e.g. the client's embedded wallet, or signTransaction (see below).
String txHash = EvmRpc.sendRawTransaction(
    signedRlpHex,
    "https://sepolia.infura.io/v3/<your-key>"
).join();

System.out.println("Submitted tx: " + txHash);
```

This is the building block `sendTransaction` uses internally after signing. It's the right fit for a **sign-on-client / broadcast-on-server** split: the client signs with its embedded wallet and your backend only relays the signed payload to the network.

## Building the Nonce

Fetch the current pending nonce from your RPC before each send — concurrent `sendTransaction` calls against the same wallet without nonce coordination will conflict:

```java theme={"system"}
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.protocol.core.DefaultBlockParameterName;

Web3j w3 = Web3j.build(new HttpService("https://sepolia.infura.io/v3/<your-key>"));
BigInteger nonce = w3
    .ethGetTransactionCount(walletProperties.accountAddress(), DefaultBlockParameterName.PENDING)
    .send()
    .getTransactionCount();
```

## Gas Estimation

EIP-1559 fees vary block to block — query the latest base fee + tip estimate, then bake them into the transaction:

```java theme={"system"}
BigInteger baseFee  = w3.ethGetBlockByNumber(DefaultBlockParameterName.PENDING, false)
    .send().getBlock().getBaseFeePerGas();
BigInteger tip      = new BigInteger("1000000000");        // 1 gwei
BigInteger maxFee   = baseFee.multiply(BigInteger.TWO).add(tip);
```

## Common Transaction Types

### ETH Transfer

```java theme={"system"}
EvmTransaction transfer = EvmTransaction.builder()
    .chainId(1L)
    .nonce(nonce)
    .maxFeePerGas(maxFee)
    .maxPriorityFeePerGas(tip)
    .gasLimit(new BigInteger("21000"))
    .to("0xRecipientAddress")
    .value(new BigInteger("100000000000000000"))           // 0.1 ETH in wei
    .data("0x")
    .build();
```

### Contract Interaction

```java theme={"system"}
EvmTransaction call = EvmTransaction.builder()
    .chainId(1L)
    .nonce(nonce)
    .maxFeePerGas(maxFee)
    .maxPriorityFeePerGas(tip)
    .gasLimit(new BigInteger("100000"))
    .to("0xContractAddress")
    .value(BigInteger.ZERO)
    .data("0xFunctionSelector...")
    .build();
```

## Error Handling

```java theme={"system"}
import java.util.concurrent.CompletionException;
import xyz.dynamic.waas.core.exceptions.DynamicSdkException;

try {
    String txHash = client.sendTransaction(opts).join();
    log.info("Submitted: {}", txHash);
} catch (CompletionException ce) {
    if (ce.getCause() instanceof DynamicSdkException dse) {
        log.error("Send failed: {}", dse.getMessage(), dse);
    } else {
        throw ce;
    }
}
```

`sendTransaction` returns the JSON-RPC error verbatim when the broadcast itself fails (e.g. `nonce too low`, `replacement transaction underpriced`) — match on the error message or retry with a refreshed nonce.

## Next Steps

* [Sign transactions](/java/evm/sign-transaction) — get the signed RLP without broadcasting
* [Sign messages](/java/evm/sign-messages)
* [Sign typed data (EIP-712)](/java/evm/sign-typed-data)
* [Delegated access](/java/evm/delegated-access)
