SINAI STANDARD

Issuer Dashboard

No-code web interface for creating and managing compliant Token-2022 tokens

Issuer Dashboard

The Dashboard is a Next.js 14 application that provides a no-code interface for token issuers. It connects to both Solana (via the SDK) and the Compliance Oracle (via REST + WebSocket) to manage the full token lifecycle from a browser.

Browser (Phantom / Solflare)

    ├── useAksumKit()       → SDK → Solana (on-chain txs)
    └── useOracleClient()   → Oracle REST API (allowlist, config)
         useRealtimeEvents() → Oracle WebSocket (live events)

Quick Start

1. Clone and Install

cd packages/dashboard
pnpm install

2. Configure Environment

# .env.local
NEXT_PUBLIC_RPC_URL=https://api.devnet.solana.com
NEXT_PUBLIC_ORACLE_URL=http://localhost:3000
NEXT_PUBLIC_ORACLE_WS_URL=ws://localhost:3000/ws
VariableDefaultDescription
NEXT_PUBLIC_RPC_URLhttps://api.devnet.solana.comSolana RPC endpoint
NEXT_PUBLIC_ORACLE_URLhttp://localhost:3000Oracle REST API base URL
NEXT_PUBLIC_ORACLE_WS_URLws://localhost:3000/wsOracle WebSocket for real-time events

3. Start the Oracle

The Dashboard depends on a running Oracle instance for allowlist management, config reads, and real-time events.

cd packages/oracle
pnpm dev

4. Start the Dashboard

cd packages/dashboard
pnpm dev

Opens at http://localhost:3001.

Pages

/create — Token Creation

Step-by-step wizard for creating a compliant Token-2022 mint:

  1. Token Details — name, symbol, decimals, initial supply
  2. Hook Selection — toggle Allowlist, Tax, Hold Period, Max Balance
  3. Hook Configuration — allowlist/denylist mode, tax rate + vault, hold period days
  4. Initialization — after mint creation, initialize each selected hook

The wizard calls useAksumKit().createToken() which auto-selects single-hook or Router mode based on the number of hooks enabled.

/allowlist — Wallet Management

Manage which wallets are authorized to hold the token:

  • Add wallets — paste addresses (comma or newline separated)
  • CSV upload — bulk import from .csv or .txt files
  • Remove wallets — one-click removal from the current list
  • Live status — wallet list auto-loads when a mint address is entered

All operations go through the Oracle API (useOracleClient()), which batches on-chain transactions automatically.

/compliance — Live Monitoring

Real-time compliance event feed powered by WebSocket:

  • Event stream — live feed of allowlist changes, transfer validations, tax events
  • Stats — transfer count, blocked count, wallets verified
  • Connection status — WebSocket health indicator with auto-reconnect

Uses useRealtimeEvents(mint, eventTypes) which connects to the Oracle WebSocket and buffers up to 100 events.

/config — Hook Configuration

Update compliance parameters for an existing token:

  • Tax rate — adjust basis points (e.g. 150 = 1.5%)
  • Hold period — change lock-up duration
  • Max balance — update per-wallet cap
  • Toggle hooks — enable/disable individual hooks

Reads current config via useOracleClient().getTokenConfig() and submits updates through the SDK managers.

Wallet Integration

The Dashboard uses @solana/wallet-adapter-react for wallet connections. Supported wallets:

  • Phantom
  • Solflare
  • Any Wallet Standard compatible wallet

The wallet provider is configured in src/lib/wallet-provider.tsx and wraps the entire app. All pages require a connected wallet to function.

SDK Provider

The SdkProvider wraps the app and exposes the useAksumKit() hook:

import { useAksumKit } from "@/lib/sdk-provider";
 
const {
  connected,           // boolean — wallet connected?
  provider,            // AnchorProvider | null
  createToken,         // (params) => { mint, signature }
  getAllowlistManager,  // (mint) => AllowlistManager
  getTaxManager,       // (mint) => TaxManager
  getHoldManager,      // (mint) => HoldPeriodManager
  getMaxBalanceManager, // (mint) => MaxBalanceManager
} = useAksumKit();

Internally, it loads Anchor IDLs for all four hook programs and constructs Program instances when a wallet is connected.

Oracle Client

The useOracleClient() hook returns an OracleClient singleton for REST API calls:

import { useOracleClient } from "@/lib/oracle-client";
 
const oracle = useOracleClient();
 
// Allowlist operations
await oracle.addWallets(mint, ["wallet1...", "wallet2..."]);
await oracle.removeWallets(mint, ["wallet1..."]);
const { wallets } = await oracle.listWallets(mint);
const { verified } = await oracle.checkWallet(mint, wallet);
 
// Token config
const config = await oracle.getTokenConfig(mint);
await oracle.updateTokenConfig(mint, { tax: { bps: 200 } });
 
// Webhooks
await oracle.registerWebhook(url, ["wallet.verified"], mint);

Real-Time Events

The useRealtimeEvents hook provides a WebSocket connection with auto-reconnect:

import { useRealtimeEvents } from "@/hooks/useRealtimeEvents";
 
const { events, isConnected, error } = useRealtimeEvents(
  mintAddress,
  ["wallet.verified", "wallet.removed", "transfer.blocked"]
);
 
// events: SinaiEvent[] — most recent 100, newest first
// isConnected: boolean — WebSocket connection status
// error: string | null — last error message

Reconnection uses exponential backoff (1s base, 30s max).