UNPKG

@arcium-hq/client

Version:

Client SDK for interacting with encrypted Solana programs

207 lines (153 loc) 5.17 kB
# 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.