External Signers & Raw Tx

toRawTx() to hand a built transaction to an external signer or existing RPC client — a synchronous ethers/viem/web3.js request (EvmRawTx) on EVM, or the underlying @solana/web3.js Transaction on Solana.

toRawTx() is the lowest-level handoff: it hands a transaction you built with wative-core to your own signer or RPC client, so you can slot it into an existing ethers / viem / @solana/web3.js stack. Neither form signs or broadcasts.

EVM — EvmTransaction.toRawTx()

Synchronous. Returns a plain EvmRawTx (the TransactionRequest shape every major EVM client consumes). It returns whatever fields are currently set; fields not yet resolved (nonce, gasLimit, the gas-price family) are simply omitted, leaving your consumer to auto-fill them from its own provider. It does not mutate, sign, or hit the network.

evm-handoff.ts
const evm = acc.wallets[0].evm;
const tx = await evm.buildTransaction({
  to: "0x1234567890123456789012345678901234567890",
  value: 1_000_000_000_000_000n,
  chainId: 1,
});

const raw = tx.toRawTx(); // synchronous — EvmRawTx

// Hand it to ethers, viem, web3.js, or raw JSON-RPC:
const response = await ethersWallet.sendTransaction(raw);

EvmRawTx

FieldTypeAlways present?
fromstringyes
tostringyes
valuebigintyes
datastringyes
typeEvmTxTypeyes
chainIdChainIdyes
noncenumberonly if set
gasPricebigintonly if set
maxFeePerGasbigintonly if set
maxPriorityFeePerGasbigintonly if set
rpcUrlstringonly if set
gasLimitbigintonly if set
accessListReadonlyArray<{ address: string; storageKeys: ReadonlyArray<string> }>only if set

Solana — SvmTransaction.toRawTx()

Asynchronous. Returns the underlying @solana/web3.js Transaction, fully populated with its instructions, fee payer, and recentBlockhash. You can sign it with your own Keypair, append instructions, or route it through your own RPC. It does not sign or broadcast.

svm-handoff.ts
const svm = acc.wallets[0].svm;
const tx = svm.buildTransaction({ recipient, amount: 5000n });

const built = await tx.toRawTx(); // @solana/web3.js Transaction

// Sign and send it with your own stack:
built.partialSign(myKeypair);
const sig = await connection.sendRawTransaction(built.serialize());

Because Solana's toRawTx() builds the transaction, calling it also seals the SvmTransaction's fields — they can no longer be reassigned afterwards (build a new transaction to change one). The object it returns is the live built transaction, handed back by reference.

External fee payer

SvmTransaction.sign() can only produce the from account's signature and refuses a distinct feePayer. For a sponsored / relayer flow, take the raw transaction and have the external fee payer sign it there:

external-fee-payer.ts
const tx = new SvmTransaction({
  from: senderPubkey,
  recipient,
  amount: 5000n,
  feePayer: relayerPubkey,   // distinct from `from`
  recentBlockhash,
});

const built = await tx.toRawTx(); // sign() would refuse this feePayer; toRawTx does not
built.partialSign(relayerKeypair); // fee payer signs externally
built.partialSign(senderKeypair);

Offline Solana handoff with recentBlockhash

Solana's toRawTx() needs a recentBlockhash at build time. Supply one in the constructor and it can produce the @solana/web3.js Transaction with no bound address and no RPC call — the whole point of a raw-tx handoff. Without a supplied blockhash, it needs a bound address so it can fetch one over RPC.

offline-handoff.ts
import { SvmTransaction } from "wative-core";

const tx = new SvmTransaction({
  from: "SenderPubkey…",
  recipient: "RecipientPubkey…",
  amount: 5000n,
  recentBlockhash: "9xQe…recentBlockhash", // makes the build fully offline
});

const built = await tx.toRawTx(); // no Address, no network

Last updated on