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

# Wallet & cross-device

> Create, send, and recover — with one status check that keeps every device in sync.

The wallet client runs the user-facing actions (create, send, recover) against
your backend. Approving happens on the user's device; Meru completes the transfer
and covers the fee.

## Construct

<CodeGroup>
  ```ts React Native theme={null}
  import { MeruDeviceWallet } from "@meru.app/device-signer/wallet";

  const wallet = new MeruDeviceWallet({
    baseUrl: "https://your-app.com/api/meru",
    userId: session.user.id,
    getToken: async () => auth.current()?.token ?? null,
  });
  ```

  ```dart Flutter theme={null}
  final wallet = MeruDeviceWallet(
    baseUrl: 'https://your-app.com/api/meru',
    getToken: () async => auth.current?.token,
    keyId: 'meru.device-key.${session.user.id}',
  );
  ```

  ```swift iOS theme={null}
  let wallet = MeruDeviceWallet(
      baseURL: URL(string: "https://your-app.com/api/meru")!,
      userId: session.user.id,
      getToken: { auth.current?.token }
  )
  ```

  ```kotlin Android theme={null}
  val wallet = MeruDeviceWallet(
      baseUrl = "https://your-app.com/api/meru",
      keys = DeviceKeyStore(applicationContext),
      userId = session.user.id,
      getToken = { auth.current?.token },
  )
  ```
</CodeGroup>

## Cross-device: always call `status()` first

The wallet key never leaves the device, so signing in on a new phone does **not**
copy it. `status()` combines "does this user have a wallet?" with "does this device
have its key?" and tells you the one right action.

| `status().state` | Meaning                                                             | Do                           |
| ---------------- | ------------------------------------------------------------------- | ---------------------------- |
| `create`         | The user has no wallet yet.                                         | `enroll({ activate: true })` |
| `recover`        | The user has a wallet on another device; this one needs setting up. | `recover()`                  |
| `ready`          | This device is ready to send.                                       | `send` / `signMessage`       |

<Warning>
  On a second device, calling `enroll()` instead of `recover()` would start a
  **separate** wallet. Always branch on `status()`.
</Warning>

* **Receiving** works on any device right away — the wallet address is public.
* **Sending** from a new device needs `recover()` once. It restores this device to
  the user's existing wallet (same wallet, same address) through Meru's recovery
  service, authorized by the user's login.

## Methods

| Call                   | What it does                                                          |
| ---------------------- | --------------------------------------------------------------------- |
| `status()`             | `create` / `recover` / `ready` for this device.                       |
| `enroll({ activate })` | Set up the wallet on this device (optionally activate it right away). |
| `activate()`           | One-time wallet setup, covered by Meru.                               |
| `send(to, amount)`     | Send dollars. Approved on-device; Meru covers the fee.                |
| `recover()`            | Restore this device to the user's existing wallet.                    |
| `signMessage()`        | Prove control of the wallet without moving money.                     |
| `forget()`             | Remove this device's key on logout.                                   |

## Send

<CodeGroup>
  ```ts React Native theme={null}
  const txHash = await wallet.send("GB7C…FB2Q", 5);
  ```

  ```dart Flutter theme={null}
  final txHash = await wallet.send('GB7C…FB2Q', 5);
  ```

  ```swift iOS theme={null}
  let txHash = try await wallet.send(to: "GB7C…FB2Q", amount: 5)
  ```

  ```kotlin Android theme={null}
  val txHash = wallet.send("GB7C…FB2Q", 5.0)
  ```
</CodeGroup>

## Logout

Remove the device's key and clear the session. Losing the key is fine — the wallet
is recoverable by signing in again.

<CodeGroup>
  ```ts React Native theme={null}
  await wallet.forget();
  await auth.logout();
  ```

  ```swift iOS theme={null}
  try wallet.forget()
  auth.logout()
  ```

  ```kotlin Android theme={null}
  wallet.forget()
  auth.logout()
  ```
</CodeGroup>
