# Wallet Mock
Fully functional end-to-end (E2E) tests for your decentralized application (dApp). This package installs a fully operational, headless Web3 Wallet into the [Playwright](https://github.com/microsoft/playwright) Browser Context. The wallet can be configured to execute on the blockchain or return mock responses. It is discoverable through [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) and leverages [viem](https://github.com/wevm/viem) `Account` and `Transport` interfaces for easy customization.

## Features
- Create comprehensive E2E tests for your dApps, including real blockchain transactions
- Mock specific calls or all calls to the wallet
- All wallet actions are pre-approved by default, eliminating the need for user interaction
- All wallet interactions are headless, meaning, no user interaction is required. You should be testing your dApp, not the wallet

## Quick start
### Install
```shell
npm install -D @finn_gal/playwright-wallet-mock-ts
```
### Example
```ts
import { test } from "@playwright/test";
import { installMockWallet } from "@finn_gal/playwright-wallet-mock-ts";
import { privateKeyToAccount } from "viem/accounts";
import { http } from "viem";
import { mainnet } from "viem/chains";

test.beforeEach(async ({ page }) => {
  await installMockWallet({
    page,
    account: privateKeyToAccount(
      "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
    ),
    defaultChain: {
      ...mainnet,
      rpcUrls: {
        default: {
          http: ["https://eth-mainnet.public.blastapi.io"],
        },
      },
    },
    transports: { [mainnet.id]: http() },
  });
});

test("Your Test", async ({ page }) => {
  await page.getByRole("button", { name: "Log In" }).click();
  await page.getByRole("button", { name: "Choose Wallet" }).click();
  await page.getByRole("menuitem", { name: "Mock Wallet" }).click();
});
```
> **Note:** This setup will execute actual transactions on the blockchain without user intervention using the provided Private Key.

## Mocking
Here's a simple example of how to mock a specific function while using regular RPC calls for all other functions:

```ts
await installMockWallet({
  page,
  account: privateKeyToAccount(
    "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
  ),
  defaultChain: sepolia,
  transports: {
    [sepolia.id]: (config) => {
      return custom({
        request: async ({ method, params }) => {
          // Mock only this RPC call
          if (method === "eth_sendTransaction") {
            return "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
          }

          return await http()(config).request({ method, params });
        },
      })(config);
    }
  },
});
```

## Wallet Methods Implementation Status

### Implemented 
- [x] `eth_accounts` - Returns wallet addresses
- [x] `eth_requestAccounts` - Returns wallet addresses
- [x] `wallet_requestPermissions` - Returns basic permissions
- [x] `wallet_revokePermissions` - Returns basic permissions
- [x] `wallet_getPermissions` - Returns empty permissions array
- [x] `wallet_switchEthereumChain` - Switches the current chain
- [x] `personal_sign` - Signs messages
- [x] `eth_signTypedData_v4` - Signs typed data (EIP-712)
- [x] `eth_sendTransaction` - Sends transactions

### Not Implemented Yet 
- [ ] `eth_signTypedData` - Basic typed data signing
- [ ] `eth_signTypedData_v3` - Version 3 of typed data signing

### Other RPC Methods 
All other standard RPC methods are automatically passed through to the wallet client for processing.

## Testing with Hardhat
To test with a local Hardhat node:

1. Start your local Hardhat Node:
   ```shell
   npx hardhat node
   ```

2. Connect the Mock Wallet to your Hardhat Node:
   ```ts
   import { hardhat } from "viem/chains";

   await installMockWallet({
     page,
     account: privateKeyToAccount(
       "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
     ),
     defaultChain: hardhat,
   });
   ```