npm package: @onyx-aleo/sdk
Description: Official JavaScript/TypeScript SDK for ONYX — privacy-preserving luxury goods authentication on Aleo
Author: ONYX Protocol
Latest version: 1.0.0

# @onyx-aleo/sdk

> Official JavaScript / TypeScript SDK for **ONYX** — privacy-preserving luxury goods authentication built on the [Aleo](https://aleo.org) blockchain.

[![npm version](https://img.shields.io/npm/v/@onyx-aleo/sdk)](https://www.npmjs.com/package/@onyx-aleo/sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-gold.svg)](https://opensource.org/licenses/MIT)
[![Node ≥ 18](https://img.shields.io/node/v/@onyx-aleo/sdk)](https://nodejs.org)

---

## Installation

```bash
npm install @onyx-aleo/sdk
# or
yarn add @onyx-aleo/sdk
# or
pnpm add @onyx-aleo/sdk
```

**Requirements:** Node.js ≥ 18 (uses the Web Crypto API and native `fetch`)

---

## Quick Start

```ts
import { OnyxClient } from "@onyx-aleo/sdk";

const onyx = new OnyxClient({
  baseUrl: "https://api.onyx-aleo.xyz",
  apiKey: "your-jwt-token", // optional for public endpoints
});

// Verify a luxury item's NFC tag
const result = await onyx.artifacts.verify("bhp256(serial_hash, tag_nonce)");
console.log(result.brand?.displayName); // "Hermès"
console.log(result.artifact?.stolen);   // false

// Browse the marketplace
const { listings } = await onyx.listings.list({
  currency: "USDC",
  sort: "newest",
  limit: 20,
});
```

---

## Authentication

ONYX uses wallet-signature authentication. The SDK ships a helper for each step:

```ts
// 1. Request a challenge nonce
const { nonce, message } = await onyx.auth.challenge("aleo1youraddress...");

// 2. Sign the message with your Aleo wallet (Leo Wallet / Puzzle)
const signature = await window.leoWallet.signMessage(message);

// 3. Exchange signature for a JWT
const { token } = await onyx.auth.login("aleo1youraddress...", signature, nonce);

// 4. Create an authenticated client
const authed = new OnyxClient({
  baseUrl: "https://api.onyx-aleo.xyz",
  apiKey: token,
});
```

---

## API Reference

### `OnyxClient`

| Namespace | Purpose |
|---|---|
| `onyx.auth` | Obtain an authentication token |
| `onyx.brands` | Register a brand, view stats |
| `onyx.artifacts` | Mint, transfer, verify luxury items |
| `onyx.listings` | Browse and create marketplace listings |
| `onyx.sales` | Manage atomic purchase flows |
| `onyx.webhooks` | Register and manage webhook endpoints |

### Brands

```ts
// Register your brand (authenticated)
const brand = await onyx.brands.register({ displayName: "MyBrand" });

// Your brand profile
const me = await onyx.brands.me();
console.log(me.artifactCount);

// All registered brands (public)
const brands = await onyx.brands.list();
```

### Artifacts

```ts
// Mint a new item (brand authentication required)
const artifact = await onyx.artifacts.mint({
  tagHash: "bhp256...",
  modelId: "bag-001",
  serialHash: "bhp256...",
  initialOwner: "aleo1owner...",
  txId: "at1abc...",
});

// Transfer ownership
await onyx.artifacts.transfer({
  tagHash: "bhp256...",
  toAddress: "aleo1new_owner...",
  txId: "at1xyz...",
});

// Verify any item — no auth needed
const { valid, brand, artifact, listing } = await onyx.artifacts.verify("bhp256...");
```

### Listings & Marketplace

```ts
// Browse listings  
const { listings, total } = await onyx.listings.list({
  brand: "aleo1brand...",
  currency: "USDC",
  minPrice: 1000,
  maxPrice: 50000,
  sort: "price_asc",
  page: 1,
  limit: 20,
});

// Single listing
const listing = await onyx.listings.get("listing-id");

// Create a listing (authenticated seller)
const newListing = await onyx.listings.create({
  tagCommitment: "...",
  tagHash: "bhp256...",
  modelId: "bag-001",
  title: "Hermès Birkin 30 — Togo Noir",
  description: "2023, pristine condition, full provenance chain on Aleo.",
  condition: "like_new",
  price: 18500,
  currency: "USDC",
  imageUrl: "https://your-cdn.com/image.jpg",
});
```

### Sales

```ts
// Initiate a purchase (buyer authentication)
const sale = await onyx.sales.create({
  listingId: "listing-id",
  tagCommitment: "...",
});

// Poll sale status
const status = await onyx.sales.getByListingId("listing-id");
console.log(status.status); // "pending" | "paid" | "completed"
```

---

## Webhooks

### Registering a Webhook

```ts
const wh = await onyx.webhooks.register({
  url: "https://yourserver.com/onyx-webhook",
  events: ["artifact.minted", "sale.completed", "artifact.stolen"],
  secret: process.env.WEBHOOK_SECRET!, // store this securely
});
console.log(wh.id);
```

### Handling Incoming Events

```ts
import {
  verifyWebhookSignature,
  parseWebhookPayload,
  type WebhookPayload,
} from "@onyx-aleo/sdk";

// Express example
app.post("/onyx-webhook", express.raw({ type: "application/json" }), async (req, res) => {
  const sig = req.headers["x-onyx-signature"] as string;

  const valid = await verifyWebhookSignature(req.body, sig, process.env.WEBHOOK_SECRET!);
  if (!valid) return res.status(401).send("Invalid signature");

  const payload = parseWebhookPayload(JSON.parse(req.body.toString()));

  switch (payload.event) {
    case "artifact.minted":
      console.log("New item registered:", payload.data);
      break;
    case "sale.completed":
      console.log("Sale completed:", payload.data);
      break;
    case "artifact.stolen":
      console.log("Stolen report:", payload.data);
      break;
  }

  res.sendStatus(200);
});
```

### Webhook Events

| Event | Description |
|---|---|
| `artifact.minted` | A new item was registered by a brand |
| `artifact.transferred` | Ownership transferred |
| `artifact.stolen` | Item flagged as stolen |
| `listing.created` | A listing was published |
| `listing.cancelled` | A listing was cancelled |
| `sale.created` | A buyer initiated a purchase |
| `sale.completed` | Atomic swap completed on-chain |
| `sale.cancelled` | Sale cancelled or refunded |

### Signature Format

The `X-Onyx-Signature` header uses the format `sha256=<hex-hmac>` where the HMAC is computed over the raw request body using HMAC-SHA256 and your webhook secret.

---

## Error Handling

```ts
import { OnyxClient, OnyxError } from "@onyx-aleo/sdk";

try {
  const artifact = await onyx.artifacts.verify("invalid-hash");
} catch (err) {
  if (err instanceof OnyxError) {
    console.error(err.message);  // Human-readable message
    console.error(err.status);   // HTTP status code
    console.error(err.code);     // Machine-readable code, e.g. "NOT_FOUND"
  }
}
```

---

## TypeScript

All types are exported from the package root:

```ts
import type {
  Brand,
  Artifact,
  Listing,
  Sale,
  VerifyResult,
  WebhookPayload,
  WebhookEvent,
  OnyxClientConfig,
} from "@onyx-aleo/sdk";
```

---

## License

MIT — see [LICENSE](LICENSE).

---

Built with zero-knowledge proofs on [Aleo](https://aleo.org). ONYX: trust without disclosure.