# Vault System

The Vault system provides businesses with deterministic deposit addresses for their users. Each user gets a unique address that accepts any enabled token, with automatic processing and webhook notifications.

## Overview

**Key Features:**

* **One Address Per User** - Each user gets a single deposit address that accepts ANY enabled token
* **Deterministic Addresses** - Addresses are computed using CREATE2, same across all supported chains
* **Permissionless** - No on-chain registration required, works immediately
* **Automatic Processing** - Deposits are detected and processed automatically
* **Webhook Notifications** - Real-time notifications when deposits are processed
* **Low Fees** - 0.25% default fee on all deposits

## How It Works

### Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                         User Flow                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  1. Business creates user     2. User deposits tokens            │
│     via API/Dashboard            to their address                │
│           │                           │                          │
│           ▼                           ▼                          │
│  ┌─────────────────┐         ┌─────────────────┐                │
│  │ MakaPay Backend │         │ Deposit Address │                │
│  │ computeAddress()│         │  (CREATE2)      │                │
│  └────────┬────────┘         └────────┬────────┘                │
│           │                           │                          │
│           ▼                           ▼                          │
│  ┌─────────────────┐         ┌─────────────────┐                │
│  │ Deposit Address │         │ Deposit Detected│                │
│  │ returned to     │         │ by cron job     │                │
│  │ business        │         └────────┬────────┘                │
│  └─────────────────┘                  │                          │
│                                       ▼                          │
│                              ┌─────────────────┐                │
│  3. Funds swept to           │ Factory.process()│                │
│     business wallet          │ sweeps funds    │                │
│           ▲                  └────────┬────────┘                │
│           │                           │                          │
│           └───────────────────────────┘                          │
│                                                                  │
│  4. Webhook sent to business with deposit details                │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### Address Computation

Deposit addresses are deterministic using CREATE2:

```
salt = keccak256(userId, casinoAddress)
address = CREATE2(factory, salt, walletBytecode)
```

**Important:** The same `userId` + `casinoAddress` combination always produces the same deposit address, regardless of which token is being deposited.

## Smart Contracts

### Contract Addresses

| Contract       | Address                                      | Networks                   |
| -------------- | -------------------------------------------- | -------------------------- |
| Factory        | `0xDEBd5F39a53e86DC1887eaf9eBc9B8a8E635bEA2` | Sepolia, MakaChain Testnet |
| Implementation | `0x74260BBA1dD0a990Eef6950f58D2eC14f14403e1` | Sepolia, MakaChain Testnet |

### Factory Functions

#### `computeAddress(string userId, address casino)`

Computes the deterministic deposit address for a user.

```solidity
function computeAddress(
    string calldata userId,
    address casino
) external view returns (address)
```

**Parameters:**

* `userId` - Your internal user identifier (e.g., "user\_123", "player\_abc")
* `casino` - Your business wallet address (where funds are sent after processing)

**Returns:** The deposit address for this user

#### `process(string userId, address casino, address token, bytes callbackData)`

Processes a deposit by sweeping funds from the deposit address to the casino wallet.

```solidity
function process(
    string calldata userId,
    address casino,
    address token,
    bytes calldata callbackData
) external returns (address wallet, uint256 amount, uint256 fee)
```

**Parameters:**

* `userId` - The user's identifier
* `casino` - Your business wallet address
* `token` - The token contract address being processed
* `callbackData` - Optional data passed to your callback (usually the userId encoded)

**Returns:**

* `wallet` - The deposit wallet address
* `amount` - Total amount processed (before fee)
* `fee` - Fee amount deducted

### Fee Structure

| Type                   | Fee            | Recipient        |
| ---------------------- | -------------- | ---------------- |
| Default (unregistered) | 0.25% (25 bps) | MakaPay Treasury |
| Registered Casino      | Custom (0-1%)  | Custom recipient |

Fees are automatically deducted during the `process()` call:

* Fee is sent to the fee recipient
* Remaining funds are sent to the casino wallet

## Dashboard Setup

### 1. Configure Your Vault

Navigate to **Dashboard > Vault > Settings**:

1. **Business Name** - Your business display name
2. **Wallet Address** - Where processed funds are sent
3. **Enabled Tokens** - Select which tokens to accept (USDT, USDC, etc.)

### 2. Create User Addresses

Navigate to **Dashboard > Vault > Users**:

1. Click **Create User**
2. Enter the **User ID** (your internal identifier)
3. The deposit address is generated automatically

### 3. Configure Webhooks (Optional)

Navigate to **Dashboard > Vault > Settings > Webhooks**:

1. Enter your **Webhook URL**
2. Add a **Webhook Secret** for signature verification
3. Select which events to receive

## API Integration

### Authentication

All API endpoints require an API key in the `x-api-key` header:

```bash
curl -X GET "https://app.makapay.io/api/vault/v1/config" \
  -H "x-api-key: YOUR_API_KEY"
```

### Vault Configuration Endpoints

You can fully configure your vault via the API — no dashboard needed. See the [API Reference](/developers/api-reference.md#vault-configuration-api) for detailed documentation of all parameters and response formats.

| Method | Endpoint                        | Description               |
| ------ | ------------------------------- | ------------------------- |
| POST   | `/api/vault/v1/config`          | Create vault account      |
| GET    | `/api/vault/v1/config`          | Get vault configuration   |
| PATCH  | `/api/vault/v1/config`          | Update vault settings     |
| POST   | `/api/vault/v1/config/tokens`   | Add accepted token        |
| DELETE | `/api/vault/v1/config/tokens`   | Remove accepted token     |
| GET    | `/api/vault/v1/config/webhooks` | Get webhook config        |
| PUT    | `/api/vault/v1/config/webhooks` | Create/update webhook     |
| DELETE | `/api/vault/v1/config/webhooks` | Delete webhook            |
| POST   | `/api/vault/v1/config/webhooks` | Regenerate webhook secret |

#### Quick Setup Example

```bash
# 1. Create your vault
curl -X POST https://app.makapay.io/api/vault/v1/config \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "My Casino",
    "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
    "enabledTokens": [
      {"chainId": 137, "token": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", "tokenSymbol": "USDT"},
      {"chainId": 56, "token": "0x55d398326f99059ff775485246999027b3197955", "tokenSymbol": "USDT"}
    ]
  }'

# 2. Set up a webhook
curl -X PUT https://app.makapay.io/api/vault/v1/config/webhooks \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yoursite.com/webhook/vault",
    "events": ["deposit.completed", "deposit.failed"]
  }'
# → Save the `secret` from the response for signature verification

# 3. Generate deposit addresses for your users
curl -X POST https://app.makapay.io/api/vault/v1/users \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"externalUserId": "player_42", "chainId": 137, "tokenAddress": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"}'
```

### Read-Only Endpoints

#### Get Vault Configuration

```http
GET /api/vault/v1/config
```

**Response:**

```json
{
  "success": true,
  "data": {
    "publicId": "biz_abc123",
    "businessName": "My Casino",
    "walletAddress": "0x...",
    "feeBps": 25,
    "isActive": true,
    "enabledTokens": [
      {
        "chainId": 11155111,
        "tokenSymbol": "USDT",
        "tokenAddress": "0x..."
      }
    ]
  }
}
```

#### Create User / Get Deposit Address

```http
POST /api/vault/v1/users
Content-Type: application/json

{
  "externalUserId": "user_123",
  "chainId": 11155111,
  "tokenAddress": "0x..."
}
```

**Response:**

```json
{
  "success": true,
  "data": {
    "depositAddress": "0x...",
    "externalUserId": "user_123",
    "chainId": 11155111,
    "tokenSymbol": "USDT",
    "isNew": true
  }
}
```

#### Get User Info

```http
GET /api/vault/v1/users?externalUserId=user_123
```

**Response:**

```json
{
  "success": true,
  "data": {
    "externalUserId": "user_123",
    "depositAddress": "0x...",
    "chainId": 11155111,
    "tokenSymbol": "USDT",
    "totalDeposited": "1000000000",
    "depositCount": 5,
    "lastDepositAt": 1704067200000
  }
}
```

#### List Deposits

```http
GET /api/vault/v1/deposits?limit=50&status=completed
```

**Query Parameters:**

* `limit` - Max results (default: 50, max: 100)
* `status` - Filter by status: `detected`, `processing`, `completed`, `failed`
* `externalUserId` - Filter by user

**Response:**

```json
{
  "success": true,
  "data": {
    "deposits": [
      {
        "depositId": "abc123",
        "externalUserId": "user_123",
        "amount": "1000000",
        "fee": "2500",
        "netAmount": "997500",
        "chainId": 11155111,
        "tokenSymbol": "USDT",
        "status": "completed",
        "depositTxHash": "0x...",
        "processTxHash": "0x...",
        "createdAt": 1704067200000,
        "processedAt": 1704067260000
      }
    ],
    "total": 1
  }
}
```

#### Get Supported Tokens (Public)

```http
GET /api/vault/v1/business/{publicId}/tokens
```

No authentication required. Returns publicly available token information.

**Response:**

```json
{
  "tokens": [
    {
      "chainId": 11155111,
      "symbol": "USDT",
      "address": "0x..."
    },
    {
      "chainId": 11155111,
      "symbol": "USDC",
      "address": "0x..."
    }
  ]
}
```

## Webhooks

### Webhook Events

| Event               | Description                    |
| ------------------- | ------------------------------ |
| `deposit.completed` | Deposit successfully processed |
| `deposit.failed`    | Deposit processing failed      |
| `deposit.*`         | All deposit events             |

### Webhook Payload

```json
{
  "event": "deposit.completed",
  "data": {
    "depositId": "abc123",
    "externalUserId": "user_123",
    "amount": "1000000",
    "fee": "2500",
    "netAmount": "997500",
    "tokenSymbol": "USDT",
    "tokenAddress": "0x...",
    "chainId": 11155111,
    "depositAddress": "0x...",
    "status": "completed",
    "depositTxHash": "0x...",
    "processTxHash": "0x...",
    "timestamp": 1704067260000
  },
  "timestamp": 1704067260000
}
```

### Webhook Signature Verification

If you configure a webhook secret, requests include an `X-Webhook-Signature` header:

```
X-Webhook-Signature: sha256(JSON.stringify(payload) + secret)
```

**Verification Example (Node.js):**

```javascript
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHash('sha256')
    .update(JSON.stringify(payload) + secret)
    .digest('hex');
  return signature === expected;
}

// In your webhook handler:
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const isValid = verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook...
  const { event, data } = req.body;

  if (event === 'deposit.completed') {
    // Credit user's balance
    await creditUserBalance(data.externalUserId, data.netAmount);
  }

  res.json({ received: true });
});
```

## Integration Examples

### Computing Address On-Chain (Solidity)

```solidity
interface ICasinoWalletFactory {
    function computeAddress(
        string calldata userId,
        address casino
    ) external view returns (address);
}

contract MyIntegration {
    ICasinoWalletFactory public factory =
        ICasinoWalletFactory(0xDEBd5F39a53e86DC1887eaf9eBc9B8a8E635bEA2);

    function getDepositAddress(string calldata userId) external view returns (address) {
        return factory.computeAddress(userId, address(this));
    }
}
```

### Computing Address Off-Chain (JavaScript)

```javascript
import { createPublicClient, http } from 'viem';
import { sepolia } from 'viem/chains';

const FACTORY_ADDRESS = '0xDEBd5F39a53e86DC1887eaf9eBc9B8a8E635bEA2';
const FACTORY_ABI = [
  {
    inputs: [
      { name: 'userId', type: 'string' },
      { name: 'casino', type: 'address' }
    ],
    name: 'computeAddress',
    outputs: [{ name: '', type: 'address' }],
    stateMutability: 'view',
    type: 'function'
  }
];

const client = createPublicClient({
  chain: sepolia,
  transport: http()
});

async function getDepositAddress(userId, casinoAddress) {
  const address = await client.readContract({
    address: FACTORY_ADDRESS,
    abi: FACTORY_ABI,
    functionName: 'computeAddress',
    args: [userId, casinoAddress]
  });
  return address;
}

// Usage
const depositAddress = await getDepositAddress('user_123', '0xYourWallet...');
console.log('Deposit to:', depositAddress);
```

### Full Integration Flow

```javascript
// 1. Create user and get deposit address
const response = await fetch('https://app.makapay.io/api/vault/v1/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.MAKAPAY_API_KEY
  },
  body: JSON.stringify({
    externalUserId: 'user_123',
    chainId: 11155111,
    tokenAddress: '0x...' // USDT address
  })
});

const { data } = await response.json();
const depositAddress = data.depositAddress;

// 2. Show address to user (they send tokens here)
console.log('Send USDT to:', depositAddress);

// 3. Handle webhook when deposit is processed
app.post('/webhooks/makapay', async (req, res) => {
  const { event, data } = req.body;

  if (event === 'deposit.completed') {
    // Credit user in your system
    await db.users.update({
      where: { externalId: data.externalUserId },
      data: {
        balance: { increment: BigInt(data.netAmount) }
      }
    });

    console.log(`Credited ${data.netAmount} to user ${data.externalUserId}`);
  }

  res.json({ received: true });
});
```

## Supported Networks

| Network           | Chain ID | Status      |
| ----------------- | -------- | ----------- |
| Sepolia Testnet   | 11155111 | Active      |
| MakaChain Testnet | 777177   | Active      |
| MakaChain Mainnet | 777178   | Coming Soon |
| Ethereum Mainnet  | 1        | Coming Soon |
| Polygon           | 137      | Coming Soon |
| BSC               | 56       | Coming Soon |

## Deposit Statuses

| Status       | Description                                  |
| ------------ | -------------------------------------------- |
| `detected`   | Deposit detected, awaiting processing        |
| `processing` | Currently being processed on-chain           |
| `completed`  | Successfully processed, funds sent to wallet |
| `failed`     | Processing failed (will retry automatically) |

## Best Practices

### User ID Guidelines

* Use unique, stable identifiers (database IDs, UUIDs)
* Don't use email addresses (may change)
* Don't use session tokens (temporary)
* Keep IDs under 100 characters

### Security

1. **Store API keys securely** - Use environment variables, never commit to code
2. **Verify webhook signatures** - Always validate the `X-Webhook-Signature` header
3. **Use HTTPS** - All webhook endpoints must use HTTPS
4. **Idempotency** - Handle duplicate webhook deliveries gracefully

### Error Handling

1. **Check deposit status** - Poll the deposits endpoint if webhooks fail
2. **Retry logic** - Failed deposits are automatically retried
3. **Monitor failed deposits** - Set up alerts for repeated failures

## Troubleshooting

### Deposit Not Detected

1. Verify the correct deposit address was used
2. Check the token is in the enabled tokens list
3. Ensure minimum deposit amount (> 0.001 tokens)
4. Wait for block confirmations

### Webhook Not Received

1. Verify webhook URL is accessible from the internet
2. Check webhook is enabled and active
3. Ensure the event type is selected
4. Check your server logs for incoming requests

### Process Transaction Failed

1. Check the casino wallet address is correct
2. Verify sufficient gas on the processing account
3. Check the token contract is valid
4. Review error message in the deposit record

## Rate Limits

| Endpoint      | Limit    |
| ------------- | -------- |
| Create User   | 100/min  |
| Get User      | 1000/min |
| List Deposits | 100/min  |
| Get Config    | 100/min  |

## Support

* **Documentation**: [docs.makapay.com](https://docs.makapay.io)
* **GitHub Issues**: [github.com/makapay/issues](https://github.com/makapay/issues)
* **Email**: <support@makapay.com>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.makapay.io/guides/vault.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
