@arcium-hq/client 0.10.3 → 0.11.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.
@@ -0,0 +1,79 @@
1
+ import { BorshCoder, convertIdlToCamelCase } from '@anchor-lang/core';
2
+ import { DISCRIMINATOR_SIZE } from './constants.js';
3
+ import { ARCIUM_IDL } from './idl/index.js';
4
+ import type { ArciumIdlType } from './idl/index.js';
5
+
6
+ type IdlAccountName = ArciumIdlType['accounts'][number]['name'];
7
+
8
+ // Names are validated against the IDL account-name union at compile time, so a
9
+ // typo or stale tier fails `tsc` rather than only throwing at load.
10
+ const MEMPOOL_DECODER_ACCOUNT_NAMES = [
11
+ 'tinyMempool',
12
+ 'smallMempool',
13
+ 'mediumMempool',
14
+ 'largeMempool',
15
+ ] as const satisfies readonly IdlAccountName[];
16
+ const EXECUTING_POOL_DECODER_ACCOUNT_NAMES = [
17
+ 'tinyExecPool',
18
+ 'smallExecPool',
19
+ 'mediumExecPool',
20
+ 'largeExecPool',
21
+ ] as const satisfies readonly IdlAccountName[];
22
+
23
+ /** @internal */
24
+ export type MempoolDecoderAccountName = typeof MEMPOOL_DECODER_ACCOUNT_NAMES[number];
25
+ /** @internal */
26
+ export type ExecutingPoolDecoderAccountName = typeof EXECUTING_POOL_DECODER_ACCOUNT_NAMES[number];
27
+ /** @internal */
28
+ export type PoolDecoderAccountName = MempoolDecoderAccountName | ExecutingPoolDecoderAccountName;
29
+
30
+ type PoolAccountKind = 'mempool' | 'executing pool';
31
+
32
+ function discriminatorKey(discriminator: ArrayLike<number>): string {
33
+ return Buffer.from(discriminator).toString('hex');
34
+ }
35
+
36
+ // Discriminator bytes are read from the IDL at load time rather than pinned, so the
37
+ // decoder tracks the program's account layout as the single source of truth; a
38
+ // missing or renamed tier throws here instead of silently misrouting at runtime.
39
+ const accountDiscriminatorCoder = new BorshCoder(convertIdlToCamelCase(ARCIUM_IDL)).accounts;
40
+
41
+ function buildPoolAccountMap<const AccountNames extends readonly IdlAccountName[]>(
42
+ accountNames: AccountNames,
43
+ ): ReadonlyMap<string, AccountNames[number]> {
44
+ return new Map<string, AccountNames[number]>(accountNames.map((name): [string, AccountNames[number]] => [
45
+ discriminatorKey(accountDiscriminatorCoder.accountDiscriminator(name)),
46
+ name,
47
+ ]));
48
+ }
49
+
50
+ const MEMPOOL_ACCOUNT_BY_DISCRIMINATOR = buildPoolAccountMap(MEMPOOL_DECODER_ACCOUNT_NAMES);
51
+ const EXECUTING_POOL_ACCOUNT_BY_DISCRIMINATOR = buildPoolAccountMap(EXECUTING_POOL_DECODER_ACCOUNT_NAMES);
52
+
53
+ function getPoolAccountNameByDiscriminator<AccountName extends PoolDecoderAccountName>(
54
+ accountData: Uint8Array,
55
+ accountsByDiscriminator: ReadonlyMap<string, AccountName>,
56
+ kind: PoolAccountKind,
57
+ ): AccountName {
58
+ if (accountData.length < DISCRIMINATOR_SIZE) {
59
+ throw new Error(`${kind} account data is shorter than discriminator size`);
60
+ }
61
+
62
+ const key = discriminatorKey(accountData.subarray(0, DISCRIMINATOR_SIZE));
63
+ const accountName = accountsByDiscriminator.get(key);
64
+ if (accountName === undefined) {
65
+ throw new Error(`Unknown ${kind} account discriminator: ${key}`);
66
+ }
67
+
68
+ return accountName;
69
+ }
70
+
71
+ /** @internal */
72
+ export function getMempoolAccountNameByDiscriminator(accountData: Uint8Array): MempoolDecoderAccountName {
73
+ return getPoolAccountNameByDiscriminator(accountData, MEMPOOL_ACCOUNT_BY_DISCRIMINATOR, 'mempool');
74
+ }
75
+
76
+ /** @internal */
77
+ export function getExecutingPoolAccountNameByDiscriminator(accountData: Uint8Array): ExecutingPoolDecoderAccountName {
78
+ return getPoolAccountNameByDiscriminator(accountData, EXECUTING_POOL_ACCOUNT_BY_DISCRIMINATOR, 'executing pool');
79
+ }
package/src/onchain.ts CHANGED
@@ -1,137 +1,35 @@
1
- import { Program, AnchorProvider } from '@anchor-lang/core';
1
+ import anchorPkg, { Program, AnchorProvider } from '@anchor-lang/core';
2
2
  import * as anchor from '@anchor-lang/core';
3
- import { ConfirmOptions, PublicKey } from '@solana/web3.js';
3
+ import type { AccountInfo, ConfirmOptions, PublicKey } from '@solana/web3.js';
4
4
  import { ARCIUM_IDL, ArciumIdlType } from './idl/index.js';
5
5
  import { sha256 } from './cryptography/cryptography.js';
6
6
  import { Arcium } from './idl/arcium.js';
7
7
  import {
8
- COMP_DEF_ACC_SEED,
9
8
  COMP_DEF_OFFSET_SIZE,
10
- DISCRIMINATOR_SIZE,
11
- MAX_ACCOUNT_SIZE,
9
+ DEFAULT_UPLOAD_TX_BATCH_SIZE,
12
10
  MAX_EMBIGGEN_IX_PER_TX,
11
+ MAX_RAW_CIRCUIT_BYTES_PER_ACC,
13
12
  MAX_REALLOC_PER_IX,
14
13
  MAX_UPLOAD_PER_TX_BYTES,
15
- OFFSET_BUFFER_SIZE,
14
+ RAW_CIRCUIT_ACCOUNT_HEADER_SIZE,
16
15
  } from './constants.js';
17
16
  import {
18
- getArciumProgramId,
19
17
  getMXEAccAddress,
20
18
  getComputationAccAddress,
19
+ getCompDefAccAddress,
21
20
  getFeePoolAccAddress,
22
21
  getRawCircuitAccAddress,
23
22
  getLookupTableAddress,
24
23
  } from './pda.js';
25
24
  import { ComputationReference, isNullRef, optionalLog } from './utils.js';
25
+ import {
26
+ getExecutingPoolAccountNameByDiscriminator,
27
+ getMempoolAccountNameByDiscriminator,
28
+ } from './idlAccounts.js';
29
+ import { normalizeRecoveryPeers } from './recoveryPeers.js';
30
+ import { assertRawCircuitUploadLength, getRawCircuitAccountCount } from './rawCircuit.js';
26
31
 
27
- const TINY_MEMPOOL_ACC_NAME: Arcium['accounts']['21']['name'] = 'tinyMempool';
28
- const TINY_MEMPOOL_DISCRIMINATOR: Arcium['accounts']['21']['discriminator'] = [
29
- 176,
30
- 33,
31
- 67,
32
- 108,
33
- 73,
34
- 135,
35
- 110,
36
- 166,
37
- ];
38
-
39
- const TINY_EXECPOOL_ACC_NAME: Arcium['accounts']['20']['name'] = 'tinyExecPool';
40
- const TINY_EXECPOOL_DISCRIMINATOR: Arcium['accounts']['20']['discriminator'] = [
41
- 80,
42
- 245,
43
- 5,
44
- 90,
45
- 154,
46
- 189,
47
- 190,
48
- 172,
49
- ];
50
-
51
- const SMALL_MEMPOOL_ACC_NAME: Arcium['accounts']['19']['name'] = 'smallMempool';
52
- const SMALL_MEMPOOL_DISCRIMINATOR: Arcium['accounts']['19']['discriminator'] = [
53
- 123,
54
- 153,
55
- 151,
56
- 118,
57
- 126,
58
- 71,
59
- 73,
60
- 92,
61
- ];
62
-
63
- const SMALL_EXECPOOL_ACC_NAME: Arcium['accounts']['18']['name'] = 'smallExecPool';
64
- const SMALL_EXECPOOL_DISCRIMINATOR: Arcium['accounts']['18']['discriminator'] = [
65
- 37,
66
- 147,
67
- 249,
68
- 253,
69
- 217,
70
- 136,
71
- 3,
72
- 87,
73
- ];
74
- const MEDIUM_MEMPOOL_ACC_NAME: Arcium['accounts']['12']['name'] = 'mediumMempool';
75
- const MEDIUM_MEMPOOL_DISCRIMINATOR: Arcium['accounts']['12']['discriminator'] = [
76
- 10,
77
- 249,
78
- 58,
79
- 39,
80
- 255,
81
- 231,
82
- 199,
83
- 168,
84
- ];
85
-
86
- const MEDIUM_EXECPOOL_ACC_NAME: Arcium['accounts']['11']['name'] = 'mediumExecPool';
87
- const MEDIUM_EXECPOOL_DISCRIMINATOR: Arcium['accounts']['11']['discriminator'] = [
88
- 97,
89
- 117,
90
- 128,
91
- 202,
92
- 213,
93
- 76,
94
- 5,
95
- 163,
96
- ];
97
-
98
- const LARGE_MEMPOOL_ACC_NAME: Arcium['accounts']['9']['name'] = 'largeMempool';
99
- const LARGE_MEMPOOL_DISCRIMINATOR: Arcium['accounts']['9']['discriminator'] = [
100
- 16,
101
- 168,
102
- 90,
103
- 235,
104
- 249,
105
- 207,
106
- 73,
107
- 223,
108
- ];
109
-
110
- const LARGE_EXECPOOL_ACC_NAME: Arcium['accounts']['8']['name'] = 'largeExecPool';
111
- const LARGE_EXECPOOL_DISCRIMINATOR: Arcium['accounts']['8']['discriminator'] = [
112
- 147,
113
- 145,
114
- 148,
115
- 170,
116
- 30,
117
- 13,
118
- 43,
119
- 216,
120
- ];
121
-
122
- const MEMPOOL_DISCRIMINATOR_MAP = {
123
- [TINY_MEMPOOL_DISCRIMINATOR.toString()]: TINY_MEMPOOL_ACC_NAME,
124
- [SMALL_MEMPOOL_DISCRIMINATOR.toString()]: SMALL_MEMPOOL_ACC_NAME,
125
- [MEDIUM_MEMPOOL_DISCRIMINATOR.toString()]: MEDIUM_MEMPOOL_ACC_NAME,
126
- [LARGE_MEMPOOL_DISCRIMINATOR.toString()]: LARGE_MEMPOOL_ACC_NAME,
127
- } as const;
128
-
129
- const EXECPOOL_DISCRIMINATOR_MAP = {
130
- [TINY_EXECPOOL_DISCRIMINATOR.toString()]: TINY_EXECPOOL_ACC_NAME,
131
- [SMALL_EXECPOOL_DISCRIMINATOR.toString()]: SMALL_EXECPOOL_ACC_NAME,
132
- [MEDIUM_EXECPOOL_DISCRIMINATOR.toString()]: MEDIUM_EXECPOOL_ACC_NAME,
133
- [LARGE_EXECPOOL_DISCRIMINATOR.toString()]: LARGE_EXECPOOL_ACC_NAME,
134
- } as const;
32
+ const { BN } = anchorPkg;
135
33
 
136
34
  /**
137
35
  * Represents a mempool account of any size (tiny, small, medium, or large).
@@ -169,17 +67,8 @@ export type CircuitSource = anchor.IdlTypes<ArciumIdlType>['circuitSource'];
169
67
  * @throws Error if the account cannot be fetched or the discriminator is unknown.
170
68
  */
171
69
  export async function getMempoolAccInfo(provider: AnchorProvider, mempoolAccPubkey: anchor.web3.PublicKey): Promise<MempoolAccount> {
172
- const accData = await provider.connection.getAccountInfo(mempoolAccPubkey);
173
- if (accData === null) {
174
- throw new Error(`Failed to fetch mempool account ${mempoolAccPubkey.toBase58()}`);
175
- }
176
-
177
- const discriminator = Array.from(accData.data.subarray(0, DISCRIMINATOR_SIZE)).toString();
178
- const accName = MEMPOOL_DISCRIMINATOR_MAP[discriminator];
179
-
180
- if (accName === undefined) {
181
- throw new Error(`Unknown mempool account discriminator: ${discriminator}`);
182
- }
70
+ const accData = requireAccountInfo(await provider.connection.getAccountInfo(mempoolAccPubkey), mempoolAccPubkey, 'mempool');
71
+ const accName = getMempoolAccountNameByDiscriminator(accData.data);
183
72
  const program = getArciumProgram(provider);
184
73
  return program.coder.accounts.decode(accName, accData.data);
185
74
  }
@@ -192,21 +81,24 @@ export async function getMempoolAccInfo(provider: AnchorProvider, mempoolAccPubk
192
81
  * @throws Error if the account cannot be fetched or the discriminator is unknown.
193
82
  */
194
83
  export async function getExecutingPoolAccInfo(provider: AnchorProvider, executingPoolAccPubkey: anchor.web3.PublicKey): Promise<ExecutingPoolAccount> {
195
- const accData = await provider.connection.getAccountInfo(executingPoolAccPubkey);
196
- if (accData === null) {
197
- throw new Error(`Failed to fetch executing pool account ${executingPoolAccPubkey.toBase58()}`);
198
- }
199
-
200
- const discriminator = Array.from(accData.data.subarray(0, DISCRIMINATOR_SIZE)).toString();
201
- const accName = EXECPOOL_DISCRIMINATOR_MAP[discriminator];
202
-
203
- if (accName === undefined) {
204
- throw new Error(`Unknown executing pool account discriminator: ${discriminator}`);
205
- }
84
+ const accData = requireAccountInfo(await provider.connection.getAccountInfo(executingPoolAccPubkey), executingPoolAccPubkey, 'executing pool');
85
+ const accName = getExecutingPoolAccountNameByDiscriminator(accData.data);
206
86
  const program = getArciumProgram(provider);
207
87
  return program.coder.accounts.decode(accName, accData.data);
208
88
  }
209
89
 
90
+ function requireAccountInfo(
91
+ accountInfo: AccountInfo<Buffer> | null,
92
+ pubkey: PublicKey,
93
+ label: 'mempool' | 'executing pool',
94
+ ): AccountInfo<Buffer> {
95
+ if (accountInfo === null) {
96
+ throw new Error(`Failed to fetch ${label} account ${pubkey.toBase58()}`);
97
+ }
98
+
99
+ return accountInfo;
100
+ }
101
+
210
102
  /**
211
103
  * Return all computation references in the mempool for a given account.
212
104
  * Only non-stake computations are included.
@@ -286,18 +178,18 @@ export async function getMempoolPriorityFeeStats(
286
178
  const refs = await getComputationsInMempool(arciumProgram, mempoolAddress);
287
179
 
288
180
  if (refs.length === 0) {
289
- const zero = new anchor.BN(0);
181
+ const zero = new BN(0);
290
182
  return { mean: zero, median: zero, min: zero, max: zero, count: 0 };
291
183
  }
292
184
 
293
185
  const fees = refs.map(ref => ref.priorityFee).sort((a, b) => a.cmp(b));
294
186
 
295
- const sum = fees.reduce((acc, fee) => acc.add(fee), new anchor.BN(0));
296
- const mean = sum.div(new anchor.BN(fees.length));
187
+ const sum = fees.reduce((acc, fee) => acc.add(fee), new BN(0));
188
+ const mean = sum.div(new BN(fees.length));
297
189
 
298
190
  const mid = Math.floor(fees.length / 2);
299
191
  const median = fees.length % 2 === 0
300
- ? fees[mid - 1].add(fees[mid]).div(new anchor.BN(2))
192
+ ? fees[mid - 1].add(fees[mid]).div(new BN(2))
301
193
  : fees[mid];
302
194
 
303
195
  return {
@@ -408,7 +300,8 @@ export function getCircuitState(circuitSource: CircuitSource): CircuitState {
408
300
  * @param mxeProgramId - Public key of the MXE program.
409
301
  * @param rawCircuit - Raw circuit data as a Uint8Array.
410
302
  * @param logging - Whether to log progress (default: true).
411
- * @param chunkSize - Number of upload transactions to send in parallel (default: 500).
303
+ * @param chunkSize - Number of upload transactions to send in parallel. Defaults to
304
+ * {@link DEFAULT_UPLOAD_TX_BATCH_SIZE}.
412
305
  * @param confirmOptions - Transaction confirmation options.
413
306
  * @returns Array of transaction signatures for all upload and finalize transactions.
414
307
  */
@@ -418,7 +311,7 @@ export async function uploadCircuit(
418
311
  mxeProgramId: anchor.web3.PublicKey,
419
312
  rawCircuit: Uint8Array,
420
313
  logging: boolean = true,
421
- chunkSize: number = 500,
314
+ chunkSize: number = DEFAULT_UPLOAD_TX_BATCH_SIZE,
422
315
  confirmOptions?: ConfirmOptions,
423
316
  ): Promise<string[]> {
424
317
  const compDefAccInfo = getCompDefAccInfo(circuitName, mxeProgramId);
@@ -432,8 +325,8 @@ export async function uploadCircuit(
432
325
  return [];
433
326
  }
434
327
 
435
- // 9 = 8-byte discriminator + 1-byte bump for ComputationDefinitionRaw account
436
- const numAccs = Math.ceil(rawCircuit.length / (MAX_ACCOUNT_SIZE - 9));
328
+ assertRawCircuitUploadLength(rawCircuit.length, compDefAcc.definition.circuitLen, circuitName);
329
+ const numAccs = getRawCircuitAccountCount(rawCircuit.length);
437
330
  const sigs: string[] = [];
438
331
  const uploadPromises = [];
439
332
  for (let i = 0; i < numAccs; i++) {
@@ -442,8 +335,8 @@ export async function uploadCircuit(
442
335
  provider,
443
336
  program,
444
337
  rawCircuit.subarray(
445
- i * (MAX_ACCOUNT_SIZE - 9),
446
- (i + 1) * (MAX_ACCOUNT_SIZE - 9),
338
+ i * MAX_RAW_CIRCUIT_BYTES_PER_ACC,
339
+ (i + 1) * MAX_RAW_CIRCUIT_BYTES_PER_ACC,
447
340
  ),
448
341
  i,
449
342
  compDefAccInfo,
@@ -476,8 +369,6 @@ export async function buildFinalizeCompDefTx(
476
369
  mxeProgramId: anchor.web3.PublicKey,
477
370
  ): Promise<anchor.web3.Transaction> {
478
371
  const program = getArciumProgram(provider);
479
- const compDefOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
480
- compDefOffsetBuffer.writeUInt32LE(compDefOffset, 0);
481
372
  return program.methods
482
373
  .finalizeComputationDefinition(compDefOffset, mxeProgramId)
483
374
  .accounts({
@@ -494,15 +385,14 @@ async function uploadToCircuitAcc(
494
385
  compDefAccInfo: { pubkey: anchor.web3.PublicKey; offset: number },
495
386
  mxeProgramId: anchor.web3.PublicKey,
496
387
  shouldLog: boolean = true,
497
- chunkSize: number = 500,
388
+ chunkSize: number = DEFAULT_UPLOAD_TX_BATCH_SIZE,
498
389
  confirmOptions?: ConfirmOptions,
499
390
  ): Promise<string[]> {
500
391
  const rawCircuitPda = getRawCircuitAccAddress(compDefAccInfo.pubkey, rawCircuitIndex);
501
392
  const existingAcc = await provider.connection.getAccountInfo(rawCircuitPda);
502
393
 
503
394
  // Skip entirely if account exists with correct size (pre-seeded at genesis or already uploaded)
504
- // Account layout: 8-byte discriminator + 1-byte bump + circuit data
505
- const requiredAccountSize = rawCircuitPart.length + 9;
395
+ const requiredAccountSize = rawCircuitPart.length + RAW_CIRCUIT_ACCOUNT_HEADER_SIZE;
506
396
  if (existingAcc !== null && existingAcc.data.length >= requiredAccountSize) {
507
397
  optionalLog(
508
398
  shouldLog,
@@ -725,19 +615,8 @@ export function getArciumProgram(provider: AnchorProvider): Program<Arcium> {
725
615
  */
726
616
  function getCompDefAccInfo(circuitName: string, mxeProgramId: anchor.web3.PublicKey): { pubkey: anchor.web3.PublicKey; offset: number } {
727
617
  const offset = getCompDefAccOffset(circuitName);
728
- const pda = getCompDefAccPDA(getArciumProgramId(), mxeProgramId, offset);
729
- return { pubkey: pda, offset: Buffer.from(offset).readUInt32LE(0) };
730
- }
731
-
732
- /**
733
- * Return the PDA for a computation definition account, given the program ID, MXE program ID, and offset.
734
- * @param arciumProgramId - Public key of the Arcium program.
735
- * @param mxeProgramId - Public key of the MXE program.
736
- * @param offset - Offset as a Uint8Array.
737
- * @returns PDA for the computation definition account.
738
- */
739
- function getCompDefAccPDA(arciumProgramId: anchor.web3.PublicKey, mxeProgramId: anchor.web3.PublicKey, offset: Uint8Array): anchor.web3.PublicKey {
740
- return anchor.web3.PublicKey.findProgramAddressSync([Buffer.from(COMP_DEF_ACC_SEED, 'utf-8'), mxeProgramId.toBuffer(), offset], arciumProgramId)[0];
618
+ const offsetNumber = Buffer.from(offset).readUInt32LE(0);
619
+ return { pubkey: getCompDefAccAddress(mxeProgramId, offsetNumber), offset: offsetNumber };
741
620
  }
742
621
 
743
622
  /**
@@ -746,17 +625,22 @@ function getCompDefAccPDA(arciumProgramId: anchor.web3.PublicKey, mxeProgramId:
746
625
  * Call initMxePart2 afterwards to finish allocation and add keygen to mempool.
747
626
  * @param provider - Anchor provider to use for transactions.
748
627
  * @param mxeProgramId - Public key to use as the MXE program ID.
628
+ * @param recoveryPeers - Array of 100 node offsets for recovery peers (0 for unused slots).
749
629
  * @param confirmOptions - Transaction confirmation options.
750
630
  * @returns Transaction signature.
751
631
  */
752
632
  export async function initMxePart1(
753
633
  provider: AnchorProvider,
754
634
  mxeProgramId: anchor.web3.PublicKey,
635
+ recoveryPeers: number[],
755
636
  confirmOptions?: ConfirmOptions,
756
637
  ): Promise<string> {
757
638
  const program = getArciumProgram(provider);
639
+ const paddedRecoveryPeers = normalizeRecoveryPeers(recoveryPeers);
758
640
  const tx = await program.methods
759
- .initMxePart1()
641
+ .initMxePart1(
642
+ paddedRecoveryPeers
643
+ )
760
644
  .accountsPartial({
761
645
  signer: provider.publicKey,
762
646
  mxeProgram: mxeProgramId,
@@ -772,9 +656,12 @@ export async function initMxePart1(
772
656
  * @param provider - Anchor provider to use for transactions.
773
657
  * @param clusterOffset - Cluster offset to associate with the MXE.
774
658
  * @param mxeProgramId - Public key to use as the MXE program ID.
775
- * @param recoveryPeers - Array of 100 node offsets for recovery peers (0 for unused slots).
776
659
  * @param keygenOffset - Computation offset for the keygen computation.
777
660
  * @param keyRecoveryInitOffset - Computation offset for the key_recovery_init computation.
661
+ * @param recoveryPeers - Recovery peer node offsets. Slots set to 0 are treated as unused.
662
+ * The non-zero count must be either 0 (recovery disabled) or at least
663
+ * `MIN_RECOVERY_PEERS` (4). The array is padded with zeros up to
664
+ * `MAX_RECOVERY_PEERS` (100); passing more than that throws.
778
665
  * @param lutOffset - Lookup table offset for the MXE's address lookup table.
779
666
  * @param mxeAuthority - Optional authority for the MXE (defaults to provider.publicKey).
780
667
  * @param confirmOptions - Transaction confirmation options.
@@ -792,20 +679,10 @@ export async function initMxePart2(
792
679
  confirmOptions?: ConfirmOptions,
793
680
  ): Promise<string> {
794
681
  const program = getArciumProgram(provider);
795
- // Ensure recoveryPeers has exactly 100 elements
796
- const paddedRecoveryPeers = [...recoveryPeers];
797
- while (paddedRecoveryPeers.length < 100) {
798
- paddedRecoveryPeers.push(0);
799
- }
800
- if (paddedRecoveryPeers.length > 100) {
801
- throw new Error('recoveryPeers must have at most 100 elements');
802
- }
803
682
 
804
683
  const tx = await program.methods
805
684
  .initMxePart2(
806
685
  clusterOffset,
807
- mxeProgramId,
808
- paddedRecoveryPeers,
809
686
  keygenOffset,
810
687
  keyRecoveryInitOffset,
811
688
  lutOffset,
@@ -821,6 +698,14 @@ export async function initMxePart2(
821
698
  return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
822
699
  }
823
700
 
701
+ /**
702
+ * Reclaim the rent locked in a finished computation account.
703
+ * @param provider - Anchor provider to use for transactions.
704
+ * @param clusterOffset - Offset of the cluster that ran the computation.
705
+ * @param computationOffset - Offset of the computation whose rent is being claimed.
706
+ * @param confirmOptions - Transaction confirmation options.
707
+ * @returns Transaction signature.
708
+ */
824
709
  export async function claimComputationRent(
825
710
  provider: AnchorProvider,
826
711
  clusterOffset: number,