Skip to main content

Overview

DynamicEvmWalletClient::signTransaction signs an EIP-1559 (Type 2) transaction and returns the signed RLP hex, ready to push directly to any JSON-RPC eth_sendRawTransaction endpoint. If you also want to broadcast in the same call, see sendTransaction. Reach for signTransaction when you need the signed payload out-of-band — co-signing, custom relayers, or batched broadcasts.

Prerequisites

Build the Transaction

EvmTransaction is an immutable builder backed by BigInteger fields, so values up to uint256 round-trip without precision loss:
import java.math.BigInteger;
import xyz.dynamic.waas.evm.EvmTransaction;

EvmTransaction tx = EvmTransaction.builder()
    .chainId(11155111L)                                       // Sepolia
    .nonce(BigInteger.ZERO)
    .maxFeePerGas(new BigInteger("10000000000"))              // 10 gwei
    .maxPriorityFeePerGas(new BigInteger("1000000000"))       // 1 gwei
    .gasLimit(new BigInteger("21000"))
    .to("0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB")
    .value(BigInteger.ZERO)
    .data("0x")
    .build();
EIP-155 replay protection comes from chainId (already included in EIP-1559 envelopes), so you don’t need to apply the legacy v + 2 * chainId + 8 adjustment yourself.

Sign the Transaction

import xyz.dynamic.waas.evm.opts.SignTransactionOpts;

String signedRlpHex = client.signTransaction(SignTransactionOpts.builder()
    .transaction(tx)
    .walletProperties(walletProperties)
    .externalServerKeyShares(externalServerKeyShares)
    .build()
).join();

System.out.println("Signed RLP: " + signedRlpHex);
signedRlpHex is a 0x-prefixed hex string carrying the full signed transaction envelope — pass it directly to eth_sendRawTransaction on any RPC.

Broadcasting Yourself

If you don’t want sendTransaction to manage signing for you — for example the transaction was signed on a client and your server only needs to relay it — broadcast the signed RLP with the static EvmRpc.sendRawTransaction helper. It needs no wallet, MPC, or key shares:
import xyz.dynamic.waas.evm.EvmRpc;

String txHash = EvmRpc.sendRawTransaction(
    signedRlpHex,
    "https://sepolia.infura.io/v3/<your-key>"
).join();
Or, if you’d rather manage the JSON-RPC client yourself, push the signed RLP through web3j directly:
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.protocol.core.methods.response.EthSendTransaction;

Web3j w3 = Web3j.build(new HttpService("https://sepolia.infura.io/v3/<your-key>"));

EthSendTransaction resp = w3.ethSendRawTransaction(signedRlpHex).send();
if (resp.hasError()) {
    throw new RuntimeException("Broadcast failed: " + resp.getError().getMessage());
}
System.out.println("Transaction hash: " + resp.getTransactionHash());

Common Transaction Types

ETH Transfer

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

Contract Interaction

EvmTransaction call = EvmTransaction.builder()
    .chainId(1L)
    .nonce(nonce)
    .maxFeePerGas(maxFee)
    .maxPriorityFeePerGas(maxPriorityFee)
    .gasLimit(new BigInteger("100000"))
    .to("0xContractAddress")
    .value(BigInteger.ZERO)
    .data("0xFunctionSelector...")                   // ABI-encoded call data
    .build();

Next Steps