sicmundu

arcium-frontend

Build encrypted Solana frontends with Arcium. Use when creating Arcium apps, encrypting user inputs, deriving PDAs, integrating wallets, or troubleshooting Arcium transactions.

sicmundu 1 Updated 4mo ago

Resources

1
GitHub

Install

npx skillscat add sicmundu/arcium-skills-frontend/arcium-frontend

Install via the SkillsCat registry.

SKILL.md

Arcium Frontend Development

Guide for building encrypted Solana applications using Arcium.

When to Use This Skill

Use this skill when:

  • Building a new Arcium-powered frontend
  • Adding encrypted computations to existing apps
  • Integrating Solana wallet adapters
  • Deriving Arcium PDAs
  • Encrypting user inputs
  • Building and sending encrypted instructions
  • Troubleshooting Arcium-related errors

Required Dependencies

npm install @arcium-hq/client @coral-xyz/anchor @solana/web3.js

Environment Variables

Variable Required Default
ARCIUM_CLUSTER_OFFSET Yes
NEXT_PUBLIC_MXE_PROGRAM_ID Yes
NEXT_PUBLIC_RPC_URL No devnet

Core Flow

  1. Setup provider → Create Anchor provider from wallet
  2. Fetch MXE keygetMXEPublicKey(provider, programId)
  3. Generate offset → Random 8-byte computation offset
  4. Encrypt values → X25519 key exchange + RescueCipher
  5. Derive PDAs → MXE, cluster, computation, comp def accounts
  6. Build instruction → Encode discriminator + encrypted data
  7. Send transaction → Sign and submit with compute budget

Key Imports

import * as anchor from '@coral-xyz/anchor';
import { PublicKey, SystemProgram } from '@solana/web3.js';
import {
  getMXEPublicKey,
  getClusterAccAddress,
  getMXEAccAddress,
  getMempoolAccAddress,
  getExecutingPoolAccAddress,
  getComputationAccAddress,
  getCompDefAccAddress,
  getArciumAccountBaseSeed,
  getCompDefAccOffset,
  getArciumProgramId,
  x25519,
  RescueCipher,
  deserializeLE,
} from '@arcium-hq/client';

Encryption Pattern

// 1. Fetch MXE public key
const mxePublicKey = await getMXEPublicKey(provider, programId);

// 2. Generate ephemeral keypair
const privateKey = x25519.utils.randomPrivateKey();
const publicKey = x25519.getPublicKey(privateKey);

// 3. Derive shared secret
const sharedSecret = x25519.getSharedSecret(privateKey, mxePublicKey);

// 4. Encrypt values
const cipher = new RescueCipher(sharedSecret);
const nonce = nacl.randomBytes(16);
const values = [BigInt(10), BigInt(7), BigInt(5)];
const ciphertexts = cipher.encrypt(values, nonce);

PDA Derivation Pattern

// Cluster-based PDAs
const clusterOffset = 768109697; // from ARCIUM_CLUSTER_OFFSET
const clusterAccount = getClusterAccAddress(clusterOffset);
const mempoolAccount = getMempoolAccAddress(clusterOffset);
const executingPool = getExecutingPoolAccAddress(clusterOffset);

// Program-based PDAs
const mxeAccount = getMXEAccAddress(programId);
const computationOffset = new anchor.BN(nacl.randomBytes(8), 'le');
const computationAccount = getComputationAccAddress(clusterOffset, computationOffset);

// Comp def account
const baseSeed = getArciumAccountBaseSeed('ComputationDefinitionAccount');
const offsetBytes = getCompDefAccOffset('my_computation');
const [compDefAccount] = PublicKey.findProgramAddressSync(
  [baseSeed, programId.toBuffer(), offsetBytes],
  getArciumProgramId()
);

Account Ordering

Standard order for encrypted instructions:

  1. payer (signer, writable)
  2. mxeAccount (not signer, not writable)
  3. mempoolAccount (not signer, writable)
  4. executingPool (not signer, writable)
  5. computationAccount (not signer, writable)
  6. compDefAccount (not signer, not writable)
  7. clusterAccount (not signer, writable)
  8. Game-specific accounts
  9. SystemProgram.programId
  10. arciumProgramId

Common Errors

Error Cause Solution
ARCIUM_CLUSTER_OFFSET is missing Missing env var Add to .env.local
MXE Public Key not found MXE not initialized Initialize MXE account first
Account not found Wrong PDA derivation Check cluster offset matches network

Detailed References

For in-depth explanations, see: