# Gas Sponsorship with Privy

The City stack supports gas sponsorship through Privy's embedded wallet infrastructure. When enabled, your app covers transaction fees on behalf of users, so they never need to hold ETH (or any native token) just to interact with your product. This is especially useful for onboarding new users who may not have funded wallets yet.

***

### Prerequisites

Before writing any code, you need to configure gas sponsorship in the Privy dashboard.

1. Navigate to your app's settings and enable **Gas Sponsorship**.
2. Select the chains you want to sponsor transactions on (e.g. Ethereum mainnet, Base, Arbitrum).
3. Fund your gas credit balance. Privy will draw from this balance to cover user transaction fees.

For EVM apps, Privy recommends pairing gas sponsorship with smart wallets. Smart wallets support native sponsorship without requiring a separate relayer, and they let you register a paymaster URL directly in the dashboard. If you're using embedded wallets (which is the default in the City stack), this is handled for you.

***

### Installation

Install the City SDK alongside Privy's React auth package:

```bash
bun add @cityprotocol/core @privy-io/react-auth
```

If you need lower-level wallet or provider access (for example, to construct custom transactions or interact with contracts outside the City SDK), add Viem as well:

```bash
bun add @cityprotocol/core @privy-io/react-auth viem
```

***

### Provider Setup

Wrap your app in `PrivyProvider` at the root of your component tree. This handles authentication, wallet creation, and sponsorship configuration in one place.

```
import { PrivyProvider } from "@privy-io/react-auth";
import React from "react";
import ReactDOM from "react-dom/client";

import { App } from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <PrivyProvider
    appId={import.meta.env.VITE_PRIVY_APP_ID}
    config={{
      loginMethods: ["wallet"],
      embeddedWallets: {
        ethereum: {
          createOnLogin: "users-without-wallets",
        },
      },
    }}
  >
    <App />
  </PrivyProvider>,
);
```

The `createOnLogin: "users-without-wallets"` setting tells Privy to automatically generate an embedded wallet for any user who doesn't already have one. This means a user can sign in with email or social login and immediately have a wallet ready to go, no browser extension required.

***

### Sending a Sponsored Transaction

Use Privy's `useSendTransaction` hook to fire off a transaction with gas sponsorship. The `sponsor: true` flag tells Privy to route the transaction through your configured paymaster so the user pays zero gas.

```
import { useSendTransaction, useWallets } from "@privy-io/react-auth";

export function SponsoredTransfer() {
  const { wallets } = useWallets();
  const { sendTransaction } = useSendTransaction();

  async function handleSend() {
    if (!wallets[0]) {
      throw new Error("No Privy wallet is available for the current user.");
    }

    await sendTransaction(
      {
        to: "0xE3070d3e4309afA3bC9a6b057685743CF42da77C",
        value: 100000,
      },
      {
        sponsor: true,
      },
    );
  }

  return <button onClick={handleSend}>Send sponsored transaction</button>;
}
```

This pattern works for any raw transaction. If you need to send contract calls (like an ERC-20 transfer or a vault deposit), you would encode the calldata yourself or use Viem's contract utilities, then pass the resulting transaction object to `sendTransaction` with `sponsor: true`.

***

### Using Gas Sponsorship with City SDK

The `@cityprotocol/core` package does not include its own gas sponsorship layer. It doesn't need to. Instead, sponsorship is handled entirely at the wallet level by Privy, and the City SDK handles the financial logic (vault interactions, deposit flows, cooldowns, and so on).

In practice, this means your integration is a composition of three layers:

**Privy** manages authentication, wallet creation, and gas sponsorship. It gives your users a wallet and makes sure they never see a gas fee.

**City SDK** provides the onchain methods: creating vaults, depositing and withdrawing assets, reading balances and cooldown states, and querying portfolio data from the subgraph.

**Your app** ties it all together into a user experience. You decide when to sponsor, what flows to expose, and how to present vault interactions to end users.

***

### Typical Integration Flow

A common pattern looks like this:

1. The user logs in through Privy. An embedded smart wallet is created automatically if they don't have one.
2. Your frontend uses `CityClient` read methods (like `previewDeposit` or `maxDeposit`) to display quotes and limits in the UI.
3. When the user submits an action (say, a vault deposit), you call the corresponding City SDK write method. The SDK builds the transaction, handles any required ERC-20 approvals, and returns a transaction hash.
4. Privy's sponsorship layer intercepts the transaction at the wallet level and covers the gas, so the user confirms the action without needing native tokens in their wallet.
5. For portfolio views and transaction history, you use `CityPortfolioClient` to pull indexed data from the subgraph, combined with live onchain reads from `CityClient` for real-time balances and cooldown states.

The key thing to remember: Privy owns the wallet and gas layer, City owns the protocol interaction layer. They don't overlap, and you don't need to wire them together explicitly. As long as your `CityClient` is initialized with the Viem wallet client that Privy provides, sponsored transactions will flow through naturally.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://city-protocol.gitbook.io/docs/software-development-kit/wallet/gas-sponsorship-with-privy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
