This guide covers the common actions and operations that are supported by both MetaMask and Coinbase Wallet. These actions form the foundation of wallet testing with OnchainTestKit.
Base Actions
All wallets support these fundamental actions through the BaseActionType
enum:
enum BaseActionType {
IMPORT_WALLET_FROM_SEED = "importWalletFromSeed" ,
IMPORT_WALLET_FROM_PRIVATE_KEY = "importWalletFromPrivateKey" ,
SWITCH_NETWORK = "switchNetwork" ,
CONNECT_TO_DAPP = "connectToDapp" ,
HANDLE_TRANSACTION = "handleTransaction" ,
HANDLE_SIGNATURE = "handleSignature" ,
CHANGE_SPENDING_CAP = "changeSpendingCap" ,
REMOVE_SPENDING_CAP = "removeSpendingCap" ,
}
Wallet Import and Setup
Import from Seed Phrase
await metamask . handleAction ( BaseActionType . IMPORT_WALLET_FROM_SEED , {
seedPhrase: "test test test test test test test test test test test junk" ,
password: "MyPassword123!"
});
Import from Private Key
await metamask . handleAction ( BaseActionType . IMPORT_WALLET_FROM_PRIVATE_KEY , {
privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
});
Network Operations
Switch Network
Basic Network Switch
Testnet Switch
await wallet . handleAction ( BaseActionType . SWITCH_NETWORK , {
networkName: "Base Sepolia"
});
dApp Connection
Connect to dApp
test ( 'connect wallet to dApp' , async ({ page , metamask }) => {
// Click connect button on dApp
await page . getByTestId ( 'ockConnectButton' ). click ();
// Select wallet from modal
await page . getByRole ( 'button' , { name: 'MetaMask' }). click ();
// Handle connection in wallet
await metamask . handleAction ( BaseActionType . CONNECT_TO_DAPP );
// Verify connection
await expect ( page . getByTestId ( 'wallet-connected' )). toBeVisible ();
});
Transaction Handling
Approve Transaction
await wallet . handleAction ( BaseActionType . HANDLE_TRANSACTION , {
approvalType: ActionApprovalType . APPROVE
});
Reject Transaction
await wallet . handleAction ( BaseActionType . HANDLE_TRANSACTION , {
approvalType: ActionApprovalType . REJECT
});
Complete Transaction Flow
test ( 'complete transaction' , async ({ page , metamask }) => {
// Trigger transaction on dApp
await page . getByRole ( 'button' , { name: 'Send Transaction' }). click ();
// Wait for wallet notification
await page . waitForTimeout ( 1000 );
// Approve transaction
await metamask . handleAction ( BaseActionType . HANDLE_TRANSACTION , {
approvalType: ActionApprovalType . APPROVE
});
// Wait for confirmation
await expect ( page . getByText ( 'Transaction confirmed' )). toBeVisible ();
});
Signature Handling
Sign Message
await wallet . handleAction ( BaseActionType . HANDLE_SIGNATURE , {
approvalType: ActionApprovalType . APPROVE
});
Sign Typed Data
test ( 'sign typed data' , async ({ page , metamask }) => {
// Trigger signature request
await page . getByRole ( 'button' , { name: 'Sign Message' }). click ();
// Approve signature
await metamask . handleAction ( BaseActionType . HANDLE_SIGNATURE , {
approvalType: ActionApprovalType . APPROVE
});
// Verify signature
await expect ( page . getByTestId ( 'signature-result' )). toBeVisible ();
});
Token Approvals
Change Spending Cap
await wallet . handleAction ( BaseActionType . CHANGE_SPENDING_CAP , {
approvalType: ActionApprovalType . APPROVE
});
Remove Spending Cap
await wallet . handleAction ( BaseActionType . REMOVE_SPENDING_CAP , {
approvalType: ActionApprovalType . APPROVE
});
Notification Detection
Both wallets support detecting the type of notification currently displayed:
const notificationType = await wallet . identifyNotificationType ();
// Returns: 'Transaction' | 'SpendingCap' | 'Signature' | 'RemoveSpendCap'
switch ( notificationType ) {
case 'Transaction' :
await wallet . handleAction ( BaseActionType . HANDLE_TRANSACTION , {
approvalType: ActionApprovalType . APPROVE
});
break ;
case 'SpendingCap' :
await wallet . handleAction ( BaseActionType . CHANGE_SPENDING_CAP , {
approvalType: ActionApprovalType . APPROVE
});
break ;
case 'Signature' :
await wallet . handleAction ( BaseActionType . HANDLE_SIGNATURE , {
approvalType: ActionApprovalType . APPROVE
});
break ;
}
Approval Types
All approval actions support these types:
enum ActionApprovalType {
APPROVE = "approve" ,
REJECT = "reject" ,
}
Complete Example
Here’s a complete example that demonstrates multiple common actions:
import { createOnchainTest , BaseActionType , ActionApprovalType } from '@coinbase/onchaintestkit' ;
import { metamaskWalletConfig } from './config/metamaskWalletConfig' ;
const test = createOnchainTest ( metamaskWalletConfig );
test ( 'complete wallet flow' , async ({ page , metamask }) => {
if ( ! metamask ) throw new Error ( 'MetaMask fixture is required' );
// Connect to dApp
await page . getByTestId ( 'ockConnectButton' ). click ();
await page . getByRole ( 'button' , { name: 'MetaMask' }). click ();
await metamask . handleAction ( BaseActionType . CONNECT_TO_DAPP );
// Switch network
await page . getByTestId ( 'switch-network' ). click ();
await metamask . handleAction ( BaseActionType . SWITCH_NETWORK , {
networkName: 'Base Sepolia' ,
isTestnet: true
});
// Perform swap transaction
await page . locator ( 'input[placeholder="0.0"]' ). fill ( '0.1' );
await page . getByRole ( 'button' , { name: 'Swap' }). click ();
// Handle spending cap if needed
let notificationType = await metamask . identifyNotificationType ();
if ( notificationType === 'SpendingCap' ) {
await metamask . handleAction ( BaseActionType . CHANGE_SPENDING_CAP , {
approvalType: ActionApprovalType . APPROVE
});
}
// Handle transaction
notificationType = await metamask . identifyNotificationType ();
if ( notificationType === 'Transaction' ) {
await metamask . handleAction ( BaseActionType . HANDLE_TRANSACTION , {
approvalType: ActionApprovalType . APPROVE
});
}
// Verify success
await expect ( page . getByRole ( 'link' , { name: 'View on Explorer' })). toBeVisible ();
});
Best Practices
Always check for wallet fixture existence before using it in tests
Never use production wallets or seed phrases in tests
Use identifyNotificationType()
when handling complex flows with multiple approval steps
Next Steps