SINAI STANDARD

Getting Started

Install the Sinai Standard SDK and create your first compliant token

Installation

pnpm add @sinai-standard/sdk @sinai-standard/types

Peer dependencies:

pnpm add @coral-xyz/anchor@^0.31.1 @solana/web3.js@^1.95.0 @solana/spl-token@^0.4.9

Important: Use @solana/web3.js v1. Anchor 0.31 is not compatible with v2 (@solana/kit).

Quick Start

1. Create a Compliant Token

import { Connection, Keypair } from "@solana/web3.js";
import { AksumKit } from "@sinai-standard/sdk";
 
const connection = new Connection("https://api.devnet.solana.com");
const issuer = Keypair.fromSecretKey(/* your key */);
 
const kit = new AksumKit({ connection, payer: issuer });
 
// Create a token with KYC allowlist + 1.5% tax
const token = await kit.createToken({
  name: "Dubai Real Estate Fund I",
  symbol: "DREF1",
  decimals: 6,
  supply: 10_000_000,
  hooks: {
    allowlist: { mode: "allowlist" },
    tax: { bps: 150, maxBps: 500, vault: taxWalletPubkey },
  },
});
 
console.log("Mint:", token.mint.toBase58());

2. Manage the Allowlist

import { AllowlistManager } from "@sinai-standard/sdk";
 
const allowlist = new AllowlistManager(allowlistProgram, token.mint);
 
// Initialize the allowlist registry
await allowlist.initialize(issuer.publicKey, "allowlist");
await allowlist.initializeExtraAccountMetas(issuer.publicKey);
 
// Add KYC-verified investors
await allowlist.addWallets(issuer.publicKey, [
  investorA.publicKey,
  investorB.publicKey,
]);
 
// Check the registry state
const registry = await allowlist.fetchRegistry();
console.log("Wallets:", registry.walletCount);
console.log("Active:", registry.isActive);

3. Transfer Tokens

// Transfer with automatic hook account resolution
await token.transfer(
  sourceATA,      // source token account
  destinationATA, // destination token account
  owner,          // owner keypair (signer)
  1_000_000,      // amount (in base units)
  6               // decimals
);

Transfers are automatically validated against all attached hooks. If the source or destination is not on the allowlist, the transaction will be rejected on-chain.

4. Manage Tax Settings

import { TaxManager } from "@sinai-standard/sdk";
 
const tax = new TaxManager(taxProgram, token.mint);
 
// Initialize tax config: 2% fee, 10% hard cap
await tax.initialize(issuer.publicKey, 200, 1000, taxVaultPubkey);
await tax.initializeExtraAccountMetas(issuer.publicKey);
 
// Update the tax rate later
await tax.updateTaxRate(issuer.publicKey, 150); // 1.5%
 
// Exempt certain wallets from tax
await tax.addExemptWallets(issuer.publicKey, [marketMaker.publicKey]);
 
// Calculate expected tax
const taxAmount = tax.calculateTax(BigInt(1_000_000), 200);
// => 20_000n (2% of 1M)

5. Set Up Hold Periods

import { HoldPeriodManager } from "@sinai-standard/sdk";
 
const hold = new HoldPeriodManager(holdProgram, token.mint);
 
// 90-day hold period
await hold.initialize(issuer.publicKey, 90 * 24 * 60 * 60);
await hold.initializeExtraAccountMetas(issuer.publicKey);
 
// Record when an investor acquires tokens
await hold.recordAcquisition(
  issuer.publicKey,  // payer
  issuer.publicKey,  // authority
  investor.publicKey // wallet to lock
);
 
// Check if the hold period has expired
const unlocked = await hold.isUnlocked(investor.publicKey);
console.log("Can transfer:", unlocked);

6. Enforce Max Balance

import { MaxBalanceManager } from "@sinai-standard/sdk";
 
const maxBal = new MaxBalanceManager(maxBalanceProgram, token.mint);
 
// Cap each wallet at 100,000 tokens
await maxBal.initialize(issuer.publicKey, BigInt(100_000_000_000));
await maxBal.initializeExtraAccountMetas(issuer.publicKey);
 
// Check the configured limit
const config = await maxBal.fetchConfig();
console.log("Max balance:", config.maxBalance.toString());

Next Steps

On this page