Quick Start
Copy
Ask AI
import { Effect } from 'effect'
import { AbiEncoderService, DefaultAbiEncoder } from 'voltaire-effect'
const abi = [
{ type: 'function', name: 'balanceOf', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] }
] as const
const program = Effect.gen(function* () {
const encoder = yield* AbiEncoderService
const calldata = yield* encoder.encodeFunction(abi, 'balanceOf', ['0x1234567890123456789012345678901234567890'])
return calldata
}).pipe(Effect.provide(DefaultAbiEncoder))
Function Encoding
Encode function calls to calldata:Copy
Ask AI
const encoder = yield* AbiEncoderService
const transferAbi = [
{
type: 'function',
name: 'transfer',
inputs: [{ name: 'to', type: 'address' }, { name: 'amount', type: 'uint256' }],
outputs: [{ type: 'bool' }]
}
] as const
const calldata = yield* encoder.encodeFunction(
transferAbi,
'transfer',
['0x1234567890123456789012345678901234567890', 1000000000000000000n]
)
// Returns: 0xa9059cbb000000000000000000000000...
Function Decoding
Decode function return data:Copy
Ask AI
const encoder = yield* AbiEncoderService
const result = yield* encoder.decodeFunction(
erc20Abi,
'balanceOf',
'0x0000000000000000000000000000000000000000000000000de0b6b3a7640000'
)
// Returns: [1000000000000000000n]
Event Topic Encoding
Encode event signatures for log filtering:Copy
Ask AI
const encoder = yield* AbiEncoderService
const erc20Abi = [
{
type: 'event',
name: 'Transfer',
inputs: [
{ name: 'from', type: 'address', indexed: true },
{ name: 'to', type: 'address', indexed: true },
{ name: 'value', type: 'uint256' }
]
}
] as const
// Get event signature topic
const topics = yield* encoder.encodeEventTopics(erc20Abi, 'Transfer')
// Returns: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef']
// Filter by indexed parameters
const filteredTopics = yield* encoder.encodeEventTopics(
erc20Abi,
'Transfer',
['0x1234567890123456789012345678901234567890'] // from address
)
Event Log Decoding
Decode event logs into structured data:Copy
Ask AI
const encoder = yield* AbiEncoderService
const decoded = yield* encoder.decodeEventLog(
erc20Abi,
'Transfer',
logData, // non-indexed parameters
logTopics // event signature + indexed parameters
)
// Returns: { from: '0x...', to: '0x...', value: 1000000000000000000n }
Error Handling
Copy
Ask AI
import { AbiEncodeError, AbiDecodeError } from 'voltaire-effect'
const program = Effect.gen(function* () {
const encoder = yield* AbiEncoderService
return yield* encoder.encodeFunction(abi, 'transfer', [recipient, amount])
}).pipe(
Effect.catchTag('AbiEncodeError', (e) => {
console.error(`Encoding ${e.functionName} failed: ${e.message}`)
return Effect.fail(e)
}),
Effect.catchTag('AbiDecodeError', (e) => {
console.error(`Decoding failed for ${e.data}: ${e.message}`)
return Effect.fail(e)
})
)
Service Interface
Copy
Ask AI
type AbiEncoderShape = {
readonly encodeFunction: (
abi: readonly unknown[],
functionName: string,
args: readonly unknown[]
) => Effect.Effect<`0x${string}`, AbiEncodeError>
readonly decodeFunction: (
abi: readonly unknown[],
functionName: string,
data: `0x${string}`
) => Effect.Effect<readonly unknown[], AbiDecodeError>
readonly encodeEventTopics: (
abi: readonly unknown[],
eventName: string,
args?: readonly unknown[]
) => Effect.Effect<readonly `0x${string}`[], AbiEncodeError>
readonly decodeEventLog: (
abi: readonly unknown[],
eventName: string,
data: `0x${string}`,
topics: readonly `0x${string}`[]
) => Effect.Effect<Record<string, unknown>, AbiDecodeError>
}
Error Types
Copy
Ask AI
class AbiEncodeError extends Data.TaggedError("AbiEncodeError")<{
readonly functionName: string
readonly args: readonly unknown[]
readonly message: string
readonly cause?: unknown
}> {}
class AbiDecodeError extends Data.TaggedError("AbiDecodeError")<{
readonly data: `0x${string}`
readonly message: string
readonly cause?: unknown
}> {}

