# peertalkid-js

Official JavaScript SDK for [PeerTalkID](https://id.peertalk.chat) — Anonymous persistent identity for the web.

No email. No password. No tracking. 12 words. That's it.

[![Privacy Score](https://img.shields.io/badge/Privacy%20Score-93%25-0d9488)](https://id.peertalk.chat)
[![License](https://img.shields.io/badge/License-Proprietary-0d9488)](https://id.peertalk.chat/developers#license)

---

## Install

```bash
npm install https://id.peertalk.chat/sdk/peertalkid-js-1.0.0.tgz
```

---

## Quick Start

### Frontend (Browser)

```html
<!-- Option 1: Script Tag (no npm needed) -->
<script src="https://id.peertalk.chat/peertalkid-button.js"></script>
<peertalkid-button onlogin="onLogin"></peertalkid-button>

<script>
function onLogin(session) {
  console.log('Logged in:', session.accountId);
}
</script>
```

```js
// Option 2: npm
import { PeerTalkID } from 'peertalkid-js';

const client = new PeerTalkID();

// Redirect to PeerTalkID login
client.login('https://your-site.com/callback');

// After redirect back — get token from URL
const { token, state } = client.getTokenFromUrl();
if (client.verifyState(state)) {
  const session = await client.verify(token);
  console.log(session.accountId);
}
```

### Backend (Node.js)

```js
import { verifyToken, peertalkidMiddleware } from 'peertalkid-js/server';

// Single verify
const session = await verifyToken(req.headers.authorization?.replace('Bearer ', ''));
if (session.valid) {
  console.log(session.accountId, session.isPremium);
}

// Express middleware
import express from 'express';
const app = express();

app.use('/api', peertalkidMiddleware({ required: true }));

app.get('/api/profile', (req, res) => {
  res.json({ user: req.peertalkid });
});
```

### React

```jsx
import { usePeerTalkID, PeerTalkIDProvider, PeerTalkIDButton } from 'peertalkid-js/react';

// Wrap your app
function App() {
  return (
    <PeerTalkIDProvider>
      <MyApp />
    </PeerTalkIDProvider>
  );
}

// Use the hook
function Profile() {
  const { isLoggedIn, accountId, isPremium, login, logout } = usePeerTalkID();

  if (!isLoggedIn) {
    return <button onClick={login}>Sign in with PeerTalkID</button>;
  }

  return (
    <div>
      <p>Welcome, {accountId}</p>
      {isPremium && <p>★ Premium</p>}
      <button onClick={logout}>Logout</button>
    </div>
  );
}

// Or just use the pre-built button
function Header() {
  return (
    <PeerTalkIDButton
      theme="dark"
      size="medium"
      onLogin={(session) => console.log(session)}
    />
  );
}
```

---

## API Reference

### Client (`peertalkid-js`)

| Method | Description |
|---|---|
| `verify(token)` | Verify an access token |
| `login(redirectUrl)` | Redirect to PeerTalkID login |
| `getLoginUrl(redirectUrl)` | Get login URL without redirecting |
| `getTokenFromUrl()` | Extract token from URL hash after redirect |
| `verifyState(state)` | Verify CSRF state |
| `getUserInfo(token)` | Get user info (OIDC) |
| `refresh(refreshToken)` | Refresh access token |
| `logout(token)` | Logout current session |
| `logoutAll(token)` | Logout from all devices |
| `status()` | Check service status |

### Server (`peertalkid-js/server`)

| Export | Description |
|---|---|
| `verifyToken(token)` | Verify token server-side |
| `peertalkidMiddleware(options)` | Express.js middleware |
| `PeerTalkIDServer` | Server SDK class |

### React (`peertalkid-js/react`)

| Export | Description |
|---|---|
| `usePeerTalkID()` | React Hook |
| `PeerTalkIDProvider` | Context Provider |
| `PeerTalkIDButton` | Pre-built React Button |

---

## Session Object

```ts
{
  valid:         boolean,
  sub:           string,   // accountId (UUID)
  accountId:     string,   // alias for sub
  peertalkid_premium: boolean,
  isPremium:     boolean,  // alias
  peertalkid_avatar:  string,
  peertalkid_name:    string | null,
  scope:         string,   // 'openid profile'
  expires_in:    number,   // seconds
  profile: {
    displayName: string | null,
    avatarSeed:  string,
  }
}
```

---

## Privacy

PeerTalkID has a **93% privacy score** — higher than any commercial alternative:

| Service | Privacy Score |
|---|---|
| **PeerTalkID** | **93%** |
| Wallet Connect | 67% |
| Auth0 / Clerk | 41% |
| Sign in with Google | 12% |

- ✓ No email required
- ✓ No IP address stored
- ✓ AES-256-GCM session encryption
- ✓ Ed25519 cryptographic signatures
- ✓ SHA-256 wallet hash (server never sees public key)
- ✓ No third-party tracking

---

## License

BSL 1.1 — Source available, commercial competing use restricted for 4 years. Converts to Apache 2.0 in 2030.

[Full License](https://id.peertalk.chat/developers#license)