npm package: @oviato/sdk
Description: Framework-agnostic SDK for Oviato authentication and wallet operations
Latest version: 0.3.1

# Oviato SDK

Framework-agnostic JavaScript SDK for Oviato authentication and wallet operations. Build custom UIs with full control, or use [@oviato/connect](https://www.npmjs.com/package/@oviato/connect) for React.

## Features

- **Framework-agnostic** - Works with React, Vue, Svelte, vanilla JS, or any framework
- **Passkey authentication** - Modern WebAuthn-based login with biometrics
- **Multi-chain wallet** - Bitcoin, Ethereum, BASE support
- **TypeScript native** - Full type safety and IntelliSense
- **Tiny bundle** - ~32 KB UMD (~11 KB gzipped)
- **CDN ready** - Drop-in `<script>` tag support
- **Dark mode** - Theme support with auto system preference detection
- **x402 Payments** - ERC-3009 gasless USDC payments protocol
- **EIP-712 Signing** - Typed data signing for EVM chains

## Installation

### NPM

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

### CDN

```html
<script src="https://cdn.jsdelivr.net/npm/@oviato/sdk@latest/dist/oviato.min.js"></script>
<script>
  const { initialize, login, getSession } = OviatoSDK;
</script>
```

## Quick Start

### 1. Initialize the SDK

```typescript
import { initialize } from '@oviato/sdk';

await initialize({
  appId: 'your-app-id',
  network: 'bitcoinmainnet', // or bitcointestnet, ethmainnet, basemainnet
});
```

### 2. Authenticate Users

```typescript
import { authenticate, login, register } from '@oviato/sdk';

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

// Or use explicit methods
await login(); // For returning users
await register({ username: 'bob' }); // For new users
```

### 3. Access Session Data

```typescript
import { getSession, isAuthenticated } from '@oviato/sdk';

const session = getSession();
if (session) {
  console.log(session.address); // User's wallet address
  console.log(session.publicKey); // User's public key
  console.log(session.network); // Current network
}

const isAuth = isAuthenticated(); // true/false
```

### 4. Wallet Operations

```typescript
import { signMessage, sendTransfer, signPsbt } from '@oviato/sdk';

// Sign a message
const signature = await signMessage('Hello Oviato!');

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

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

## API Reference

### Initialization

#### `initialize(options)`

Initialize the SDK with your app configuration.

```typescript
await initialize({
  appId: string,                      // Your Oviato app ID
  network?: string,                   // Default: 'bitcoinmainnet'
  theme?: 'light' | 'dark' | 'auto',  // UI theme (default: 'light')
  env?: 'prod' | 'staging'            // Default: 'prod'
});
```

Returns `Promise<OviatoConfig>`

### Authentication

#### `authenticate(options?)`

Smart authentication - automatically detects if user is new or returning.

```typescript
await authenticate({
  username?: string  // Optional: Pre-fill username
});
```

Returns `Promise<BridgeResponse<UserSession>>`

#### `login(options?)`

Explicit login for returning users with passkeys.

```typescript
await login({
  username?: string  // Optional: Pre-fill username
});
```

Returns `Promise<BridgeResponse<UserSession>>`

#### `register(options)`

Create a new account with passkey.

```typescript
await register({
  username: string, // Required for new accounts
});
```

Returns `Promise<BridgeResponse<UserSession>>`

### Session Management

#### `getSession()`

Get the current user session.

```typescript
const session = getSession();
// Returns: UserSession | null
```

#### `isAuthenticated()`

Check if user is authenticated.

```typescript
const isAuth = isAuthenticated();
// Returns: boolean
```

#### `clearSession()`

Log out the current user.

```typescript
clearSession();
```

### Wallet Operations

#### `signMessage(message)`

Sign an arbitrary message.

```typescript
await signMessage('Hello World');
```

Returns `Promise<BridgeResponse<{ signature: string }>>`

#### `sendTransfer(options)`

Send cryptocurrency to an address.

```typescript
await sendTransfer({
  to: string, // Recipient address
  amount: number, // Amount in smallest unit (satoshis, wei, lamports)
  fee: number, // Fee in smallest unit
});
```

Returns `Promise<BridgeResponse<{ txid: string, explorerUrl: string }>>`

#### `switchNetwork(network)`

Switch to a different blockchain network.

```typescript
await switchNetwork('basemainnet');
```

**Supported Networks:**

| Network           | ID               |
| ----------------- | ---------------- |
| Bitcoin Mainnet   | `bitcoinmainnet` |
| Bitcoin Testnet   | `bitcointestnet` |
| Ethereum Mainnet  | `ethmainnet`     |
| Ethereum Sepolia  | `ethsepolia`     |
| BASE Mainnet      | `basemainnet`    |
| BASE Sepolia      | `basesepolia`    |

Returns `Promise<BridgeResponse<{ network: string, session: UserSession }>>`

#### `signPsbt(options)`

Sign a Bitcoin PSBT (Partially Signed Bitcoin Transaction).

```typescript
await signPsbt({
  psbt: string,          // Base64 encoded PSBT
  signInputs: number[],  // Input indices to sign
  broadcast?: boolean    // Auto-broadcast after signing (default: false)
});
```

Returns `Promise<BridgeResponse<{ psbt: string, txid?: string }>>`

#### `signTypedData(options)`

Sign EIP-712 typed data (EVM chains only).

```typescript
await signTypedData({
  domain: {
    name: 'MyApp',
    version: '1',
    chainId: 8453,  // BASE mainnet
  },
  types: {
    Message: [{ name: 'content', type: 'string' }]
  },
  message: { content: 'Hello' },
  primaryType: 'Message',
});
```

Returns `Promise<BridgeResponse<{ signature: string }>>`

### x402 Payment Protocol

The SDK includes full support for the x402 payment protocol, enabling gasless USDC payments via ERC-3009.

#### `x402Sign(options)`

Sign an x402 payment authorization.

```typescript
import { x402Sign, isPaymentRequired, getPaymentDetails } from '@oviato/sdk';

// Check if a response requires payment
const response = await fetch('https://api.example.com/premium');

if (isPaymentRequired(response)) {
  const paymentRequired = getPaymentDetails(response);

  const result = await x402Sign({
    paymentRequired,
    acceptIndex: 0,  // Which payment option to use
  });

  if (result.status === 'success') {
    // Retry request with payment header
    const paidResponse = await fetch('https://api.example.com/premium', {
      headers: {
        'X-PAYMENT': result.data.signedPayload,
      },
    });
  }
}
```

### RPC Client

Direct RPC calls to Oviato backend services.

#### `rpc.getBalance(params)`

```typescript
const balance = await rpc.getBalance({
  address: 'bc1q...',
});
```

#### `rpc.getTransactionHistory(params)`

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

#### `rpcRequest(method, params?)`

Make custom RPC calls.

```typescript
const result = await rpcRequest('customMethod', {
  param1: 'value',
});
```

### OVI.ID Resolution

#### `resolveUsername(username)`

Resolve a username to wallet addresses across networks.

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

## State Management

The SDK uses vanilla Zustand for state management, making it framework-agnostic.

### Subscribe to State Changes

```typescript
import { oviStore } from '@oviato/sdk';

const unsubscribe = oviStore.subscribe((state) => {
  console.log('Session:', state.session);
  console.log('Ready:', state.ready);
  console.log('Loading:', state.isLoading);
});

// Cleanup
unsubscribe();
```

### Direct Store Access

```typescript
const state = oviStore.getState();
console.log(state.session);
console.log(state.config);
```

## Framework Integration

### React

For React apps, use [@oviato/connect](https://www.npmjs.com/package/@oviato/connect) which provides hooks and components built on this SDK.

Or integrate manually:

```tsx
import { useEffect, useState } from 'react';
import { oviStore, initialize, login } from '@oviato/sdk';

function App() {
  const [session, setSession] = useState(oviStore.getState().session);

  useEffect(() => {
    initialize({ appId: 'your-app-id' });

    const unsubscribe = oviStore.subscribe((state) => {
      setSession(state.session);
    });

    return unsubscribe;
  }, []);

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

### Vue

```vue
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { oviStore, initialize, login } from '@oviato/sdk';

const session = ref(null);
let unsubscribe;

onMounted(async () => {
  await initialize({ appId: 'your-app-id' });

  unsubscribe = oviStore.subscribe((state) => {
    session.value = state.session;
  });

  session.value = oviStore.getState().session;
});

onUnmounted(() => {
  unsubscribe?.();
});
</script>

<template>
  <div>
    <p v-if="session">Connected: {{ session.address }}</p>
    <button v-else @click="login">Login</button>
  </div>
</template>
```

### Svelte

```svelte
<script>
import { onMount, onDestroy } from 'svelte';
import { oviStore, initialize, login } from '@oviato/sdk';

let session = null;
let unsubscribe;

onMount(async () => {
  await initialize({ appId: 'your-app-id' });

  unsubscribe = oviStore.subscribe((state) => {
    session = state.session;
  });

  session = oviStore.getState().session;
});

onDestroy(() => {
  unsubscribe?.();
});
</script>

{#if session}
  <p>Connected: {session.address}</p>
{:else}
  <button on:click={login}>Login</button>
{/if}
```

## TypeScript

Full TypeScript support with exported types:

```typescript
import type {
  UserSession,
  OviatoConfig,
  BridgeResponse,
  LoginOptions,
  RegisterOptions,
  AuthenticateOptions,
  ConnectStore,
  RpcConfig,
} from '@oviato/sdk';
```

## Error Handling

All async methods return a `BridgeResponse` object:

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

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

## 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](./LICENSE-OVIATO.txt). 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)