📄 src/web3/session/writeClient.ts
D-OPEN SOVEREIGN

Documentation & Insights

Bridges a connected WalletConnector to a concrete EvmWriteClient. Kept out of
client/ and wallet/ so neither layer needs to know about the other:
WalletConnector stays viem-free (client/types.ts), EvmWriteClient stays
connector-agnostic (client/EvmWriteClient.ts) — this is the seam.
Same bridge as createWriteClient, but for a key that only ever exists
decrypted-in-memory — for callers with their own encrypted vault (e.g. an
admin tool) that want to sign without ever persisting the key via
wallet/credentials.ts's plaintext localStorage or going through the
connector registry.
1import type { EvmWalletConnector, WalletConnector } from '../client/types';
2import { EvmWriteClient } from '../client/EvmWriteClient';
3import { getReadyEvmClient } from '../client/registry';
4import { addressFromPrivateKey, createPrivateKeyWalletClient } from '../wallet/PrivateKeyConnector';
5
6/**
7 * Bridges a connected WalletConnector to a concrete EvmWriteClient. Kept out of
8 * client/ and wallet/ so neither layer needs to know about the other:
9 * WalletConnector stays viem-free (client/types.ts), EvmWriteClient stays
10 * connector-agnostic (client/EvmWriteClient.ts) — this is the seam.
11 */
12export async function createWriteClient(
13  connector: WalletConnector,
14  chainId: number,
15  environment: 'production' | 'staging' = 'production'
16): Promise<EvmWriteClient> {
17  const evmConnector = connector as EvmWalletConnector;
18  if (typeof evmConnector.getWalletClient !== 'function') {
19    throw new Error(`Connector '${connector.type}' does not support EVM write operations`);
20  }
21
22  const accounts = await connector.getAccounts();
23  const account = accounts[0];
24  if (!account) {
25    throw new Error(`No account available for wallet '${connector.type}' — connect() first`);
26  }
27
28  // Writes need the contract ABI resolved, not just the address — this waits
29  // for both (see getReadyEvmClient's comment in client/registry.ts).
30  const evmClient = await getReadyEvmClient(chainId, environment);
31  const walletClient = await evmConnector.getWalletClient(chainId);
32  return new EvmWriteClient(connector.type, evmClient, walletClient, account);
33}
34
35/**
36 * Same bridge as createWriteClient, but for a key that only ever exists
37 * decrypted-in-memory — for callers with their own encrypted vault (e.g. an
38 * admin tool) that want to sign without ever persisting the key via
39 * wallet/credentials.ts's plaintext localStorage or going through the
40 * connector registry.
41 */
42export async function createPrivateKeyWriteClient(
43  chainId: number,
44  privateKey: string,
45  environment: 'production' | 'staging' = 'production'
46): Promise<EvmWriteClient> {
47  const evmClient = await getReadyEvmClient(chainId, environment);
48  const walletClient = createPrivateKeyWalletClient(chainId, privateKey);
49  const account = addressFromPrivateKey(privateKey);
50  return new EvmWriteClient('private_key', evmClient, walletClient, account);
51}
52