Adapters
The @mure/sdk uses an adapter pattern to stay wallet-agnostic. An adapter implements the AdapterServiceApi contract, which tells the SDK how to send transactions, read the current account, and read the current chain.
The only adapter shipped today is built on viem, but you can write your own by satisfying the same interface.
AdapterService
AdapterService is an Effect Context.Service. It defines the boundary between the SDK and the blockchain.
Interface
| Method | Signature | Description |
|---|---|---|
sendTransaction | (tx: Transaction) => Effect<Hex, AdapterServiceError> | Send a single transaction and return its hash. |
sendTransactions | (txs: Transaction[]) => Effect<Hex[], AdapterServiceError> | Send a batch of transactions via sendCalls ( EIP-5792 ) and return the hashes. |
account | Effect<CAIPAccountCompact> | The active account address in CAIP-10 compact format. |
chain | Effect<CAIPChainCompact> | The active chain identifier in CAIP-2 format. |
AdapterServiceError
All adapter failures are surfaced as AdapterServiceError, a typed Effect error that carries the original cause.
import { AdapterServiceError } from "@mure/sdk";
// Error shape:
// {
// _tag: "AdapterServiceError",
// cause: Error // the original viem or provider error
// }ViemAdapter
ViemAdapter is the production adapter for any EVM chain. It wraps a viem WalletClient and implements the full AdapterServiceApi.
Factory: viem()
The viem() helper is the easiest way to create an adapter. It accepts either a ready-made WalletClient or a configuration object.
import { http } from "viem";
import { sepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { createWalletClient } from "viem";
import { viem } from "@mure/sdk";
const walletClient = createWalletClient({
chain: sepolia,
transport: http(),
account: privateKeyToAccount("0x..."), // replace with your private key
});
const adapter = viem(walletClient);import { http } from "viem";
import { sepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { viem } from "@mure/sdk";
const adapter = viem({
chain: sepolia,
transport: http(),
account: privateKeyToAccount("0x..."), // replace with your private key
});Batch transactions with sendTransactions
ViemAdapter supports EIP-5792 batch calls through the sendTransactions method. It calls viem's sendCalls with experimental_fallback: true, polls the call status until it is no longer pending, and returns the resulting transaction hashes. If the wallet does not support sendCalls, viem falls back to sending the transactions sequentially.
import { Effect } from "effect";
import { AdapterService } from "@mure/sdk";
const program = Effect.gen(function* () {
const adapter = yield* AdapterService;
const hashes = yield* adapter.sendTransactions([
{ to: "0x...", data: "0x...", value: 0n },
{ to: "0x...", data: "0x...", value: 0n },
]);
return hashes;
});Low-level: ViemAdapter
If you already have a WalletClient and want to skip the viem() factory, use ViemAdapter directly.
import { ViemAdapter } from "@mure/sdk";
const adapter = ViemAdapter(walletClient);Usage
An adapter is required to create a Client. Pass it to createClient along with the API URL.
import { viem, createClient } from "@mure/sdk";
import { http } from "viem";
import { sepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
const adapter = viem({
chain: sepolia,
transport: http(),
account: privateKeyToAccount("0x..."), // replace with your private key
});
const client = createClient({ adapter });For advanced Effect patterns, you can provide the adapter Layer to any program that requires AdapterService.
import { Effect } from "effect";
import { AdapterService } from "@mure/sdk";
const program = Effect.gen(function* () {
const adapter = yield* AdapterService;
const account = yield* adapter.account;
console.log("Connected:", account);
});
const runnable = program.pipe(Effect.provide(adapter));