Quick Start
Copy
Ask AI
import { Effect } from 'effect'
import { TransactionSerializerService, DefaultTransactionSerializer } from 'voltaire-effect'
const program = Effect.gen(function* () {
const serializer = yield* TransactionSerializerService
const bytes = yield* serializer.serialize(tx)
const decoded = yield* serializer.deserialize(bytes)
return { bytes, decoded }
}).pipe(Effect.provide(DefaultTransactionSerializer.Live))
Serialize
Serialize a transaction to RLP-encoded bytes:Copy
Ask AI
import * as S from 'effect/Schema'
import * as Transaction from 'voltaire-effect/primitives/Transaction'
const serializer = yield* TransactionSerializerService
const tx = S.decodeSync(Transaction.EIP1559Schema)({
type: Transaction.Type.EIP1559,
chainId: 1n,
nonce: 0n,
maxPriorityFeePerGas: 1000000000n,
maxFeePerGas: 20000000000n,
gasLimit: 21000n,
to: '0x1234567890123456789012345678901234567890',
value: 1000000000000000000n,
data: new Uint8Array(),
accessList: [],
yParity: 0,
r: new Uint8Array(32),
s: new Uint8Array(32)
})
const bytes = yield* serializer.serialize(tx)
// Returns: Uint8Array of RLP-encoded transaction
Deserialize
Deserialize RLP-encoded bytes back to a transaction:Copy
Ask AI
const serializer = yield* TransactionSerializerService
const tx = yield* serializer.deserialize(rlpBytes)
// Returns the decoded transaction object
Get Signing Payload
Get the hash that should be signed for a transaction:Copy
Ask AI
const serializer = yield* TransactionSerializerService
const signingHash = yield* serializer.getSigningPayload(tx)
// Returns: Uint8Array (32 bytes) - Keccak-256 hash of unsigned tx
Transaction Types
The serializer supports all Ethereum transaction types:Legacy (Type 0)
Copy
Ask AI
import * as S from 'effect/Schema'
import * as Transaction from 'voltaire-effect/primitives/Transaction'
const legacyTx = S.decodeSync(Transaction.LegacySchema)({
type: Transaction.Type.Legacy,
nonce: 0n,
gasPrice: 20000000000n,
gasLimit: 21000n,
to: '0x...',
value: 0n,
data: new Uint8Array(),
v: 27n,
r: new Uint8Array(32),
s: new Uint8Array(32)
})
EIP-2930 Access List (Type 1)
Copy
Ask AI
import * as S from 'effect/Schema'
import * as Transaction from 'voltaire-effect/primitives/Transaction'
const eip2930Tx = S.decodeSync(Transaction.EIP2930Schema)({
type: Transaction.Type.EIP2930,
chainId: 1n,
nonce: 0n,
gasPrice: 20000000000n,
gasLimit: 21000n,
to: '0x...',
value: 0n,
data: new Uint8Array(),
accessList: [
{ address: '0x...', storageKeys: [] }
],
yParity: 0,
r: new Uint8Array(32),
s: new Uint8Array(32)
})
EIP-1559 Fee Market (Type 2)
Copy
Ask AI
import * as S from 'effect/Schema'
import * as Transaction from 'voltaire-effect/primitives/Transaction'
const eip1559Tx = S.decodeSync(Transaction.EIP1559Schema)({
type: Transaction.Type.EIP1559,
chainId: 1n,
nonce: 0n,
maxPriorityFeePerGas: 1000000000n,
maxFeePerGas: 20000000000n,
gasLimit: 21000n,
to: '0x...',
value: 0n,
data: new Uint8Array(),
accessList: [],
yParity: 0,
r: new Uint8Array(32),
s: new Uint8Array(32)
})
EIP-4844 Blob (Type 3)
Copy
Ask AI
import * as S from 'effect/Schema'
import * as Transaction from 'voltaire-effect/primitives/Transaction'
const eip4844Tx = S.decodeSync(Transaction.EIP4844Schema)({
type: Transaction.Type.EIP4844,
chainId: 1n,
nonce: 0n,
maxPriorityFeePerGas: 1000000000n,
maxFeePerGas: 20000000000n,
maxFeePerBlobGas: 1000000000n,
gasLimit: 21000n,
to: '0x...',
value: 0n,
data: new Uint8Array(),
accessList: [],
blobVersionedHashes: [new Uint8Array(32)],
yParity: 0,
r: new Uint8Array(32),
s: new Uint8Array(32)
})
EIP-7702 Set Code (Type 4)
Copy
Ask AI
import * as S from 'effect/Schema'
import * as Transaction from 'voltaire-effect/primitives/Transaction'
const eip7702Tx = S.decodeSync(Transaction.EIP7702Schema)({
type: Transaction.Type.EIP7702,
chainId: 1n,
nonce: 0n,
maxPriorityFeePerGas: 1000000000n,
maxFeePerGas: 20000000000n,
gasLimit: 21000n,
to: '0x...',
value: 0n,
data: new Uint8Array(),
accessList: [],
authorizationList: [
{ chainId: 1n, address: '0x...', nonce: 0n, yParity: 0, r: new Uint8Array(32), s: new Uint8Array(32) }
],
yParity: 0,
r: new Uint8Array(32),
s: new Uint8Array(32)
})
Error Handling
Copy
Ask AI
import { SerializeError, DeserializeError } from 'voltaire-effect'
const program = Effect.gen(function* () {
const serializer = yield* TransactionSerializerService
return yield* serializer.serialize(tx)
}).pipe(
Effect.catchTag('SerializeError', (e) => {
console.error(`Serialize failed: ${e.message}`)
return Effect.fail(e)
}),
Effect.catchTag('DeserializeError', (e) => {
console.error(`Deserialize failed: ${e.message}`)
return Effect.fail(e)
})
)
Service Interface
Copy
Ask AI
type TransactionSerializerShape = {
readonly serialize: (tx: unknown) => Effect.Effect<Uint8Array, SerializeError>
readonly deserialize: (bytes: Uint8Array) => Effect.Effect<unknown, DeserializeError>
readonly getSigningPayload: (tx: unknown) => Effect.Effect<Uint8Array, SerializeError>
}
Error Types
Copy
Ask AI
class SerializeError extends Data.TaggedError("SerializeError")<{
readonly transaction: unknown
readonly message: string
readonly cause?: unknown
}> {}
class DeserializeError extends Data.TaggedError("DeserializeError")<{
readonly bytes: Uint8Array
readonly message: string
readonly cause?: unknown
}> {}

