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

# Quickstart

> Connect a Startale smart account in a React app, sign messages with ERC-1271, and send a UserOperation on Soneium Mainnet.

This guide integrates the Startale App SDK into a React project. By the end you will have an application that:

* Connects to a user's Startale smart account through wagmi.
* Produces an ERC-1271 signature and verifies it offchain with viem.
* Sends a transaction packaged as an ERC-4337 UserOperation on Soneium Mainnet.

<Info>
  The reference stack is Vite + React 18 with wagmi 2, viem 2, and TanStack Query. The same code paths apply in Next.js. See [SDK installation](/app-sdk/installation) for framework variants.
</Info>

## Prerequisites

| Requirement     | Version                                           |
| --------------- | ------------------------------------------------- |
| Node.js         | 20 or later                                       |
| Package manager | pnpm 9, npm, yarn, or bun                         |
| React project   | Scaffold one below if you do not already have one |

If you do not have a React project, scaffold one with Vite:

```bash theme={null}
pnpm create vite@latest startale-quickstart --template react-ts
cd startale-quickstart
pnpm install
```

<Steps>
  <Step title="Install the SDK">
    Install `@startale/app-sdk` with its peer dependencies.

    <CodeGroup>
      ```bash pnpm theme={null}
      pnpm add @startale/app-sdk wagmi viem @tanstack/react-query
      ```

      ```bash npm theme={null}
      npm install @startale/app-sdk wagmi viem @tanstack/react-query
      ```

      ```bash yarn theme={null}
      yarn add @startale/app-sdk wagmi viem @tanstack/react-query
      ```

      ```bash bun theme={null}
      bun add @startale/app-sdk wagmi viem @tanstack/react-query
      ```
    </CodeGroup>

    Each package has a specific role in the integration:

    * `@startale/app-sdk` exposes the Startale connector and the underlying EIP-1193 provider.
    * `wagmi` provides the React hooks, `useAccount`, `useConnect`, `useSendTransaction`, that drive the integration.
    * `viem` is the typed RPC client wagmi uses for read and write operations.
    * `@tanstack/react-query` caches asynchronous state, including the connector's readiness and the smart-account address resolution.

    The SDK ships with a wagmi connector by default. To use the SDK without wagmi, see [Initialization](/app-sdk/initialization).
  </Step>

  <Step title="Configure the wagmi client">
    Create `src/wagmi.ts`. This file declares the supported chain, registers the Startale connector, and configures an HTTP transport.

    ```ts src/wagmi.ts theme={null}
    import { startaleConnector } from '@startale/app-sdk'
    import { http, createConfig } from 'wagmi'
    import { soneium } from 'wagmi/chains'

    export const config = createConfig({
      chains: [soneium],
      connectors: [
        startaleConnector({
          appName: 'Startale Quickstart',
          appLogoUrl: 'https://your-app.com/logo.png',
        }),
      ],
      transports: {
        [soneium.id]: http(),
      },
    })

    declare module 'wagmi' {
      interface Register {
        config: typeof config
      }
    }
    ```

    `createConfig` returns a typed wagmi configuration. The `chains` field declares which chains the application supports, and the connector derives its `appChainIds` from this list automatically.

    `startaleConnector` accepts a preference object. `appName` and `appLogoUrl` appear inside the Startale App popup so the user can identify the requesting application. Use a short name and a square HTTPS image URL.

    `http()` with no argument routes to the default public RPC for the chain. Production traffic should use a dedicated endpoint. See [Networks](/concepts/networks) for the current options.

    The `declare module 'wagmi'` block registers this configuration as the active one for type inference. Without it, hooks like `useAccount` cannot infer chain-aware return types in your application code.

    <Tip>
      Add `soneiumMinato` to the `chains` array when you need a testing flow. See [Networks](/concepts/networks) for the testnet endpoints.
    </Tip>
  </Step>

  <Step title="Wrap the application">
    Wrap the application in `WagmiProvider` and `QueryClientProvider` in `src/main.tsx`. Both providers are required. `WagmiProvider` exposes the config and connection state to wagmi hooks. `QueryClientProvider` backs the React Query cache that wagmi uses internally for asynchronous state.

    ```tsx src/main.tsx theme={null}
    import { StrictMode } from 'react'
    import { createRoot } from 'react-dom/client'
    import { WagmiProvider } from 'wagmi'
    import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
    import { config } from './wagmi'
    import { App } from './App'

    const queryClient = new QueryClient()

    createRoot(document.getElementById('root')!).render(
      <StrictMode>
        <WagmiProvider config={config}>
          <QueryClientProvider client={queryClient}>
            <App />
          </QueryClientProvider>
        </WagmiProvider>
      </StrictMode>,
    )
    ```
  </Step>

  <Step title="Connect a wallet">
    Add a button that triggers the Startale connector. The example uses three wagmi hooks: `useAccount` reads the current connection state, `useConnect` exposes the registered connectors and a `connect` action, and `useDisconnect` clears the local connection.

    ```tsx src/App.tsx theme={null}
    import { useAccount, useConnect, useDisconnect } from 'wagmi'

    export function App() {
      const { address, status } = useAccount()
      const { connect, connectors } = useConnect()
      const { disconnect } = useDisconnect()
      const startale = connectors[0]

      if (status === 'connected') {
        return (
          <div>
            <p>Connected as {address}</p>
            <button onClick={() => disconnect()}>Disconnect</button>
          </div>
        )
      }

      return (
        <button onClick={() => connect({ connector: startale })}>
          Connect Startale
        </button>
      )
    }
    ```

    `connectors[0]` returns the Startale connector because it is the only one registered in `wagmi.ts`. When multiple connectors are configured, identify Startale by `connector.id === 'startaleApp'` rather than relying on array position.

    Run the dev server:

    ```bash theme={null}
    pnpm dev
    ```

    Click the button. A popup opens to `app.startale.com`. The user signs in with Google, LINE, Apple, or MetaMask, approves the connection, and the popup closes. The application receives the user's smart-account address in `address`.

    <Check>
      The address returned is a smart account, not an externally owned account. The same address resolves on every application that integrates the Startale App SDK.
    </Check>
  </Step>

  <Step title="Sign a message">
    Produce an ERC-1271 signature with `useSignMessage`. Smart accounts do not sign with a private key in the standard ECDSA path. Signatures are produced through the account contract and verified by calling `isValidSignature` on the same contract.

    ```tsx theme={null}
    import { useAccount, useSignMessage } from 'wagmi'

    export function SignButton() {
      const { address } = useAccount()
      const { signMessageAsync } = useSignMessage()

      if (!address) return null

      const onClick = async () => {
        const signature = await signMessageAsync({
          message: 'I am verifying ownership of my Startale wallet.',
        })
        console.log({ address, signature })
      }

      return <button onClick={onClick}>Sign message</button>
    }
    ```

    Verify the signature offchain with viem's `verifyMessage`:

    ```ts theme={null}
    import { createPublicClient, http } from 'viem'
    import { soneium } from 'viem/chains'

    const publicClient = createPublicClient({ chain: soneium, transport: http() })

    const isValid = await publicClient.verifyMessage({
      address,
      message: 'I am verifying ownership of my Startale wallet.',
      signature,
    })
    ```

    `verifyMessage` calls `isValidSignature` on the smart-account contract. The same code path verifies signatures whether the account is deployed or counterfactual. See [Smart accounts](/concepts/smart-accounts) for the ERC-6492 wrapping behavior.

    <Info>
      ERC-1271 verification is a contract call and requires a `publicClient` configured against the same chain as the signing account. When the verifier runs on different infrastructure, use the same chain identifier on both sides.
    </Info>
  </Step>

  <Step title="Send a transaction">
    The application calls `useSendTransaction` exactly as it would with any wagmi-compatible wallet. The SDK transforms the request into an ERC-4337 UserOperation, attaches a paymaster signature if one is configured, and submits the operation through the bundler. The user signs in the popup.

    ```tsx theme={null}
    import { useSendTransaction } from 'wagmi'

    export function SendButton() {
      const { sendTransactionAsync, isPending } = useSendTransaction()

      const onClick = async () => {
        const hash = await sendTransactionAsync({
          to: '0x000000000000000000000000000000000000dEaD',
          value: 0n,
        })
        console.log({ hash })
      }

      return (
        <button onClick={onClick} disabled={isPending}>
          {isPending ? 'Sending...' : 'Send transaction'}
        </button>
      )
    }
    ```

    A popup opens with the transaction details. The user reviews and approves; the application receives a transaction hash that resolves to a confirmed UserOperation onchain.

    <Info>
      **Who pays the gas?** Inside the Startale App (Mini Apps), the host paymaster sponsors gas automatically. Standalone dapps configure a paymaster through [`paymasterOptions`](/app-sdk/custom-paymaster); without one, the user pays gas from their smart account's ETH balance. See [Gas sponsorship](/concepts/gasless) for the full model.
    </Info>
  </Step>
</Steps>

<Check>
  The integration is complete: connect, sign, send. Every signature verifies through ERC-1271, and the same code runs on Soneium Minato.
</Check>

## Next steps

<Columns cols={2}>
  <Card title="Configure a paymaster" icon="bolt" href="/app-sdk/custom-paymaster">
    Wire an SCS paymaster or your own ERC-7677 service into the SDK.
  </Card>

  <Card title="Charge in USDSC" icon="dollar-sign" href="/app-sdk/pay-with-usdsc">
    Standard ERC-20 transfers in the Startale stablecoin.
  </Card>

  <Card title="Sign typed data" icon="signature" href="/app-sdk/sign-messages">
    EIP-712 for orders, permits, and consent flows.
  </Card>

  <Card title="Build a Mini App" icon="table-cells" href="/miniapps/quickstart">
    Run the project inside the Startale App with access to host context.
  </Card>

  <Card title="Handle errors" icon="triangle-exclamation" href="/app-sdk/errors">
    User rejections, chain mismatches, wrong calls and popup blockers.
  </Card>
</Columns>
