All signing operations require crypto services. See Crypto Overview for details on
CryptoLive and individual services.Simple ETH Transfer
Copy
Ask AI
import { Effect, Schedule, Layer } from 'effect'
import { SignerService, Signer, LocalAccount, Provider, HttpTransport, withTimeout } from 'voltaire-effect'
import { Secp256k1Live, KeccakLive } from 'voltaire-effect/crypto'
import { Hex } from '@tevm/voltaire'
const privateKey = Hex.fromHex('0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80')
// Compose layers first
const CryptoLayer = Layer.mergeAll(Secp256k1Live, KeccakLive)
const TransportLayer = HttpTransport({
url: 'https://eth.llamarpc.com',
timeout: '30 seconds',
retrySchedule: Schedule.exponential('500 millis').pipe(Schedule.jittered, Schedule.recurs(3))
})
const DepsLayer = Layer.mergeAll(CryptoLayer, TransportLayer)
const SignerLayer = Signer.fromPrivateKey(privateKey, Provider).pipe(Layer.provide(DepsLayer))
const program = Effect.gen(function* () {
const signer = yield* SignerService
return yield* signer.sendTransaction({
to: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
value: 1000000000000000000n
})
}).pipe(
withTimeout('30 seconds'),
Effect.provide(SignerLayer)
)
EIP-1559 Transaction
Copy
Ask AI
import { Effect, Layer } from 'effect'
// Compose layers first
const CryptoLayer = Layer.mergeAll(Secp256k1Live, KeccakLive)
const TransportLayer = HttpTransport({ url: 'https://eth.llamarpc.com' })
const DepsLayer = Layer.mergeAll(CryptoLayer, TransportLayer)
const SignerLayer = Signer.fromPrivateKey(privateKey, Provider).pipe(Layer.provide(DepsLayer))
const program = Effect.gen(function* () {
const signer = yield* SignerService
return yield* signer.sendTransaction({
to: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
value: 1000000000000000000n,
maxFeePerGas: 50000000000n,
maxPriorityFeePerGas: 2000000000n
})
}).pipe(Effect.provide(SignerLayer))
Sign Message (EIP-191)
Copy
Ask AI
import { Effect, Layer } from 'effect'
// Compose layers first
const CryptoLayer = Layer.mergeAll(Secp256k1Live, KeccakLive)
const TransportLayer = HttpTransport({ url: 'https://eth.llamarpc.com' })
const DepsLayer = Layer.mergeAll(CryptoLayer, TransportLayer)
const SignerLayer = Signer.fromPrivateKey(privateKey, Provider).pipe(Layer.provide(DepsLayer))
const program = Effect.gen(function* () {
const signer = yield* SignerService
return yield* signer.signMessage(Hex.fromString('Hello, Ethereum!'))
}).pipe(Effect.provide(SignerLayer))
Sign EIP-712 Typed Data
Copy
Ask AI
import { Effect, Layer } from 'effect'
const typedData = {
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
],
Permit: [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
]
},
primaryType: 'Permit',
domain: { name: 'MyToken', version: '1', chainId: 1n, verifyingContract: '0x...' },
message: { owner: '0x...', spender: '0x...', value: 1000000n, nonce: 0n, deadline: 1700000000n }
}
// Compose layers first
const CryptoLayer = Layer.mergeAll(Secp256k1Live, KeccakLive)
const TransportLayer = HttpTransport({ url: 'https://eth.llamarpc.com' })
const DepsLayer = Layer.mergeAll(CryptoLayer, TransportLayer)
const SignerLayer = Signer.fromPrivateKey(privateKey, Provider).pipe(Layer.provide(DepsLayer))
const program = Effect.gen(function* () {
const signer = yield* SignerService
return yield* signer.signTypedData(typedData)
}).pipe(Effect.provide(SignerLayer))
Browser Wallet (MetaMask)
Copy
Ask AI
import { Effect, Layer } from 'effect'
import { JsonRpcAccount, BrowserTransport, Signer, Provider } from 'voltaire-effect'
// Compose layers first
const BrowserLayer = Layer.mergeAll(
Signer.Live,
JsonRpcAccount(userAddress),
Provider
).pipe(Layer.provide(BrowserTransport))
const program = Effect.gen(function* () {
const signer = yield* SignerService
const accounts = yield* signer.requestAddresses()
return yield* signer.sendTransaction({ to: '0x...', value: 1000000000000000000n })
}).pipe(Effect.provide(BrowserLayer))
Send and Wait
Copy
Ask AI
import { Effect, Layer } from 'effect'
import { SignerService, waitForTransactionReceipt, Signer, Provider, HttpTransport } from 'voltaire-effect'
import { Secp256k1Live, KeccakLive } from 'voltaire-effect/crypto'
// Compose layers first
const CryptoLayer = Layer.mergeAll(Secp256k1Live, KeccakLive)
const TransportLayer = HttpTransport({ url: 'https://eth.llamarpc.com' })
const DepsLayer = Layer.mergeAll(CryptoLayer, TransportLayer)
const SignerLayer = Signer.fromPrivateKey(privateKey, Provider).pipe(Layer.provide(DepsLayer))
const program = Effect.gen(function* () {
const signer = yield* SignerService
const txHash = yield* signer.sendTransaction({ to: '0x...', value: 1000000000000000000n })
const receipt = yield* waitForTransactionReceipt(txHash, { confirmations: 3, timeout: '60 seconds' })
return { hash: txHash, status: receipt.status, blockNumber: receipt.blockNumber }
}).pipe(Effect.provide(SignerLayer))
Switch Chain
Copy
Ask AI
import { Effect, Layer } from 'effect'
// Compose layers first
const BrowserLayer = Layer.mergeAll(
Signer.Live,
JsonRpcAccount(userAddress),
Provider
).pipe(Layer.provide(BrowserTransport))
const program = Effect.gen(function* () {
const signer = yield* SignerService
yield* signer.switchChain(10) // Optimism
}).pipe(Effect.provide(BrowserLayer))
See Also
- Signer Service — Complete SignerService API
- Provider Service — JSON-RPC provider operations
- Contract Interactions — Write to smart contracts
- HD Wallet Guide — Create wallets from mnemonic
- EIP-1559 — Fee market change specification
- Effect Error Management — Typed error handling

