TypeScript SDK for the Styx Private Memo Program & Virtual State Layer on Solana - Privacy, governance, VTAs, referrals, and novel primitives
npm install @styxstack/pmp-sdkbash
npm install @styxstack/pmp-sdk @solana/web3.js
or
pnpm add @styxstack/pmp-sdk @solana/web3.js
`
Quick Start
`typescript
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import {
StyxPMP,
StyxGovernance,
StyxNovel,
generateX25519Keypair,
deriveSharedSecret
} from '@styxstack/pmp-sdk';
// Connect to Solana
const connection = new Connection('https://api.mainnet-beta.solana.com');
const styx = new StyxPMP(connection);
// Your wallet
const sender = Keypair.generate();
const recipient = new PublicKey('RecipientPubkeyHere...');
// Key exchange (both parties do this)
const myKeys = generateX25519Keypair();
const theirPubkey = / get from recipient /;
const sharedSecret = deriveSharedSecret(myKeys.privateKey, theirPubkey);
// Send encrypted message
const signature = await styx.sendPrivateMessage(
sender,
recipient,
"Hello, World!",
sharedSecret
);
console.log('Sent:', signature);
`
API Reference
$3
Main SDK class.
`typescript
const styx = new StyxPMP(connection, programId?);
`
| Parameter | Type | Description |
|-----------|------|-------------|
| connection | Connection | Solana RPC connection |
| programId | PublicKey | Optional custom program ID (defaults to mainnet) |
$3
#### sendPrivateMessage()
Send an encrypted private message.
`typescript
await styx.sendPrivateMessage(
sender, // Keypair - sender wallet
recipient, // PublicKey - recipient address
message, // string | Uint8Array - message content
sharedSecret,// Uint8Array - 32-byte shared secret
options? // { stealth?: boolean }
);
`
#### sendPrivateTransfer()
Send SOL with hidden metadata.
`typescript
await styx.sendPrivateTransfer(
sender, // Keypair - sender wallet
recipient, // PublicKey - recipient address
amountSol, // number - amount in SOL
memo? // string - optional memo
);
`
#### sendRoutedMessage()
Send a message through multiple relay hops.
`typescript
await styx.sendRoutedMessage(
sender, // Keypair
recipient, // PublicKey
hops, // PublicKey[] - relay nodes
message, // Uint8Array
sharedSecret // Uint8Array
);
`
#### sendRatchetMessage()
Send a forward-secret message using double-ratchet.
`typescript
await styx.sendRatchetMessage(
sender, // Keypair
ephemeralKeypair, // Keypair - new key per message
counter, // bigint - message counter
chainKey, // Uint8Array - ratchet chain key
message, // Uint8Array
sharedSecret // Uint8Array
);
`
#### submitComplianceReveal()
Submit disclosure to an auditor.
`typescript
await styx.submitComplianceReveal(
sender, // Keypair
messageId, // Uint8Array - tx signature
auditor, // PublicKey - auditor address
disclosureKey, // Uint8Array - decryption key
revealType // 'full' | 'amount' | 'recipient' | 'metadata'
);
`
#### subscribeToMessages()
Listen for incoming messages.
`typescript
const subscriptionId = styx.subscribeToMessages((payload, signature) => {
console.log('New message:', signature);
});
// Later: unsubscribe
await styx.unsubscribe(subscriptionId);
`
#### getRecentMessages()
Get historical messages.
`typescript
const messages = await styx.getRecentMessages(100);
for (const msg of messages) {
console.log(msg.signature, msg.timestamp);
}
`
$3
`typescript
import {
encryptRecipient,
decryptRecipient,
encryptAmount,
decryptAmount,
deriveSharedSecret,
generateX25519Keypair,
encryptPayload,
decryptPayload
} from '@styxstack/pmp-sdk';
`
| Function | Description |
|----------|-------------|
| generateX25519Keypair() | Generate X25519 key pair for key exchange |
| deriveSharedSecret(privateKey, publicKey) | Derive shared secret via X25519 |
| encryptPayload(message, secret) | ChaCha20-Poly1305 encrypt |
| decryptPayload(ciphertext, secret) | ChaCha20-Poly1305 decrypt |
| encryptRecipient(sender, recipient) | Keccak256 XOR mask |
| decryptRecipient(sender, encrypted) | Reverse XOR mask |
Program IDs
| Network | Program ID |
|---------|------------|
| Mainnet | GhSTPRZFBnWXMjt6xFnpY2ZHFwijFoC44KkxXSEC94X9 |
| Devnet | CFTbFxMeu5cMPWvaaWNdtsv85H7cfkjYVAgXvQ5r643d |
`typescript
import { STYX_PMP_PROGRAM_ID, STYX_PMP_DEVNET_PROGRAM_ID } from '@styxstack/pmp-sdk';
`
Security Model
$3
- ChaCha20-Poly1305 - Message encryption
- X25519 - Key exchange
- Keccak-256 - Nullifiers and hashing
$3
- Keccak256 XOR - Recipient obfuscation
- Amount masking - Transfer privacy
- Nullifier verification - Double-spend prevention
- PDA derivation - Ghost PDA proofs
âš ï¸ Important: Always encrypt payloads client-side before sending!
Virtual State Layer (VSL)
$3
`typescript
import { StyxGovernance, buildVoteInstruction } from '@styxstack/pmp-sdk';
const governance = new StyxGovernance(styx);
// Create proposal (inscribed, zero rent!)
await governance.createProposal(proposer, {
title: 'Increase treasury allocation',
descriptionHash: keccak256(description),
votingEndSlot: currentSlot + 432000n, // ~2 days
quorumBps: 1000, // 10%
isToken22: true
});
// Cast private vote (identity hidden by nullifier)
await governance.castVote(voter, {
proposalId,
voterSecret: mySecret, // Generates nullifier
vote: 'yes',
isToken22: true
});
`
$3
`typescript
import { StyxReferral, calculateReferralChainRewards } from '@styxstack/pmp-sdk';
const referral = new StyxReferral(styx);
// Register referral (inscribed to chain)
await referral.register(newUser, {
referrer: myReferrerPubkey,
parentChainHash: referrerChainHash
});
// Calculate progressive rewards
const rewards = calculateReferralChainRewards(1_000_000n);
// Level 0: 300,000 (30%)
// Level 1: 150,000 (15%)
// Level 2: 75,000 (7.5%)
// ...halves each level
`
Novel Primitives
$3
Lock messages until a specific slot:
`typescript
import { StyxNovel, buildTimeCapsuleInstruction } from '@styxstack/pmp-sdk';
const novel = new StyxNovel(styx);
// Create time-locked message
await novel.createTimeCapsule(
sender,
recipient,
secretMessage,
senderSecret,
400000000n // Unlock at slot 400M
);
`
$3
Prove knowledge of secret WITHOUT revealing it:
`typescript
import { deriveGhostPDA, GHOST_ACTION_AUTHENTICATE } from '@styxstack/pmp-sdk';
// Prover knows secret
const secret = crypto.getRandomValues(new Uint8Array(32));
const secretHash = keccak256(secret);
// Prove knowledge
await novel.proveSecretKnowledge(
prover,
secret,
GHOST_ACTION_AUTHENTICATE
);
// Program verifies PDA derivation → prover MUST know secret
`
$3
All instruction builders work with Solana Mobile Wallet Adapter:
`typescript
import { buildVoteInstruction, STYX_PMP_PROGRAM_ID } from '@styxstack/pmp-sdk';
import { transact } from '@solana-mobile/mobile-wallet-adapter-protocol';
// Build instruction (no signing yet)
const voteIx = buildVoteInstruction(STYX_PMP_PROGRAM_ID, wallet.publicKey, options);
const tx = new Transaction().add(voteIx);
// Sign with mobile wallet
await transact(async (mwa) => {
const signed = await mwa.signTransactions([tx]);
await connection.sendRawTransaction(signed[0].serialize());
});
`
Program IDs
| Network | Program ID |
|---------|------------|
| Mainnet | GhSTPRZFBnWXMjt6xFnpY2ZHFwijFoC44KkxXSEC94X9 |
| Devnet | CFTbFxMeu5cMPWvaaWNdtsv85H7cfkjYVAgXvQ5r643d |
| Treasury | 13xnC9kDksJMBE9FYVW1S7dukLjRDgrh4Dzm6eq5moon |
`typescript
import { STYX_PMP_PROGRAM_ID, TREASURY, PROTOCOL_FEE_LAMPORTS } from '@styxstack/pmp-sdk';
`
Fee Structure
| Operation | Fee |
|-----------|-----|
| Private Message | 0.001 SOL |
| Private Transfer | 0.001 SOL |
| Private Vote | 0.001 SOL |
| VTA Transfer | 0.001 SOL |
| Time Capsule | 0.001 SOL |
| Ghost PDA | 0.001 SOL |
| Referral Register | FREE |
| Referral Claim | FREE |
| Compliance Reveal | FREE |
💠Support Development
If you find this SDK valuable:
Send SOL to: 13xnC9kDksJMBE9FYVW1S7dukLjRDgrh4Dzm6eq5moon
Or contact @solanadevdao
License
Apache-2.0
Attribution Required: When using this SDK, please include:
`
Powered by Styx Stack - https://github.com/QuarksBlueFoot/StyxStack
Created by @moonmanquark (Bluefoot Labs)
``