> For the complete documentation index, see [llms.txt](https://city-protocol.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://city-protocol.gitbook.io/docs/software-development-kit/wallet/common-frontend-flows.md).

# Common Frontend Flows

#### Gated Page Load

1. Read `ready` and `authenticated` from `usePrivy()`.
2. If `ready` is `false`, render a loading state.
3. If `ready` is `true` but `authenticated` is `false`, render a connect prompt that calls `login`.
4. Once `authenticated` is `true`, read `user.wallet.address` and fetch any user-specific data from your backend using the identity token.

#### Authenticated API Request

1. Obtain `identityToken` from `useIdentityToken()`.
2. Attach it as `Authorization: Bearer <identityToken>` on every request to your backend.
3. On the server, pass the header to `verifyPrivyWallet` to extract the user.
4. Use the returned `user.wallet.address` to look up balances, vault positions, or any City-powered feature.

#### Connecting a Wallet to Vault Operations

Once the wallet is verified, combine both SDK clients for a full-stack flow:

```
// Client-side: create a CityClient with the user's wallet
import { CityClient } from "@cityprotocol/core";

const cityClient = new CityClient(walletClient);

// Now the same wallet that Privy authenticated can call vault methods
const hash = await cityClient.deposit({
  vault: "0xVaultAddress",
  assets: 1000000n,
});
```

The `walletClient` here is a Viem wallet client backed by the same account Privy manages. This ensures the on-chain signer and the backend-verified identity always correspond to the same address.
