Quick Start
Get started with the Arcium TypeScript SDK for encrypted Solana computations
Introduction
Arcium is a decentralized confidential computing network that enables secure processing of encrypted data through Multi-Party Computation (MPC) on Solana. Unlike traditional computation that requires data to be decrypted, Arcium allows computations to run on fully encrypted data, maintaining privacy throughout the entire process.
The SDK provides client-side libraries for interacting with encrypted Solana programs and the Arcium network. The SDK works seamlessly with Anchor and Solana's existing tooling.
Whether you're building private DeFi applications, secure AI systems, or confidential gaming experiences, the Arcium TypeScript SDK gives you the tools to process sensitive data without compromising its confidentiality.
Installation
Install the Arcium client SDK for encryption, PDA helpers, and computation management:
npm install @arcium-hq/clientOverview
This guide will walk you through the complete flow of using the Arcium TypeScript SDK to submit and process encrypted computations:
- Setup: Configure your Anchor provider and Arcium cluster connection
- Encrypt: Establish encryption keys and encrypt your computation inputs
- Submit: Send encrypted computations to the Arcium network
- Monitor: Track computation finalization on-chain
- Decrypt: Retrieve and decrypt computation results
Prerequisites
Complete the Arcium Installation Guide to set up your development environment. This Quick Start guide assumes you have a Solana program with Arcium integration and are familiar with Arcium and Solana concepts.
Setup Anchor Provider
Configure your Anchor provider and get your MXE program ID. This establishes the connection to Solana and identifies your encrypted computation program.
import * as from "@coral-xyz/anchor";
// Initialize Anchor provider from environment variables
.setProvider(.AnchorProvider.env());
const = .getProvider();
// Your MXE program ID
const = new .web3.PublicKey("YourProgramIdHere");Configure Cluster Account
Get the Arcium cluster account address. The cluster account represents a group of ARX nodes that will execute your encrypted computations.
import { , } from "@arcium-hq/client";
// Get cluster offset from environment (set by `arcium localnet` or your .env)
const = ();
const = (.);getArciumEnv() reads ARCIUM_CLUSTER_OFFSET from environment variables. This is automatically set when running arcium localnet.
For devnet/testnet deployments, set ARCIUM_CLUSTER_OFFSET in your .env file. Get your cluster offset from the deployment guide.
Generate Keys and Derive Shared Secret
Perform x25519 key exchange with the MXE to derive a shared secret. This shared secret enables you to encrypt data that the MXE can then compute on.
import * as from "@coral-xyz/anchor";
import { , , } from "@arcium-hq/client";
import { } from "@solana/web3.js";
// Generate client keypair for encryption/decryption
// Note: In production, consider deriving this from your user keypair using signed message-based derivation
const = ..();
const = .();
// Fetch MXE public key with retry logic
// → Expand "Helper Functions" accordion below for full implementation
const = await getMXEPublicKeyWithRetry(
provider as .,
programId
);
// Derive shared secret and create cipher instance
const = .(, );
const = new ();Important
Security: Keep clientPrivateKey in memory until decryption completes. Never log or persist private keys.
Local Testing: ARX nodes generate MXE keys on startup, so getMXEPublicKey may initially return null. The getMXEPublicKeyWithRetry helper function below handles this with configurable retry logic (default: 20 retries × 500ms).
Helper Functions
Encrypt Input Data
Encrypt your computation inputs using the cipher from Step 3. Your sensitive data will remain encrypted throughout the entire computation process.
import { } from "crypto";
import * as from "@coral-xyz/anchor";
import { } from "@arcium-hq/client";
// Prepare your computation inputs
const = [(42), (100)];
// Generate a 16-byte nonce
const = (16);
// Encrypt inputs - returns number[][] where ciphertext[i] corresponds to inputs[i]
// Each encrypted value is a 32-byte array
const = cipher.encrypt(, );
// Generate unique computation offset (8 random bytes as identifier)
const = new .BN((8), "hex");
// Convert nonce to BN for Solana transaction serialization
const = new .BN(().());- Input values must be < 2^252 (Curve25519 scalar field limit)
encrypt()returnsnumber[][]whereciphertext[i]is the encrypted form ofinputs[i]computationOffsetis a unique 8-byte identifier that tracks this computation on-chainnonceBNconverts the nonce bytes to a BigNumber for Solana transaction serialization
Set Up Event Listener
Load your Anchor program and set up the event listener before submitting the transaction. This ensures you can receive the encrypted computation results when they're ready.
import * as from "@coral-xyz/anchor";
import { } from "@coral-xyz/anchor";
import { } from "../target/types/your_program";
// Load your Anchor program using workspace pattern
const = .workspace.YourProgram as <>;
// Type-safe event listener helper
type = .<(typeof )["idl"]>;
const = async < extends keyof >(: ): <[]> => {
let : number;
const = await new <[]>(() => {
= .addEventListener(, () => {
();
});
});
await .removeEventListener();
return ;
};
// Set up event listener BEFORE submitting transaction
const = ("yourResultEvent");Set up the event listener before submitting the transaction to avoid race
conditions. The awaitEvent helper automatically cleans up after the event fires.
Submit Computation Transaction
Submit the encrypted computation for execution. The Arcium network will process your encrypted data without ever decrypting it.
import * as from "@coral-xyz/anchor";
import {
,
,
,
,
,
,
} from "@arcium-hq/client";
// From previous steps:
// - provider, programId (Step 1)
// - arciumEnv, clusterAccount (Step 2)
// - clientPublicKey (Step 3)
// - computationOffset, ciphertext, nonceBN (Step 4)
// - program, resultEventPromise (Step 5)
// Get computation definition offset for your encrypted instruction
// The instruction name must match the function name in your Rust MXE program
// (e.g., if your function is `add_together`, use "add_together")
const = .(("your_instruction_name")).();
// Submit the computation transaction
const = await program.methods
.yourComputationMethod(
computationOffset,
.(ciphertext[0]),
.(ciphertext[1]),
.(clientPublicKey),
nonceBN
)
.accountsPartial({
: (arciumEnv.arciumClusterOffset, computationOffset),
,
: (programId),
: (arciumEnv.arciumClusterOffset),
: (arciumEnv.arciumClusterOffset),
: (programId, ),
// ... your program-specific accounts
})
.rpc({ : true, : "confirmed" });
.("Computation submitted:", );- Replace
yourComputationMethodwith your program's instruction name (must match your MXE function name) - Add your program-specific accounts toaccountsPartialalongside required Arcium accounts -clientPublicKeyis required for ECDH key exchange: we fetch the MXE public key usinggetMXEPublicKey, and sendclientPublicKeyto the MXE so it can derive the same shared secret. See encryption documentation for more details
Await Computation Finalization
Wait for the computation to finalize on-chain. This confirms that the MPC nodes have completed processing your encrypted computation.
import * as from "@coral-xyz/anchor";
import { } from "@arcium-hq/client";
// Wait for computation finalization
const = await (
provider as .,
computationOffset,
programId,
"confirmed"
);
.("Computation finalized:", );Decrypt Results
After finalization completes, retrieve the event and decrypt the result. Use the same cipher instance from Step 3 to decrypt the encrypted computation output.
// Await the event (listener was set up in Step 5)
const = await resultEventPromise;
// Decrypt the result
// The result uses nonce + 1 (nonces must be unique per operation)
const = .(.nonce); // Convert from number[]
const = cipher.decrypt([.encryptedResult], )[0];
.("Decrypted result:", );Event structure: The resultEvent structure shown here (encryptedResult, nonce) is a generic example. Your actual event structure depends on your program's implementation and IDL definition.
Nonce handling: Convert the event's nonce to Uint8Array for decryption. The result nonce is your input nonce + 1 (nonces must be unique per operation to ensure cryptographic freshness).
Complete Example
For a complete working example showing all steps together, see the Hello World guide which includes a full test file demonstrating the entire flow from encryption to decryption.
You can also explore the example programs repository:
arcium-hq/examples
31
What's Next
Explore the API
- Client API Reference: Detailed docs for encryption, PDA helpers, and encrypted instruction management.
Dive Deeper
- Arcium Developer Docs: Framework internals, encrypted instruction design, deployment, and lifecycle.