.claude/skills/voltaire-effect-schemas/SKILL.md
This skill should be used when the user asks about "voltaire branded types", "Effect Schema Ethereum", "Address schema", "Hash schema", "Uint8Array branded", "S.decode address", "ParseError", "voltaire primitives", "type safety Ethereum", or needs to understand how voltaire-effect handles type-safe Ethereum data.
npx skillsauth add cyotee/crane Voltaire Effect Schemas & Branded TypesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
voltaire-effect provides 150+ Effect Schema wrappers that decode raw input into Voltaire's branded Uint8Array types. This gives compile-time type safety (Address vs Hash are distinct types) with zero runtime overhead, validated once at the boundary.
Branded types add a nominal tag to Uint8Array, preventing type confusion at compile time:
type AddressType = Uint8Array & { readonly __tag: "Address" }
type HashType = Uint8Array & { readonly __tag: "Hash" }
// TypeScript prevents mixing:
function transfer(to: AddressType, txHash: HashType) { ... }
transfer(myHash, myAddress) // ← Compile error! Types don't match
At runtime both are plain Uint8Array - brands exist only in the type system.
import * as Address from 'voltaire-effect/primitives/Address'
import * as Hash from 'voltaire-effect/primitives/Hash'
import * as S from 'effect/Schema'
// Synchronous (throws on failure)
const addr = S.decodeSync(Address.Hex)('0x742d35Cc6634C0532925a3b844Bc9e7595f251e3')
// Returns: AddressType (branded Uint8Array)
// Effectful (typed ParseError)
const addrEffect = S.decode(Address.Hex)(input)
// Type: Effect<AddressType, ParseError, never>
// Either for branching
const addrEither = S.decodeEither(Address.Hex)(input)
// Type: Either<AddressType, ParseError>
Encoding to checksummed hex requires the Keccak service:
import { KeccakLive } from 'voltaire-effect/crypto/Keccak256'
const checksummed = await Effect.runPromise(
S.encode(Address.Checksummed)(addr).pipe(Effect.provide(KeccakLive))
)
// "0x742d35Cc6634C0532925a3b844Bc9e7595f251e3"
const parseAddress = (input: string) =>
S.decode(Address.Hex)(input).pipe(
Effect.catchTag('ParseError', () =>
Effect.succeed(Address.zero())
)
)
ParseError contains a structured issue tree describing exactly what went wrong - field path, expected type, received value.
| Schema | Input | Output | Size |
|--------|-------|--------|------|
| Address.Hex | 0x${string} (40 hex chars) | AddressType | 20 bytes |
| Hash.Hex | 0x${string} (64 hex chars) | HashType | 32 bytes |
| Signature.Hex | 0x${string} (130 hex chars) | SignatureType | 65 bytes |
| Address.Checksummed | EIP-55 checksummed | AddressType | 20 bytes |
Integer schemas cover the full Solidity range:
| Schema | Range |
|--------|-------|
| Uint8 - Uint256 | 0 to 2^N - 1 |
| Int8 - Int256 | -2^(N-1) to 2^(N-1) - 1 |
Schemas for complex Ethereum structures:
Transaction - Full transaction object with EIP-1559/4844/7702 supportBlock - Block header and bodyLog - Event log entriesTransactionReceipt - Execution receiptDecode once at the boundary; downstream operations skip re-validation:
Raw input ("0xabc...")
│
▼ S.decode(Address.Hex)
AddressType (branded, validated)
│
├──▶ getBalance(addr) ← no re-validation
├──▶ Contract.read(addr) ← no re-validation
└──▶ Address.toHex(addr) ← no re-validation
Decoded branded values work directly with both Voltaire and Effect functions:
// Works with Voltaire's native functions
import { keccak256 } from '@tevm/voltaire'
const hash = keccak256(addr) // Accepts Uint8Array
// Works with Effect Schema encoding
const hex = S.encodeSync(Address.Hex)(addr) // "0x742d..."
development
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
documentation
Write to contracts and send transactions. Use when executing state-changing contract functions.
development
HTTP and WebSocket transports for blockchain connectivity. Use when configuring network connections.
data-ai
Read contract data with type-safe ABI. Use when querying smart contract view/pure functions.