.claude/skills/voltaire-effect-services/SKILL.md
This skill should be used when the user asks about "ProviderService", "SignerService", "TransportService", "HttpTransport", "WebSocketTransport", "JSON-RPC Effect", "getBalance", "getBlock", "getBlockNumber", "sendTransaction", "voltaire-effect provider", "Layer.provide", or needs to understand the voltaire-effect service system.
npx skillsauth add cyotee/crane Voltaire Effect ServicesInstall 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.
Services in voltaire-effect are typed dependencies declared in Effect signatures and injected via layers at program boundaries. This eliminates hidden globals and enables seamless test substitution.
┌─────────────────────────────────────────────────────────────────────────────┐
│ SERVICE ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Application Code │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ const bal = yield* getBalance(addr) │ │
│ │ // Type: Effect<bigint, GetBalanceError, ProviderService> │ │
│ └────────────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ Effect.provide(layers) │
│ │ │
│ Service Implementations ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Provider │ │ Signer │ │ Transport │ │
│ │ ───────── │ │ ───────── │ │ ────────── │ │
│ │ getBalance │ │ sign │ │ HTTP │ │
│ │ getBlock │ │ signMessage │ │ WebSocket │ │
│ │ call │ │ signTyped │ │ Browser │ │
│ │ getLogs │ │ sendTx │ │ Test │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
The primary service for reading blockchain state via JSON-RPC:
Use free functions instead of yielding ProviderService directly:
import { getBlockNumber, getBalance, getBlock, getLogs } from 'voltaire-effect'
const program = Effect.gen(function* () {
const blockNum = yield* getBlockNumber()
const balance = yield* getBalance(addr)
const block = yield* getBlock({ blockNumber: blockNum })
const logs = yield* getLogs({ fromBlock: 0n, toBlock: 'latest' })
return { blockNum, balance, block, logs }
})
| Category | Functions |
|----------|-----------|
| Blocks | getBlockNumber, getBlock, getBlockReceipts, getUncleCount |
| Accounts | getBalance, getTransactionCount, getCode, getStorageAt |
| Transactions | getTransaction, getTransactionReceipt, waitForTransactionReceipt |
| Simulation | readContract, multicall, simulateContract, simulateV1, simulateV2 |
| Gas | getGasPrice, getMaxPriorityFeePerGas, getFeeHistory |
| Events | getLogs |
| Streaming | watchBlocks, subscribe, unsubscribe |
import { Provider, HttpTransport } from 'voltaire-effect'
const ProviderLayer = Provider.pipe(
Layer.provide(HttpTransport('https://eth.llamarpc.com'))
)
Manages the network connection. Three production transports and one test transport:
import { HttpTransport } from 'voltaire-effect'
HttpTransport('https://eth.llamarpc.com')
// With options
HttpTransport({
url: 'https://eth.llamarpc.com',
timeout: '30 seconds',
headers: { 'Authorization': 'Bearer ...' },
retrySchedule: Schedule.exponential('500 millis').pipe(
Schedule.jittered,
Schedule.compose(Schedule.recurs(5))
)
})
HTTP transport supports automatic request batching - concurrent requests are batched into a single HTTP call.
import { WebSocketTransport } from 'voltaire-effect'
WebSocketTransport('wss://eth.llamarpc.com')
import { BrowserTransport } from 'voltaire-effect'
BrowserTransport() // Uses window.ethereum
import { TestTransport } from 'voltaire-effect'
TestTransport({
eth_blockNumber: '0x10',
eth_getBalance: '0xde0b6b3a7640000'
})
For state-changing operations. Unlike Provider, Signer still requires direct yielding:
import { Signer } from 'voltaire-effect'
const program = Effect.gen(function* () {
const signer = yield* Signer
const txHash = yield* signer.sendTransaction({
to: recipient,
value: 1000000000000000000n
})
return txHash
})
Create a Signer from an existing Provider and Account:
const SignerLayer = Signer.fromProvider
// Requires ProviderService + AccountService
const AppLayer = Layer.mergeAll(TransportLayer, CryptoLayer)
// Provider depends on Transport
const ProviderLayer = Provider.pipe(
Layer.provide(HttpTransport('https://eth.llamarpc.com'))
)
import { Secp256k1Live } from 'voltaire-effect/crypto/Secp256k1'
import { KeccakLive } from 'voltaire-effect/crypto/Keccak256'
const FullLayer = Layer.mergeAll(
ProviderLayer,
Secp256k1Live,
KeccakLive,
SignerLayer
)
await Effect.runPromise(program.pipe(Effect.provide(FullLayer)))
Override settings for individual calls using FiberRef helpers:
import { withTimeout, withRetrySchedule, withoutCache, withTracing } from 'voltaire-effect'
// Timeout
const fast = yield* getBalance(addr).pipe(withTimeout("5 seconds"))
// Custom retry
const resilient = yield* getBalance(addr).pipe(
withRetrySchedule(Schedule.recurs(1))
)
// Bypass cache
const fresh = yield* getBlockNumber().pipe(withoutCache)
// Debug tracing
const traced = yield* getBlock(n).pipe(withTracing())
Reduce network overhead by batching contract reads:
import { multicall } from 'voltaire-effect'
const results = yield* multicall({
contracts: [
{ address: usdc, abi: erc20Abi, functionName: 'balanceOf', args: [user] },
{ address: dai, abi: erc20Abi, functionName: 'balanceOf', args: [user] },
{ address: weth, abi: erc20Abi, functionName: 'balanceOf', args: [user] },
],
allowFailure: true // Returns Either[] instead of throwing
})
For detailed service method signatures, see:
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.