Client
The @mure/sdk client wraps the lower-level @mure/api-v2 client and a blockchain adapter into one interface. It handles transaction creation, API communication, and on-chain submission in one call.
Installation
Creating a Client
Use createClient to instantiate the client. You must provide an Adapter — the SDK ships with a viem adapter out of the box.
import { createClient, viem } 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 });API configuration
Pass API options under the api key. Both fields are optional, so createClient({ adapter }) stays valid.
const client = createClient({
adapter,
api: {
url: "https://api.mure.app/v2", // optional, defaults to this URL
apiKey: process.env.MURE_API_KEY, // optional
},
});createClient throws ClientConfigError synchronously when api.apiKey is a blank string. An absent key is allowed. See Authentication for credential semantics.
Transfer
The transfer method creates a transfer intent via the API and immediately submits the resulting transaction through the adapter.
import { eth } from "@mure/sdk/accounts/evm";
const hash = await client.transfer({
to: eth("0x8f664a25158021EFb4470f9036431664ce9f7895"), // recipient address
asset: "USDC",
amount: 10_000_000n, // 10 USDC (6 decimals)
});transfer resolves to the transaction hash as a bare hex string. It does not return an outcome array.
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
from | Address | No | Source address and chain. Defaults to the adapter's connected account. |
to | Address | Yes | Destination address and chain (same chain as from). |
asset | string | { in: Address; out: Address } | Yes | Token symbol, CAIP-10 asset, or swap pair. See Swaps. |
amount | bigint | Yes | Amount to transfer as a bigint. |
deadline | string | No | Latest execution time (ISO 8601). Defaults to +1 hour. |
callData | string | No | Hex-encoded calldata forwarded to recipient. |
Explicit from
When from is omitted, the client uses the adapter's connected account. You can also provide it explicitly:
import { sepolia } from "@mure/sdk/accounts/evm";
const hash = await client.transfer({
from: sepolia("0x3165fd5B9D37Ac9619aC5895CA33F308aB02a053"), // sender address
to: sepolia("0x8f664a25158021EFb4470f9036431664ce9f7895"), // recipient address
asset: "USDC",
amount: 10_000_000n, // 10 USDC (6 decimals)
});Swaps
To swap one asset for another on the same chain, pass an { in, out } object instead of a single asset string.
Both fields accept the same address formats as from and to.
import { base, eth } from "@mure/sdk/accounts/evm";
const USDC = eth("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
const NATIVE_ETH = eth("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE");
const hash = await client.transfer({
to: eth("0x8f664a25158021EFb4470f9036431664ce9f7895"),
asset: { in: USDC, out: NATIVE_ETH },
amount: 10_000_000n,
});Cross-chain bridges
To move assets across chains, set to to an address on a different chain than from. The SDK submits a single transfer call and Mure selects a bridge route automatically.
import { base, eth } from "@mure/sdk/accounts/evm";
const USDC = eth("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
const hash = await client.transfer({
from: eth("0x3165fd5B9D37Ac9619aC5895CA33F308aB02a053"),
to: base("0x8f664a25158021EFb4470f9036431664ce9f7895"),
asset: { in: USDC, out: USDC },
amount: 10_000_000n,
});Submission and confirmation
transfer is two operations in one call:
- POST a transfer intent to the API.
- Hand the returned transaction to the adapter.
The SDK adds no confirmation step of its own. Whether the user sees a prompt depends on the adapter's account. The examples on this page use privateKeyToAccount, so submission is silent. A browser-wallet transport prompts through the wallet.
The public transfer API has no preview option. To inspect the intent before you submit it, create the intent with ApiClient.createTransfer, then send the transaction with client.send.
import { Account } from "@mure/chains/caip";
import { ApiClient } from "@mure/api-v2/client";
import { Effect } from "effect";
import { ClientService } from "@mure/sdk";
const program = Effect.gen(function* () {
const api = yield* ApiClient;
const client = yield* ClientService;
// 1. Create the intent and inspect it.
const intent = yield* api.createTransfer({
payload: {
from: Account.expand(
"eip155:1:0x3165fd5B9D37Ac9619aC5895CA33F308aB02a053",
),
to: Account.expand("eip155:1:0x8f664a25158021EFb4470f9036431664ce9f7895"),
asset: Account.expandAssetReference("USDC"),
amount: 10_000_000n,
},
});
console.log("Submitting to", intent.tx.to, "value", intent.tx.value);
// 2. Submit only after you decide.
const [outcome] = yield* client.send(intent.tx);
return outcome;
});Provide the ClientService and ApiClient layers to run it.
const runnable = program.pipe(
Effect.provide(ClientService.layer),
Effect.provide(adapter),
Effect.provide(
ApiClient.layer({
baseUrl: "https://api.mure.app/v2",
apiKey: process.env.MURE_API_KEY,
}),
),
);
Effect.runPromise(runnable).then(console.log).catch(console.error);Send
For transactions you have already constructed, use client.send to broadcast them through the configured adapter. Pass one transaction or an array.
const outcomes = await client.send([
{ to: "0x...", data: "0x...", value: 0n },
{ to: "0x...", data: "0x...", value: 0n },
]);send returns one outcome per input, in input order.
| Status | Payload | Meaning |
|---|---|---|
success | hash | The transaction was included in a block. |
reverted | hash | The transaction was included but reverted on-chain. |
failed | cause | The adapter rejected the transaction before inclusion. |
unknown | hash? | The adapter could not confirm the result within the poll bound. |
A single transaction resolves to a one-element outcome array.
const [outcome] = await client.send({ to: "0x...", data: "0x...", value: 0n });The adapter owns batching. When the wallet supports EIP-5792, send submits the batch with one call and polls the call status. When the wallet does not support batching, the adapter sends the transactions sequentially and reports each result. A batch does not fail as a whole because one transaction failed.
send is useful when you want to combine Mure-generated transactions with your own calls, or when you are using a wallet model such as account abstraction or EIP-7702 that is covered by Mure's Unified Entrypoint.
Reading transfers and tokens
List transfers
const transfers = await client.listTransfers(); // all transfers
const swaps = await client.listTransfers({ type: "swap" }); // filteredThe args parameter is optional. Omit it to list every transfer.
| Field | Type | Required | Description |
|---|---|---|---|
type | "transfer" | "swap" | "bridge" | No | Filter by transfer type. |
Returns { items: TransferSummary[] }.
| Field | Type | Description |
|---|---|---|
id | string | Transfer id. |
type | "transfer" | "swap" | "bridge" | Transfer type. |
status | "draft" | "pending" | "confirmed" | "failed" | "expired" | "finalized" | Transfer status. |
createdAt | Date | Creation time. |
updatedAt | Date | Last update time. |
orderId | `0x${string}` (optional) | Order id when the transfer has one. |
metadata | { chainId: "eip155:<ref>"; hash?: "0x<hex>" } | Chain id and transaction hash. |
Get one transfer
const transfer = await client.getTransfer({ id: "int_transfer_01..." });The args parameter is required and must contain id.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Transfer id. |
Returns a single TransferSummary with the fields listed above.
List tokens
const tokens = await client.listTokens(); // all tokens
const mainnet = await client.listTokens({ chainId: "eip155:1" }); // filteredThe args parameter is optional. Omit it to list every token.
| Field | Type | Required | Description |
|---|---|---|---|
chainId | `eip155:${number}` | No | Filter by chain. |
Returns { items: TokenDefinition[] }.
| Field | Type | Description |
|---|---|---|
symbol | string | Token symbol. |
chainId | string | Chain id. |
address | string | CAIP-10 account for the symbol and chain pair. |
decimals | number | Token decimals. |
metadata | string | null | Extra token metadata. |
EVM account helpers
The SDK ships with small helpers that build CAIP-10 identifiers for common EVM chains. They are available from @mure/sdk/accounts/evm.
import {
eth,
sepolia,
base,
baseSepolia,
hyperliquid,
hyperliquidTestnet,
} from "@mure/sdk/accounts/evm";
const mainnetAccount = eth("0x8f664a25158021EFb4470f9036431664ce9f7895");
// => "eip155:1:0x8f664a25158021EFb4470f9036431664ce9f7895"Use these helpers to keep addresses chain-scoped and avoid hand-written CAIP-10 strings in examples.
Imports
The SDK exposes one root entry and four documented subpaths.
| Import path | Exports |
|---|---|
@mure/sdk | createClient, ClientService, ClientServiceError, ClientConfigError, viem, ViemAdapter, AdapterService, AdapterServiceError, and the public types. |
@mure/sdk/adapters | AdapterService, AdapterServiceError, ViemAdapter, viem. |
@mure/sdk/accounts/evm | eth, sepolia, base, baseSepolia, hyperliquid, hyperliquidTestnet. |
@mure/sdk/chains | toCAIP. |
@mure/sdk/chains/evm | toCAIP. |
Error Handling
All SDK errors are surfaced as ClientServiceError. Wrap calls in try/catch to handle failures.
import { ClientServiceError } from "@mure/sdk";
import { eth } from "@mure/sdk/accounts/evm";
try {
const hash = await client.transfer({
to: eth("0x..."), // recipient address
asset: "USDC",
amount: 10_000_000n, // 10 USDC (6 decimals)
});
} catch (error) {
if (error instanceof ClientServiceError) {
console.error("Transfer failed:", error.message);
}
}Effect-TS Integration
For advanced use cases, you can access the client inside an Effect program.
import { Effect } from "effect";
import { ClientService } from "@mure/sdk";
import { eth } from "@mure/sdk/accounts/evm";
const program = Effect.gen(function* () {
const client = yield* ClientService;
const hash = yield* client.transfer({
to: eth("0x..."), // recipient address
asset: "USDC",
amount: 10_000_000n, // 10 USDC (6 decimals)
});
return hash;
});The ClientService is a Context.Service. Provide it via ClientService.layer combined with an Adapter and ApiClient.layer.
import { ClientService } from "@mure/sdk";
import { ApiClient } from "@mure/api-v2/client";
import { Effect } from "effect";
const runnable = program.pipe(
Effect.provide(ClientService.layer),
Effect.provide(adapter),
Effect.provide(
ApiClient.layer({
baseUrl: "https://api.mure.app/v2",
apiKey: process.env.MURE_API_KEY,
}),
),
);
Effect.runPromise(runnable).then(console.log).catch(console.error);