@arcium-hq/client
Version:
Client SDK for interacting with encrypted Solana programs
207 lines (153 loc) • 5.17 kB
Markdown
# Arcium Client SDK
The Arcium Client SDK is a TypeScript library for interacting with the Arcium Solana program, enabling secure multi-party computation on encrypted data.
## Installation
```bash
npm install @arcium-hq/client
# or
yarn add @arcium-hq/client
# or
pnpm add @arcium-hq/client
```
## Quick Start
### 1. Setup and Environment
```typescript
import { getArciumEnv } from "@arcium-hq/client";
import * as anchor from "@coral-xyz/anchor";
// Get Arcium environment configuration
const arciumEnv = getArciumEnv();
// Setup Anchor provider
anchor.setProvider(anchor.AnchorProvider.env());
const provider = anchor.getProvider();
```
### 2. Encryption Setup
To send private data for computation within Arcium, you need to encrypt it using a shared secret derived from your keypair and the Arcium MXE's public key.
#### Generate a client keypair:
```typescript
import { x25519 } from "@arcium-hq/client";
const privateKey = x25519.utils.randomPrivateKey();
const publicKey = x25519.getPublicKey(privateKey);
```
#### Obtain the MXE's public key:
```typescript
import { getMXEPublicKey } from "@arcium-hq/client";
// Fetch the MXE public key (handles the complex extraction logic internally)
const mxePublicKey = await getMXEPublicKey(provider, program.programId);
if (!mxePublicKey) {
throw new Error("MXE public key not set");
}
```
#### Compute the shared secret and initialize cipher:
```typescript
import { RescueCipher } from "@arcium-hq/client";
const sharedSecret = x25519.getSharedSecret(privateKey, mxePublicKey);
const cipher = new RescueCipher(sharedSecret);
```
### 3. Encrypt and Submit Data
```typescript
import { randomBytes } from "crypto";
import { deserializeLE } from "@arcium-hq/client";
// Prepare your data as BigInts
const val1 = BigInt(123);
const val2 = BigInt(456);
const plaintext = [val1, val2];
// Generate a random nonce (16 bytes)
const nonce = randomBytes(16);
// Encrypt the data
const ciphertext = cipher.encrypt(plaintext, nonce);
// Submit to your program
const computationOffset = new anchor.BN(randomBytes(8), "hex");
const sig = await program.methods
.yourComputationMethod(
computationOffset,
Array.from(ciphertext[0]),
Array.from(ciphertext[1]),
Array.from(publicKey),
new anchor.BN(deserializeLE(nonce).toString())
)
.accountsPartial({
// Account setup - see Account Helpers section
})
.rpc({ skipPreflight: true, commitment: "confirmed" });
```
### 4. Track and Finalize Computation
```typescript
import { awaitComputationFinalization } from "@arcium-hq/client";
// Wait for computation to complete
const finalizeSig = await awaitComputationFinalization(
provider as anchor.AnchorProvider,
computationOffset,
program.programId,
"confirmed"
);
console.log("Computation finalized:", finalizeSig);
```
### 5. Decrypt Results
```typescript
// Listen for program events
const event = await awaitEvent("yourResultEvent");
// Decrypt the result using the same cipher
const decrypted = cipher.decrypt([event.encryptedResult], event.nonce)[0];
console.log("Decrypted result:", decrypted);
```
## Account Helpers
The SDK provides helper functions to derive all necessary Arcium PDAs:
```typescript
import {
getMXEAccAddress,
getMempoolAccAddress,
getCompDefAccAddress,
getExecutingPoolAccAddress,
getComputationAccAddress,
getCompDefAccOffset,
getArciumAccountBaseSeed,
getArciumProgAddress,
} from "@arcium-hq/client";
// Get various account addresses
const mxeAccount = getMXEAccAddress(program.programId);
const mempoolAccount = getMempoolAccAddress(program.programId);
const executingPool = getExecutingPoolAccAddress(program.programId);
// Get computation definition address
const compDefOffset = getCompDefAccOffset("your_computation_name");
const compDefAccount = getCompDefAccAddress(
program.programId,
Buffer.from(compDefOffset).readUInt32LE()
);
// Get computation account for a specific offset
const computationAccount = getComputationAccAddress(
program.programId,
computationOffset
);
```
## Circuit Management
### Upload a Circuit
```typescript
import { uploadCircuit } from "@arcium-hq/client";
import * as fs from "fs";
const rawCircuit = fs.readFileSync("build/your_circuit.arcis");
await uploadCircuit(
provider as anchor.AnchorProvider,
"your_circuit_name",
program.programId,
rawCircuit,
true // use raw circuit
);
```
### Finalize Computation Definition
```typescript
import { buildFinalizeCompDefTx } from "@arcium-hq/client";
const finalizeTx = await buildFinalizeCompDefTx(
provider as anchor.AnchorProvider,
Buffer.from(compDefOffset).readUInt32LE(),
program.programId
);
// Set blockhash and sign
const latestBlockhash = await provider.connection.getLatestBlockhash();
finalizeTx.recentBlockhash = latestBlockhash.blockhash;
finalizeTx.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;
finalizeTx.sign(owner);
// Send transaction
await provider.sendAndConfirm(finalizeTx);
```
## API Reference
<!-- TODO: Add API reference url -->
For detailed API documentation, please refer to the [API reference](https://github.com/arcium-hq) included with the package.