Mysten Incubation
ReferenceAdapters

Custom Adapters

You can create custom adapters by implementing the SignerAdapter interface or extending BaseSignerAdapter.

Extending BaseSignerAdapter

BaseSignerAdapter handles common boilerplate — account list management, change notifications, and cleanup. You only need to implement the initialization and key management logic.

import { BaseSignerAdapter, buildManagedAccount } from '@mysten-incubation/dev-wallet/adapters';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import type { ManagedAccount, CreateAccountOptions } from '@mysten-incubation/dev-wallet';

class LocalStorageAdapter extends BaseSignerAdapter {
	readonly id = 'local-storage';
	readonly name = 'LocalStorage';

	async initialize(): Promise<void> {
		const stored = localStorage.getItem('dev-wallet-keys');
		if (!stored) return;

		const entries: Array<{ secret: string; label: string }> = JSON.parse(stored);
		const accounts = entries.map((entry) => {
			// secret is a Bech32-encoded private key from getSecretKey()
			const keypair = Ed25519Keypair.fromSecretKey(entry.secret);
			const address = keypair.getPublicKey().toSuiAddress();
			return buildManagedAccount(keypair, address, entry.label);
		});

		this.setInitialAccounts(accounts);
	}

	async createAccount(options?: CreateAccountOptions): Promise<ManagedAccount> {
		const keypair = new Ed25519Keypair();
		const address = keypair.getPublicKey().toSuiAddress();
		const label = options?.label ?? `Account ${this.getAccounts().length + 1}`;
		const account = buildManagedAccount(keypair, address, label);
		this.addAccount(account);
		this.persist();
		return account;
	}

	async removeAccount(address: string): Promise<boolean> {
		const removed = this.removeAccountByAddress(address);
		if (removed) this.persist();
		return removed;
	}

	private persist(): void {
		const data = this.getAccounts().map((acc) => ({
			secret: (acc.signer as Ed25519Keypair).getSecretKey(),
			label: acc.label,
		}));
		localStorage.setItem('dev-wallet-keys', JSON.stringify(data));
	}
}

Using Your Custom Adapter

import { DevWallet } from '@mysten-incubation/dev-wallet';

const adapter = new LocalStorageAdapter();
await adapter.initialize();

const wallet = new DevWallet({
	adapters: [adapter],
});

BaseSignerAdapter Helper Methods

MethodDescription
setInitialAccounts(accounts)Set the initial account list during initialize()
addAccount(account)Add a ManagedAccount and notify listeners
removeAccountByAddress(address)Remove an account and notify listeners
replaceAccount(address, account)Replace an account (e.g., after rename)
_performRename(address, label)Rename by rebuilding the account with a new label
notifyListeners()Manually trigger account change notifications

The ManagedAccount Interface

interface ManagedAccount {
	address: string; // Sui address
	label: string; // Human-readable name
	signer: Signer; // Can sign transactions and messages
	walletAccount: ReadonlyWalletAccount; // Wallet-standard account
}

On this page