Mysten Incubation
ReferenceAdapters

Adapters

Pluggable key-management layer — InMemory, WebCrypto, Passkey, and Remote CLI signers

Adapters are the pluggable key management layer of the dev wallet. Each adapter manages its own set of accounts and provides signers for transaction signing.

What is a SignerAdapter?

A SignerAdapter handles:

  • Key generation and storage — how keypairs are created and where they live
  • Account lifecycle — creating, importing, removing, and renaming accounts
  • Signing — providing a Signer for each account that can sign transactions and messages

DevWallet aggregates accounts from all its adapters into a single wallet. You can use multiple adapters simultaneously — for example, InMemory for quick testing and WebCrypto for persistent accounts.

Adapter comparison

AdapterKey typePersistenceAuto-signBest for
InMemoryEd25519NoneYesQuick prototyping, unit tests
WebCryptoSecp256r1IndexedDBYesPersistent dev accounts
PasskeySecp256r1Browser + OSNoTesting passkey flows
Remote CLIAnyExternalNoUsing sui CLI keystore

Using multiple adapters

import { DevWallet } from '@mysten-incubation/dev-wallet';
import {
	InMemorySignerAdapter,
	WebCryptoSignerAdapter,
} from '@mysten-incubation/dev-wallet/adapters';

const adapters = [new InMemorySignerAdapter(), new WebCryptoSignerAdapter()];

// Initialize all adapters
await Promise.all(adapters.map((a) => a.initialize()));

const wallet = new DevWallet({ adapters });
// wallet.accounts includes accounts from both adapters

The BaseSignerAdapter base class

All built-in adapters extend BaseSignerAdapter, which handles common boilerplate:

  • Account list management (setInitialAccounts, addAccount, removeAccountByAddress, replaceAccount)
  • Change notification via onAccountsChanged listeners
  • Cleanup via destroy()

If you need a custom adapter, extending BaseSignerAdapter is the recommended approach. See Custom Adapters.

The SignerAdapter interface

interface SignerAdapter {
	readonly id: string;
	readonly name: string;
	readonly allowAutoSign?: boolean;

	initialize(): Promise<void>;
	getAccounts(): ManagedAccount[];
	getAccount(address: string): ManagedAccount | undefined;

	createAccount?(options?: CreateAccountOptions): Promise<ManagedAccount>;
	importAccount?(options: ImportAccountOptions): Promise<ManagedAccount>;
	listAvailableAccounts?(): Promise<
		Array<{ address: string; scheme: string; alias?: string | null }>
	>;
	removeAccount?(address: string): Promise<boolean>;
	renameAccount?(address: string, label: string): Promise<boolean>;

	onAccountsChanged(callback: (accounts: ManagedAccount[]) => void): () => void;
	destroy(): void;
}

On this page