> ## Documentation Index
> Fetch the complete documentation index at: https://docs.immutable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Admin Security

> Secure wallet management and studio security best practices

## Wallet Management

### Wallet Types

| Wallet Type          | Purpose                       | Security Level           |
| -------------------- | ----------------------------- | ------------------------ |
| **Developer Wallet** | Testing, deploying to testnet | Low (hot wallet OK)      |
| **Deployer Wallet**  | Mainnet contract deployment   | Medium (hardware wallet) |
| **Treasury Wallet**  | Holding funds, revenue        | High (multisig)          |
| **Minter Wallet**    | Backend minting operations    | Medium (server-side)     |

### Developer Wallet Setup

For local development and testnet:

#### MetaMask Setup

1. Install [MetaMask](https://metamask.io)
2. Add Immutable Chain Testnet:
   * Network Name: `Immutable Testnet`
   * RPC: `https://rpc.testnet.immutable.com`
   * Chain ID: `13473`
   * Symbol: `tIMX`
3. Get test tokens from the [Faucet](https://hub.immutable.com/faucet)

#### Hardhat Configuration

```typescript theme={null}
// hardhat.config.ts
import { HardhatUserConfig } from 'hardhat/config';

const config: HardhatUserConfig = {
<HardhatNetworkConfig />
};

export default config;
```

<Warning>
  **Never commit `.env` files to version control.** Add `.env` and `.env.local` to your `.gitignore` file to prevent accidentally exposing private keys or API secrets.
</Warning>

## Production Treasury: Multisig

For production funds, use a multisig wallet like [Safe](https://safe.global).

### Why Multisig?

* **No single point of failure**: Multiple signatures required
* **Team accountability**: Track who approved transactions
* **Recovery**: Lost keys don't mean lost funds

### Setting Up Safe

1. Go to [Safe](https://app.safe.global)
2. Connect to Immutable Chain
3. Create a new Safe with:
   * Multiple owner addresses (team members)
   * Threshold (e.g., 2 of 3 signatures required)
4. Fund the Safe with IMX for gas

### Transaction Flow

```
Team Member A proposes transaction
    ↓
Team Member B reviews and signs
    ↓
Threshold reached → Transaction executes
```

## Backend Minting Wallet

Your backend needs a wallet for minting operations.

### Key Management Options

| Option                   | Pros              | Cons                    |
| ------------------------ | ----------------- | ----------------------- |
| **Environment Variable** | Simple            | Less secure             |
| **AWS KMS**              | Secure, auditable | More complex            |
| **HashiCorp Vault**      | Enterprise-grade  | Infrastructure overhead |

### Using AWS KMS with viem

```typescript theme={null}
import { KMSClient, SignCommand } from '@aws-sdk/client-kms';
import { createWalletClient, http, type Account } from 'viem';
import { immutableZkEvm } from 'viem/chains';

// Create a KMS-backed account for viem
async function createKMSAccount(keyId: string): Promise<Account> {
  const kms = new KMSClient({ region: 'us-east-1' });

  return {
    address: '0x...', // Derive from KMS public key
    type: 'local',
    signMessage: async ({ message }) => {
      const command = new SignCommand({
        KeyId: keyId,
        Message: Buffer.from(message as string),
        SigningAlgorithm: 'ECDSA_SHA_256',
        MessageType: 'DIGEST',
      });
      const response = await kms.send(command);
      // Process and return signature
      return '0x...' as `0x${string}`;
    },
    signTransaction: async (tx) => {
      // Sign transaction with KMS
      return '0x...' as `0x${string}`;
    },
    signTypedData: async (data) => {
      // Sign typed data with KMS
      return '0x...' as `0x${string}`;
    },
  };
}

// Use with viem
const account = await createKMSAccount(process.env.KMS_KEY_ID!);
const walletClient = createWalletClient({
  account,
  chain: immutableZkEvm,
  transport: http(),
});
```

### Rate Limiting & Monitoring

Protect your minting wallet:

```typescript theme={null}
import rateLimit from 'express-rate-limit';

const mintLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 100, // 100 requests per minute
  message: 'Too many mint requests',
});

app.post('/api/mint', mintLimiter, async (req, res) => {
  // Log all mint operations
  logger.info('Mint request', {
    recipient: req.body.address,
    tokenId: req.body.tokenId,
    timestamp: new Date(),
  });
  
  // Process mint...
});
```

## Security Checklist

### Development

* [ ] Use separate wallet for testnet
* [ ] Never use mainnet private keys in development
* [ ] Clear browser wallet state between projects

### Production

* [ ] Treasury in multisig (Safe)
* [ ] Deployer wallet on hardware device
* [ ] Minting wallet keys in secure storage (KMS/Vault)
* [ ] Rate limiting on minting endpoints
* [ ] Monitoring and alerts for unusual activity
* [ ] Regular key rotation schedule
* [ ] Incident response plan documented

## Gas Management

### Estimating Costs

```typescript theme={null}
import { createPublicClient, http, formatEther } from 'viem';
import { immutableZkEvm } from 'viem/chains';

const publicClient = createPublicClient({
  chain: immutableZkEvm,
  transport: http(),
});

async function estimateGas(to: `0x${string}`, data: `0x${string}`) {
  const gasEstimate = await publicClient.estimateGas({ to, data });
  const gasPrice = await publicClient.getGasPrice();
  
  const maxCost = gasEstimate * gasPrice;
  console.log(`Max cost: ${formatEther(maxCost)} IMX`);
}
```

### Maintaining Balance

Set up alerts when wallet balance drops:

```typescript theme={null}
import { createPublicClient, http, formatEther, parseEther } from 'viem';
import { immutableZkEvm } from 'viem/chains';

const publicClient = createPublicClient({
  chain: immutableZkEvm,
  transport: http(),
});

async function checkBalance(address: `0x${string}`, threshold: bigint) {
  const balance = await publicClient.getBalance({ address });
  
  if (balance < threshold) {
    await sendAlert(`Wallet ${address} balance low: ${formatEther(balance)} IMX`);
  }
}

// Run periodically
setInterval(() => checkBalance(MINTER_WALLET, parseEther('10')), 60000);
```

## Funds Recovery

### From Passport Wallet

Players control their Passport wallets. Recovery is through their authentication provider (Google, Apple, etc.).

### From Studio Wallets

* **Multisig**: Recover with threshold of remaining signers
* **Single-sig**: Depends on backup strategy
* **KMS**: AWS manages key durability

<Tip>
  Always test your recovery procedures before you need them.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Contracts" icon="file-contract" href="/docs/products/asset-contracts/overview">
    Deploy contracts from your secure wallet
  </Card>

  <Card title="Minting" icon="wand-magic-sparkles" href="/docs/products/asset-contracts/erc721">
    Set up backend minting
  </Card>
</CardGroup>
