### start() Source: https://onchaintestkit.xyz/onchaintestkit/node/api-reference Starts the Anvil node, allocating a port, spawning the process, and waiting for it to become ready. Example usage shows how to start the node and log its RPC URL. ```APIDOC ## start() ### Description Starts the Anvil node with the configured options. Allocates a port, spawns the process, and waits for readiness. ### Method `async start(): Promise` ### Example ```typescript const node = new LocalNodeManager() await node.start() console.log(`Node running at ${node.rpcUrl}`) ``` ``` -------------------------------- ### Comprehensive Coinbase Wallet Test Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/coinbase A full test example demonstrating dApp navigation, wallet connection, passkey setup, network switching, and transaction approval with Coinbase Wallet. ```typescript import { createOnchainTest, CoinbaseSpecificActionType, BaseActionType } from '@coinbase/onchaintestkit'; import { configure } from '@coinbase/onchaintestkit'; const config = configure() .withLocalNode({ chainId: 84532, forkUrl: process.env.E2E_TEST_FORK_URL, }) .withCoinbase() .withSeedPhrase({ seedPhrase: process.env.E2E_TEST_SEED_PHRASE!, password: 'COMPLEXPASSWORD1', }) .build(); const test = createOnchainTest(config); test('comprehensive Coinbase test', async ({ page, coinbase, node }) => { if (!coinbase) throw new Error('Coinbase fixture is required'); // Navigate to dApp await page.goto('https://app.example.com'); // Connect wallet await page.getByTestId('connect-wallet').click(); await page.getByRole('button', { name: 'Coinbase' }).click(); await coinbase.handleAction(BaseActionType.CONNECT_TO_DAPP); // Setup passkey const [passkeyPopup] = await Promise.all([ page.context().waitForEvent('page'), page.getByTestId('enable-passkey').click(), ]); await coinbase.handleAction(CoinbaseSpecificActionType.HANDLE_PASSKEY_POPUP, { mainPage: page, popup: passkeyPopup, passkeyAction: 'register', passkeyConfig: { name: 'Test Passkey', rpId: 'localhost', rpName: 'Example dApp', userId: 'test-user', isUserVerified: true, }, }); // Add custom network await coinbase.handleAction(CoinbaseSpecificActionType.ADD_NETWORK, { network: { name: 'Local Test Network', rpcUrl: `http://localhost:${node?.port}`, chainId: 84532, symbol: 'ETH', }, }); // Switch to the network await coinbase.handleAction(BaseActionType.SWITCH_NETWORK, { networkName: 'Local Test Network', }); // Perform transaction with passkey approval await page.getByRole('button', { name: 'Send Transaction' }).click(); const [txPopup] = await Promise.all([ page.context().waitForEvent('page'), page.getByRole('button', { name: 'Confirm' }).click(), ]); await coinbase.handleAction(CoinbaseSpecificActionType.HANDLE_PASSKEY_POPUP, { mainPage: page, popup: txPopup, passkeyAction: 'approve', }); // Verify success await expect(page.getByText('Transaction complete')).toBeVisible(); }); ``` -------------------------------- ### MetaMask Complete Example Configuration Source: https://onchaintestkit.xyz/onchaintestkit/configuration A comprehensive configuration for MetaMask, including local node setup, seed phrase, and network details. Ensure environment variables are set. ```typescript // e2e/config/metamask.config.ts import { baseSepolia } from "viem/chains" import { configure } from "@coinbase/onchaintestkit" export const DEFAULT_PASSWORD = "PASSWORD" export const DEFAULT_SEED_PHRASE = process.env.E2E_TEST_SEED_PHRASE const config = configure() .withLocalNode({ chainId: baseSepolia.id, forkUrl: process.env.E2E_TEST_FORK_URL, forkBlockNumber: BigInt(process.env.E2E_TEST_FORK_BLOCK_NUMBER ?? "0"), hardfork: "cancun", }) .withMetaMask() .withSeedPhrase({ seedPhrase: DEFAULT_SEED_PHRASE ?? "", password: DEFAULT_PASSWORD, }) .withNetwork({ name: "Base Sepolia", chainId: baseSepolia.id, symbol: "ETH", rpcUrl: "http://localhost:8545", }) .build() export const metamaskWalletConfig = config ``` -------------------------------- ### Comprehensive MetaMask Test Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/metamask A full example demonstrating MetaMask setup, account and network management, token addition, dApp connection, and transaction handling within a test. ```typescript import { createOnchainTest, MetaMaskSpecificActionType, BaseActionType } from '@coinbase/onchaintestkit'; import { configure } from '@coinbase/onchaintestkit'; import { baseSepolia } from "viem/chains" const config = configure() .withLocalNode({ chainId: baseSepolia.id, forkUrl: process.env.E2E_TEST_FORK_URL, }) .withMetaMask() .withSeedPhrase({ seedPhrase: process.env.E2E_TEST_SEED_PHRASE!, password: 'PASSWORD', }) .withNetwork({ name: "Base Sepolia", chainId: baseSepolia.id, symbol: "ETH", // placeholder for the actual rpcUrl, which is auto injected by the node fixture rpcUrl: "http://localhost:8545", }) .build(); const test = createOnchainTest(config); test('comprehensive MetaMask test', async ({ page, metamask }) => { if (!metamask) throw new Error('MetaMask fixture is required'); // Add accounts await metamask.handleAction(MetaMaskSpecificActionType.ADD_ACCOUNT, { accountName: 'DeFi Account', }); // Add custom network await metamask.handleAction(MetaMaskSpecificActionType.ADD_NETWORK, { network: { name: 'Base Mainnet', rpcUrl: 'https://mainnet.base.org', chainId: 8453, symbol: 'ETH', }, }); // Switch network await metamask.handleAction(BaseActionType.SWITCH_NETWORK, { networkName: 'Base Mainnet', }); // Add tokens await metamask.handleAction(MetaMaskSpecificActionType.ADD_TOKEN, { tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', tokenSymbol: 'USDC', tokenDecimals: 6, }); // Connect to dApp await page.goto('https://app.example.com'); await page.getByTestId('connect-wallet').click(); await page.getByRole('button', { name: 'MetaMask' }).click(); await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP); // Perform transaction await page.getByRole('button', { name: 'Send Transaction' }).click(); await metamask.handleAction(BaseActionType.HANDLE_TRANSACTION, { approvalType: ActionApprovalType.APPROVE, }); }); ``` -------------------------------- ### Basic Wallet Action Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Demonstrates how to perform a basic wallet action, such as connecting to a dApp. ```typescript await wallet.handleAction(BaseActionType.CONNECT_TO_DAPP); ``` -------------------------------- ### Install Foundry and Verify Source: https://onchaintestkit.xyz/onchaintestkit/installation Installs Foundry using the official installer script and verifies the installation by checking the anvil version. Remember to update your PATH. ```bash curl -L https://foundry.paradigm.xyz | bash source ~/.bashrc anvil --version ``` -------------------------------- ### Coinbase Wallet Complete Example Configuration Source: https://onchaintestkit.xyz/onchaintestkit/configuration A comprehensive configuration for Coinbase Wallet, including local node setup, seed phrase, and network details. Ensure environment variables are set. ```typescript // e2e/config/coinbase.config.ts import { baseSepolia } from "viem/chains" import { configure } from "@coinbase/onchaintestkit" export const DEFAULT_PASSWORD = "COMPLEXPASSWORD1" export const DEFAULT_SEED_PHRASE = process.env.E2E_TEST_SEED_PHRASE const config = configure() .withLocalNode({ chainId: baseSepolia.id, forkUrl: process.env.E2E_TEST_FORK_URL, forkBlockNumber: BigInt(process.env.E2E_TEST_FORK_BLOCK_NUMBER ?? "0"), hardfork: "cancun", }) .withCoinbase() .withSeedPhrase({ seedPhrase: DEFAULT_SEED_PHRASE ?? "", password: DEFAULT_PASSWORD, }) .withNetwork({ name: "Base Sepolia", chainId: baseSepolia.id, symbol: "ETH", rpcUrl: "http://localhost:8545", }) .build() export const coinbaseWalletConfig = config ``` -------------------------------- ### Install Foundry Source: https://onchaintestkit.xyz/onchaintestkit/quickstart Install Foundry, a blockchain development toolkit, using the provided curl command and then update it. ```bash curl -L https://foundry.paradigm.xyz | bash foundryup ``` -------------------------------- ### Install OnchainTestKit with Bun Source: https://onchaintestkit.xyz/onchaintestkit/installation Installs OnchainTestKit, Playwright, and necessary wallet extensions using Bun. Ensure Playwright browsers are installed with system dependencies. ```bash bun add -D @coinbase/onchaintestkit @playwright/test bunx playwright install --with-deps bun prepare-metamask bun prepare-coinbase ``` -------------------------------- ### Wallet Action with Options Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Shows how to execute a wallet action with specific options, like approving a transaction. ```typescript await wallet.handleAction(BaseActionType.HANDLE_TRANSACTION, { approvalType: ActionApprovalType.APPROVE }); ``` -------------------------------- ### Network Switching Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Illustrates how to switch the wallet to a different network, specifying network name and testnet status. ```typescript await wallet.handleAction(BaseActionType.SWITCH_NETWORK, { networkName: 'Base Sepolia', isTestnet: true }); ``` -------------------------------- ### Install OnchainTestKit with npm Source: https://onchaintestkit.xyz/onchaintestkit/installation Installs OnchainTestKit, Playwright, and necessary wallet extensions using npm. Ensure Playwright browsers are installed with system dependencies. ```bash npm install -D @coinbase/onchaintestkit @playwright/test npx playwright install --with-deps npm run prepare-metamask npm run prepare-coinbase ``` -------------------------------- ### Install OnchainTestKit with Yarn Source: https://onchaintestkit.xyz/onchaintestkit/installation Installs OnchainTestKit, Playwright, and necessary wallet extensions using Yarn. Ensure Playwright browsers are installed with system dependencies. ```bash yarn add -D @coinbase/onchaintestkit @playwright/test yarn playwright install --with-deps yarn prepare-metamask yarn prepare-coinbase ``` -------------------------------- ### Complete Passkey Flow Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/coinbase Demonstrates a full end-to-end flow involving connecting a wallet, registering a passkey, and approving a transaction using the passkey. ```typescript test('complete passkey flow', async ({ page, coinbase }) => { if (!coinbase) throw new Error('Coinbase fixture is required'); // Connect wallet await page.getByTestId('connect-wallet').click(); await page.getByRole('button', { name: 'Coinbase' }).click(); await coinbase.handleAction(BaseActionType.CONNECT_TO_DAPP); // Register passkey const [registerPopup] = await Promise.all([ page.context().waitForEvent('page'), page.getByTestId('setup-passkey').click(), ]); await coinbase.handleAction(CoinbaseSpecificActionType.HANDLE_PASSKEY_POPUP, { mainPage: page, popup: registerPopup, passkeyAction: 'register', passkeyConfig: { name: 'Test Passkey', rpId: 'localhost', rpName: 'Test dApp', userId: 'user-' + Date.now(), isUserVerified: true, }, }); // Use passkey for transaction await page.getByRole('button', { name: 'Send ETH' }).click(); const [txPopup] = await Promise.all([ page.context().waitForEvent('page'), page.getByRole('button', { name: 'Confirm' }).click(), ]); await coinbase.handleAction(CoinbaseSpecificActionType.HANDLE_PASSKEY_POPUP, { mainPage: page, popup: txPopup, passkeyAction: 'approve', }); // Verify transaction success await expect(page.getByText('Transaction successful')).toBeVisible(); }); ``` -------------------------------- ### Build Smart Contracts Source: https://onchaintestkit.xyz/onchaintestkit/smart-contracts Installs project dependencies and builds the smart contracts using Forge. ```bash cd smart-contracts # Install dependencies forge install foundry-rs/forge-std OpenZeppelin/openzeppelin-contracts # Build contracts forge build ``` -------------------------------- ### Verify OnchainTestKit Installation Source: https://onchaintestkit.xyz/onchaintestkit/installation Commands to check if Node.js, Playwright, and Anvil are installed correctly, and to list available Playwright browsers. ```bash # Check Node.js node --version # Check Playwright npx playwright --version # Check Anvil anvil --version # List installed browsers npx playwright show-browsers ``` -------------------------------- ### Set Up Contract State for Tests Source: https://onchaintestkit.xyz/onchaintestkit/contracts/smart-contract-manager Deploys contracts and executes calls as specified in a setup configuration. Useful for complex test scenario setup. ```typescript async setContractState( config: SetupConfig, node: LocalNodeManager ): Promise ``` -------------------------------- ### Start Local Node Source: https://onchaintestkit.xyz/onchaintestkit/node/api-reference Starts the Anvil node, allocates a port, spawns the process, and waits for readiness. Use this to initialize the node before interacting with it. ```typescript const node = new LocalNodeManager() await node.start() console.log(`Node running at ${node.rpcUrl}`) ``` -------------------------------- ### Example: Default Balance Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Set the default balance in wei for newly generated test accounts. ```typescript defaultBalance: parseEther("100") ``` -------------------------------- ### MetaMask Basic Setup Source: https://onchaintestkit.xyz/onchaintestkit/configuration Configure MetaMask with a seed phrase for basic testing. Ensure the E2E_TEST_SEED_PHRASE environment variable is set. ```typescript import { configure } from '@coinbase/onchaintestkit'; const metamaskConfig = configure() .withMetaMask() .withSeedPhrase({ seedPhrase: process.env.E2E_TEST_SEED_PHRASE!, password: 'PASSWORD', }) .build(); ``` -------------------------------- ### Start Local Node Manager Source: https://onchaintestkit.xyz/onchaintestkit/node/overview Initializes and starts a LocalNodeManager instance with specified chain, fork, and hardfork configurations. Automatically allocates an available port for the node. Use this to set up your testing environment. ```typescript import { LocalNodeManager } from '@coinbase/onchaintestkit' import { baseSepolia } from 'viem/chains' // Create a node manager with automatic port allocation const node = new LocalNodeManager({ chainId: baseSepolia.id, forkUrl: process.env.E2E_TEST_FORK_URL, forkBlockNumber: BigInt(process.env.E2E_TEST_FORK_BLOCK_NUMBER ?? "0"), hardfork: "cancun", }) // Start the node await node.start() console.log(`Node running on port ${node.getPort()}`) // Manipulate chain state const snapshotId = await node.snapshot() // ...run tests... await node.revert(snapshotId) // Clean up await node.stop() ``` -------------------------------- ### Install OnchainTestKit and Playwright Dependencies Source: https://onchaintestkit.xyz/onchaintestkit/quickstart Install the necessary OnchainTestKit and Playwright packages as development dependencies and download Playwright's browser binaries. ```bash yarn add -D @coinbase/onchaintestkit @playwright/test yarn playwright install --with-deps ``` -------------------------------- ### Complete dApp Wallet Flow Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/common-actions Demonstrates a full end-to-end test scenario for a dApp, including connecting to the dApp, switching networks, performing a swap, and handling transaction approvals. ```typescript 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(); }); ``` -------------------------------- ### WalletSetupContext Interface Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Contextual information provided during wallet setup. This can include details like the local node port. ```typescript interface WalletSetupContext { localNodePort?: number; } ``` -------------------------------- ### Example: Fork URL Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Specify a URL to fork from, enabling fork mode for the local node. ```typescript forkUrl: "https://mainnet.base.org" ``` -------------------------------- ### Complete MetaMask Account Management Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/metamask Demonstrates a full cycle of account management operations within MetaMask, including adding, switching, and removing accounts. ```typescript test('MetaMask account management', async ({ page, metamask }) => { if (!metamask) throw new Error('MetaMask fixture is required'); // Add a new account await metamask.handleAction(MetaMaskSpecificActionType.ADD_ACCOUNT, { accountName: 'DeFi Account', }); // Add another account await metamask.handleAction(MetaMaskSpecificActionType.ADD_ACCOUNT, { accountName: 'Trading Account', }); // Switch between accounts await metamask.handleAction(MetaMaskSpecificActionType.SWITCH_ACCOUNT, { accountName: 'DeFi Account', }); // Remove an account await metamask.handleAction(MetaMaskSpecificActionType.REMOVE_ACCOUNT, { accountName: 'Trading Account', }); }); ``` -------------------------------- ### Example: Basic Local Testing Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Configure a local node for testing with a specific chain ID, default balance, and number of accounts. ```typescript const node = new LocalNodeManager({ chainId: 31337, defaultBalance: parseEther("1000"), totalAccounts: 5, }) ``` -------------------------------- ### Configure MetaMask with Custom Setup Source: https://onchaintestkit.xyz/onchaintestkit/wallets/metamask Sets up MetaMask with a seed phrase and includes custom actions like importing accounts, adding tokens, and configuring networks. ```typescript const metamaskConfig = configure() .withMetaMask() .withSeedPhrase({ seedPhrase: process.env.E2E_TEST_SEED_PHRASE!, password: 'PASSWORD', }) .withCustomSetup(async (wallet, context) => { // Import additional accounts await wallet.handleAction(BaseActionType.IMPORT_WALLET_FROM_PRIVATE_KEY, { privateKey: process.env.SECONDARY_PRIVATE_KEY!, }); // Add custom tokens await wallet.handleAction(MetaMaskSpecificActionType.ADD_TOKEN, { tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', tokenSymbol: 'USDC', tokenDecimals: 6, }); // Add custom networks await wallet.handleAction(MetaMaskSpecificActionType.ADD_NETWORK, { network: { name: 'Base Mainnet', rpcUrl: 'https://mainnet.base.org', chainId: 8453, symbol: 'ETH', }, }); }) .build(); ``` -------------------------------- ### Coinbase Wallet Basic Setup Source: https://onchaintestkit.xyz/onchaintestkit/configuration Configure Coinbase Wallet with a seed phrase for basic testing. Ensure the E2E_TEST_SEED_PHRASE environment variable is set. ```typescript import { configure } from '@coinbase/onchaintestkit'; const coinbaseConfig = configure() .withCoinbase() .withSeedPhrase({ seedPhrase: process.env.E2E_TEST_SEED_PHRASE!, password: 'COMPLEXPASSWORD1', }) .build(); ``` -------------------------------- ### Example: Fixed Port Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Configure the node to use a specific, fixed port for the RPC server. ```typescript const node = new LocalNodeManager({ port: 8545, // Always use port 8545 chainId: 31337, }) ``` -------------------------------- ### Example: Mnemonic Phrase Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Provide a mnemonic phrase for generating deterministic test accounts. ```typescript mnemonic: "test test test test test test test test test test test junk" ``` -------------------------------- ### Basic ERC20 Token Deployment and Minting Source: https://onchaintestkit.xyz/onchaintestkit/contracts/smart-contract-manager Demonstrates deploying an ERC20 token using SmartContractManager and then minting tokens. Ensure the node is started and clients are initialized before deployment. ```typescript import { SmartContractManager } from '@coinbase/onchaintestkit/contracts/SmartContractManager'; import { LocalNodeManager } from '@coinbase/onchaintestkit/node/LocalNodeManager'; async function deployToken() { const node = new LocalNodeManager({ chainId: 31337 }); await node.start(); try { const scm = new SmartContractManager(process.cwd()); await scm.initialize(node); // Deploy ERC20 token const tokenAddress = await scm.deployContract({ name: 'ERC20Token', args: ['Test Token', 'TEST', 1000000n * 10n ** 18n], salt: '0x' + '01'.repeat(32), deployer: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', }); console.log(`Token deployed at: ${tokenAddress}`); // Mint tokens await scm.executeCall({ target: tokenAddress, functionName: 'mint', args: ['0x70997970C51812dc3A010C7d01b50e0d17dc79C8', 1000n * 10n ** 18n], account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', }); } finally { await node.stop(); } } ``` -------------------------------- ### Example: Fork Block Number Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Set a specific block number to fork from. This option requires `forkUrl` to be set. ```typescript forkBlockNumber: 18000000n ``` -------------------------------- ### Add Multiple Tokens to MetaMask Example Source: https://onchaintestkit.xyz/onchaintestkit/wallets/metamask Demonstrates adding multiple ERC-20 tokens, such as USDC and DAI, to MetaMask in a single test. ```typescript test('add multiple tokens', async ({ page, metamask }) => { // Add USDC await metamask.handleAction(MetaMaskSpecificActionType.ADD_TOKEN, { tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', tokenSymbol: 'USDC', tokenDecimals: 6, }); // Add DAI await metamask.handleAction(MetaMaskSpecificActionType.ADD_TOKEN, { tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', tokenSymbol: 'DAI', tokenDecimals: 18, }); }); ``` -------------------------------- ### Example: Custom Port Range Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Configure the node to use a dynamic port within a specified range for the RPC server. ```typescript const node = new LocalNodeManager({ portRange: [20000, 30000], // Use ports 20000-30000 chainId: 31337, }) ``` -------------------------------- ### Example: Forking Mainnet Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Set up a node to fork from Ethereum Mainnet using an environment variable for the RPC URL, a specific block number, and the Cancun hardfork. ```typescript const node = new LocalNodeManager({ chainId: 1, forkUrl: process.env.ETH_MAINNET_RPC, forkBlockNumber: 18500000n, hardfork: "cancun", }) ``` -------------------------------- ### Example: Base Sepolia Fork Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Configure a node to fork from Base Sepolia, using environment variables for the RPC URL and mnemonic, and a dynamic fork block number. ```typescript const node = new LocalNodeManager({ chainId: baseSepolia.id, forkUrl: process.env.BASE_SEPOLIA_RPC, forkBlockNumber: BigInt(process.env.FORK_BLOCK || "0"), mnemonic: process.env.TEST_MNEMONIC, }) ``` -------------------------------- ### ConfigBuilder Methods Interface Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Defines the fluent interface for building onchain test configurations, allowing chaining of various setup methods. ```typescript interface ConfigBuilder { withMetaMask(): ConfigBuilder; withCoinbase(): ConfigBuilder; withSeedPhrase(config: SeedPhraseConfig): ConfigBuilder; withNetwork(network: NetworkConfig): ConfigBuilder; withLocalNode(config: LocalNodeConfig): ConfigBuilder; withCustomSetup(setup: CustomSetupFunction): ConfigBuilder; build(): OnchainTestConfig; } ``` -------------------------------- ### setContractState() Source: https://onchaintestkit.xyz/onchaintestkit/contracts/smart-contract-manager Deploys contracts and executes calls as specified in a setup config. This is useful for setting up complex test scenarios. ```APIDOC ## setContractState(config: SetupConfig, node: LocalNodeManager) ### Description Deploys contracts and executes calls as specified in a setup config. This is useful for setting up complex test scenarios. ### Parameters #### Path Parameters - **config** (SetupConfig) - Required - Setup configuration with deployments and calls - **node** (LocalNodeManager) - Required - The local node manager instance ### Returns - **Promise** ``` -------------------------------- ### GitHub Actions E2E Test Workflow Source: https://onchaintestkit.xyz/onchaintestkit/ci-cd A basic GitHub Actions workflow to run end-to-end tests for a project. It includes steps for checking out code, setting up Node.js, installing dependencies, building contracts, preparing wallet extensions, building the application, and running E2E tests. ```yaml name: E2E Tests on: push: branches: [main, develop] pull_request: branches: [main] jobs: e2e: runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' - name: Set up Corepack + yarn run: | npm install -g corepack yarn set version 4.9.2 - name: Install root dependencies run: yarn - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 - name: Build contracts run: | cd smart-contracts forge install foundry-rs/forge-std forge install OpenZeppelin/openzeppelin-contracts forge build - name: Install Playwright browsers run: yarn playwright install --with-deps - name: Prepare wallet extensions run: | yarn prepare-metamask yarn prepare-coinbase - name: Build application run: | echo "E2E_TEST_SEED_PHRASE=${{ secrets.E2E_TEST_SEED_PHRASE }}" > .env echo "E2E_CONTRACT_PROJECT_ROOT=../smart-contracts" >> .env yarn build - name: Install xvfb run: sudo apt-get update && sudo apt-get install -y xvfb - name: Run E2E tests env: NODE_OPTIONS: '--dns-result-order=ipv4first' run: xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" yarn test:e2e ``` -------------------------------- ### Coinbase Wallet Configuration Interface Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Defines the configuration object for setting up a Coinbase wallet, including optional seed phrase, network, and custom setup functions. ```typescript interface CoinbaseConfig { type: 'coinbase'; seedPhrase?: { phrase: string; password: string; }; network?: NetworkConfig; customSetup?: (wallet: CoinbaseWallet, context: WalletSetupContext) => Promise; } ``` -------------------------------- ### Error Handling with Try-Catch Block Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Provides an example of how to wrap wallet actions in a try-catch block to handle potential errors like timeouts or rejections. ```typescript try { await wallet.handleAction(BaseActionType.CONNECT_TO_DAPP); } catch (error) { if (error.message.includes('timeout')) { // Handle timeout } else if (error.message.includes('rejected')) { // Handle rejection } } ``` -------------------------------- ### Advanced Coinbase Wallet Configuration Source: https://onchaintestkit.xyz/onchaintestkit/wallets/coinbase Advanced configuration including network settings and custom setup actions like adding tokens and accounts. ```typescript const coinbaseConfig = configure() .withCoinbase() .withSeedPhrase({ seedPhrase: process.env.E2E_TEST_SEED_PHRASE!, password: 'COMPLEXPASSWORD1', }) .withNetwork({ name: 'Base Sepolia', chainId: 84532, symbol: 'ETH', rpcUrl: 'https://sepolia.base.org', }) .withCustomSetup(async (wallet, context) => { // Add custom tokens await wallet.handleAction(CoinbaseSpecificActionType.ADD_TOKEN, { tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', tokenSymbol: 'USDC', tokenDecimals: 6, }); // Add additional accounts await wallet.handleAction(CoinbaseSpecificActionType.ADD_ACCOUNT, { accountName: 'DeFi Operations', }); }) .build(); ``` -------------------------------- ### Prepare Metamask and Coinbase Wallets Source: https://onchaintestkit.xyz/onchaintestkit/quickstart Run these commands to prepare the Metamask and Coinbase wallet extensions for testing. ```bash yarn prepare-metamask yarn prepare-coinbase ``` -------------------------------- ### Get Node Port Source: https://onchaintestkit.xyz/onchaintestkit/node/api-reference Retrieves the allocated port number for the running node instance. Returns null if the node has not been started. ```typescript const port = node.getPort() // Use port for configuration ``` -------------------------------- ### Create Foundry Project Source: https://onchaintestkit.xyz/onchaintestkit/smart-contracts Initializes a new Foundry project for smart contract development. ```bash mkdir smart-contracts && cd smart-contracts forge init ``` -------------------------------- ### configure() Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Creates a configuration builder to set up wallet and network options for onchain tests. ```APIDOC ## configure() ### Description Creates a configuration builder. ### Signature ```typescript function configure(): ConfigBuilder; ``` ``` -------------------------------- ### General Configuration Builder Source: https://onchaintestkit.xyz/onchaintestkit/configuration Use the `configure()` function to chain methods for setting up wallet and network configurations for your tests. ```typescript import { configure } from '@coinbase/onchaintestkit'; const config = configure() .withLocalNode({ chainId: 1337 }) .withMetaMask() .withNetwork({ name: 'Base Sepolia', rpcUrl: 'http://localhost:8545', chainId: 84532, symbol: 'ETH', }) .withSeedPhrase({ seedPhrase: process.env.E2E_TEST_SEED_PHRASE!, password: 'PASSWORD', }) .build(); ``` -------------------------------- ### getPort() Source: https://onchaintestkit.xyz/onchaintestkit/node/api-reference Retrieves the allocated port number for the node instance. Returns null if the node has not been started. ```APIDOC ## getPort() ### Description Returns the allocated port number for this node instance, or `null` if not started. ### Method `getPort(): number | null` ### Example ```typescript const port = node.getPort() // Use port for configuration ``` ``` -------------------------------- ### Example SimpleToken Contract Source: https://onchaintestkit.xyz/onchaintestkit/smart-contracts A basic ERC20 token contract with minting functionality controlled by the owner. ```solidity // smart-contracts/src/SimpleToken.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract SimpleToken is ERC20, Ownable { uint256 public constant MAX_SUPPLY = 1000000 * 10**18; constructor() ERC20("Simple Token", "STK") Ownable(msg.sender) { _mint(msg.sender, MAX_SUPPLY / 10); } function mint(address to, uint256 amount) public onlyOwner { require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply"); _mint(to, amount); } } ``` -------------------------------- ### initialize() Source: https://onchaintestkit.xyz/onchaintestkit/contracts/smart-contract-manager Initializes viem clients and ensures the proxy is deployed. This method must be called before using other methods of the SmartContractManager. ```APIDOC ## initialize(node: LocalNodeManager) ### Description Initializes viem clients and ensures the proxy is deployed. Must be called before using other methods. ### Parameters #### Path Parameters - **node** (LocalNodeManager) - Required - The local node manager instance ### Returns - **Promise** ``` -------------------------------- ### Initialize OnchainTestKit with Configuration Source: https://onchaintestkit.xyz/onchaintestkit/configuration Import and use the createOnchainTest function with your wallet configuration to set up your testing environment. ```typescript import { createOnchainTest } from '@coinbase/onchaintestkit'; import { metamaskWalletConfig } from './config/metamask.config'; const test = createOnchainTest(metamaskWalletConfig); test('my test', async ({ page, metamask, node }) => { // Your test code here console.log(`Local node running on port: ${node?.port}`); }); ``` -------------------------------- ### PasskeyAuthenticator Class Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference WebAuthn virtual authenticator for Coinbase Wallet. Manages the setup, creation, retrieval, and cleanup of WebAuthn credentials. ```APIDOC ## PasskeyAuthenticator ### Description WebAuthn virtual authenticator for Coinbase Wallet. Manages the setup, creation, retrieval, and cleanup of WebAuthn credentials. ### Instance Methods #### setup(options: PasskeySetupOptions): Promise - **Description**: Sets up the WebAuthn virtual authenticator. - **Parameters**: - `options` (PasskeySetupOptions) - Options for setting up the authenticator. #### createCredential(options: CredentialCreationOptions): Promise - **Description**: Creates a new WebAuthn credential. - **Parameters**: - `options` (CredentialCreationOptions) - Options for creating the credential. - **Returns**: `Promise` #### getCredential(options: CredentialRequestOptions): Promise - **Description**: Retrieves an existing WebAuthn credential. - **Parameters**: - `options` (CredentialRequestOptions) - Options for retrieving the credential. - **Returns**: `Promise` #### cleanup(): Promise - **Description**: Cleans up the WebAuthn virtual authenticator. ``` -------------------------------- ### stop() Source: https://onchaintestkit.xyz/onchaintestkit/node/api-reference Stops the running Anvil node and performs necessary cleanup of resources. Example shows a simple call to stop the node. ```APIDOC ## stop() ### Description Stops the running Anvil node and cleans up resources. ### Method `async stop(): Promise` ### Example ```typescript await node.stop() ``` ``` -------------------------------- ### Get Available Accounts Source: https://onchaintestkit.xyz/onchaintestkit/node/api-reference Retrieves a list of all available Ethereum account addresses managed by the local node. These accounts are pre-funded for testing. ```typescript const accounts = await node.getAccounts() console.log(`Available accounts: ${accounts.length}`) ``` -------------------------------- ### Get Proxy Address Source: https://onchaintestkit.xyz/onchaintestkit/contracts/proxy-deployer Retrieves the fixed address where the deterministic deployment proxy is deployed. This address is constant across all EVM-compatible chains. ```typescript const proxyAddress = proxyDeployer.getProxyAddress(); console.log(`Proxy deployed at: ${proxyAddress}`); ``` -------------------------------- ### Download Wallet Extensions Source: https://onchaintestkit.xyz/onchaintestkit/quickstart Download the MetaMask and Coinbase Wallet browser extensions required for testing. ```bash # Download MetaMask yarn prepare-metamask # Download Coinbase Wallet yarn prepare-coinbase ``` -------------------------------- ### Reset Chain State Source: https://onchaintestkit.xyz/onchaintestkit/node/api-reference Resets the chain state to its initial configuration or to a specified fork block. This is useful for starting tests from a clean slate. ```typescript await node.reset(forkBlock) ``` -------------------------------- ### Manage Coinbase Accounts Source: https://onchaintestkit.xyz/onchaintestkit/wallets/coinbase Demonstrates adding multiple accounts and switching between them using Coinbase Wallet. ```typescript test('manage Coinbase accounts', async ({ page, coinbase }) => { // Add multiple accounts await coinbase.handleAction(CoinbaseSpecificActionType.ADD_ACCOUNT, { accountName: 'Trading Account', }); await coinbase.handleAction(CoinbaseSpecificActionType.ADD_ACCOUNT, { accountName: 'Savings Account', }); // Switch to specific account await coinbase.handleAction(CoinbaseSpecificActionType.SWITCH_ACCOUNT, { accountName: 'Trading Account', }); }); ``` -------------------------------- ### Initialize SmartContractManager Clients Source: https://onchaintestkit.xyz/onchaintestkit/contracts/smart-contract-manager Initializes viem clients and ensures the proxy is deployed. This method must be called before using other SmartContractManager methods. ```typescript async initialize(node: LocalNodeManager): Promise ``` -------------------------------- ### Optional Environment Variables for Forking and RPC Source: https://onchaintestkit.xyz/onchaintestkit/configuration Configure fork settings, smart contract project paths, custom RPC endpoints, and test timeouts using these environment variables. ```bash # Fork configuration E2E_TEST_FORK_URL="https://mainnet.base.org" E2E_TEST_FORK_BLOCK_NUMBER="12345678" # Smart contract project E2E_CONTRACT_PROJECT_ROOT="../smart-contracts" # Custom RPC endpoints E2E_BASE_MAINNET_RPC="https://my-custom-rpc.com" E2E_BASE_SEPOLIA_RPC="https://my-testnet-rpc.com" # Test timeouts E2E_TEST_TIMEOUT="60000" ``` -------------------------------- ### Passkey Handling Action for Coinbase Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Shows how to handle passkey-related popups in Coinbase Wallet, specifying the action and configuration details. ```typescript await coinbase.handleAction(CoinbaseSpecificActionType.HANDLE_PASSKEY_POPUP, { mainPage: page, popup: popup, passkeyAction: 'register', passkeyConfig: { name: 'Test Passkey', rpId: 'localhost', rpName: 'My dApp', userId: 'user123', isUserVerified: true } }); ``` -------------------------------- ### Configure Function Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Initializes a configuration builder for setting up onchain tests. ```typescript function configure(): ConfigBuilder; ``` -------------------------------- ### MetaMask Wallet Configuration Interface Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Defines the configuration object for setting up a MetaMask wallet, including optional seed phrase, network, and custom setup functions. ```typescript interface MetaMaskConfig { type: 'metamask'; seedPhrase?: { phrase: string; password: string; }; network?: NetworkConfig; customSetup?: (wallet: MetaMask, context: WalletSetupContext) => Promise; } ``` -------------------------------- ### Import Wallet from Private Key (MetaMask) Source: https://onchaintestkit.xyz/onchaintestkit/wallets/common-actions Imports a wallet into MetaMask using a private key. ```typescript await metamask.handleAction(BaseActionType.IMPORT_WALLET_FROM_PRIVATE_KEY, { privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" }); ``` -------------------------------- ### Test Onchain Interactions with Mainnet Fork Source: https://onchaintestkit.xyz/onchaintestkit/node/overview Configures and starts a LocalNodeManager to fork from Ethereum mainnet at a specific block number. This allows testing interactions against a realistic, live state. ```typescript // Fork mainnet for realistic testing const node = new LocalNodeManager({ chainId: 1, forkUrl: "https://eth-mainnet.g.alchemy.com/v2/YOUR-API-KEY", forkBlockNumber: 18000000n, }) await node.start() // Test against real mainnet state ``` -------------------------------- ### ConfigBuilder Methods Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Methods available on the ConfigBuilder to customize wallet and network settings. ```APIDOC ## ConfigBuilder Methods ### withMetaMask() Adds MetaMask wallet configuration. ### withCoinbase() Adds Coinbase wallet configuration. ### withSeedPhrase(config: SeedPhraseConfig) Configures the wallet with a seed phrase. ### withNetwork(network: NetworkConfig) Sets the network configuration for the wallet. ### withLocalNode(config: LocalNodeConfig) Configures a local node connection. ### withCustomSetup(setup: CustomSetupFunction) Provides a custom setup function for wallet initialization. ### build(): OnchainTestConfig Builds the final onchain test configuration. ``` -------------------------------- ### Example: Manual Mining Mode Configuration Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Configure the node to disable automatic mining and set a custom block gas limit. Blocks must be mined manually using `node.mine()`. ```typescript const node = new LocalNodeManager({ noMining: true, blockGasLimit: 30_000_000n, }) await node.start() // Manually mine blocks when needed await node.mine(1) ``` -------------------------------- ### Deploy SimpleToken with CREATE2 Source: https://onchaintestkit.xyz/onchaintestkit/smart-contracts Deploys the SimpleToken contract deterministically using CREATE2 with a specified salt and deployer address. Verifies deployment by checking the contract's bytecode. ```typescript test("should deploy SimpleToken contract using CREATE2", async ({ page, smartContractManager, node, }) => { if (!smartContractManager || !node) { throw new Error("SmartContractManager or node not initialized") } // Deploy the SimpleToken contract const salt = "0x0000000000000000000000000000000000000000000000000000000000000001" as Hex const deployer = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" as Address // Anvil's first account const tokenAddress = await smartContractManager.deployContract({ name: "SimpleToken", args: [], salt, deployer, }) // Verify the contract was deployed expect(tokenAddress).toBeDefined() expect(tokenAddress).toMatch(/^0x[a-fA-F0-9]{40}$/) // Create a public client to verify the deployment const publicClient = createPublicClient({ chain: localhost, transport: http(`http://localhost:${node.port}`), }) // Check the contract code exists const code = await publicClient.getBytecode({ address: tokenAddress }) expect(code).toBeDefined() expect(code).not.toBe("0x") console.log(`SimpleToken deployed at: ${tokenAddress}`) }) ``` -------------------------------- ### wallet.handleAction() Source: https://onchaintestkit.xyz/onchaintestkit/wallets/api-reference Handles various wallet actions, such as connecting to a dApp, approving transactions, or switching networks. ```APIDOC ## wallet.handleAction(actionType, options) ### Description Handles a specific wallet action. ### Parameters #### actionType - **BaseActionType** (enum) - The type of action to perform (e.g., CONNECT_TO_DAPP, HANDLE_TRANSACTION, SWITCH_NETWORK). #### options - **object** - Optional. Options specific to the action type. - **approvalType** (ActionApprovalType) - For transaction handling. - **networkName** (string) - For network switching. - **isTestnet** (boolean) - For network switching. ### Example ```typescript await wallet.handleAction(BaseActionType.CONNECT_TO_DAPP); await wallet.handleAction(BaseActionType.HANDLE_TRANSACTION, { approvalType: ActionApprovalType.APPROVE }); await wallet.handleAction(BaseActionType.SWITCH_NETWORK, { networkName: 'Base Sepolia', isTestnet: true }); ``` ``` -------------------------------- ### Initialize LocalNodeManager with Environment Variables Source: https://onchaintestkit.xyz/onchaintestkit/node/configuration Instantiate the LocalNodeManager using values from environment variables for chain ID, fork URL, fork block number, and mnemonic. ```typescript const node = new LocalNodeManager({ chainId: baseSepolia.id, forkUrl: process.env.E2E_TEST_FORK_URL, forkBlockNumber: BigInt(process.env.E2E_TEST_FORK_BLOCK_NUMBER ?? "0"), mnemonic: process.env.E2E_TEST_SEED_PHRASE, }) ``` -------------------------------- ### Interact with Deployed Contract via UI Source: https://onchaintestkit.xyz/onchaintestkit/smart-contracts Simulates connecting a wallet (MetaMask) and interacting with a deployed contract through a web UI. Ensure MetaMask is available and configured. ```typescript test("should connect wallet and interact with deployed contract", async ({ page, metamask, smartContractManager, node, }) => { if (!metamask) { throw new Error("MetaMask is not defined") } // Deploy contract first const salt = "0x0000000000000000000000000000000000000000000000000000000000000006" as Hex const deployer = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" as Address const tokenAddress = await smartContractManager.deployContract({ name: "SimpleToken", args: [], salt, deployer, }) // Connect wallet to the app await page.getByTestId("ockConnectButton").first().click() await page .getByTestId("ockModalOverlay") .first() .getByRole("button", { name: "MetaMask" }) .click() // Handle MetaMask connection await metamask.handleAction(BaseActionType.CONNECT_TO_DAPP) // Verify wallet is connected await page.waitForSelector("text=/0x[a-fA-F0-9]{4}.*[a-fA-F0-9]{4}/", { timeout: 10000, }) // Now the user could interact with the deployed contract through the UI console.log(`User can now interact with token at: ${tokenAddress}`) }) ```