Utility Functions
With connection management implemented, the next step is adding the utility functions to your wallet's controller.ts file:
- getWalletInstance()
- getPublicKey()
- getNetwork()
- getSigner()
- getBalance()
- getProvider()
- switchNetwork()
- signMessage()
- getMLDSAPublicKey()
- getHashedMLDSAKey()
- signMLDSAMessage()
- verifyMLDSASignature()
These utility functions provide wallet interaction and account information retrieval.
Best Practice
Define and export the provider interface in your wallet's interface.ts file. This enables full TypeScript code analysis and auto-completion for developers integrating your wallet through WalletConnect.
export interface MyWallet {
isEnabled: boolean;
signMessage: (message: string) => Promise<boolean>;
...
};If your wallet is a fork of an existing wallet, consider reusing the original wallet's interface rather than creating a new one. Many forks only modify the UI while maintaining the same underlying API.
getWalletInstance()
This method returns the typed wallet's injected provider object.
class OPWallet implements WalletBase {
getWalletInstance(): OPWallet | null {
return (this._isConnected && this.walletBase) || null;
}
}getPublicKey()
This method returns the current account's public key as a hexadecimal string.
If your wallet returns the key in a different format (binary, base64, etc.), convert it to match the required format.
Format Requirements
- Hexadecimal encoding (no 0x prefix).
- Lowercase characters.
Example: 021b7614841c6105ee9e6f3918a960a7c6f92624d132e879744e8baa595c75e712
class OPWallet implements WalletBase {
async getPublicKey(): Promise<string> {
return this.walletBase.getPublicKey();
}
}getNetwork()
This method returns the current network as a WalletChainType value.
Supported Networks
The WalletChainType enum recognizes the following networks:
- BITCOIN_MAINNET
- BITCOIN_TESTNET
- BITCOIN_TESTNET4
- BITCOIN_REGTEST
- BITCOIN_SIGNET
- FRACTAL_BITCOIN_MAINNET
- FRACTAL_BITCOIN_TESTNET
Network Mapping
WalletConnect only supports three networks. The conversion mapping is:
- BITCOIN_MAINNET --> network.bitcoin
- BITCOIN_TESTNET --> network.testnet
- BITCOIN_REGTEST --> network.regtest
- All other networks --> null (unsupported)
Networks not in the mapping (TESTNET4, SIGNET, Fractal networks) will result in a null network property in WalletConnectProvider.
class SomeWallet implements WalletBase {
getChainName(name: string) {
switch (name.toLocaleLowerCase()) {
case 'testnet': return WalletChainType.BITCOIN_TESTNET;
case 'regtest': return WalletChainType.BITCOIN_REGTEST;
case 'testnet4': return WalletChainType.BITCOIN_TESTNET4;
case 'signet': return WalletChainType.BITCOIN_SIGNET;
case 'mainnet': return WalletChainType.BITCOIN_MAINNET;
}
return WalletChainType.BITCOIN_MAINNET;
}
async getNetwork(): Promise<WalletChainType> {
// Safe guard and verification omitted to shorten code sample
const chainInfo = await this.walletBase.getChain();
return this.getChainName(chainInfo.networkName);
}
}getSigner()
This method is not yet implemented and is reserved for future use. Must return null or throw.
getBalance()
This method returns the current account bitcoin(BTC) balance as a WalletBalance object.
Required Properties
Values must be provided for the following WalletBalance properties:
- unconfirmed: Unconfirmed balance.
- confirmed: Confirmed balance.
- total: Total balance (confirmed + unconfirmed).
Optional Properties
If your wallet supports the following properties, you can optionally provide values for them:
- csv_1 related balances.
- csv_75 related balances.
- p2wda related balances.
- usd value
For the complete interface definition, refer to the WalletBalance Interface in the codebase.
class OPWallet implements WalletBase {
async getBalance(): Promise<&;WalletBalance | null> {
if (!this.isInstalled() || !this.walletBase) {
throw new Error(notInstalledError);
}
return (await this.walletBase.getBalance()) as WalletBalance | null;
}
}getProvider()
This method returns a RPC provider for executing OP-20 operations.
The provider property of WalletConnect exposes this provider, enabling applications to interact with OP-20 functionality.
The simplest way is to copy the getProvider() implementation from an existing wallet. The method is identical across wallets and only depends on the currently selected network.
public async getProvider(): Promise<AbstractRpcProvider | null> {
if (!this._isConnected || !this.walletBase) return null;
const chain = await this.walletBase.getChain();
switch (chain.enum) {
case UnisatChainType.BITCOIN_MAINNET:
return new JSONRpcProvider('https://mainnet.opnet.org', networks.bitcoin);
case UnisatChainType.BITCOIN_TESTNET:
return new JSONRpcProvider('https://testnet.opnet.org', networks.testnet);
case UnisatChainType.BITCOIN_REGTEST:
return new JSONRpcProvider('https://regtest.opnet.org', networks.regtest);
// TODO: Add Fractal Mainnet & Testnet when available
default:
return null;
}
}switchNetwork()
This method requests a network change on the connected wallet.
async switchNetwork(network: WalletNetwork|WalletChainType): Promise<void> {
if (!this._isConnected || !this.walletBase) return;
const unisatChainType = this.walletNetworkToUnisatChain(network)
await this.walletBase.switchChain(unisatChainType);
}signMessage()
This method signs a message using the connected wallet. An optional signing algorithm can be specified. The default algorithm must be ECDSA.
async signMessage(message: string, messageType?: MessageType): Promise<string | null> {
if (!this._isConnected || !this.walletBase) return null;
return this.walletBase.signMessage(message, messageType);
}getMLDSAPublicKey()
This method returns the current account's MLDSA public key.
async getMLDSAPublicKey(): Promise<string | null> {
if (!this._isConnected || !this.walletBase?.web3) return null;
return this.walletBase.web3.getMLDSAPublicKey();
}getHashedMLDSAKey()
This method returns a SHA-256 hash of the current account's MLDSA public key.
async getHashedMLDSAKey(): Promise<string | null> {
const mldsaPublicKey = await this.getMLDSAPublicKey();
if (!mldsaPublicKey) return null;
const publicKeyBuffer = Buffer.from(mldsaPublicKey, 'hex');
const hash = MessageSigner.sha256(publicKeyBuffer);
return hash.toString('hex');
}signMLDSAMessage()
This method sign a message using the MLDSA post-quantum signature algorithm.
The message parameter can accepts two formats:
- A regular string is signed as-is signed using its UTF-8 representation.
- A hexadecimal string (e.g. 0x1a2b3c... or 1a2b3c...) that is converted to a binary buffer before signing.
async signMLDSAMessage(message: string): Promise<MLDSASignature | null> {
if (!this._isConnected || !this.walletBase?.web3) return null;
return this.walletBase.web3.signMLDSAMessage(message);
}verifyMLDSASignature()
This method verifies an ML-DSA signature against the original message.
The message parameter must match the format used during signing. If the original message was signed as hexadecimal data, verification must use the same hexadecimal string.
async verifyMLDSASignature(message: string, signature: MLDSASignature): Promise<boolean> {
if (!this._isConnected || !this.walletBase?.web3) return false;
return this.walletBase.web3.verifyMLDSASignature(message, signature);
}