# Prepare the Device in Advance

> Coming soon, upon request — this feature is turned on for your tenant by the Aurea team. [Contact us](https://www.aureahub.com/contact)

Make a new MPC wallet ready to sign in seconds: the device does the slow part of the wallet's setup in the background, before the user asks for the wallet — for example while the user goes through your sign-up or identity checks.

## Preview

> Note: **Preview, opt-in per tenant.** Device preparation is off for every tenant until Aurea turns it on for yours, first in sandbox. Nothing changes for a tenant that leaves it off: wallets are made exactly as in [MPC Wallet Setup](https://docs.aureahub.com/docs/guide-wallet-setup.md). Write to [help@aureahub.com](mailto:help@aureahub.com?subject=Device%20preparation) to try it.

## How It Works

A `cggmp` MPC wallet needs two ceremonies before its first signature: the key generation (seconds) and the auxiliary ceremony (minutes of computation on a phone: [Start Aux Ceremony](https://docs.aureahub.com/docs/mpc-aux-start.md)). The auxiliary part does not depend on the key, so the device can run it first, on its own time:

1. **Prepare** (background, after sign-in): the device computes its own secret primes, then runs the auxiliary ceremony with Aurea's cosigner in a preparation session ([Start a Preparation](https://docs.aureahub.com/docs/mpc-preparations-create.md)). The result stays sealed on the device. The preparation is `ready` when both sides agree on it.
2. **Create** (the user's click): the key generation names the ready preparation ([Start DKG Ceremony](https://docs.aureahub.com/docs/mpc-dkg-start.md) › `preparation`). The new wallet is complete when the key generation ends: no auxiliary ceremony, and its backup can be made at once.

- **One preparation makes one wallet.** It is used up when the key generation starts, whatever its outcome. An unused one expires (`ttlDays`, at most 30 days).
- **Never in the way.** Without a ready preparation, or when one cannot be used, the wallet is made exactly as before — only slower. Your users never see an error because of a preparation.
- **Per user and device.** A preparation belongs to the signed-in user and to the device that made it (a device key whose private part never leaves the device). At most `maxOpen` open preparations per user.

## Turning It On

1. Ask [help@aureahub.com](mailto:help@aureahub.com?subject=Device%20preparation). Aurea turns your tenant's mode to `shadow` first, if you want to measure (preparations run, wallets are made as before), then `on`.
2. Your clients read the mode with [Get the Preparation Settings](https://docs.aureahub.com/docs/mpc-preparations-config.md) and prepare only when it says `on` or `shadow`. The SDKs below do it for you.
3. Turning it off takes effect at once: clients stop preparing, open preparations expire unused, and wallets already made stay ordinary wallets.

## Web: Embedded Wallet

With the [embedded wallet](https://docs.aureahub.com/docs/guide-embedded-wallet.md), the wallet frame prepares the device in the user's browser. It needs a version of `@aureahub/wallet-embed` with `prepare()`: we tell you which when we turn the preview on for your tenant.

```typescript
import { createWallet } from '@aureahub/wallet-embed'

// After sign-in: the tenant's and the signed-in user's ids at Aurea (UUIDs, from your server)
const wallet = createWallet({ vault, tenantPk: 'pk_live_EXAMPLE', preparedFor: { tenantId, userId } })

// In the background; keep the vault frame mounted while it runs
void wallet.prepare({ onProgress: (s) => console.debug(s.state, s.phase, s.done, s.total) })

// Later, from the user's click: seconds when the preparation is ready, as before otherwise
const { walletId, address, prepared } = await wallet.create()
```

- `prepare()` never rejects: it resolves with `ready`, `unavailable` (off for your tenant, or an older frame: creation works as before) or `failed` (try again later). It never blocks `create()`.
- Call it right after sign-in, and again when the user comes back to the page: it resumes where it stopped. The frame works while it is mounted; pass `boost: true` when the user is on the wallet step, so the frame may use more of the device.
- Your server carries three more paths for the frame: `GET /preparations/config`, `GET|POST /preparations` and `GET|DELETE /preparations/{id}` — `isAllowedHubPath` lists them ([Embedded Wallet › Your Server Carries the Calls](https://docs.aureahub.com/docs/guide-embedded-wallet.md); pass `DELETE` on those paths only).
- An answer with `storage: "best_effort"` means the browser may delete the frame's data on your site (some browsers clear a frame's storage when they quit): the preparation may be lost — nothing else happens — and the wallet's own backup matters as always.

## iOS and Android

Aurea's native MPC SDKs for iOS (Swift) and Android (Kotlin) are shared with tenants on request, with this preview. They prepare the device with the same API:

```swift
// iOS
let mpc = AureaMPC(config: AureaConfig(preparation: .hub), transport: transport)
let status = try await mpc.prepare { s in print(s.state, s.progress) }   // after sign-in
// Later, from the user's click: createWallet uses a ready preparation by itself
let created = try await mpc.createWallet(passphrase: passphrase) { _ in }
```

```kotlin
// Android
val mpc = AureaMPC(context, AureaConfig(preparation = PreparationMode.HUB), transport)
val status = mpc.prepare { s -> Log.d("prep", "${s.state} ${s.progress}") }   // after sign-in, in a coroutine
// Later, from the user's click: createWallet uses a ready preparation by itself
val created = mpc.createWallet(passphrase) { }
```

- **States** (upper case in Kotlin): `unavailable` (off for your tenant), `primes` (computing the device's primes), `running` (the preparation ceremony), `ready` (with its `preparationId`), `failed` (try again later). `prepare()` is idempotent: call it at every app open after sign-in.
- **In the background.** The primes are the long part and are saved one by one, so the work can run in the platform's background slots and continue where it stopped: a `BGProcessingTask` on iOS, a WorkManager job on Android (prefer charging and a battery that is not low). Run the preparation ceremony itself while the app is in the foreground.
- **Storage.** The preparation stays on the device in the platform's secure storage (Keychain, this device only; Android Keystore), sealed like the wallet's own shares. It is never backed up or synced.

## Your Own Client

A client of your own runs the same steps with the MPC routes:

1. [Get the Preparation Settings](https://docs.aureahub.com/docs/mpc-preparations-config.md): go on only with `mode` `on` or `shadow` (a `404` without `details.code` means the same as `off`).
2. Make a P-256 **device key** whose private part never leaves the device (WebCrypto non-extractable, Secure Enclave, StrongBox), and a new `clientRef` (UUID).
3. [Start a Preparation](https://docs.aureahub.com/docs/mpc-preparations-create.md) with the key's public part. Join the answer's `sessionId` as `DEVICE` and `BACKUP` (relay version 2, with the cosigner's roster statement) and run the auxiliary ceremony for both parties with the device's own primes, as in [Start Aux Ceremony](https://docs.aureahub.com/docs/mpc-aux-start.md).
4. Check the two outputs (3 parties; `DEVICE` index 0, `BACKUP` index 1; the same digest), **store them sealed on the device first**, then post the digest: [Relay: Post Result](https://docs.aureahub.com/docs/mpc-relay-result.md) with `{ "moniker": "DEVICE", "result": { "auxDigest": "<64 hex>" } }`.
5. Wait for `state: "ready"` ([Get a Preparation](https://docs.aureahub.com/docs/mpc-preparations-get.md), every few seconds).
6. At creation, send `preparation: { id, proof: { ts, sig } }` in [Start DKG Ceremony](https://docs.aureahub.com/docs/mpc-dkg-start.md). Run the key generation as usual; when Aurea's result names `auxComplete: true` with the same `preparationId` and `auxDigest`, complete both key shares with the prepared outputs and delete the preparation from the device. Without it, keep the key shares and run the auxiliary ceremony as before.

```text
auxDigest = SHA-256( "aurea-aux-digest/v1" ‖ 0x00 ‖ u16be(n) ‖ for each party j in 0..n:
                     lp32(N_j) ‖ lp32(hat_N_j) ‖ lp32(s_j) ‖ lp32(t_j) )
lp32(x)   = u32be(length) ‖ x as a big-endian unsigned integer, no leading zero byte
            (N_j: the party's Paillier modulus; hat_N_j, s_j, t_j: its ring-Pedersen parameters — public values)

proof.sig = ECDSA P-256 SHA-256 by the device key, r ‖ s (64 bytes), base64url, over
            "aurea-mpc-prep-use/v1" 0x00 preparationId 0x00 tenantId 0x00 userId 0x00 ts
            (ids in lower case; ts = proof.ts, Unix seconds as decimal text, within 5 minutes of now)
```

## Resume and Clean Up

At every start, compare what the device holds with [List Preparations](https://docs.aureahub.com/docs/mpc-preparations-list.md) (the device finds its own by `deviceKeyFp`):

|  |  |  |
| --- | --- | --- |
| Held here, ready | — | Usable. |
| Held here, running | — | Wait: the other side is finishing. |
| Held here, ended | — | `consumed`, `failed`, `expired`, `revoked`: delete it from the device. |
| Not held here, open | — | The device lost it (storage cleared): [Delete a Preparation](https://docs.aureahub.com/docs/mpc-preparations-delete.md), then prepare again. |
| Primes only | — | Continue: start the preparation ceremony with the primes kept. |

A preparation ceremony that stops half-way (app killed, page closed) cannot continue: its session expires, the preparation ends as `failed` (`session_expired`), and the next run starts a new one with the primes the device kept.

## Security

- The same secrets as a wallet made today, computed by the same parties and kept in the same places: the device's primes and auxiliary outputs are made and kept on the device only, never by Aurea; Aurea receives only public values and the device key's public part.
- One preparation makes one wallet; it is bound to your tenant, the user and the device key, and checked again when it is used. A stolen access token on another device cannot use it (the device key's proof fails, and nothing is used up).
- The wallet's backup and recovery are unchanged ([MPC Wallet Setup](https://docs.aureahub.com/docs/guide-wallet-setup.md)).

## Errors

- `409` `MPC_PREPARATION_UNAVAILABLE` (`details.reason`: `off`, `tenant_cosigner`, `wire`, `scheme`) — the device does not prepare: make wallets as before.
- `409` `MPC_PREPARATION_LIMIT` — the user has `maxOpen` open preparations: use or delete one.
- `503` `MPC_PREPARATION_BUSY` — try again after `Retry-After`.
- At creation, `404` `MPC_PREPARATION_NOT_FOUND` or `409` `MPC_PREPARATION_UNUSABLE` (`details.reason`) — nothing was used up: send the same `dkg/start` again without `preparation`. For `consumed`, `expired`, `revoked` and `failed`, also delete the preparation from the device.

---

Web version: https://docs.aureahub.com/#guide-device-preparation
