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

# Using Midnight embedded wallets

Embedded Midnight wallets are MPC wallets created from a user's social or email
login — no browser extension required. Like all Midnight wallets, they expose
**three surfaces**:

| Surface | What it is | Where Dynamic exposes it |
| :- | :- | :- |
| **Unshielded** | Public address and state. The wallet's main address. | `wallet.address` |
| **Shielded** | Private address and state. A separate token pool. | `wallet.additionalAddresses` (`midnight_shielded`) |
| **DUST** | Fee-generation state. DUST pays for Midnight transactions. | `wallet.additionalAddresses` (`midnight_dust`) |

`NIGHT` exists as both a shielded and an unshielded asset — different token
types in different pools, not the same balance shown twice.

> [!NOTE]
>
> This page covers **embedded** Midnight wallets (created via social/email
> login). For **external wallets** (e.g. 1am), see
> [Using Midnight external wallets](https://docs.dynamic.xyz/docs/react/wallets/using-wallets/midnight/using-midnight-wallets.md).

## Enabling Midnight

**1. Enable Midnight in the Dynamic Console**

Enable Midnight under [Chains & Networks](https://console.dynamic.xyz/dashboard/chains-and-networks).

**2. Enable Private Key Exports in the Dynamic Console**

Midnight embedded wallets internally derive signing keys via the key export mechanism. **Private Key Exports must be enabled** in your environment settings or all wallet operations (balance reads, signing, transfers) will fail with a 403 error.

Go to **Embedded Wallets → Security** in the [Dynamic Console](https://console.dynamic.xyz/dashboard/embedded-wallets) and toggle **Private Key Exports** on.

> [!WARNING]
>
> Without this setting enabled, Midnight wallets cannot initialise — calls to `getFormattedBalances()`, `signMessage()`, and all other wallet methods will fail.

**3. Install the connector**

```bash npm theme={"system"}
npm i @dynamic-labs/midnight
```

```bash yarn theme={"system"}
yarn add @dynamic-labs/midnight
```

**4. Add the embedded connector to DynamicContextProvider**

Use `DynamicWaasMidnightConnectors` for embedded (MPC) wallets.

```tsx React theme={"system"}
import { DynamicContextProvider, DynamicWidget } from '@dynamic-labs/sdk-react-core';
import { DynamicWaasMidnightConnectors } from '@dynamic-labs/midnight';

const App = () => (
  <DynamicContextProvider
    settings={{
      environmentId: 'YOUR_ENVIRONMENT_ID',
      walletConnectors: [DynamicWaasMidnightConnectors],
    }}
  >
    <DynamicWidget />
  </DynamicContextProvider>
);

export default App;
```

## Getting a Midnight wallet

Narrow a wallet with `isMidnightWallet` before calling Midnight methods. The
guard both confirms the chain and gives you the typed wallet — all operations
below are called directly on it.

```tsx React theme={"system"}
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
import { isMidnightWallet } from '@dynamic-labs/midnight';

const { primaryWallet } = useDynamicContext();

if (!primaryWallet || !isMidnightWallet(primaryWallet)) {
  throw new Error('This wallet is not a Midnight wallet');
}

// `primaryWallet` is now a typed Midnight wallet.
```

## Reading balances

`getFormattedBalances()` returns display-ready strings for all three surfaces in
one call:

```tsx React theme={"system"}
const { unshieldedBalance, shieldedTokenCount, dustBalance, dustSyncing } =
  await primaryWallet.getFormattedBalances();

// unshieldedBalance  -> unshielded NIGHT as a display string, e.g. "3.0" (undefined if none)
// shieldedTokenCount -> number of distinct token types with a positive shielded balance
//                       (shielded NIGHT is a separate token type from unshielded NIGHT)
// dustBalance        -> { balance: string, cap: string } (undefined if no DUST)
// dustSyncing        -> true while DUST is still syncing in the background (embedded only)
```

Poll `dustSyncing` to know when all surfaces are ready:

```tsx React theme={"system"}
async function waitForSync() {
  const { dustSyncing } = await primaryWallet.getFormattedBalances();
  if (dustSyncing) {
    setTimeout(waitForSync, 2500); // retry until ready
  }
}
waitForSync();
```

Individual getters are also available:

```tsx React theme={"system"}
const shielded   = await primaryWallet.getShieldedBalance();   // string | undefined
const unshielded = await primaryWallet.getUnshieldedBalance(); // string | undefined
const dust       = await primaryWallet.getDustBalance();       // { balance: string, cap: string }
```

For raw, per-token amounts (a pool can hold more than just NIGHT), use
`getBalances()`, which returns `{ shielded, unshielded, dust }` keyed by token
type, with `bigint` values:

```tsx React theme={"system"}
const { shielded, unshielded, dust } = await primaryWallet.getBalances();
```

> [!NOTE]
>
> The first balance read on a device runs a one-time background sync (the DUST
> state can take a while to fold). Subsequent reads resume from a local
> checkpoint and return quickly.

## Signing a message

```tsx React theme={"system"}
const signature = await primaryWallet.signMessage('Hello Midnight');
```

## Sending tokens

Embedded Midnight wallets support both **unshielded** (public) and **shielded**
(private) transfers for NIGHT and other tokens. Amounts are in the token's
smallest (atomic) unit unless `token.decimals` is set.

### Simple send

`sendBalance` builds, proves, and broadcasts in one call, and routes to the
right pool automatically based on the recipient prefix (`mn_shield…` →
shielded, otherwise unshielded). It returns the transaction hash.

```tsx React theme={"system"}
// Unshielded NIGHT transfer
const txHash = await primaryWallet.sendBalance({
  toAddress: 'mn_addr...',
  amount: '100000000', // atomic units
});

// Shielded NIGHT transfer — same call, shielded recipient
await primaryWallet.sendBalance({
  toAddress: 'mn_shield...',
  amount: '100000000',
});

// Shielded transfer of a non-NIGHT token
await primaryWallet.sendBalance({
  toAddress: 'mn_shield...',
  amount: '50',
  token: {
    address: 'tokenTypeHex', // token type identifier
    decimals: 6,             // optional, defaults to 0
  },
});
```

> [!NOTE]
>
> `sendBalance` routes based on the recipient address prefix: `mn_addr` draws
> from the unshielded pool; `mn_shield` draws from the shielded pool. Cross-pool
> transfers (unshielded → shielded or vice versa) are not supported.
>
> The optional `token` parameter lets you send tokens other than native NIGHT.
> Pass `token.address` with the token type identifier and `token.decimals` if
> the amount needs decimal conversion. Omit `token` entirely for NIGHT transfers.

### Step-by-step send

For more control, run the three steps yourself — **build → sign → submit**.
This lets you inspect or persist the serialized transaction between steps. Set
`type` to `'unshielded'` or `'shielded'` per transfer.

```tsx React theme={"system"}
// 1. Build an unsigned transaction.
const { serializedTransaction } = await primaryWallet.createTransferTransaction({
  transfers: [
    {
      type: 'unshielded',       // or 'shielded'
      recipientAddress: 'mn_addr...',
      amount: '100000000',      // atomic units
      tokenType: 'tokenTypeHex', // optional — omit for native NIGHT
    },
  ],
});

// 2. Sign + ZK-prove (unshielded segments are MPC-signed; shielded/dust are proven).
const finalizedTransaction =
  await primaryWallet.signTransaction(serializedTransaction);

// 3. Broadcast.
const { txHash } = await primaryWallet.submitTransaction(finalizedTransaction);
```

> [!NOTE]
>
> Transactions are paid for in **DUST**, generated by registered unshielded
> NIGHT. If a wallet has no DUST, register it first (see below).

## Registering for DUST

DUST is the resource that pays for Midnight transactions. It is generated over
time by unshielded NIGHT that has been registered for generation. Call
`registerDust()` once to designate the wallet's NIGHT for DUST generation.

```tsx React theme={"system"}
const result = await primaryWallet.registerDust();
// result.status -> 'registered' | 'already_registered' | 'already_has_dust' | 'no_utxos'
```

> [!TIP]
>
> Fund the wallet with unshielded NIGHT before registering — DUST is generated
> from NIGHT UTxOs, so a wallet with no NIGHT has nothing to register.

Registration is one-off, and DUST is **not** minted by it. It accrues on chain
over time, at a rate set by how much NIGHT the wallet holds, so a zero balance
immediately after registering is expected. Poll `getFormattedBalances()` until
`dustBalance` appears.

Calling `registerDust()` again once the NIGHT is already registered returns
`already_registered` with `registeredCount: 0` — nothing is left to register, so
this is a success, not a failure.

> [!NOTE]
>
> If DUST stays at zero for a long time, the wallet is likely holding too little
> NIGHT to generate at a visible rate. Funding more NIGHT increases the rate.

## Recovering reserved UTxOs

If a transaction is built or signed but never submitted, its inputs stay
reserved. These methods release them:

```tsx React theme={"system"}
// Release the inputs of a specific built/signed transaction.
await primaryWallet.revertTransaction(serializedTransaction);

// Release every finalized-but-unsubmitted transaction the wallet knows about.
await primaryWallet.revertAllPending();
```

> [!WARNING]
>
> `resetWalletCache()` is a last resort. It clears the wallet's persisted state
> and forces a full cold re-sync on the next operation. Use it only when inputs
> stay stuck after `revertTransaction` and `revertAllPending`.
>
> ```tsx React theme={"system"}
> await primaryWallet.resetWalletCache();
> ```

## Calling contracts

Embedded Midnight wallets can act as the settlement half of a contract call —
balancing, paying DUST, signing and submitting, all inside the wallet iframe —
while your app runs the circuit and generates the proof.

```tsx React theme={"system"}
const walletProvider = await primaryWallet.getWalletProvider();
```

See [Deploying and calling Midnight contracts](https://docs.dynamic.xyz/docs/react/wallets/using-wallets/midnight/midnight-contracts.md).

## Resources

* [Enabling Chains & Networks](https://docs.dynamic.xyz/docs/react/chains/enabling-chains.md)
* [Deploying and calling Midnight contracts](https://docs.dynamic.xyz/docs/react/wallets/using-wallets/midnight/midnight-contracts.md)
* [Using Midnight external wallets](https://docs.dynamic.xyz/docs/react/wallets/using-wallets/midnight/using-midnight-wallets.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.