@arcium-hq/client 0.1.47 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -68
- package/build/index.cjs +3288 -7549
- package/build/index.d.ts +4998 -18427
- package/build/index.mjs +3287 -7544
- package/package.json +11 -9
package/README.md
CHANGED
|
@@ -1,102 +1,206 @@
|
|
|
1
1
|
# Arcium Client SDK
|
|
2
2
|
|
|
3
|
-
The Arcium
|
|
3
|
+
The Arcium Client SDK is a TypeScript library for interacting with the Arcium Solana program, enabling secure multi-party computation on encrypted data.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @arcium-hq/client
|
|
9
|
+
# or
|
|
10
|
+
yarn add @arcium-hq/client
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @arcium-hq/client
|
|
13
|
+
```
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
## Quick Start
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
### 1. Setup and Environment
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
```typescript
|
|
20
|
+
import { getArciumEnv } from "@arcium-hq/client";
|
|
21
|
+
import * as anchor from "@coral-xyz/anchor";
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
// Get Arcium environment configuration
|
|
24
|
+
const arciumEnv = getArciumEnv();
|
|
25
|
+
|
|
26
|
+
// Setup Anchor provider
|
|
27
|
+
anchor.setProvider(anchor.AnchorProvider.env());
|
|
28
|
+
const provider = anchor.getProvider();
|
|
17
29
|
```
|
|
18
30
|
|
|
19
|
-
|
|
31
|
+
### 2. Encryption Setup
|
|
32
|
+
|
|
33
|
+
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.
|
|
20
34
|
|
|
21
|
-
|
|
35
|
+
#### Generate a client keypair:
|
|
22
36
|
|
|
23
|
-
|
|
37
|
+
```typescript
|
|
38
|
+
import { x25519 } from "@arcium-hq/client";
|
|
24
39
|
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
const privateKey = x25519.utils.randomSecretKey();
|
|
41
|
+
const publicKey = x25519.getPublicKey(privateKey);
|
|
42
|
+
```
|
|
27
43
|
|
|
28
|
-
|
|
29
|
-
const publicKey = x25519.getPublicKey(privateKey);
|
|
30
|
-
```
|
|
44
|
+
#### Obtain the MXE's public key:
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
```typescript
|
|
47
|
+
import { getMXEPublicKey } from "@arcium-hq/client";
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const mxePublicKey = new Uint8Array([
|
|
38
|
-
/* ... 32 bytes of the MXE public key ... */
|
|
39
|
-
]);
|
|
40
|
-
```
|
|
49
|
+
// Fetch the MXE public key (handles the complex extraction logic internally)
|
|
50
|
+
const mxePublicKey = await getMXEPublicKey(provider, program.programId);
|
|
41
51
|
|
|
42
|
-
|
|
52
|
+
if (!mxePublicKey) {
|
|
53
|
+
throw new Error("MXE public key not set");
|
|
54
|
+
}
|
|
55
|
+
```
|
|
43
56
|
|
|
44
|
-
|
|
45
|
-
const sharedSecret = x25519.getSharedSecret(privateKey, mxePublicKey);
|
|
46
|
-
```
|
|
57
|
+
#### Compute the shared secret and initialize cipher:
|
|
47
58
|
|
|
48
|
-
|
|
59
|
+
```typescript
|
|
60
|
+
import { RescueCipher } from "@arcium-hq/client";
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
const sharedSecret = x25519.getSharedSecret(privateKey, mxePublicKey);
|
|
63
|
+
const cipher = new RescueCipher(sharedSecret);
|
|
64
|
+
```
|
|
52
65
|
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
### 3. Encrypt and Submit Data
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { randomBytes } from "crypto";
|
|
70
|
+
import { deserializeLE } from "@arcium-hq/client";
|
|
71
|
+
|
|
72
|
+
// Prepare your data as BigInts
|
|
73
|
+
const val1 = BigInt(123);
|
|
74
|
+
const val2 = BigInt(456);
|
|
75
|
+
const plaintext = [val1, val2];
|
|
76
|
+
|
|
77
|
+
// Generate a random nonce (16 bytes)
|
|
78
|
+
const nonce = randomBytes(16);
|
|
79
|
+
|
|
80
|
+
// Encrypt the data
|
|
81
|
+
const ciphertext = cipher.encrypt(plaintext, nonce);
|
|
82
|
+
|
|
83
|
+
// Submit to your program
|
|
84
|
+
const computationOffset = new anchor.BN(randomBytes(8), "hex");
|
|
85
|
+
|
|
86
|
+
const sig = await program.methods
|
|
87
|
+
.yourComputationMethod(
|
|
88
|
+
computationOffset,
|
|
89
|
+
Array.from(ciphertext[0]),
|
|
90
|
+
Array.from(ciphertext[1]),
|
|
91
|
+
Array.from(publicKey),
|
|
92
|
+
new anchor.BN(deserializeLE(nonce).toString())
|
|
93
|
+
)
|
|
94
|
+
.accountsPartial({
|
|
95
|
+
// Account setup - see Account Helpers section
|
|
96
|
+
})
|
|
97
|
+
.rpc({ skipPreflight: true, commitment: "confirmed" });
|
|
98
|
+
```
|
|
55
99
|
|
|
56
|
-
|
|
57
|
-
_The plaintext should be an array of BigInts._
|
|
100
|
+
### 4. Track and Finalize Computation
|
|
58
101
|
|
|
59
|
-
|
|
60
|
-
|
|
102
|
+
```typescript
|
|
103
|
+
import { awaitComputationFinalization } from "@arcium-hq/client";
|
|
61
104
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
105
|
+
// Wait for computation to complete
|
|
106
|
+
const finalizeSig = await awaitComputationFinalization(
|
|
107
|
+
provider as anchor.AnchorProvider,
|
|
108
|
+
computationOffset,
|
|
109
|
+
program.programId,
|
|
110
|
+
"confirmed"
|
|
111
|
+
);
|
|
65
112
|
|
|
66
|
-
|
|
67
|
-
|
|
113
|
+
console.log("Computation finalized:", finalizeSig);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 5. Decrypt Results
|
|
68
117
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
118
|
+
```typescript
|
|
119
|
+
// Listen for program events
|
|
120
|
+
const event = await awaitEvent("yourResultEvent");
|
|
72
121
|
|
|
73
|
-
|
|
74
|
-
|
|
122
|
+
// Decrypt the result using the same cipher
|
|
123
|
+
const decrypted = cipher.decrypt([event.encryptedResult], event.nonce)[0];
|
|
124
|
+
console.log("Decrypted result:", decrypted);
|
|
125
|
+
```
|
|
75
126
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
127
|
+
## Account Helpers
|
|
128
|
+
|
|
129
|
+
The SDK provides helper functions to derive all necessary Arcium PDAs:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import {
|
|
133
|
+
getMXEAccAddress,
|
|
134
|
+
getMempoolAccAddress,
|
|
135
|
+
getCompDefAccAddress,
|
|
136
|
+
getExecutingPoolAccAddress,
|
|
137
|
+
getComputationAccAddress,
|
|
138
|
+
getCompDefAccOffset,
|
|
139
|
+
getArciumAccountBaseSeed,
|
|
140
|
+
getArciumProgAddress,
|
|
141
|
+
} from "@arcium-hq/client";
|
|
142
|
+
|
|
143
|
+
// Get various account addresses
|
|
144
|
+
const mxeAccount = getMXEAccAddress(program.programId);
|
|
145
|
+
const mempoolAccount = getMempoolAccAddress(program.programId);
|
|
146
|
+
const executingPool = getExecutingPoolAccAddress(program.programId);
|
|
147
|
+
|
|
148
|
+
// Get computation definition address
|
|
149
|
+
const compDefOffset = getCompDefAccOffset("your_computation_name");
|
|
150
|
+
const compDefAccount = getCompDefAccAddress(
|
|
151
|
+
program.programId,
|
|
152
|
+
Buffer.from(compDefOffset).readUInt32LE()
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// Get computation account for a specific offset
|
|
156
|
+
const computationAccount = getComputationAccAddress(
|
|
157
|
+
program.programId,
|
|
158
|
+
computationOffset
|
|
159
|
+
);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Circuit Management
|
|
163
|
+
|
|
164
|
+
### Upload a Circuit
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { uploadCircuit } from "@arcium-hq/client";
|
|
168
|
+
import * as fs from "fs";
|
|
169
|
+
|
|
170
|
+
const rawCircuit = fs.readFileSync("build/your_circuit.arcis");
|
|
171
|
+
|
|
172
|
+
await uploadCircuit(
|
|
173
|
+
provider as anchor.AnchorProvider,
|
|
174
|
+
"your_circuit_name",
|
|
175
|
+
program.programId,
|
|
176
|
+
rawCircuit,
|
|
177
|
+
true // use raw circuit
|
|
178
|
+
);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Finalize Computation Definition
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { buildFinalizeCompDefTx } from "@arcium-hq/client";
|
|
185
|
+
|
|
186
|
+
const finalizeTx = await buildFinalizeCompDefTx(
|
|
187
|
+
provider as anchor.AnchorProvider,
|
|
188
|
+
Buffer.from(compDefOffset).readUInt32LE(),
|
|
189
|
+
program.programId
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
// Set blockhash and sign
|
|
193
|
+
const latestBlockhash = await provider.connection.getLatestBlockhash();
|
|
194
|
+
finalizeTx.recentBlockhash = latestBlockhash.blockhash;
|
|
195
|
+
finalizeTx.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;
|
|
196
|
+
finalizeTx.sign(owner);
|
|
197
|
+
|
|
198
|
+
// Send transaction
|
|
199
|
+
await provider.sendAndConfirm(finalizeTx);
|
|
200
|
+
```
|
|
86
201
|
|
|
87
|
-
|
|
88
|
-
_When your program receives results from Arcium (e.g., via an event), they will likely be encrypted. Use the same `cipher` instance and the `nonce` provided in the result/event to decrypt._
|
|
202
|
+
## API Reference
|
|
89
203
|
|
|
90
|
-
|
|
91
|
-
// Assuming `event.encryptedResult` is a Uint8Array or number[]
|
|
92
|
-
// and `event.resultNonce` is a Uint8Array or number[] from the Arcium callback
|
|
93
|
-
const resultCiphertextArray = [event.encryptedResult];
|
|
94
|
-
const resultNonceArray = new Uint8Array(event.resultNonce);
|
|
204
|
+
<!-- TODO: Add API reference url -->
|
|
95
205
|
|
|
96
|
-
|
|
97
|
-
resultCiphertextArray,
|
|
98
|
-
resultNonceArray
|
|
99
|
-
);
|
|
100
|
-
// decryptedResult will be an array of bigints
|
|
101
|
-
const resultValue = decryptedResult[0];
|
|
102
|
-
```
|
|
206
|
+
For detailed API documentation, please refer to the [API reference](https://github.com/arcium-hq) included with the package.
|