Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions js/examples/browser/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# IDKit Browser Example

A simple browser example demonstrating World ID verification using IDKit 4.0.
A simple browser example demonstrating World ID verification using the IDKit core package.

## Usage

Expand All @@ -20,12 +20,12 @@ cd js/examples/browser
pnpm dev
```

Open http://localhost:5173 in your browser (Vite will auto-open it)
Open http://localhost:4000 in your browser (Vite will auto-open it)

#### Production

The example already uses the `@worldcoin/idkit` import. In production, install the package:
The example uses `@worldcoin/idkit-core` for pure TypeScript/browser usage. In production:

```bash
npm install @worldcoin/idkit
npm install @worldcoin/idkit-core
```
49 changes: 29 additions & 20 deletions js/examples/browser/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ <h3>Error</h3>
</section>

<script type="module">
// Import IDKit (alias resolves to local dist or npm package)
import { useWorldBridgeStore, VerificationLevel } from '@worldcoin/idkit';
// Import IDKit core (pure TypeScript, no dependencies)
import { createSession, initIDKit } from '@worldcoin/idkit-core';

// Demo app configuration (WASM auto-initializes on first use)
// Demo app configuration
const APP_ID = 'app_ce4cb73cb75fc3b73b71ffb4de178410'; // Replace with your actual app ID
const ACTION = 'test-action';

Expand All @@ -62,27 +62,26 @@ <h3>Error</h3>
errorDiv.hidden = true;
};

// Function to verify with World ID
async function verify(verificationLevel) {
// Initialize WASM on page load
await initIDKit();

// Function to verify with World ID using the new Session API
async function verify(requests) {
try {
hideAll();

const store = useWorldBridgeStore();
store.reset(); // Clear any previous state

statusDiv.hidden = false;
statusText.textContent = 'Creating verification request...';
statusText.textContent = 'Creating verification session...';

// createClient returns a client with the connectorURI
const client = await store.createClient({
// Create a new session with the requests
const session = await createSession({
app_id: APP_ID,
action: ACTION,
verification_level: verificationLevel,
signal: 'demo-signal-' + Date.now(),
requests: requests,
});

// Use client.connectorURI (not store.connectorURI which is a stale snapshot)
const url = client.connectorURI;
// Get the connector URL from the session
const url = session.connectorURI;
console.log('Connect URL:', url);

qrDiv.hidden = false;
Expand All @@ -92,8 +91,8 @@ <h3>Error</h3>

statusText.textContent = 'Waiting for scan...';

// Use client.pollForUpdates() which handles polling automatically
const proof = await client.pollForUpdates({
// Poll for updates until proof is received
const proof = await session.pollForUpdates({
pollInterval: 2000, // Poll every 2 seconds
timeout: 120000, // 2 minute timeout
});
Expand All @@ -111,10 +110,20 @@ <h3>Error</h3>
}
}

// Helper to create a signal with timestamp
const makeSignal = () => 'demo-signal-' + Date.now();

// Button event listeners
document.getElementById('verifyOrb').addEventListener('click', () => verify(VerificationLevel.Orb));
document.getElementById('verifyFace').addEventListener('click', () => verify(VerificationLevel.Face));
document.getElementById('verifyDevice').addEventListener('click', () => verify(VerificationLevel.Device));
document.getElementById('verifyOrb').addEventListener('click', () =>
verify([{ credential_type: 'orb', signal: makeSignal() }])
);
document.getElementById('verifyFace').addEventListener('click', () =>
verify([{ credential_type: 'face', signal: makeSignal() }])
);
document.getElementById('verifyDevice').addEventListener('click', () =>
verify([{ credential_type: 'device', signal: makeSignal() }])
);

</script>
</body>
</html>
3 changes: 3 additions & 0 deletions js/examples/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@worldcoin/idkit-core": "workspace:*"
},
"devDependencies": {
"vite": "^7.0.0"
}
Expand Down
7 changes: 0 additions & 7 deletions js/examples/browser/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { defineConfig } from 'vite';
import { resolve } from 'path';

export default defineConfig({
resolve: {
alias: {
// Resolve to the locally-built core package output in this monorepo.
'@worldcoin/idkit': resolve(__dirname, '../../packages/core/dist/index.js'),
},
},
server: {
port: 4000,
open: true,
Expand Down
119 changes: 72 additions & 47 deletions js/packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,18 @@ pnpm add @worldcoin/idkit
## Quick Start

```typescript
import {
useWorldBridgeStore,
VerificationLevel,
} from '@worldcoin/idkit'
import { useWorldBridgeStore } from '@worldcoin/idkit'

// 1. Get store instance
const store = useWorldBridgeStore()

// 2. Create client - returns immutable client object
// 2. Create client with explicit requests
const client = await store.createClient({
app_id: 'app_staging_xxxxx',
action: 'my-action',
verification_level: VerificationLevel.Orb,
signal: 'user-id-123',
requests: [
{ credential_type: 'orb', signal: 'user-id-123' },
],
})

// 3. Display QR code for World App
Expand All @@ -41,38 +39,60 @@ try {
}
```

## V2 API
## Multiple Credential Types

```typescript
const store = useWorldBridgeStore()
You can request verification with multiple credential types. The user can satisfy the request with any of them:

await store.createClient({
```typescript
const client = await store.createClient({
app_id: 'app_staging_xxxxx',
action: 'my-action',
verification_level: VerificationLevel.Orb,
signal: 'user-id-123',
requests: [
{ credential_type: 'orb', signal: 'user-id-123' },
{ credential_type: 'device', signal: 'user-id-123' },
],
})
```

console.log('Scan this:', store.connectorURI)

await store.pollForUpdates()
## Credential Types

if (store.result) {
console.log('Proof received:', store.result)
}
```
- `orb` - Verified via Orb biometric scan (highest trust)
- `face` - Verified via Face ID
- `device` - Verified via device binding
- `document` - Verified via document scan
- `secure_document` - Verified via secure document scan

## API Reference

### Creating a Client

```typescript
const client = await store.createClient(config)
```

**Properties:**
**Config:**
```typescript
interface IDKitConfig {
app_id: `app_${string}` // Your World ID app ID
action: string // Action identifier
requests: RequestConfig[] // Required: credential type requests
bridge_url?: string // Custom bridge URL (optional)
partner?: boolean // Partner mode (optional)
}

interface RequestConfig {
credential_type: CredentialType
signal?: string | AbiEncodedValue // Optional signal for this request
}

type CredentialType = 'orb' | 'face' | 'device' | 'document' | 'secure_document'
```

**Client Properties:**
- `connectorURI: string` - QR code URL for World App
- `requestId: string` - Unique request ID

**Methods:**
**Client Methods:**
- `pollForUpdates(options?: WaitOptions): Promise<ISuccessResult>` - Poll for proof (auto-polls)
- `pollOnce(): Promise<Status>` - Poll once for status (manual polling)

Expand All @@ -91,44 +111,24 @@ interface WaitOptions {
const store = useWorldBridgeStore()
```

**V3 Methods:**
**Methods:**
- `createClient(config: IDKitConfig): Promise<WorldBridgeClient>` - Create new client
- `reset(): void` - Clear state and start over

**V2 State (backward compat):**
**State (for reactive frameworks):**
- `verificationState: VerificationState` - Current verification state
- `connectorURI: string | null` - QR code URL for World App
- `result: ISuccessResult | null` - Proof data when verified
- `errorCode: AppErrorCodes | null` - Error code if failed

**V2 Methods (deprecated):**
- `pollForUpdates(): Promise<void>` - Check for proof (call repeatedly) ⚠️ Use `client.pollForUpdates()` with auto-polling instead
- `reset(): void` - Clear state and start over

### Types
### Result Types

```typescript
interface IDKitConfig {
app_id: `app_${string}`
action: string
signal?: string
verification_level?: VerificationLevel
bridge_url?: string
partner?: boolean
}

interface ISuccessResult {
proof: string
merkle_root: string
nullifier_hash: string
verification_level: VerificationLevel
}

enum VerificationLevel {
Orb = 'orb',
Face = 'face',
Device = 'device',
Document = 'document',
SecureDocument = 'secure_document',
verification_level: CredentialType // The credential type used
}
```

Expand All @@ -142,6 +142,31 @@ hashToField(input: string): HashFunctionOutput
solidityEncode(types: string[], values: unknown[]): AbiEncodedValue
```

## React Integration

```tsx
import { useWorldBridgeStore, IDKitWidget } from '@worldcoin/idkit'

function MyComponent() {
const handleSuccess = (result) => {
console.log('Verified:', result)
}

return (
<IDKitWidget
app_id="app_staging_xxxxx"
action="my-action"
requests={[
{ credential_type: 'orb', signal: 'user-123' },
]}
onSuccess={handleSuccess}
>
{({ open }) => <button onClick={open}>Verify with World ID</button>}
</IDKitWidget>
)
}
```

## Examples

See [examples/browser](../../examples/browser) for a complete working example.
Expand Down
22 changes: 2 additions & 20 deletions js/packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@worldcoin/idkit",
"name": "@worldcoin/idkit-core",
"version": "4.0.1",
"description": "Core IDKit SDK for World ID - Browser and Node.js support",
"description": "Core IDKit SDK for World ID - Pure TypeScript, no dependencies",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
Expand All @@ -11,11 +11,6 @@
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./react": {
"types": "./dist/react.d.ts",
"import": "./dist/react.js",
"require": "./dist/react.cjs"
}
},
"files": [
Expand Down Expand Up @@ -46,23 +41,10 @@
"type": "git",
"url": "https://github.com/worldcoin/idkit"
},
"dependencies": {
"zustand": "^4.5"
},
"peerDependencies": {
"react": ">=17.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
},
"devDependencies": {
"@types/node": "^20.0.0",
"@types/react": "^18.2.0",
"@vitest/coverage-v8": "^2.0.0",
"happy-dom": "^15.0.0",
"react": "^18.2.0",
"tsup": "^8.0.0",
"typescript": "^5.3.0",
"vitest": "^2.0.0"
Expand Down
Loading