Transactions Overview

The build → sign → simulate → send → track flow shared by EVM and Solana, driven from an Address with buildTransaction(), signTransaction(), simulateTransaction() and sendTransaction().

Every value transfer and contract call in wative-core moves through one lifecycle: build → sign → simulate → send → track. The same four verbs work on EVM and Solana — you drive them from an Address (or its per-chain wallet.evm / wallet.svm view), which owns the key and the Network. The shapes differ per chain, but the steps and the method names do not.

The lifecycle

Buildaddress.buildTransaction(params) returns a concrete EvmTransaction or SvmTransaction. This is a structural, offline step: no network call is made.

Signaddress.signTransaction(tx) (or await tx.sign()) produces the signed bytes. Signing is local ECDSA/ed25519; it touches the network only to auto-fill fields you left out (EVM nonce/gas/fees, Solana recentBlockhash).

Simulate (optional)address.simulateTransaction(tx) pre-flights the transaction (eth_call + gas estimate on EVM, simulateTransaction on Solana) and resolves a SimulationResult. It never broadcasts.

Sendaddress.sendTransaction(tx) broadcasts and returns a TransactionTracker synchronously. It signs first if the transaction is not yet signed.

Track — await the tracker's lifecycle promises (whenSubmitted(), whenMined(), whenConfirmed()) or subscribe to its change / confirmed / failed events.

send-flow.ts
import { Workspace } from "wative-core";

const ws = await Workspace.open({ path, password: "wsp-pwd" });
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
const evm = acc.wallets[0].evm; // an EvmSigner (an Address view)

// 1 — build (offline; nonce/gas fill in at sign time)
const tx = await evm.buildTransaction({
  to: "0x1234567890123456789012345678901234567890",
  value: 1_000_000_000_000_000n,
  chainId: 1,
});

// 2 — simulate (optional pre-flight, RPC)
const sim = await evm.simulateTransaction(tx);
if (!sim.success) throw new Error(sim.error);

// 3 — send + track (RPC)
const tracker = evm.sendTransaction(tx);
const hash = await tracker.whenSubmitted();
const receipt = await tracker.whenConfirmed();

Installation, if you have not added the package yet:

pnpm add wative-core
npm install wative-core

Offline vs RPC steps

Building is always offline. Only signing, simulating, sending, and tracking reach the network — and even signing is fully offline when you supply every field yourself.

StepMethodReaches the network?
BuildbuildTransaction()No — structural only
SignsignTransaction() / tx.sign()Only to auto-fill omitted fields (EVM nonce/gas/fees, SVM recentBlockhash); fully offline if you supply them
SimulatesimulateTransaction()Yes
SendsendTransaction()Yes
TrackTransactionTracker promises/eventsYes (polls the node)

The Transaction type

Transaction is the polymorphic interface both chains implement. EvmTransaction and SvmTransaction are the concrete classes — you can think of a built transaction as EvmTransaction | SvmTransaction.

The interface declares only the members that are identical across chains:

MemberTypeNotes
vmVmToken"evm" or "svm" — discriminates the union
statusTransactionStatus"draft" → … → "confirmed" / "failed" (see Tracking & Lifecycle)
sign()Promise<this> | thisIdempotent; caches the signed bytes
send()TransactionTrackerSigns first if needed
simulate()Promise<SimulationResult>Pre-flight only

Per-chain members such as toRawTx(), hash, and from live on the concrete classes and are intentionally not on the interface — hold the concrete EvmTransaction / SvmTransaction type (which buildTransaction() returns) to reach them. See External Signers & Raw Tx.

Driving it from an Address

The four *Transaction helpers on an Address are thin, ownership-checked delegates — each throws PARAMETER_ERROR if tx.from does not match the address's own public key.

MethodReturnsDelegates to
buildTransaction(params)EvmTransaction / SvmTransactionthe chain dialect
signTransaction(tx)the same tx (generic)tx.sign()
simulateTransaction(tx)Promise<SimulationResult>tx.simulate()
sendTransaction(tx)TransactionTrackertx.send()

Per-chain and topic pages

Last updated on