Skip to main content
import { Transaction } from 'voltaire-effect'
import { Effect } from 'effect'
import * as S from 'effect/Schema'

// Parse from RLP bytes
const tx = S.decodeSync(Transaction.Serialized)(rawBytes)

// Serialize to bytes
const bytes = S.encodeSync(Transaction.Serialized)(tx)

Schemas

Serialized — Bidirectional schema for RLP-encoded transaction bytes. Rpc — Bidirectional schema for JSON-RPC transaction format. Schema — Union schema for all transaction types (validates struct fields). LegacySchema — Type 0 transactions. EIP2930Schema — Type 1 access list transactions. EIP1559Schema — Type 2 dynamic fee transactions. EIP4844Schema — Type 3 blob transactions. EIP7702Schema — Type 4 EOA delegation transactions.
import { Transaction } from 'voltaire-effect'
import * as S from 'effect/Schema'

// Decode from RLP bytes
const tx = S.decodeSync(Transaction.Serialized)(rawBytes)

// Decode from RPC format
const tx2 = S.decodeSync(Transaction.Rpc)({
  type: '0x2',
  chainId: '0x1',
  nonce: '0x0',
  // ...
})

// Validate specific transaction type
const eip1559Tx = S.decodeSync(Transaction.EIP1559Schema)({
  type: Transaction.Type.EIP1559,
  chainId: 1n,
  nonce: 0n,
  maxPriorityFeePerGas: 1000000000n,
  maxFeePerGas: 100000000000n,
  gasLimit: 21000n,
  to: '0x1234567890123456789012345678901234567890',
  value: 0n,
  data: new Uint8Array(),
  accessList: [],
  yParity: 0,
  r: new Uint8Array(32),
  s: new Uint8Array(32),
})

Pure Functions

hash(tx) — Computes Keccak-256 hash of serialized transaction. Returns HashType. getSigningHash(tx) — Computes hash for signing (pre-signature). Returns HashType. getSender(tx) — Recovers sender address from signature. Returns AddressType. getRecipient(tx) — Gets recipient address. Returns AddressType | null. getChainId(tx) — Gets chain ID. Returns bigint | null. getGasPrice(tx, baseFee?) — Gets effective gas price. Returns bigint. getNonce(tx) — Gets nonce. Returns bigint. getGasLimit(tx) — Gets gas limit. Returns bigint. getValue(tx) — Gets value in wei. Returns bigint. getData(tx) — Gets input data. Returns Uint8Array. getAccessList(tx) — Gets access list (empty for legacy). Returns AccessList. getBlobCount(tx) — Gets blob count (EIP-4844 only). Returns number. getBlobVersionedHashes(tx) — Gets blob hashes (EIP-4844 only). Returns VersionedHash[]. getAuthorizationCount(tx) — Gets authorization count (EIP-7702 only). Returns number. getAuthorizations(tx) — Gets authorization list (EIP-7702 only). Returns AuthorizationList.

Predicates

isSigned(tx) — Checks if transaction has valid signature. Returns boolean. isContractCreation(tx) — Checks if to is null. Returns boolean. isContractCall(tx) — Checks if to is set and data is non-empty. Returns boolean. hasAccessList(tx) — Checks if transaction has access list. Returns boolean. detectType(bytes) — Detects transaction type from serialized data. Returns Type.

Type Guards

isLegacy(tx) — Type guard for Legacy transactions. Returns tx is Legacy. isEIP2930(tx) — Type guard for EIP-2930 transactions. Returns tx is EIP2930. isEIP1559(tx) — Type guard for EIP-1559 transactions. Returns tx is EIP1559. isEIP4844(tx) — Type guard for EIP-4844 transactions. Returns tx is EIP4844. isEIP7702(tx) — Type guard for EIP-7702 transactions. Returns tx is EIP7702.
if (Transaction.isEIP1559(tx)) {
  console.log(tx.maxFeePerGas) // TypeScript knows this exists
}

Mutation Functions

withNonce(tx, nonce) — Returns new transaction with updated nonce. withGasLimit(tx, gasLimit) — Returns new transaction with updated gas limit. withGasPrice(tx, gasPrice) — Returns new transaction with updated gas price. withData(tx, data) — Returns new transaction with updated data. replaceWith(tx, options?) — Returns new transaction with fee bump for replacement. format(tx) — Returns human-readable string representation.
const bumped = Transaction.replaceWith(tx, { feeBumpPercent: 10n })
const updated = Transaction.withNonce(tx, 42n)

Effect Functions (Validation)

assertSigned(tx)Effect<void, UnsignedTransactionError> verifySignature(tx)Effect<boolean, InvalidSignatureError> validateChainId(tx)Effect<void, InvalidChainIdError> validateGasLimit(tx)Effect<void, InvalidGasLimitError> validateGasPrice(tx)Effect<void, InvalidGasPriceError> validateNonce(tx)Effect<void, InvalidNonceError> validateValue(tx)Effect<void, InvalidValueError>
import { Transaction } from 'voltaire-effect'
import { Effect, pipe } from 'effect'

const validated = pipe(
  Effect.all({
    signed: Transaction.assertSigned(tx),
    gasLimit: Transaction.validateGasLimit(tx),
    nonce: Transaction.validateNonce(tx),
  }),
  Effect.map(() => tx)
)

Types

type Tx = Transaction.Any
type Legacy = Transaction.Legacy
type EIP1559 = Transaction.EIP1559
type EIP2930 = Transaction.EIP2930
type EIP4844 = Transaction.EIP4844
type EIP7702 = Transaction.EIP7702
type AccessList = Transaction.AccessList
type AuthorizationList = Transaction.AuthorizationList

Error Classes

  • UnsignedTransactionError — Transaction is not signed
  • InvalidSignatureError — Signature verification failed
  • InvalidChainIdError — Chain ID validation failed
  • InvalidGasLimitError — Gas limit validation failed
  • InvalidGasPriceError — Gas price validation failed
  • InvalidNonceError — Nonce validation failed
  • InvalidValueError — Value validation failed

See Also