npm package: @oviato/connect
Description: React components and hooks for Oviato authentication and wallet operations. Built on @oviato/sdk.
Latest version: 0.3.1

# Oviato Connect

React components and hooks for Oviato authentication and wallet operations. Built on [@oviato/sdk](https://www.npmjs.com/package/@oviato/sdk).

## Features

- **React & Next.js First** - Hooks, provider, and full SSR compatibility
- **Built on Oviato SDK** - Framework-agnostic core with React bindings
- **TypeScript Native** - Full type safety and IntelliSense
- **Tree-shakeable** - Optimized bundle with separate entry points
- **WebAuthn Passkeys** - Secure, passwordless authentication
- **Multi-Chain Support** - Bitcoin, Ethereum, BASE, and more
- **Pre-built Components** - Drop-in UI components for authentication
- **Dark Mode Support** - Full dark mode with auto system preference detection
- **x402 Payments** - ERC-3009 gasless USDC payments support
- **EIP-712 Signing** - Typed data signing for EVM chains

## Installation

```bash
npm install @oviato/connect
# or
pnpm add @oviato/connect
# or
yarn add @oviato/connect
```

> **Note:** For framework-agnostic usage (Vue, Svelte, vanilla JS), use [@oviato/sdk](https://www.npmjs.com/package/@oviato/sdk) instead.

## Quick Start

### Next.js App Router

```tsx
// app/layout.tsx
import { OviConnectProvider } from '@oviato/connect/client';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <OviConnectProvider appId="your-app-id" network="bitcoinmainnet">
          {children}
        </OviConnectProvider>
      </body>
    </html>
  );
}
```

```tsx
// app/page.tsx
'use client';

import { useOviConnect, ConnectButton } from '@oviato/connect/client';

export default function HomePage() {
  const { session, disconnect, isLoading } = useOviConnect();

  if (isLoading) return <div>Loading...</div>;

  if (!session) {
    return (
      <ConnectButton
        text="Connect Wallet"
        onSuccess={(data) => console.log('Connected:', data.address)}
        onError={(error) => console.error('Error:', error)}
      />
    );
  }

  return (
    <div>
      <p>Connected: {session.address}</p>
      <button onClick={disconnect}>Disconnect</button>
    </div>
  );
}
```

### Next.js Pages Router

```tsx
// pages/_app.tsx
import type { AppProps } from 'next/app';
import { OviConnectProvider } from '@oviato/connect/client';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <OviConnectProvider appId="your-app-id" network="bitcoinmainnet">
      <Component {...pageProps} />
    </OviConnectProvider>
  );
}
```

### React (Vite, CRA)

```tsx
// main.tsx or App.tsx
import { OviConnectProvider } from '@oviato/connect/client';

function App() {
  return (
    <OviConnectProvider appId="your-app-id" network="bitcoinmainnet">
      <YourApp />
    </OviConnectProvider>
  );
}
```

## Package Structure

Oviato Connect provides two entry points for optimal tree-shaking and SSR compatibility:

### `@oviato/connect` (Core - SSR Safe)

Server-safe utilities and types. Re-exports from [@oviato/sdk](https://www.npmjs.com/package/@oviato/sdk):

```ts
import {
  // Authentication
  login,
  register,
  authenticate,

  // Wallet Operations
  signMessage,
  sendTransfer,
  switchNetwork,
  signPsbt,

  // Session Management
  getSession,
  setSession,
  clearSession,
  isAuthenticated,

  // Initialization
  initialize,
  getConfig,
  isInitialized,

  // RPC & Utilities
  rpc,
  rpcRequest,
  resolveUsername,

  // Types
  type UserSession,
  type BridgeResponse,
  type OviatoConfig,
} from '@oviato/connect';
```

### `@oviato/connect/client` (React - Client Only)

Client-side React components and hooks with `'use client'` directive:

```tsx
import {
  // Provider
  OviConnectProvider,

  // Hooks
  useOviConnect,

  // Components
  ConnectButton,
  Connect,
  Button,
  Logo,
  SecuredByOviato,
} from '@oviato/connect/client';
```

## API Reference

### React Hooks

#### `useOviConnect()`

Access Oviato Connect state and methods. Must be used within `OviConnectProvider`.

```tsx
import { useOviConnect } from '@oviato/connect/client';

function MyComponent() {
  const {
    session, // Current session or null
    isLoading, // SDK initialization state
    ready, // SDK ready for use
    disconnect, // Logout function
  } = useOviConnect();

  if (isLoading) return <div>Loading...</div>;
  if (!session) return <div>Not connected</div>;

  return (
    <div>
      <p>Address: {session.address}</p>
      <p>Username: {session.username}</p>
      <button onClick={disconnect}>Disconnect</button>
    </div>
  );
}
```

### Components

#### `<OviConnectProvider>`

Wrap your app to provide Oviato Connect context.

```tsx
import { OviConnectProvider } from '@oviato/connect/client';

<OviConnectProvider appId="your-app-id" network="bitcoinmainnet" theme="auto">
  {children}
</OviConnectProvider>;
```

**Props:**

- `appId: string` - Your Oviato app ID (required)
- `network?: string` - Default network (default: 'bitcoinmainnet')
- `theme?: 'light' | 'dark' | 'auto'` - UI theme ('auto' follows system preference)
- `accentColor?: string` - Brand color
- `logoUrl?: string` - Your app logo
- `name?: string` - Your app name

#### `<ConnectButton>`

Flexible authentication button with support for custom children.

**Default Button:**

```tsx
import { ConnectButton } from '@oviato/connect/client';

<ConnectButton
  text="Connect Wallet"
  className="my-button"
  onSuccess={(data) => console.log(data.address)}
  onError={(error) => console.error(error)}
/>;
```

**Custom Children:**

```tsx
<ConnectButton onSuccess={(data) => console.log(data)}>
  <button className="custom-btn">🔐 Sign in with Passkey</button>
</ConnectButton>
```

**Props:**

- `children?: ReactNode` - Custom UI (overrides default button)
- `text?: string` - Button text (default: "Connect Wallet")
- `onSuccess?: (data) => void` - Success callback
- `onError?: (error) => void` - Error callback
- `className?: string` - CSS class for default button

#### `<Connect>`

Pre-built authentication card with username input and dark mode support.

```tsx
import { Connect } from '@oviato/connect/client';

<Connect
  callback={(data) => {
    console.log('Connected:', data.address);
  }}
  network="basemainnet"
  invertLogo
/>;
```

**Props:**

- `callback?: (data) => void` - Success callback with address and publicKey
- `network?: Network` - Override network for this authentication
- `invertLogo?: boolean` - Invert logo colors in dark mode (useful for dark logos)

### Core Functions

All core functions are re-exported from [@oviato/sdk](https://www.npmjs.com/package/@oviato/sdk). See the SDK documentation for detailed API reference.

#### Authentication

```ts
import { authenticate, login, register } from '@oviato/connect';

// Smart authentication (auto-detects new vs returning users)
await authenticate({ username: 'alice' });

// Explicit login
await login();

// Explicit register
await register({ username: 'bob' });
```

#### Wallet Operations

```ts
import { signMessage, sendTransfer, switchNetwork, signPsbt, signTypedData } from '@oviato/connect';

// Sign message
await signMessage('Hello Oviato!');

// Send transfer
await sendTransfer({
  to: 'bc1q...',
  amount: 10000, // satoshis
  fee: 1000,
});

// Switch network
await switchNetwork('basemainnet'); // BASE, Ethereum, Bitcoin supported

// Sign PSBT (Bitcoin only)
await signPsbt({
  psbt: 'cHNidP8BAH0...',
  signInputs: [0, 1],
  broadcast: true,
});

// Sign EIP-712 typed data (EVM chains)
await signTypedData({
  domain: { name: 'MyApp', version: '1', chainId: 8453 },
  types: { Message: [{ name: 'content', type: 'string' }] },
  message: { content: 'Hello' },
  primaryType: 'Message',
});
```

#### x402 Payments

```ts
import { x402Sign, isPaymentRequired, getPaymentDetails } from '@oviato/connect';

// Check if endpoint requires payment
const response = await fetch('https://api.example.com/premium');
if (isPaymentRequired(response)) {
  const paymentDetails = getPaymentDetails(response);
  const signed = await x402Sign({ paymentRequired: paymentDetails });
  // Retry with payment header
}
```

#### Session Management

```ts
import { getSession, isAuthenticated, clearSession } from '@oviato/connect';

const session = getSession();
const isAuth = isAuthenticated();

clearSession(); // Logout
```

#### RPC Client

```ts
import { rpc } from '@oviato/connect';

const balance = await rpc.getBalance({ address: 'bc1q...' });
const history = await rpc.getTransactionHistory({ address: 'bc1q...', limit: 10 });
```

#### OVI.ID Resolution

```ts
import { resolveUsername } from '@oviato/connect';

const addresses = await resolveUsername('alice');
// Returns: { bitcoin: 'bc1q...', ethereum: '0x...', ... }
```

## Examples

### Multi-Network Wallet

```tsx
'use client';
import { useOviConnect, ConnectButton } from '@oviato/connect/client';
import { switchNetwork, signMessage, sendTransfer } from '@oviato/connect';

export default function Wallet() {
  const { session, disconnect } = useOviConnect();

  if (!session) {
    return <ConnectButton text="Connect Wallet" />;
  }

  const handleNetworkSwitch = async (network: string) => {
    const result = await switchNetwork(network);
    if (result.status === 'success') {
      alert(`Switched to ${network}`);
    }
  };

  const handleSignMessage = async () => {
    const result = await signMessage('Hello from Oviato!');
    if (result.status === 'success') {
      console.log('Signature:', result.data.signature);
    }
  };

  return (
    <div>
      <h2>Connected: {session.username}</h2>
      <p>Network: {session.network}</p>
      <p>Address: {session.address}</p>

      <div>
        <button onClick={() => handleNetworkSwitch('bitcoinmainnet')}>Bitcoin</button>
        <button onClick={() => handleNetworkSwitch('ethmainnet')}>Ethereum</button>
        <button onClick={() => handleNetworkSwitch('basemainnet')}>BASE</button>
      </div>

      <button onClick={handleSignMessage}>Sign Message</button>
      <button onClick={disconnect}>Disconnect</button>
    </div>
  );
}
```

### Wallet Balance Display

```tsx
'use client';
import { useOviConnect } from '@oviato/connect/client';
import { rpc } from '@oviato/connect';
import { useEffect, useState } from 'react';

export default function Balance() {
  const { session } = useOviConnect();
  const [balance, setBalance] = useState<number | null>(null);

  useEffect(() => {
    if (!session?.address) return;

    async function fetchBalance() {
      const result = await rpc.getBalance({ address: session.address });
      if (result.result) {
        setBalance(result.result.balance);
      }
    }

    fetchBalance();
  }, [session?.address]);

  if (!session) return <div>Not connected</div>;

  return (
    <div>
      <h2>Balance: {balance !== null ? balance : 'Loading...'}</h2>
    </div>
  );
}
```

## TypeScript

Full TypeScript support with exported types:

```ts
import type {
  UserSession,
  OviatoConfig,
  BridgeResponse,
  LoginOptions,
  RegisterOptions,
  AuthenticateOptions,
} from '@oviato/connect';

import type { OviConnectProviderProps } from '@oviato/connect/client';
```

### Session Type

```ts
type UserSession = {
  username: string;
  address: string;
  publicKey: string;
  network: string;
  networkType: string;
  networkEnvironment: string;
  hdKeys: {
    mainnet: string;
    testnet: string;
  };
  auth?: {
    token: string;
    expires: string;
  };
};
```

## Framework Compatibility

| Framework              | Status          | Notes                                                                |
| ---------------------- | --------------- | -------------------------------------------------------------------- |
| Next.js 13+ App Router | ✅ Full Support | Use `/client` imports for components                                 |
| Next.js Pages Router   | ✅ Full Support | Works out of the box                                                 |
| React (Vite, CRA)      | ✅ Full Support | Standard React usage                                                 |
| Remix                  | ✅ Full Support | SSR-safe core functions                                              |
| Vue/Svelte/Angular     | 🔄 Use SDK      | Use [@oviato/sdk](https://www.npmjs.com/package/@oviato/sdk) instead |

## Error Handling

All async methods return a `BridgeResponse` object:

```ts
const result = await login();

if (result.status === 'success') {
  console.log('User:', result.data);
} else {
  console.error('Error:', result.message);
}
```

## Bundle Size

- **Core**: ~1 KB gzipped (re-exports from SDK)
- **Client (React)**: ~13 KB gzipped
- **Total**: ~14 KB gzipped

## Related Packages

- [@oviato/sdk](https://www.npmjs.com/package/@oviato/sdk) - Framework-agnostic core SDK

## License

The Oviato Core SDK is licensed under the **Apache 2.0 license** for transparency and open development.

Use of the SDK is additionally governed by the Oviato Core SDK Terms of Use. You may bundle or self-host the unmodified SDK, but modification or redistribution of altered versions is not permitted.

© 2025 Atoll27 Inc. | https://oviato.com

## Links

- [Documentation](https://docs.oviato.com)
- [Website](https://oviato.com)