# Wallet Detection

When using Protocol v2 on EVM chains, you need to detect whether your user’s wallet is an **EOA (Externally Owned Account)** or a **Smart Wallet** to properly set the `explicitDeposit` parameter in your quote requests.

## Understanding Wallet Types

**EOAs (Externally Owned Accounts)** are regular wallets controlled by a private key, like MetaMask, Coinbase Wallet, and hardware wallets. These wallets can only execute one transaction at a time and cannot batch multiple operations together. **Smart Wallets** are contract-based wallets that can execute multiple operations in a single transaction. Examples include Gnosis Safe, Argent, and ERC-4337 compatible wallets. Smart wallets can batch approvals and deposits atomically, making multi-step flows more user-friendly.

## The Problem

Protocol v2 uses the Relay Depository contracts to enable trustless cross-chain payments. For ERC20 token deposits, there are two possible transaction flows: **Explicit Deposits (2 transactions):**

1. User approves the Relay Depository contract to spend their tokens
2. User calls the `depositErc20` function to transfer tokens with an order ID

**Implicit Deposits (1 transaction):**

1. User transfers tokens directly to the solver with order ID encoded in transaction calldata

The challenge is that **implicit deposits only work reliably for EOAs**, while **explicit deposits work for all wallet types but create poor UX for EOAs** who must execute two separate transactions.

## The Solution

By detecting wallet type, you can set the `explicitDeposit` parameter to choose the optimal flow:

- **`explicitDeposit: false`** – Enables implicit deposits for EOAs (1 transaction)
- **`explicitDeposit: true`** – Uses explicit approval flow for smart wallets (2 transactions, can be batched)
- **Default**: `true` (safe fallback for all wallet types)

## When to Use Wallet Detection

You should implement wallet detection when:

- Using `protocolVersion: "v2"` or `"preferV2"`
- User is on an EVM chain
- User is depositing ERC20 tokens (not native ETH)
- You want to optimize transaction flow for your users

For native ETH deposits, wallet detection is not necessary since no approval is required.

## Detection Methods

### 1. Smart Wallet Capabilities (EIP-5792)

Check if the wallet advertises smart wallet capabilities:

```javascript
const capabilities = await wallet.getCapabilities({
	account: wallet.account,
	chainId,
});

const hasSmartWalletCapabilities = Boolean(
	capabilities?.atomicBatch?.supported ||
	capabilities?.paymasterService?.supported ||
	capabilities?.auxiliaryFunds?.supported ||
	capabilities?.sessionKeys?.supported
);
```

### 2. Contract Code Detection

Check if the wallet address has deployed contract code:

```javascript
const code = await publicClient.getCode({
	address: walletAddress,
});

const hasCode = Boolean(code && code !== "0x");
```

### 3. EIP-7702 Delegation Detection

Check if the wallet uses EIP-7702 delegation (code starts with `0xef01`):

```javascript
const isEIP7702Delegated = Boolean(
	code && code.toLowerCase().startsWith("0xef01")
);
```

**Note**: EIP-7702 delegated accounts are technically EOAs but gain smart wallet capabilities through authorization signatures. They require `explicitDeposit: true` for reliable batching and execution.

### Final Determination

```javascript
const isSmartWallet =
	hasSmartWalletCapabilities || hasCode || isEIP7702Delegated;
const isEOA = !isSmartWallet;

// Set explicitDeposit based on wallet type
const explicitDeposit = !isEOA || isEIP7702Delegated;
```

## Safety Checks

### Zero Native Balance Check

If the user has zero native currency (ETH, MATIC, etc.), force `explicitDeposit: true` to avoid failed transactions due to insufficient gas:

```javascript
if (nativeBalance === 0n) {
	explicitDeposit = true;
}
```

### Low Transaction Count Check

If the wallet has 1 or fewer transactions on the source chain, force `explicitDeposit: true` as this may indicate a new wallet requiring explicit handling:

```javascript
if (transactionCount <= 1) {
	explicitDeposit = true;
}
```

## Implementation Example

Here’s a complete implementation for detecting wallet types:

```javascript
export const detectWalletType = async (
	wallet: WalletClient,
	chainId: number
) => {
	if (!wallet.account) {
		return { isEOA: false, isEIP7702Delegated: false };
	}

try {
		// Check 1: Smart wallet capabilities
		let hasSmartWalletCapabilities = false;
		try {
			const capabilities = await wallet.getCapabilities({
				account: wallet.account,
				chainId,
			});

hasSmartWalletCapabilities = Boolean(
				capabilities?.atomicBatch?.supported ||
				capabilities?.paymasterService
					?.supported ||
				capabilities?.auxiliaryFunds
					?.supported ||
				capabilities?.sessionKeys
					?.supported
			);
		} catch (capabilitiesError) {
			// Wallet doesn't support capabilities API
		}

// Check 2 & 3: Contract code detection
		const publicClient = createPublicClient({
			chain: getChainById(chainId),
			transport: http(),
		});

const code = await publicClient.getCode({
			address: wallet.account.address,
		});

const hasCode = Boolean(code && code !== "0x");
		const isEIP7702Delegated = Boolean(
			code && code.toLowerCase().startsWith("0xef01")
		);

const isSmartWallet =
			hasSmartWalletCapabilities ||
			hasCode ||
			isEIP7702Delegated;
		const isEOA = !isSmartWallet;

return { isEOA, isEIP7702Delegated };
	} catch (error) {
		// On error, assume not EOA (safer default)
		return { isEOA: false, isEIP7702Delegated: false };
	}
};
```

## Example Scenarios

| Wallet Type                      | Detection Result       | explicitDeposit | User Experience                        |
|----------------------------------|------------------------|----------------|---------------------------------------|
| Regular EOA (MetaMask, Coinbase) | EOA detected            | `false`        | 1 transaction                          |
| Smart Wallet (Gnosis Safe, Argent)| Smart wallet detected   | `true`         | 2 transactions (can be batched)      |
| EIP-7702 Delegated EOA           | Smart wallet detected   | `true`         | 2 transactions (can be batched)      |
| Detection Error                   | Unknown                | `true`         | 2 transactions (safe fallback)        |

## API Usage

Include the `explicitDeposit` parameter in your quote requests:

```javascript
const quoteRequest = {
	user: userAddress,
	originChainId: sourceChainId,
	destinationChainId: targetChainId,
	originCurrency: sourceCurrencyAddress,
	destinationCurrency: targetCurrencyAddress,
	recipient: recipientAddress,
	amount: amountInWei,
	tradeType: "EXACT_INPUT",
	protocolVersion: "preferV2",
	explicitDeposit: explicitDepositValue, // Based on your detection
};
```

## Expected User Experience

### For EOA Users (`explicitDeposit: false`)

```markdown
✅ Step 1: Transfer USDC directly to solver with order ID encoded in calldata
✅ One wallet confirmation
✅ Faster execution and lower cost
✅ Simpler, more intuitive user experience
```

### For Smart Wallet Users (`explicitDeposit: true`)

```markdown
✅ Step 1: Approve Relay Depository contract to spend USDC
✅ Step 2: Call depositErc20() to deposit USDC
✅ Steps can be batched into single confirmation (ERC-4337/EIP-5792)
✅ Reliable, predictable execution through Depository architecture
✅ Full smart wallet capabilities (fee sponsorship, session keys, etc.)
```

## Best Practices

1. **Handle errors gracefully** – Return `{ isEOA: false, isEIP7702Delegated: false }` on errors (safer default)
2. **Add timeout** – Detection should timeout after ~1 second to avoid blocking UX
3. **Cache results** – Cache detection results per wallet/chain combination to avoid repeated calls
4. **Include safety checks** – Always check native balance and transaction count as additional safety measures
5. **Only use with Protocol v2** – The `explicitDeposit` parameter is only relevant for Protocol v2.

## Troubleshooting

### Detection Returns Incorrect Results

- Ensure you’re using the correct chain ID
- Verify the RPC endpoint is returning accurate data
- Check that wallet capabilities API is properly supported

### Quote Requests Failing

- Verify `explicitDeposit` is only included when using v2 protocol
- Ensure user has sufficient native currency for gas
- Check that the wallet address is valid

By implementing proper wallet detection, you can provide optimal user experience for both EOA and smart wallet users while ensuring transaction reliability.
