Quick Start
Copy
Ask AI
import { Effect, Layer } from 'effect'
import {
FeeEstimatorService,
DefaultFeeEstimator,
Provider,
HttpTransport
} from 'voltaire-effect'
// Compose layers first
const ProviderLayer = Provider.pipe(Layer.provide(HttpTransport('https://eth.llamarpc.com')))
const FeeEstimatorLayer = DefaultFeeEstimator.pipe(Layer.provide(ProviderLayer))
const program = Effect.gen(function* () {
const feeEstimator = yield* FeeEstimatorService
const fees = yield* feeEstimator.estimateFeesPerGas('eip1559')
return fees
}).pipe(Effect.provide(FeeEstimatorLayer))
EIP-1559 Fee Estimation
Copy
Ask AI
const feeEstimator = yield* FeeEstimatorService
const fees = yield* feeEstimator.estimateFeesPerGas('eip1559')
// { maxFeePerGas: bigint, maxPriorityFeePerGas: bigint }
console.log('Max fee:', fees.maxFeePerGas)
console.log('Priority fee:', fees.maxPriorityFeePerGas)
Legacy Gas Price
Copy
Ask AI
const fees = yield* feeEstimator.estimateFeesPerGas('legacy')
// { gasPrice: bigint }
console.log('Gas price:', fees.gasPrice)
Priority Fee Only
Copy
Ask AI
const priorityFee = yield* feeEstimator.getMaxPriorityFeePerGas()
// bigint - the current max priority fee (tip)
Custom Base Fee Multiplier
The default multiplier is 1.2 (20% buffer). UsemakeFeeEstimator for volatile networks:
Copy
Ask AI
import { makeFeeEstimator } from 'voltaire-effect'
// 1.5x multiplier for more volatile networks
const CustomFeeEstimator = makeFeeEstimator(1.5)
// Compose layers first
const ProviderLayer = Provider.pipe(Layer.provide(HttpTransport('https://...')))
const CustomFeeEstimatorLayer = CustomFeeEstimator.pipe(Layer.provide(ProviderLayer))
const program = Effect.gen(function* () {
const feeEstimator = yield* FeeEstimatorService
console.log('Multiplier:', feeEstimator.baseFeeMultiplier) // 1.5
return yield* feeEstimator.estimateFeesPerGas('eip1559')
}).pipe(Effect.provide(CustomFeeEstimatorLayer))
Error Handling
Copy
Ask AI
import { FeeEstimationError } from 'voltaire-effect'
program.pipe(
Effect.catchTag('FeeEstimationError', (e) => {
console.error('Fee estimation failed:', e.message)
// Fallback to zero fees
return Effect.succeed({ maxFeePerGas: 0n, maxPriorityFeePerGas: 0n })
})
)
- Network/RPC failures
- Pre-EIP-1559 chains (no
baseFeePerGasin block)
FiberRef Helpers
UsewithTimeout and withRetrySchedule for per-request overrides:
Copy
Ask AI
import { Effect, Schedule, Duration } from 'effect'
import { FeeEstimatorService, withTimeout, withRetrySchedule } from 'voltaire-effect'
const program = Effect.gen(function* () {
const feeEstimator = yield* FeeEstimatorService
// Fast timeout for fee estimation
const fees = yield* feeEstimator.estimateFeesPerGas('eip1559').pipe(
withTimeout("2 seconds"),
withRetrySchedule(Schedule.recurs(2))
)
return fees
})
Layer Composition
DefaultFeeEstimator requires ProviderService:
Copy
Ask AI
import * as Layer from 'effect/Layer'
// FeeEstimator depends on Provider
const DefaultFeeEstimator: Layer.Layer<FeeEstimatorService, never, ProviderService>
// Compose full stack
const ProviderLayer = Provider.pipe(Layer.provide(HttpTransport('https://eth.llamarpc.com')))
const FullStack = DefaultFeeEstimator.pipe(Layer.provide(ProviderLayer))
const program = myEffect.pipe(Effect.provide(FullStack))
Fee Value Types
Copy
Ask AI
type FeeValuesLegacy = {
readonly gasPrice: bigint
}
type FeeValuesEIP1559 = {
readonly maxFeePerGas: bigint
readonly maxPriorityFeePerGas: bigint
}
type FeeValues = FeeValuesLegacy | FeeValuesEIP1559
Service Interface
Copy
Ask AI
type FeeEstimatorShape = {
readonly estimateFeesPerGas: (
type: 'legacy' | 'eip1559'
) => Effect.Effect<FeeValues, FeeEstimationError, ProviderService>
readonly getMaxPriorityFeePerGas: () => Effect.Effect<
bigint,
FeeEstimationError,
ProviderService
>
readonly baseFeeMultiplier: number
}

