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

# Internal Wallet Operations

> Create and manage custodial wallets across multiple blockchain networks

## Overview

Internal wallets are platform-managed custodial wallets that hold user cryptocurrency across various blockchain networks. Each user can have multiple internal wallets for different networks and currencies, with the platform securely managing all private keys.

## Creating Internal Wallets

Create one or more internal wallets for a user with a single API call:

<CodeGroup>
  ```bash Create Single Wallet theme={null}
  curl -X POST "https://api.example.com/v1/wallet/internal" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "wallets": [
        {
          "network": "linea",
          "currency": "usdc"
        }
      ]
    }'
  ```

  ```bash Create Multiple Wallets theme={null}
  curl -X POST "https://api.example.com/v1/wallet/internal" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "wallets": [
        {
          "network": "linea",
          "currency": "usdc"
        },
        {
          "network": "ethereum",
          "currency": "usdt"
        },
        {
          "network": "solana",
          "currency": "usdc"
        }
      ]
    }'
  ```

  ```json Response theme={null}
  {
    "success": true
  }
  ```
</CodeGroup>

<Note>
  Wallet creation is idempotent. If a wallet already exists for the specified network and currency combination, the API returns success without creating a duplicate.
</Note>

### Network and Currency Combinations

| Network    | Supported Currencies  | Memo Required         |
| ---------- | --------------------- | --------------------- |
| `linea`    | `usdc`, `usdt`        | No                    |
| `ethereum` | `usdc`, `usdt`        | No                    |
| `solana`   | `usdc`, `usdt`, `sol` | No                    |
| `xrp`      | `xrp`                 | Yes (destination tag) |
| `bitcoin`  | `btc`                 | No                    |

<Warning>
  Always specify both `network` and `currency` as a matching pair. For example, specify `xrp` for both network and currency when creating an XRP wallet.
</Warning>

## Retrieving Internal Wallets

Get all internal wallets for the authenticated user:

<CodeGroup>
  ```bash Request theme={null}
  curl -X GET "https://api.example.com/v1/wallet/internal" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN"
  ```

  ```json Response theme={null}
  [
    {
      "id": "098aeb90-e7f7-4f81-bc2e-4963330122c5",
      "balance": "150.50",
      "currency": "usdc",
      "address": "0x0a4b21fa733e9aeaddbf070302a85c559de13c4d",
      "addressMemo": null,
      "addressId": "7c1839ee-918e-4787-b74f-deeb48ead58b",
      "type": "INTERNAL"
    },
    {
      "id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
      "balance": "0.00",
      "currency": "xrp",
      "address": "rNxp4h8apvRis6mJf9Sh8C6iRxfrDWN7AA",
      "addressMemo": "78",
      "addressId": "8d9e0f1g-2h3i-4j5k-6l7m-8n9o0p1q2r3s",
      "type": "INTERNAL"
    }
  ]
  ```
</CodeGroup>

### Response Fields

| Field         | Type         | Description                                                  |
| ------------- | ------------ | ------------------------------------------------------------ |
| `id`          | string       | Wallet identifier for transaction history queries            |
| `balance`     | string       | Current wallet balance in the specified currency             |
| `currency`    | string       | Currency held in this wallet                                 |
| `address`     | string       | Blockchain address for deposits                              |
| `addressMemo` | string\|null | Destination tag/memo (required for XRP and similar networks) |
| `addressId`   | string       | Identifier for linking wallet to card                        |
| `type`        | string       | Always "INTERNAL" for custodial wallets                      |

<Note>
  The `addressId` field is required when linking wallets to cards. Keep this identifier for card linking operations.
</Note>

## Understanding Wallet Addresses

### Standard Addresses (Most Networks)

For most networks (Ethereum, Linea, Solana, Bitcoin), only the `address` field is needed:

```json theme={null}
{
  "address": "0x0a4b21fa733e9aeaddbf070302a85c559de13c4d",
  "addressMemo": null
}
```

Users can deposit funds by sending cryptocurrency to this address.

### Memo-Required Networks (XRP, Stellar)

Some networks require a memo/destination tag to identify the recipient:

```json theme={null}
{
  "address": "rNxp4h8apvRis6mJf9Sh8C6iRxfrDWN7AA",
  "addressMemo": "78"
}
```

<Warning>
  For memo-required networks, users MUST include both the address AND the memo when depositing. Missing the memo may result in lost funds or delayed processing.
</Warning>

**Display to Users:**

```
Address: rNxp4h8apvRis6mJf9Sh8C6iRxfrDWN7AA
Destination Tag: 78
```

## Checking Wallet Balances

Balances are returned when retrieving wallet list:

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function getWalletBalance(currency) {
    const response = await fetch('https://api.example.com/v1/wallet/internal', {
      headers: {
        'x-client-key': 'YOUR_PUBLIC_KEY',
        'Authorization': `Bearer ${userToken}`
      }
    });

    const wallets = await response.json();
    const wallet = wallets.find(w => w.currency === currency);

    return wallet ? parseFloat(wallet.balance) : 0;
  }

  const usdcBalance = await getWalletBalance('usdc');
  console.log(`USDC Balance: ${usdcBalance}`);
  ```

  ```python Python theme={null}
  import requests

  def get_wallet_balance(user_token, currency):
      response = requests.get(
          'https://api.example.com/v1/wallet/internal',
          headers={
              'x-client-key': 'YOUR_PUBLIC_KEY',
              'Authorization': f'Bearer {user_token}'
          }
      )

      wallets = response.json()
      wallet = next((w for w in wallets if w['currency'] == currency), None)

      return float(wallet['balance']) if wallet else 0.0

  usdc_balance = get_wallet_balance(user_token, 'usdc')
  print(f'USDC Balance: {usdc_balance}')
  ```
</CodeGroup>

## Receiving Deposits

Once a wallet is created, users can deposit funds by sending cryptocurrency to the wallet address.

### Deposit Flow

<Steps>
  <Step title="Display Deposit Address">
    Show the wallet address (and memo if applicable) to the user in your application.
  </Step>

  <Step title="User Initiates Transfer">
    User sends cryptocurrency from their external wallet or exchange to the displayed address.
  </Step>

  <Step title="Blockchain Confirmation">
    Transaction is confirmed on the blockchain (timing varies by network).
  </Step>

  <Step title="Balance Update">
    Platform detects the deposit and updates the wallet balance automatically.
  </Step>

  <Step title="Notify User">
    Poll wallet balance or implement webhooks to notify user of confirmed deposits.
  </Step>
</Steps>

### Network Confirmation Times

| Network  | Typical Confirmation Time |
| -------- | ------------------------- |
| Linea    | 1-2 minutes               |
| Ethereum | 5-15 minutes              |
| Solana   | 5-30 seconds              |
| XRP      | 3-5 seconds               |
| Bitcoin  | 10-60 minutes             |

<Note>
  Confirmation times vary based on network congestion and gas prices. Display expected timing to users to set proper expectations.
</Note>

### Deposit Example UI

```jsx theme={null}
function DepositAddress({ wallet }) {
  const copyToClipboard = (text) => {
    navigator.clipboard.writeText(text);
  };

  return (
    <div className="deposit-container">
      <h3>Deposit {wallet.currency.toUpperCase()}</h3>

      <div className="address-field">
        <label>Address</label>
        <div className="address-display">
          <code>{wallet.address}</code>
          <button onClick={() => copyToClipboard(wallet.address)}>
            Copy
          </button>
        </div>
      </div>

      {wallet.addressMemo && (
        <div className="memo-field">
          <label>Destination Tag (Required)</label>
          <div className="address-display">
            <code>{wallet.addressMemo}</code>
            <button onClick={() => copyToClipboard(wallet.addressMemo)}>
              Copy
            </button>
          </div>
          <p className="warning">
            ⚠️ You must include this destination tag or your funds may be lost
          </p>
        </div>
      )}

      <div className="network-info">
        <p>Network: {wallet.network}</p>
        <p>Expected confirmation: 1-2 minutes</p>
      </div>
    </div>
  );
}
```

## Wallet Transaction History

View transaction history for a specific internal wallet:

<CodeGroup>
  ```bash Request theme={null}
  curl -X GET "https://api.example.com/v1/wallet/history?walletId=098aeb90-e7f7-4f81-bc2e-4963330122c5&walletType=INTERNAL&walletCurrency=usdc&page=0" \
    -H "x-client-key: YOUR_PUBLIC_KEY" \
    -H "Authorization: Bearer USER_ACCESS_TOKEN"
  ```

  ```json Response theme={null}
  [
    {
      "name": "Card purchase",
      "amount": "25.50",
      "currency": "usdc",
      "sign": "debit",
      "date": "2024-02-02T15:01:09.091Z"
    },
    {
      "name": "Wallet deposit",
      "amount": "100.00",
      "currency": "usdc",
      "sign": "credit",
      "date": "2024-02-01T10:30:00.000Z"
    },
    {
      "name": "Withdrawal",
      "amount": "50.00",
      "currency": "usdc",
      "sign": "debit",
      "date": "2024-01-31T18:20:15.000Z"
    }
  ]
  ```
</CodeGroup>

### Query Parameters

| Parameter        | Required | Description                                  |
| ---------------- | -------- | -------------------------------------------- |
| `walletId`       | Yes      | The wallet `id` from GET /v1/wallet/internal |
| `walletType`     | Yes      | Must be "INTERNAL" for internal wallets      |
| `walletCurrency` | Yes      | Currency of the wallet (e.g., "usdc", "xrp") |
| `page`           | No       | Page number (zero-indexed). Defaults to 0    |

<Note>
  Transaction history is paginated with 10 transactions per page, ordered by date descending (newest first).
</Note>

## Linking to Cards

Internal wallets can be linked to cards for payments. See the dedicated guide for details:

[Card Linking Guide →](/guides/wallet/custodial/card-linking)

**Quick Example:**

```bash theme={null}
curl -X POST "https://api.example.com/v1/wallet/internal/card_linked" \
  -H "x-client-key: YOUR_PUBLIC_KEY" \
  -H "Authorization: Bearer USER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "addressId": "7c1839ee-918e-4787-b74f-deeb48ead58b"
  }'
```

## Use Cases

<AccordionGroup>
  <Accordion title="Multi-Currency Support">
    Create wallets for different currencies to allow users to hold and spend various cryptocurrencies. For example, create USDC on Linea for low fees and USDT on Ethereum for broader compatibility.
  </Accordion>

  <Accordion title="Exchange Integration">
    Provide users with deposit addresses to fund their accounts from exchanges like Coinbase or Binance. Users send crypto from their exchange to their internal wallet address.
  </Accordion>

  <Accordion title="Cross-Network Flexibility">
    Support users on different blockchain networks. Create Solana wallets for users in the Solana ecosystem and Ethereum wallets for users in the EVM ecosystem.
  </Accordion>

  <Accordion title="Simplified Onboarding">
    For users new to cryptocurrency, internal wallets provide a familiar account-based experience without requiring wallet software or seed phrase management.
  </Accordion>

  <Accordion title="Card Payment Funding">
    Link internal wallets to cards so users can spend their cryptocurrency holdings for everyday purchases without manual transfers.
  </Accordion>
</AccordionGroup>

## Error Handling

### Wallet Already Exists

```json theme={null}
{
  "error": "Wallet already exists",
  "code": "WALLET_ALREADY_EXISTS",
  "message": "A wallet for this network and currency combination already exists"
}
```

**Solution:** This is expected behavior. The existing wallet is returned in GET requests. No action needed.

### Unsupported Network

```json theme={null}
{
  "error": "Unsupported network",
  "code": "WALLET_UNSUPPORTED_NETWORK",
  "message": "The specified network is not supported in this environment"
}
```

**Solution:** Verify the network name and ensure it's supported in your environment configuration. Contact support for network availability.

### Invalid Currency for Network

```json theme={null}
{
  "error": "Invalid currency",
  "code": "WALLET_INVALID_CURRENCY",
  "message": "The specified currency is not supported on this network"
}
```

**Solution:** Ensure the currency is valid for the specified network. For example, you cannot create a BTC wallet on the Ethereum network.

## Best Practices

<Card title="Create Wallets Proactively" icon="bolt">
  Create wallets during user onboarding rather than when needed for a transaction. This reduces friction and provides immediate deposit addresses.
</Card>

<Card title="Display Clear Instructions" icon="message">
  For memo-required networks, prominently display both the address and memo with clear warnings about including both values.
</Card>

<Card title="Monitor Deposits" icon="magnifying-glass">
  Poll wallet balances or implement webhook notifications to detect deposits quickly and update your UI in real-time.
</Card>

<Card title="Show Transaction History" icon="clock-rotate-left">
  Display transaction history to help users track their activity and verify deposits/withdrawals.
</Card>

<Card title="Handle Network Delays" icon="hourglass">
  Inform users about expected confirmation times and display pending transactions separately from confirmed balances.
</Card>

<Card title="Provide Copy Functionality" icon="copy">
  Always include a "copy to clipboard" button for addresses and memos to prevent user input errors.
</Card>

## US Environment

For US-based users, route requests to the US environment:

<Tabs>
  <Tab title="Header Method">
    ```bash theme={null}
    curl -X GET "https://api.example.com/v1/wallet/internal" \
      -H "x-client-key: YOUR_PUBLIC_KEY" \
      -H "Authorization: Bearer USER_ACCESS_TOKEN" \
      -H "x-us-env: true"
    ```
  </Tab>

  <Tab title="Query Parameter Method">
    ```bash theme={null}
    curl -X GET "https://api.example.com/v1/wallet/internal?region=us" \
      -H "x-client-key: YOUR_PUBLIC_KEY" \
      -H "Authorization: Bearer USER_ACCESS_TOKEN"
    ```
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={2}>
  <Card title="Card Linking" icon="credit-card" href="/guides/wallet/custodial/card-linking">
    Link internal wallets to cards for seamless payments
  </Card>

  <Card title="Whitelist Management" icon="list-check" href="/guides/wallet/custodial/whitelist">
    Add addresses for secure withdrawals
  </Card>

  <Card title="Withdrawals" icon="arrow-right-from-bracket" href="/guides/wallet/custodial/withdrawals">
    Withdraw funds to external addresses
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/wallet/internal">
    View complete API documentation
  </Card>
</CardGroup>
