npm package: @gamecore-api/sdk
Description: TypeScript SDK for GameCore API — browser-safe, zero dependencies
Latest version: 0.9.0

# @gamecore/sdk

TypeScript SDK for GameCore API — zero external dependencies, browser-safe.

## Install

```bash
npm install @gamecore/sdk
```

## Quick Start

```typescript
import { GameCoreClient } from "@gamecore/sdk";

const gc = new GameCoreClient({
  apiKey: "gc_live_YOUR_KEY",
  baseUrl: "https://api.gamecore-api.tech",
  onAuthError: () => window.location.href = "/login",
});

// Browse catalog
const games = await gc.catalog.getGames();
const game = await gc.catalog.getGame("honkai-star-rail");
const products = await gc.catalog.getProducts("honkai-star-rail");

// Search
const results = await gc.catalog.search("roblox");
```

## Authentication

### Telegram Auth Flow

```typescript
// 1. Start auth → get bot link
const { token, botLink } = await gc.auth.initTelegram();

// 2. Open Telegram bot (user clicks "Start")
window.open(botLink, "_blank");

// 3. Poll until user authenticates
const user = await gc.auth.pollTelegramStatus(token);
console.log("Logged in:", user.firstName);
```

### VK Auth

```typescript
const { user } = await gc.auth.verifyVk(vkAccessToken);
```

### Session

```typescript
const me = await gc.auth.getMe();       // Get current user
await gc.auth.logout();                   // Clear session
const identities = await gc.auth.getIdentities(); // Linked providers
```

## Catalog

```typescript
// All games
const games = await gc.catalog.getGames({ type: "game" });

// Homepage ranked games
const homepage = await gc.catalog.getHomepageGames();

// Single game with categories
const game = await gc.catalog.getGame("genshin-impact");

// Products (optionally filtered by category)
const products = await gc.catalog.getProducts("genshin-impact", "crystals");

// Products grouped by category
const grouped = await gc.catalog.getProductsGrouped("genshin-impact");

// Search (returns games + products)
const { games, products } = await gc.catalog.search("roblox");

// Search suggestions
const { suggestions } = await gc.catalog.searchSuggestions("rob");
```

## Cart & Checkout

```typescript
// Cart
const items = await gc.cart.get();
await gc.cart.add({ productId: 10, gameId: "roblox", gameName: "Roblox", productName: "800 Robux", price: 799, deliveryData: { username: "player123" } });
await gc.cart.remove(itemId);
await gc.cart.clear();

// Checkout (auto-generates idempotency key)
const checkout = await gc.checkout.create({
  items: [{ productId: 10, deliveryData: { username: "player123" } }],
  paymentMethod: "antilopay",
});

// Redirect to payment page
if (checkout.payment?.paymentUrl) {
  window.location.href = checkout.payment.paymentUrl;
}

// Or pay with balance
await gc.checkout.completeWithBalance(checkout.payment.code);
```

## Orders

```typescript
const orders = await gc.orders.list();
const order = await gc.orders.get("ORD-A7X9K2");
await gc.orders.cancel("ORD-A7X9K2");

// Track order in real-time (SSE)
const source = gc.sse.trackOrder("ORD-A7X9K2");
source.addEventListener("order_status", (e) => {
  const data = JSON.parse(e.data);
  console.log("Status:", data.status, "Items:", data.items);
});
```

## Profile

```typescript
// Balance (permanent + bonus with expiration details)
const balance = await gc.profile.getBalance();
// { permanent: 500, bonus: 100, total: 600, bonusDetails: [{ remaining: 100, expiresAt: "..." }] }

// Level status with progress
const level = await gc.profile.getLevelStatus();
// { currentLevel: 3, currentDiscount: 5, nextLevel: 4, requirements: { spending: { current: 5000, required: 10000 } } }

// Transaction history
const transactions = await gc.profile.getTransactions({ limit: 20 });

// Orders
const orders = await gc.profile.getOrders();

// Notifications
const notifications = await gc.profile.getNotifications();
const { count } = await gc.profile.getUnreadCount();
await gc.profile.markRead(notificationId);
await gc.profile.markAllRead();
```

## Favorites

```typescript
const favorites = await gc.favorites.list();
await gc.favorites.add(productId, "genshin-impact"); // gameId as slug string
await gc.favorites.remove(productId);
```

## Reviews

```typescript
// Public reviews (paginated)
const { data, pagination } = await gc.reviews.listPublic({ limit: 10 });

// Stats
const stats = await gc.reviews.getStats("genshin-impact");
// { averageRating: 4.8, totalReviews: 156 }

// Random reviews (for homepage)
const random = await gc.reviews.getRandom(5);

// Submit review (authenticated)
const review = await gc.reviews.create(orderId, 5, "Great service!");

// Orders waiting for review
const pending = await gc.reviews.getPending();
```

## Coupons & Gift Cards

```typescript
// Apply coupon
const result = await gc.coupons.apply("WELCOME10");
// { type: "bonus_balance", value: 10, code: "WELCOME10", bonusAmount: 100 }

await gc.coupons.remove();
const active = await gc.coupons.getActive();

// Gift cards
const card = await gc.giftCards.purchase(5); // amountUsd
await gc.giftCards.redeem("GC-XXXX-XXXX-XXXX");
```

## Referrals

```typescript
const stats = await gc.referrals.getStats();
const links = await gc.referrals.getLinks();
const link = await gc.referrals.createLink({ label: "YouTube", slug: "my-channel" });
await gc.referrals.updateLink(link.id, { label: "Updated" });
const linkStats = await gc.referrals.getLinkStats(link.id);
const commissions = await gc.referrals.getCommissions();
```

## Balance Top-up

```typescript
const methods = await gc.topup.getPaymentMethods();
const topup = await gc.topup.create(500, "lava");
// Redirect to topup.paymentUrl
const status = await gc.topup.getStatus(topup.code);
```

## SSE (Real-time Events)

```typescript
// Authenticated notification stream
const events = gc.sse.connectEvents();
events.addEventListener("notification", (e) => {
  const { type, data } = JSON.parse(e.data);
  // type: "order_completed", "balance_updated", "level_up", etc.
});

// Order tracking (no auth, uses order code)
const tracker = gc.sse.trackOrder("ORD-A7X9K2");
```

## SEO

```typescript
// entityId is numeric (canonical game ID), not slug
const seo = await gc.seo.getContent("game", 1076, "ru");
// Schema is available for "product" page type
const schema = await gc.seo.getSchema("product", 42);
```

## Webhook Verification (Server-side)

```typescript
// Import from server entrypoint (uses node:crypto)
import { verifyWebhookSignature, parseWebhookPayload } from "@gamecore/sdk/server";

const isValid = verifyWebhookSignature(
  requestBody,
  request.headers["x-webhook-signature"],
  WEBHOOK_SECRET,
);

if (isValid) {
  const payload = parseWebhookPayload(requestBody);
  console.log(payload.event, payload.data);
}
```

## Utilities

```typescript
import { convertPrice, formatPrice, generateIdempotencyKey } from "@gamecore/sdk";

const rub = convertPrice(1.99, 92.5);       // 184.08
const formatted = formatPrice(rub, "RUB");   // "184 ₽"
const key = generateIdempotencyKey();         // UUID v4
```

## Next.js App Router Examples

### Server Component (SSR catalog)

```typescript
// app/catalog/page.tsx
import { GameCoreClient } from "@gamecore/sdk";

const gc = new GameCoreClient({
  apiKey: process.env.GAMECORE_API_KEY!,
  baseUrl: process.env.GAMECORE_API_URL!,
});

export default async function CatalogPage() {
  const games = await gc.catalog.getGames();
  return <GameGrid games={games} />;
}
```

### Client Component (cart)

```typescript
"use client";
import { useEffect, useState } from "react";
import { gc } from "@/lib/gamecore-browser";

export function CartWidget() {
  const [items, setItems] = useState([]);
  useEffect(() => { gc.cart.get().then(setItems); }, []);
  return <span>{items.length} items</span>;
}
```

### Route Handler (webhook)

```typescript
// app/api/webhooks/gamecore/route.ts
import { verifyWebhookSignature, parseWebhookPayload } from "@gamecore/sdk/server";

export async function POST(req: Request) {
  const body = await req.text();
  const sig = req.headers.get("x-webhook-signature") || "";

  if (!verifyWebhookSignature(body, sig, process.env.WEBHOOK_SECRET!)) {
    return new Response("Unauthorized", { status: 401 });
  }

  const payload = parseWebhookPayload(body);
  // Handle event...
  return new Response("OK");
}
```

## API Namespaces

| Namespace | Methods |
|-----------|---------|
| `gc.site` | getConfig, getRates, getLegal |
| `gc.auth` | initTelegram, pollTelegramStatus, verifyVk, getMe, logout, getIdentities, linkVk, unlinkProvider |
| `gc.catalog` | getGames, getHomepageGames, getGame, getProducts, getProductsGrouped, search, searchSuggestions, getProduct |
| `gc.cart` | get, add, sync, remove, clear |
| `gc.checkout` | create, completeWithBalance, getPaymentMethods |
| `gc.orders` | list, get, getByPayment, cancel |
| `gc.profile` | getBalance, getLevelStatus, getTransactions, getOrders, getNotifications, getUnreadCount, markRead, markAllRead |
| `gc.favorites` | list, add, remove |
| `gc.coupons` | apply, remove, validate, getActive |
| `gc.referrals` | getStats, getLinks, createLink, updateLink, deleteLink, getLinkStats, getCommissions |
| `gc.reviews` | listPublic, getStats, getRandom, getMine, getPending, create |
| `gc.topup` | getPaymentMethods, create, getStatus |
| `gc.giftCards` | purchase, redeem, check, getMine |
| `gc.announcements` | list, get |
| `gc.analytics` | recordView |
| `gc.seo` | getContent, getSchema |
| `gc.sse` | connectEvents, trackOrder |

## Browser vs Server

| Import | Environment | Includes |
|--------|-------------|----------|
| `@gamecore/sdk` | Browser + Node | Client, types, utilities |
| `@gamecore/sdk/server` | Node only | Webhook verification (uses node:crypto) |