# Client-side SDKs

Backend wallets work well for automated trading, but some applications need client-side wallet interaction — for example, letting users sign trades from a web or mobile app. Openfort's embedded wallets work with React (via `@openfort/react` + wagmi) and React Native.

## React integration

Use Openfort's React SDK with wagmi to get a viem wallet client for Hyperliquid:

### Set up providers

```tsx
import { OpenfortProvider } from '@openfort/react'
import { OpenfortWagmiBridge } from '@openfort/react/wagmi'
import { WagmiProvider, createConfig } from 'wagmi'
import { arbitrumSepolia } from 'wagmi/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const config = createConfig({
  chains: [arbitrumSepolia],
  transports: {
    [arbitrumSepolia.id]: http(),
  },
})

const queryClient = new QueryClient()

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <QueryClientProvider client={queryClient}>
      <WagmiProvider config={config}>
        <OpenfortWagmiBridge>
          <OpenfortProvider publishableKey={process.env.NEXT_PUBLIC_OPENFORT_PUBLISHABLE_KEY!}>
            {children}
          </OpenfortProvider>
        </OpenfortWagmiBridge>
      </WagmiProvider>
    </QueryClientProvider>
  )
}
```

### Trade from the client

```tsx
import { useWalletClient } from 'wagmi'
import * as hl from '@nktkas/hyperliquid'

function TradingPanel() {
  const { data: walletClient } = useWalletClient()

  async function placeOrder() {
    if (!walletClient) return

    const transport = new hl.HttpTransport({ isTestnet: true })
    const exchange = new hl.ExchangeClient({
      wallet: walletClient,
      transport,
    })

    await exchange.order({
      orders: [
        {
          a: 4,
          b: true,
          p: '3000.0',
          s: '0.01',
          r: false,
          t: { limit: { tif: 'Gtc' } },
        },
      ],
      grouping: 'na',
    })
  }

  return <button onClick={placeOrder}>Buy ETH</button>
}
```

## Embedded wallet as agent

Use an external wallet (for example, MetaMask) as the Hyperliquid master and an Openfort embedded wallet as the agent. Users retain full custody of their funds while the embedded wallet trades on their behalf.

::::steps

### Connect external wallet as master

The user connects their existing wallet and deposits funds to Hyperliquid.

### Create Openfort embedded wallet as agent

```tsx
import { useOpenfort } from '@openfort/react'

function AgentSetup() {
  const { user } = useOpenfort()

  // The user's embedded wallet address serves as the agent
  const agentAddress = user?.wallet?.address
  // ...
}
```

### Approve embedded wallet as agent

The user signs an `approveAgent` transaction from their external wallet, authorizing the Openfort embedded wallet to trade on their behalf.

### Trade with the embedded wallet

The embedded wallet can now place orders without requiring the user to approve each transaction through their external wallet.

::::

## React Native

For a complete React Native implementation with Expo, see the demo application:

:::info
The [React Native demo](/docs/recipes/hyperliquid) includes Openfort embedded wallet authentication, live price feeds, and a guided trading flow for the Hyperliquid testnet.
:::

## Best practices

* **Initialize the agent wallet once** on first use and persist a reference — avoid creating new agents on every session
* **Separate action types clearly in your UI** — L1 actions (orders, leverage) go through the agent wallet; User Signed Actions (withdrawals, agent approvals) require the external wallet
* **Handle wallet disconnection gracefully** — check wallet availability before submitting orders and show clear error states
* **Provide feedback on which wallet signs** — users should know whether their external wallet or embedded agent is performing each action
