Skip to main content

JavaScript/TypeScript SDK

Zeq works seamlessly with JavaScript and TypeScript using the native fetch API or popular HTTP libraries. This guide covers both browser and Node.js environments.

Setup

Environment Variables

Create a .env file in your project:

ZEQ_API_URL=https://zeq.dev/api
ZEQ_TOKEN=your_bearer_token_here

For Node.js, load these using dotenv:

npm install dotenv

Then in your code:

require('dotenv').config();
const API_URL = process.env.ZEQ_API_URL;
const TOKEN = process.env.ZEQ_TOKEN;

For browser environments, store the token securely (e.g., in a secure cookie or via OAuth).

Basic HTTP Request (fetch)

const response = await fetch('https://zeq.dev/api/zeq/compute', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${TOKEN}`
},
body: JSON.stringify({
state: { x: 1.0, y: 2.0 },
time_quantum: 1
})
});

const data = await response.json();
if (data.success) {
console.log('Result:', data.data.result);
} else {
console.error('Error:', data.error.message);
}

ZeqClient Class

Here's a reusable TypeScript client wrapper:

interface ZeqState {
[key: string]: number | ZeqState;
}

interface ComputeResponse {
result: ZeqState;
proof: string;
timestamp: number;
}

interface VerifyResponse {
valid: boolean;
details: {
proof_type: string;
verified_at: number;
};
}

interface VerifyRequest {
proof: string;
expected_state: ZeqState;
}

interface PulseResponse {
current_quantum: number;
synchronized: boolean;
drift_ns: number;
}

interface RateLimitInfo {
remaining: number;
reset_at: number;
}

class ZeqClient {
private apiUrl: string;
private token: string;

constructor(apiUrl: string = process.env.ZEQ_API_URL || '',
token: string = process.env.ZEQ_TOKEN || '') {
this.apiUrl = apiUrl || 'https://zeq.dev/api';
this.token = token;
}

private async request<T>(
endpoint: string,
method: string = 'POST',
body?: any
): Promise<{ data: T; rateLimit: RateLimitInfo }> {
const url = `${this.apiUrl}${endpoint}`;

const response = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`
},
body: body ? JSON.stringify(body) : undefined
});

const rateLimit = {
remaining: parseInt(response.headers.get('X-RateLimit-Remaining') || '0'),
reset_at: parseInt(response.headers.get('X-RateLimit-Reset') || '0')
};

if (!response.ok) {
const error = await response.json();
throw new ZeqError(error.error.message, response.status, error.error.code);
}

const result = await response.json();
if (!result.success) {
throw new ZeqError(result.error.message, 400, result.error.code);
}

return { data: result.data as T, rateLimit };
}

async compute(state: ZeqState, timeQuantum: number = 1): Promise<ComputeResponse> {
const { data } = await this.request<ComputeResponse>(
'/zeq/compute',
'POST',
{ state, time_quantum: timeQuantum }
);
return data;
}

async verify(proof: string, expectedState: ZeqState): Promise<VerifyResponse> {
const { data } = await this.request<VerifyResponse>(
'/zeq/verify',
'POST',
{ proof, expected_state: expectedState }
);
return data;
}

async pulse(): Promise<PulseResponse> {
const { data } = await this.request<PulseResponse>('/zeq/pulse');
return data;
}

async operators(category: string = ''): Promise<{ operators: any[] }> {
const endpoint = category
? `/zeq/operators?category=${encodeURIComponent(category)}`
: '/zeq/operators';
const { data } = await this.request<{ operators: any[] }>(endpoint, 'GET');
return data;
}

async timebridge(timestamp: number, timezone: string = 'UTC'): Promise<{ zeqond: number }> {
const { data } = await this.request<{ zeqond: number }>(
'/zeq/timebridge',
'POST',
{ timestamp, timezone }
);
return data;
}
}

class ZeqError extends Error {
constructor(
public message: string,
public statusCode: number,
public code: string
) {
super(message);
this.name = 'ZeqError';
}
}

export { ZeqClient, ZeqError, ZeqState, ComputeResponse, VerifyResponse };

Usage Examples

Compute Example

import { ZeqClient } from './zeq-client';

const client = new ZeqClient();

async function simulateODE() {
try {
const result = await client.compute(
{ x: 1.0, y: 2.0, z: 0.5 },
5 // Compute 5 time quantums forward
);

console.log('Computed state:', result.result);
console.log('Proof:', result.proof);
} catch (error) {
if (error instanceof ZeqError) {
console.error(`API Error (${error.code}): ${error.message}`);
}
}
}

Verify Example

async function verifyComputation() {
const client = new ZeqClient();

// Get a computation result
const compute = await client.compute({ x: 1.0 }, 1);

// Verify the proof
const verification = await client.verify(
compute.proof,
compute.result
);

if (verification.valid) {
console.log('✓ Computation verified at', verification.details.verified_at);
} else {
console.warn('✗ Proof verification failed');
}
}

Pulse Example

async function checkSync() {
const client = new ZeqClient();

const pulse = await client.pulse();
console.log(`Current quantum: ${pulse.current_quantum}`);
console.log(`Synchronized: ${pulse.synchronized}`);
console.log(`Drift: ${pulse.drift_ns}ns`);

if (pulse.drift_ns > 1000) {
console.warn('High temporal drift detected');
}
}

Operators Example

async function listOperators() {
const client = new ZeqClient();

// Get all operators
const all = await client.operators();
console.log(`Total operators: ${all.operators.length}`);

// Get operators by category
const physics = await client.operators('physics');
console.log(`Physics operators: ${physics.operators.length}`);

physics.operators.forEach(op => {
console.log(` - ${op.name}: ${op.description}`);
});
}

Timebridge Example

async function convertTime() {
const client = new ZeqClient();

// Convert a Unix timestamp to Zeqond
const now = Math.floor(Date.now() / 1000);
const mapping = await client.timebridge(now, 'America/New_York');

console.log(`Unix ${now} = Zeqond ${mapping.zeqond}`);
}

Error Handling

The ZeqClient throws ZeqError with useful properties:

try {
await client.compute({ x: 1.0 }, 1);
} catch (error) {
if (error instanceof ZeqError) {
switch (error.code) {
case 'RATE_LIMIT_EXCEEDED':
console.error('Rate limited. Retry after backoff.');
break;
case 'UNAUTHORIZED':
console.error('Invalid token.');
break;
case 'TIER_LOCKED':
console.error('This feature requires a higher tier.');
break;
default:
console.error(`Unexpected error: ${error.message}`);
}
}
}

Batch Requests

For efficiency, use the /api/zeq/lattice endpoint to batch multiple computations:

async function batchCompute() {
const client = new ZeqClient();

const batch = [
{ state: { x: 1.0 }, time_quantum: 1 },
{ state: { x: 2.0 }, time_quantum: 1 },
{ state: { x: 3.0 }, time_quantum: 1 }
];

const response = await fetch('https://zeq.dev/api/zeq/lattice', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.ZEQ_TOKEN}`
},
body: JSON.stringify({ requests: batch })
});

const result = await response.json();
result.data.results.forEach((r, i) => {
console.log(`Result ${i}:`, r.result);
});
}

Rate Limit Handling

The ZeqClient.request() method returns rate limit info. Implement backoff:

async function computeWithRetry(maxRetries = 3) {
const client = new ZeqClient();

for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const result = await client.compute({ x: 1.0 }, 1);
return result;
} catch (error) {
if (error instanceof ZeqError && error.statusCode === 429) {
const backoffMs = Math.pow(2, attempt) * 1000;
console.log(`Rate limited. Retrying in ${backoffMs}ms...`);
await new Promise(resolve => setTimeout(resolve, backoffMs));
} else {
throw error;
}
}
}

throw new Error('Max retries exceeded');
}

TypeScript Best Practices

The included TypeScript interfaces help catch errors at compile time:

import { ZeqClient, ZeqState, ComputeResponse } from './zeq-client';

// Type-safe state object
const state: ZeqState = {
position: { x: 1.0, y: 2.0 },
velocity: { x: 0.5, y: -0.3 }
};

const client = new ZeqClient();
const result: ComputeResponse = await client.compute(state, 10);

// TypeScript ensures result.result is a ZeqState
const newX = result.result.position?.x; // Type-safe access

Browser Usage

For browser applications, use a secure token management strategy:

// Get token from secure backend endpoint
async function getToken() {
const response = await fetch('/api/zeq-token', {
credentials: 'include' // Include cookies
});
const { token } = await response.json();
return token;
}

// Create client with fresh token
const token = await getToken();
const client = new ZeqClient('https://zeq.dev/api', token);

Never hardcode tokens in browser code. Always fetch from a backend.

Next Steps

tip

Use the ZeqClient class in production. It handles authentication, rate limit headers, and error mapping for you.