Quick Start
Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
import { Effect } from 'effect'
// Create type-safe requests
const request = JsonRpc.Request.from({
method: 'eth_blockNumber',
params: [],
id: 1
})
// Parse responses with proper error handling
const program = Effect.gen(function* () {
const response = yield* JsonRpc.Response.parse(rawResponse)
const result = yield* JsonRpc.Response.unwrap(response)
return result
})
Request Types
JsonRpcRequest
Create and manipulate JSON-RPC 2.0 requests.Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
// Create a request
const req = JsonRpc.Request.from({
method: 'eth_getBalance',
params: ['0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0', 'latest'],
id: 1
})
// Check if notification (no id)
JsonRpc.Request.isNotification(req) // false
// Add params to existing request
const withParams = JsonRpc.Request.withParams(baseReq)(['0x...', 'latest'])
Typed Method Requests
Use namespace-specific request constructors for type safety:Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
// Eth namespace
const balanceReq = JsonRpc.Eth.GetBalanceRequest('0x...', 'latest')
const blockReq = JsonRpc.Eth.GetBlockByNumberRequest('0x1', false)
const callReq = JsonRpc.Eth.CallRequest({ to: '0x...', data: '0x...' }, 'latest')
// Wallet namespace (EIP-3326, EIP-747)
const switchChain = JsonRpc.Wallet.SwitchEthereumChainRequest('0x1')
const addChain = JsonRpc.Wallet.AddEthereumChainRequest({ chainId: '0x1', chainName: 'Mainnet', ... })
// Net namespace
const version = JsonRpc.Net.VersionRequest()
const listening = JsonRpc.Net.ListeningRequest()
// Web3 namespace
const clientVersion = JsonRpc.Web3.ClientVersionRequest()
const sha3 = JsonRpc.Web3.Sha3Request('0x68656c6c6f')
// Txpool namespace
const status = JsonRpc.Txpool.StatusRequest()
const content = JsonRpc.Txpool.ContentRequest()
// Anvil namespace (Foundry testing)
const mine = JsonRpc.Anvil.MineRequest(10)
const setBalance = JsonRpc.Anvil.SetBalanceRequest('0x...', '0x1000')
// Hardhat namespace
const reset = JsonRpc.Hardhat.ResetRequest({ forking: { jsonRpcUrl: '...' } })
Response Types
JsonRpcResponse
Parse and handle JSON-RPC responses with Effect error handling.Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
import { Effect } from 'effect'
const program = Effect.gen(function* () {
// Parse raw response
const response = yield* JsonRpc.Response.parse(rawJson)
// Check response type
if (JsonRpc.Response.isSuccess(response)) {
const result = response.result
}
if (JsonRpc.Response.isError(response)) {
const error = response.error
}
// Unwrap with automatic error handling
const result = yield* JsonRpc.Response.unwrap(response)
return result
})
JsonRpcError
Handle JSON-RPC errors with standard codes.Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
// Standard error codes
JsonRpc.Error.PARSE_ERROR // -32700
JsonRpc.Error.INVALID_REQUEST // -32600
JsonRpc.Error.METHOD_NOT_FOUND // -32601
JsonRpc.Error.INVALID_PARAMS // -32602
JsonRpc.Error.INTERNAL_ERROR // -32603
// Ethereum-specific codes (EIP-1474)
JsonRpc.Error.INVALID_INPUT // -32000
JsonRpc.Error.RESOURCE_NOT_FOUND // -32001
JsonRpc.Error.TRANSACTION_REJECTED // -32003
// Create error
const error = JsonRpc.Error.from({
code: -32603,
message: 'Internal error',
data: { details: 'Connection refused' }
})
// Format for display
const str = JsonRpc.Error.toString(error)
Batch Requests
Send multiple requests in a single call.Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
// Create batch
const batch = JsonRpc.BatchRequest.from([
JsonRpc.Eth.BlockNumberRequest(),
JsonRpc.Eth.ChainIdRequest(),
JsonRpc.Eth.GetBalanceRequest('0x...', 'latest')
])
// Add to batch
const updated = JsonRpc.BatchRequest.add(batch)(newRequest)
// Check size
const size = JsonRpc.BatchRequest.size(batch) // 3
Batch Responses
Process batch response arrays.Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
import { Effect } from 'effect'
const program = Effect.gen(function* () {
const batch = yield* JsonRpc.BatchResponse.parse(rawResponses)
// Find by ID
const response = JsonRpc.BatchResponse.findById(batch)(1)
// Get all errors
const errors = JsonRpc.BatchResponse.errors(batch)
// Get all successful results
const results = JsonRpc.BatchResponse.results(batch)
return results
})
Effect Integration
All parsing operations return Effects with proper error channels.Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
import { Effect } from 'effect'
const program = Effect.gen(function* () {
const response = yield* JsonRpc.Response.parse(rawJson)
const result = yield* JsonRpc.Response.unwrap(response)
return result
}).pipe(
Effect.catchTag('JsonRpcParseError', (e) =>
Effect.succeed({ error: 'Invalid JSON-RPC response' })
),
Effect.catchTag('JsonRpcError', (e) =>
Effect.succeed({ error: `RPC error ${e.code}: ${e.message}` })
)
)
Error Types
| Error | Description |
|---|---|
JsonRpcParseError | Failed to parse JSON-RPC message |
JsonRpcError | RPC returned an error response |
Type Exports
Copy
Ask AI
import type {
JsonRpcRequestType,
JsonRpcResponseType,
JsonRpcSuccessResponseType,
JsonRpcErrorResponseType,
JsonRpcErrorType,
JsonRpcIdType,
BatchRequestType,
BatchResponseType,
} from 'voltaire-effect/jsonrpc'
Pure Functions
All functions are referentially transparent and work without Effect context:Copy
Ask AI
import * as JsonRpc from 'voltaire-effect/jsonrpc'
// Request utilities (pure)
JsonRpc.Request.from({ method: 'eth_blockNumber', id: 1 })
JsonRpc.Request.isNotification(request)
// Response utilities (pure)
JsonRpc.Response.isSuccess(response)
JsonRpc.Response.isError(response)
// Error utilities (pure)
JsonRpc.Error.toString(error)
// Batch utilities (pure)
JsonRpc.BatchRequest.size(batch)
JsonRpc.BatchResponse.findById(batch)(id)

