Wallet Hooks

Event hooks are the final step in completing the mandatory WalletBase interface implementation. These hooks monitor wallet state changes and enable your integration to respond to those state changes.

The following hook methods must be implemented in your wallet's controller.ts file:

  • setAccountsChangedHook()
  • removeAccountsChangedHook()
  • setChainChangedHook()
  • removeChainChangedHook()
  • setDisconnectHook()
  • removeDisconnectHook()

Common Hooks Information

WalletConnect requires real-time notification of wallet state changes. Implement event hooks that monitor your wallet and relay user actions to WalletConnect as they occur.

Hook Registration Order

On Connection (hooks are registered in this order):

  1. setAccountsChangedHook()
  2. setChainChangedHook()
  3. setDisconnectHook()

On Disconnection (hooks are removed in reverse order):

  1. removeDisconnectHook()
  2. removeChainChangedHook()
  3. removeAccountsChangedHook()

Events to Monitor

WalletConnect Needs Notification when Users:

  • Change the active account.
  • Switch networks.
  • Disconnect from the wallet (e.g., through the wallet's UI).

Hook Lifecycle

On Successful Connection:

  • WalletConnect first removes any existing hook (ensure removeAccountsChangedHook() handles the case when no hook exists).
  • Then sets the new hook.

On Disconnection:

  • WalletConnect removes all registered hooks.

Accounts Changed Hooks

WalletConnect must be notified when users switch to a different account. To handle this, implement the setAccountsChangedHook() and removeAccountsChangedHook() methods.

Account addresses passed to the callback method must match the format returned by connect(). This ensures consistency between connection and account change events.

The following code example is from OPWallet:
setAccountsChangedHook/removeAccountsChangedHook implementationtypescript
class OPWallet implements WalletBase {
    setAccountsChangedHook(fn: (accounts: string[]) => void): void {
	    if (!this.isInstalled() || !this.walletBase) {
		    throw new Error(notInstalledError);
	    }

	    this.accountsChangedHookWrapper = (accounts: string[]) => {
		    if (accounts.length > 0) {
			    fn(accounts);
		    } else {
			    this._isConnected = false;
			    this.disconnectHookWrapper?.();
		    }
	    };

	    this.walletBase.on('accountsChanged', this.accountsChangedHookWrapper);
    }

    removeAccountsChangedHook(): void {
	    if (!this.isInstalled() || !this.walletBase) {
		    throw new Error(notInstalledError);
	    }

	    if (this.accountsChangedHookWrapper) {
		    this.walletBase.removeListener('accountsChanged', this.accountsChangedHookWrapper);
		    this.accountsChangedHookWrapper = undefined;
	    }
    }
}

Chain Changed Hooks

WalletConnect must be notified when users switch to a different network. To handle this, implement the setChainChangedHook() and removeChainChangedHook() methods.

Network value passed to the callback method must match the format returned by getNetwork(). This ensures consistency between network queries and network change events.

The following code example is from OPWallet:
setChainChangedHook implementationtypescript
class OPWallet implements WalletBase {
    setChainChangedHook(fn: (chainType: WalletChainType) => void): void {
	    if (!this.isInstalled() || !this.walletBase) {
		    throw new Error(notInstalledError);
	    }

	    this.chainChangedHookWrapper = (chainInfo: UnisatChainInfo) => {
            fn(this.unisatChainToWalletNetwork(chainInfo.enum));
	    };

	    this.walletBase.on('chainChanged', this.chainChangedHookWrapper);
    }

    removeChainChangedHook(): void {
	    if (!this.isInstalled() || !this.walletBase) {
		    throw new Error(notInstalledError);
	    }

	    if (this.chainChangedHookWrapper) {
		    this.walletBase.removeListener('chainChanged', this.chainChangedHookWrapper);
		    this.chainChangedHookWrapper = undefined;
	    }
    }

    unisatChainToWalletNetwork = (chainType: UnisatChainType): WalletChainType => {
        switch (chainType) {
            case UnisatChainType.BITCOIN_MAINNET: return WalletChainType.BITCOIN_MAINNET;
            case UnisatChainType.BITCOIN_TESTNET: return WalletChainType.BITCOIN_TESTNET;
            case UnisatChainType.BITCOIN_REGTEST: return WalletChainType.BITCOIN_REGTEST;
            case UnisatChainType.BITCOIN_TESTNET4: return WalletChainType.BITCOIN_TESTNET4;
            case UnisatChainType.FRACTAL_BITCOIN_MAINNET: return WalletChainType.FRACTAL_BITCOIN_MAINNET;
            case UnisatChainType.FRACTAL_BITCOIN_TESTNET: return WalletChainType.FRACTAL_BITCOIN_TESTNET;
            case UnisatChainType.BITCOIN_SIGNET: return WalletChainType.BITCOIN_SIGNET;
            default: return WalletChainType.BITCOIN_REGTEST;
        }
    }
}

Disconnect Hooks

WalletConnect must be notified when users disconnect from their wallet. To handle this, implement the setDisconnectHook() and removeDisconnectHook() methods.

This hook has no parameters. Trigger this callback only when the user disconnects through the wallet extension's UI (not when disconnect() is called programmatically).

The following code example is from OPWallet:
setDisconnectHook implementationtypescript
class OPWallet implements WalletBase {
    setDisconnectHook(fn: () => void): void {

	    if (!this.isInstalled() || !this.walletBase) {
		    throw new Error(notInstalledError);
	    }

	    this.disconnectHookWrapper = () => {
		    fn();
	    };

	    this.walletBase.on('disconnect', this.disconnectHookWrapper);
    }

    removeDisconnectHook(): void {
	    if (!this.isInstalled() || !this.walletBase) {
		    throw new Error(notInstalledError);
	    }

	    if (this.disconnectHookWrapper) {
		    this.walletBase.removeListener('disconnect', this.disconnectHookWrapper);
		    this.disconnectHookWrapper = undefined;
	    }
    }
}