@arcium-hq/client 0.8.3 → 0.8.5

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/build/index.cjs CHANGED
@@ -1809,7 +1809,7 @@ function createPacker(fields, typeName = 'Packer') {
1809
1809
  var address = "Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ";
1810
1810
  var metadata = {
1811
1811
  name: "arcium",
1812
- version: "0.8.3",
1812
+ version: "0.8.5",
1813
1813
  spec: "0.1.0",
1814
1814
  description: "The Arcium program"
1815
1815
  };
@@ -6468,6 +6468,85 @@ var instructions = [
6468
6468
  }
6469
6469
  ]
6470
6470
  },
6471
+ {
6472
+ name: "init_recovery_peer_account",
6473
+ discriminator: [
6474
+ 116,
6475
+ 29,
6476
+ 20,
6477
+ 126,
6478
+ 177,
6479
+ 149,
6480
+ 50,
6481
+ 147
6482
+ ],
6483
+ accounts: [
6484
+ {
6485
+ name: "signer",
6486
+ writable: true,
6487
+ signer: true
6488
+ },
6489
+ {
6490
+ name: "recovery_peer_account",
6491
+ writable: true,
6492
+ pda: {
6493
+ seeds: [
6494
+ {
6495
+ kind: "const",
6496
+ value: [
6497
+ 82,
6498
+ 101,
6499
+ 99,
6500
+ 111,
6501
+ 118,
6502
+ 101,
6503
+ 114,
6504
+ 121,
6505
+ 80,
6506
+ 101,
6507
+ 101,
6508
+ 114,
6509
+ 65,
6510
+ 99,
6511
+ 99,
6512
+ 111,
6513
+ 117,
6514
+ 110,
6515
+ 116
6516
+ ]
6517
+ },
6518
+ {
6519
+ kind: "arg",
6520
+ path: "peer_offset"
6521
+ }
6522
+ ]
6523
+ }
6524
+ },
6525
+ {
6526
+ name: "system_program",
6527
+ address: "11111111111111111111111111111111"
6528
+ }
6529
+ ],
6530
+ args: [
6531
+ {
6532
+ name: "peer_offset",
6533
+ type: "u32"
6534
+ },
6535
+ {
6536
+ name: "authority",
6537
+ type: "pubkey"
6538
+ },
6539
+ {
6540
+ name: "x25519_pubkey",
6541
+ type: {
6542
+ array: [
6543
+ "u8",
6544
+ 32
6545
+ ]
6546
+ }
6547
+ }
6548
+ ]
6549
+ },
6471
6550
  {
6472
6551
  name: "join_cluster",
6473
6552
  discriminator: [
@@ -8840,29 +8919,41 @@ var instructions = [
8840
8919
  ],
8841
8920
  accounts: [
8842
8921
  {
8843
- name: "node_signer",
8922
+ name: "signer",
8844
8923
  writable: true,
8845
8924
  signer: true
8846
8925
  },
8847
8926
  {
8848
- name: "node",
8927
+ name: "recovery_peer_account",
8849
8928
  pda: {
8850
8929
  seeds: [
8851
8930
  {
8852
8931
  kind: "const",
8853
8932
  value: [
8854
- 65,
8933
+ 82,
8934
+ 101,
8935
+ 99,
8936
+ 111,
8937
+ 118,
8938
+ 101,
8855
8939
  114,
8856
- 120,
8857
- 78,
8940
+ 121,
8941
+ 80,
8942
+ 101,
8943
+ 101,
8944
+ 114,
8945
+ 65,
8946
+ 99,
8947
+ 99,
8858
8948
  111,
8859
- 100,
8860
- 101
8949
+ 117,
8950
+ 110,
8951
+ 116
8861
8952
  ]
8862
8953
  },
8863
8954
  {
8864
8955
  kind: "arg",
8865
- path: "node_offset"
8956
+ path: "peer_offset"
8866
8957
  }
8867
8958
  ]
8868
8959
  }
@@ -8987,7 +9078,7 @@ var instructions = [
8987
9078
  type: "pubkey"
8988
9079
  },
8989
9080
  {
8990
- name: "node_offset",
9081
+ name: "peer_offset",
8991
9082
  type: "u32"
8992
9083
  },
8993
9084
  {
@@ -9512,6 +9603,19 @@ var accounts = [
9512
9603
  183
9513
9604
  ]
9514
9605
  },
9606
+ {
9607
+ name: "RecoveryPeerAccount",
9608
+ discriminator: [
9609
+ 126,
9610
+ 243,
9611
+ 17,
9612
+ 238,
9613
+ 223,
9614
+ 222,
9615
+ 130,
9616
+ 120
9617
+ ]
9618
+ },
9515
9619
  {
9516
9620
  name: "SmallExecPool",
9517
9621
  discriminator: [
@@ -10483,7 +10587,7 @@ var types = [
10483
10587
  {
10484
10588
  name: "x25519_pubkey",
10485
10589
  docs: [
10486
- "X25519 public key for usage when being a key recovery peer. MUST BE AT byte index 8 - 40"
10590
+ "X25519 public key. MUST BE AT byte index 8 - 40"
10487
10591
  ],
10488
10592
  type: {
10489
10593
  array: [
@@ -12090,7 +12194,7 @@ var types = [
12090
12194
  {
12091
12195
  name: "ip",
12092
12196
  docs: [
12093
- "[Ipv4Addr], represented by it's 4 octects"
12197
+ "`Ipv4Addr`, represented by its 4 octets"
12094
12198
  ],
12095
12199
  type: {
12096
12200
  array: [
@@ -12505,6 +12609,38 @@ var types = [
12505
12609
  ]
12506
12610
  }
12507
12611
  },
12612
+ {
12613
+ name: "RecoveryPeerAccount",
12614
+ serialization: "bytemuck",
12615
+ repr: {
12616
+ kind: "c"
12617
+ },
12618
+ type: {
12619
+ kind: "struct",
12620
+ fields: [
12621
+ {
12622
+ name: "authority",
12623
+ type: "pubkey"
12624
+ },
12625
+ {
12626
+ name: "x25519_pubkey",
12627
+ docs: [
12628
+ "DO NOT PUT ANYTHING ELSE BEFORE THE X25519_PUBKEY FIELD, IT'S EXPECTED TO BE AT OFFSET 40."
12629
+ ],
12630
+ type: {
12631
+ array: [
12632
+ "u8",
12633
+ 32
12634
+ ]
12635
+ }
12636
+ },
12637
+ {
12638
+ name: "bump",
12639
+ type: "u8"
12640
+ }
12641
+ ]
12642
+ }
12643
+ },
12508
12644
  {
12509
12645
  name: "SetUnset",
12510
12646
  docs: [
@@ -13469,19 +13605,19 @@ async function getMXEUtilityKey(provider, mxeProgramId, field) {
13469
13605
  return null;
13470
13606
  }
13471
13607
  /**
13472
- * Fetches and extracts the MXE x25519 public key from the MXE account.
13608
+ * Fetches and extracts the MXE X25519 public key from the MXE account.
13473
13609
  * @param provider - The Anchor provider to use for fetching accounts.
13474
13610
  * @param mxeProgramId - The public key of the MXE program.
13475
- * @returns The MXE's x25519 public key as a Uint8Array, or null if not set.
13611
+ * @returns The MXE's X25519 public key as a Uint8Array, or null if not set.
13476
13612
  */
13477
13613
  async function getMXEPublicKey(provider, mxeProgramId) {
13478
13614
  return getMXEUtilityKey(provider, mxeProgramId, 'x25519Pubkey');
13479
13615
  }
13480
13616
  /**
13481
- * Fetches and extracts the MXE arcis ed25519 verifying key from the MXE account.
13617
+ * Fetches and extracts the MXE arcis Ed25519 verifying key from the MXE account.
13482
13618
  * @param provider - The Anchor provider to use for fetching accounts.
13483
13619
  * @param mxeProgramId - The public key of the MXE program.
13484
- * @returns The MXE's arcis ed25519 verifying key as a Uint8Array, or null if not set.
13620
+ * @returns The MXE's arcis Ed25519 verifying key as a Uint8Array, or null if not set.
13485
13621
  */
13486
13622
  async function getMXEArcisEd25519VerifyingKey(provider, mxeProgramId) {
13487
13623
  return getMXEUtilityKey(provider, mxeProgramId, 'ed25519VerifyingKey');
@@ -13511,7 +13647,7 @@ function getCircuitState(circuitSource) {
13511
13647
  * @param chunkSize - The number of upload transactions to send in parallel (default: 500).
13512
13648
  * @returns An array of transaction signatures for all upload and finalize transactions.
13513
13649
  */
13514
- async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, logging = true, chunkSize = 500) {
13650
+ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, logging = true, chunkSize = 500, confirmOptions) {
13515
13651
  const compDefAccInfo = getCompDefAccInfo(circuitName, mxeProgramId);
13516
13652
  const program = getArciumProgram(provider);
13517
13653
  const compDefAcc = await program.account.computationDefinitionAccount.fetch(compDefAccInfo.pubkey);
@@ -13526,11 +13662,11 @@ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, lo
13526
13662
  const sigs = [];
13527
13663
  const uploadPromises = [];
13528
13664
  for (let i = 0; i < numAccs; i++) {
13529
- uploadPromises.push(uploadToCircuitAcc(provider, program, rawCircuit.subarray(i * (MAX_ACCOUNT_SIZE - 9), (i + 1) * (MAX_ACCOUNT_SIZE - 9)), i, compDefAccInfo, mxeProgramId, logging, chunkSize));
13665
+ uploadPromises.push(uploadToCircuitAcc(provider, program, rawCircuit.subarray(i * (MAX_ACCOUNT_SIZE - 9), (i + 1) * (MAX_ACCOUNT_SIZE - 9)), i, compDefAccInfo, mxeProgramId, logging, chunkSize, confirmOptions));
13530
13666
  }
13531
13667
  sigs.push(...(await Promise.all(uploadPromises)).flat());
13532
13668
  const finalizeCompDefTx = await buildFinalizeCompDefTx(provider, compDefAccInfo.offset, mxeProgramId);
13533
- sigs.push(await signAndSendWithBlockhash(provider, finalizeCompDefTx, await provider.connection.getLatestBlockhash()));
13669
+ sigs.push(await signAndSendWithBlockhash(provider, finalizeCompDefTx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions));
13534
13670
  return sigs;
13535
13671
  }
13536
13672
  async function queueKeyRecoveryInit(provider, clusterOffset, mxeProgramId, confirmOptions) {
@@ -13564,7 +13700,7 @@ async function buildFinalizeCompDefTx(provider, compDefOffset, mxeProgramId) {
13564
13700
  })
13565
13701
  .transaction();
13566
13702
  }
13567
- async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitIndex, compDefAccInfo, mxeProgramId, shouldLog = true, chunkSize = 500) {
13703
+ async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitIndex, compDefAccInfo, mxeProgramId, shouldLog = true, chunkSize = 500, confirmOptions) {
13568
13704
  const rawCircuitPda = getRawCircuitAccAddress(compDefAccInfo.pubkey, rawCircuitIndex);
13569
13705
  const existingAcc = await provider.connection.getAccountInfo(rawCircuitPda);
13570
13706
  // Skip entirely if account exists with correct size (pre-seeded at genesis or already uploaded)
@@ -13594,10 +13730,10 @@ async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitI
13594
13730
  const tx = await buildResizeTx(program, provider.publicKey, compDefAccInfo, mxeProgramId, rawCircuitIndex, MAX_REALLOC_PER_IX
13595
13731
  + i * (MAX_REALLOC_PER_IX * MAX_EMBIGGEN_IX_PER_TX), rawCircuitPart.length);
13596
13732
  // eslint-disable-next-line no-await-in-loop
13597
- const blockInfo = await provider.connection.getLatestBlockhash();
13733
+ const blockInfo = await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' });
13598
13734
  sigs.push(
13599
13735
  // eslint-disable-next-line no-await-in-loop
13600
- await signAndSendWithBlockhash(provider, tx, blockInfo));
13736
+ await signAndSendWithBlockhash(provider, tx, blockInfo, confirmOptions));
13601
13737
  optionalLog(shouldLog, `Sent resize tx ${i} of ${nonAsyncTxCount}`);
13602
13738
  }
13603
13739
  }
@@ -13606,7 +13742,7 @@ async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitI
13606
13742
  const remainingTxCount = Math.ceil(rawCircuitPart.length / MAX_UPLOAD_PER_TX_BYTES);
13607
13743
  optionalLog(shouldLog, `Sending ${remainingTxCount} upload txs`);
13608
13744
  const remainingTxs = [];
13609
- const blockInfo = await provider.connection.getLatestBlockhash();
13745
+ const blockInfo = await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' });
13610
13746
  for (let i = 0; i < remainingTxCount; i += chunkSize) {
13611
13747
  optionalLog(shouldLog, `Sending chunk ${i / chunkSize + 1} of ${Math.ceil(remainingTxCount / chunkSize)}`);
13612
13748
  // Array to hold promises for the current chunk
@@ -13617,7 +13753,7 @@ async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitI
13617
13753
  const offset = MAX_UPLOAD_PER_TX_BYTES * (i + j);
13618
13754
  // eslint-disable-next-line no-await-in-loop
13619
13755
  const tx = await buildUploadCircuitTx(program, provider.publicKey, compDefAccInfo, mxeProgramId, Buffer.copyBytesFrom(rawCircuitPart, offset, MAX_UPLOAD_PER_TX_BYTES), offset, rawCircuitIndex);
13620
- chunkPromises.push(signAndSendWithBlockhash(provider, tx, blockInfo));
13756
+ chunkPromises.push(signAndSendWithBlockhash(provider, tx, blockInfo, confirmOptions));
13621
13757
  }
13622
13758
  // Wait for the current chunk to complete before proceeding
13623
13759
  // eslint-disable-next-line no-await-in-loop
@@ -13720,7 +13856,7 @@ function getCompDefAccPDA(arciumProgramId, mxeProgramId, offset) {
13720
13856
  * @param mxeProgramId - The public key of the MXE program to recover.
13721
13857
  * @returns The transaction signature.
13722
13858
  */
13723
- async function recoverMxe(provider, mxeProgramId) {
13859
+ async function recoverMxe(provider, mxeProgramId, confirmOptions) {
13724
13860
  const program = getArciumProgram(provider);
13725
13861
  const tx = await program.methods
13726
13862
  .recoverMxe(mxeProgramId)
@@ -13729,7 +13865,7 @@ async function recoverMxe(provider, mxeProgramId) {
13729
13865
  mxeProgram: mxeProgramId,
13730
13866
  })
13731
13867
  .transaction();
13732
- return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: 'confirmed' }));
13868
+ return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
13733
13869
  }
13734
13870
  /**
13735
13871
  * Initializes key recovery execution by creating the MxeRecoveryAccount and
@@ -13740,7 +13876,7 @@ async function recoverMxe(provider, mxeProgramId) {
13740
13876
  * @param backupMxeProgramId - The public key of the backup MXE program that will take over.
13741
13877
  * @returns The transaction signature from part2.
13742
13878
  */
13743
- async function initKeyRecoveryExecution(provider, originalMxeProgramId, backupMxeProgramId) {
13879
+ async function initKeyRecoveryExecution(provider, originalMxeProgramId, backupMxeProgramId, confirmOptions) {
13744
13880
  // Part 1: Create MxeRecoveryAccount with partial size
13745
13881
  const program = getArciumProgram(provider);
13746
13882
  const tx1 = await program.methods
@@ -13751,7 +13887,7 @@ async function initKeyRecoveryExecution(provider, originalMxeProgramId, backupMx
13751
13887
  backupMxeProgram: backupMxeProgramId,
13752
13888
  })
13753
13889
  .transaction();
13754
- await signAndSendWithBlockhash(provider, tx1, await provider.connection.getLatestBlockhash({ commitment: 'confirmed' }));
13890
+ await signAndSendWithBlockhash(provider, tx1, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
13755
13891
  // Part 2: Reallocate to full size and create computation definition
13756
13892
  const tx2 = await program.methods
13757
13893
  .initKeyRecoveryExecutionPart2(originalMxeProgramId, backupMxeProgramId)
@@ -13762,21 +13898,21 @@ async function initKeyRecoveryExecution(provider, originalMxeProgramId, backupMx
13762
13898
  backupMxeProgram: backupMxeProgramId,
13763
13899
  })
13764
13900
  .transaction();
13765
- return signAndSendWithBlockhash(provider, tx2, await provider.connection.getLatestBlockhash({ commitment: 'confirmed' }));
13901
+ return signAndSendWithBlockhash(provider, tx2, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
13766
13902
  }
13767
13903
  /**
13768
13904
  * Submits a re-encrypted key recovery share from a recovery peer.
13769
- * Recovery peers must decrypt shares using their X25519 private key and re-encrypt
13905
+ * Recovery peers must decrypt shares using their x25519 private key and re-encrypt
13770
13906
  * them for the backup MXE before submission.
13771
13907
  * @param provider - The Anchor provider to use for transactions.
13772
13908
  * @param originalMxeProgramId - The public key of the original MXE program being recovered.
13773
13909
  * @param backupMxeProgramId - The public key of the backup MXE program.
13774
- * @param nodeOffset - The ARX node offset of the recovery peer.
13910
+ * @param peerOffset - The offset of the recovery peer.
13775
13911
  * @param peerIndex - The index of this peer in the recovery peers list.
13776
13912
  * @param share - The re-encrypted share: 5 field elements of 32 bytes each (160 bytes total).
13777
13913
  * @returns The transaction signature.
13778
13914
  */
13779
- async function submitKeyRecoveryShare(provider, originalMxeProgramId, backupMxeProgramId, nodeOffset, peerIndex, share) {
13915
+ async function submitKeyRecoveryShare(provider, originalMxeProgramId, backupMxeProgramId, peerOffset, peerIndex, share, confirmOptions) {
13780
13916
  const program = getArciumProgram(provider);
13781
13917
  // Convert to array of 5 elements, each 32 bytes
13782
13918
  const shareArrays = share.map(elem => Array.from(elem));
@@ -13789,14 +13925,14 @@ async function submitKeyRecoveryShare(provider, originalMxeProgramId, backupMxeP
13789
13925
  }
13790
13926
  }
13791
13927
  const tx = await program.methods
13792
- .submitKeyRecoveryShare(originalMxeProgramId, backupMxeProgramId, nodeOffset, peerIndex, shareArrays)
13928
+ .submitKeyRecoveryShare(originalMxeProgramId, backupMxeProgramId, peerOffset, peerIndex, shareArrays)
13793
13929
  .accountsPartial({
13794
- nodeSigner: provider.publicKey,
13930
+ signer: provider.publicKey,
13795
13931
  originalMxeProgram: originalMxeProgramId,
13796
13932
  backupMxeProgram: backupMxeProgramId,
13797
13933
  })
13798
13934
  .transaction();
13799
- return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: 'confirmed' }));
13935
+ return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
13800
13936
  }
13801
13937
  /**
13802
13938
  * Finalizes key recovery execution after the submission threshold is met.
@@ -13808,7 +13944,7 @@ async function submitKeyRecoveryShare(provider, originalMxeProgramId, backupMxeP
13808
13944
  * @param keyRecoveryFinalizeOffset - The computation offset for the key_recovery_finalize computation.
13809
13945
  * @returns The transaction signature.
13810
13946
  */
13811
- async function finalizeKeyRecoveryExecution(provider, originalMxeProgramId, backupMxeProgramId, clusterOffset, keyRecoveryFinalizeOffset) {
13947
+ async function finalizeKeyRecoveryExecution(provider, originalMxeProgramId, backupMxeProgramId, clusterOffset, keyRecoveryFinalizeOffset, confirmOptions) {
13812
13948
  const program = getArciumProgram(provider);
13813
13949
  const tx = await program.methods
13814
13950
  .finalizeKeyRecoveryExecution(originalMxeProgramId, backupMxeProgramId, clusterOffset)
@@ -13822,7 +13958,7 @@ async function finalizeKeyRecoveryExecution(provider, originalMxeProgramId, back
13822
13958
  backupMxeProgram: backupMxeProgramId,
13823
13959
  })
13824
13960
  .transaction();
13825
- return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: 'confirmed' }));
13961
+ return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
13826
13962
  }
13827
13963
  /**
13828
13964
  * Initializes an MXE (part 1). Due to Solana's 10KB per-instruction allocation limit,
@@ -13832,7 +13968,7 @@ async function finalizeKeyRecoveryExecution(provider, originalMxeProgramId, back
13832
13968
  * @param mxeProgramId - The public key to use as the MXE program ID.
13833
13969
  * @returns The transaction signature.
13834
13970
  */
13835
- async function initMxePart1(provider, mxeProgramId) {
13971
+ async function initMxePart1(provider, mxeProgramId, confirmOptions) {
13836
13972
  const program = getArciumProgram(provider);
13837
13973
  const tx = await program.methods
13838
13974
  .initMxePart1()
@@ -13841,7 +13977,7 @@ async function initMxePart1(provider, mxeProgramId) {
13841
13977
  mxeProgram: mxeProgramId,
13842
13978
  })
13843
13979
  .transaction();
13844
- return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: 'confirmed' }));
13980
+ return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
13845
13981
  }
13846
13982
  /**
13847
13983
  * Finishes MXE initialization (part 2).
@@ -13856,7 +13992,7 @@ async function initMxePart1(provider, mxeProgramId) {
13856
13992
  * @param mxeAuthority - Optional authority for the MXE (defaults to provider.publicKey).
13857
13993
  * @returns The transaction signature.
13858
13994
  */
13859
- async function initMxePart2(provider, clusterOffset, mxeProgramId, recoveryPeers, keygenOffset, keyRecoveryInitOffset, lutOffset, mxeAuthority) {
13995
+ async function initMxePart2(provider, clusterOffset, mxeProgramId, recoveryPeers, keygenOffset, keyRecoveryInitOffset, lutOffset, mxeAuthority, confirmOptions) {
13860
13996
  const program = getArciumProgram(provider);
13861
13997
  // Ensure recoveryPeers has exactly 100 elements
13862
13998
  const paddedRecoveryPeers = [...recoveryPeers];
@@ -13876,7 +14012,7 @@ async function initMxePart2(provider, clusterOffset, mxeProgramId, recoveryPeers
13876
14012
  addressLookupTable: getLookupTableAddress(mxeProgramId, lutOffset),
13877
14013
  })
13878
14014
  .transaction();
13879
- return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: 'confirmed' }));
14015
+ return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
13880
14016
  }
13881
14017
 
13882
14018
  /**
@@ -13903,38 +14039,78 @@ function getArciumEnv() {
13903
14039
  }
13904
14040
  }
13905
14041
 
14042
+ const POLL_INTERVAL_MS = 500;
13906
14043
  /**
13907
- * Waits for the finalization of a computation by listening for the finalizeComputationEvent.
13908
- * Resolves with the transaction signature once the computation is finalized.
13909
- * @param provider - The Anchor provider to use for event listening.
13910
- * @param computationOffset - The offset of the computation to wait for.
13911
- * @param mxeProgramId - The public key of the MXE program.
13912
- * @param commitment - (Optional) The desired finality/commitment level (default: 'confirmed').
13913
- * @returns The transaction signature of the finalization event.
14044
+ * Waits for a computation to finalize by polling the computation account
14045
+ * status via HTTP RPC. Does not use WebSocket subscriptions.
14046
+ *
14047
+ * Polls every 500ms (same as Agave's send_and_confirm_transaction_with_config).
14048
+ * Returns the most recent transaction signature on the computation account
14049
+ * once finalization is detected.
14050
+ *
14051
+ * @param provider - The Anchor provider.
14052
+ * @param computationOffset - The computation offset to wait for.
14053
+ * @param mxeProgramId - The MXE program public key.
14054
+ * @param commitment - Commitment level for RPC calls (default: 'confirmed').
14055
+ * @param timeoutMs - Maximum wait time in milliseconds (default: 120000).
14056
+ * @returns The transaction signature from the finalization.
14057
+ * @throws Error if the MXE account has no cluster assigned.
14058
+ * @throws Error if the computation does not finalize within timeoutMs.
13914
14059
  */
13915
- async function awaitComputationFinalization(provider, computationOffset, mxeProgramId, commitment = 'confirmed') {
14060
+ async function awaitComputationFinalization(provider, computationOffset, mxeProgramId, commitment = 'confirmed', timeoutMs = 120_000) {
14061
+ const conn = provider.connection;
13916
14062
  const arciumProgram = getArciumProgram(provider);
13917
- const eventListener = new anchor.EventManager(arciumProgram.programId, provider, arciumProgram.coder);
13918
- const finalizeComp = await awaitEvent(eventListener, 'finalizeComputationEvent', (e) => mxeProgramId.equals(e.mxeProgramId) && e.computationOffset.eq(computationOffset), commitment);
13919
- return finalizeComp.sig;
13920
- }
13921
- /**
13922
- * Waits for a specific event to occur, matching a custom check, and returns the event and its signature.
13923
- * @param eventListener - The EventManager instance to use for listening.
13924
- * @param eventName - The name of the event to listen for.
13925
- * @param eventCheck - A predicate function to check if the event matches the desired criteria.
13926
- * @param commitment - (Optional) The desired finality/commitment level (default: 'confirmed').
13927
- * @returns An object containing the event and its transaction signature.
13928
- */
13929
- async function awaitEvent(eventListener, eventName, eventCheck, commitment = 'confirmed') {
13930
- const foundEvent = await new Promise((res) => {
13931
- const listenerId = eventListener.addEventListener(eventName, (event, _slot, signature) => {
13932
- if (eventCheck(event))
13933
- res([event, signature, listenerId]);
13934
- }, commitment);
13935
- });
13936
- await eventListener.removeEventListener(foundEvent[2]);
13937
- return { event: foundEvent[0], sig: foundEvent[1] };
14063
+ // Derive computation account PDA (requires clusterOffset from MXE account)
14064
+ const mxeAccAddress = getMXEAccAddress(mxeProgramId);
14065
+ const mxeAcc = await arciumProgram.account.mxeAccount.fetch(mxeAccAddress, commitment);
14066
+ if (mxeAcc.cluster === null) {
14067
+ throw new Error('MXE account has no cluster assigned');
14068
+ }
14069
+ const compAccAddress = getComputationAccAddress(mxeAcc.cluster, computationOffset);
14070
+ const startTime = Date.now();
14071
+ let lastStatus = 'unknown';
14072
+ let rpcErrorCount = 0;
14073
+ let lastError;
14074
+ while (Date.now() - startTime < timeoutMs) {
14075
+ let compAcc;
14076
+ try {
14077
+ // eslint-disable-next-line no-await-in-loop
14078
+ compAcc = await arciumProgram.account.computationAccount.fetchNullable(compAccAddress, commitment);
14079
+ }
14080
+ catch (e) {
14081
+ rpcErrorCount++;
14082
+ lastError = e instanceof Error ? e.message : String(e);
14083
+ // eslint-disable-next-line no-await-in-loop
14084
+ await new Promise((r) => {
14085
+ setTimeout(r, POLL_INTERVAL_MS);
14086
+ });
14087
+ continue;
14088
+ }
14089
+ if (compAcc !== null && 'finalized' in compAcc.status) {
14090
+ lastStatus = 'finalized';
14091
+ for (let sigRetry = 0; sigRetry < 10; sigRetry++) {
14092
+ // eslint-disable-next-line no-await-in-loop
14093
+ const sigs = await conn.getSignaturesForAddress(compAccAddress, { limit: 1 }, commitment);
14094
+ if (sigs.length > 0)
14095
+ return sigs[0].signature;
14096
+ // eslint-disable-next-line no-await-in-loop
14097
+ await new Promise((r) => {
14098
+ setTimeout(r, POLL_INTERVAL_MS);
14099
+ });
14100
+ }
14101
+ throw new Error('Computation finalized but transaction signature not indexed after retries.');
14102
+ }
14103
+ if (compAcc !== null)
14104
+ lastStatus = 'queued';
14105
+ // eslint-disable-next-line no-await-in-loop
14106
+ await new Promise((r) => {
14107
+ setTimeout(r, POLL_INTERVAL_MS);
14108
+ });
14109
+ }
14110
+ const timeoutMsg = `Computation did not finalize within ${timeoutMs}ms (status: ${lastStatus})`;
14111
+ throw rpcErrorCount > 0
14112
+ ? new Error(timeoutMsg, { cause: new Error(`${rpcErrorCount} RPC errors, last: ${lastError}`) })
14113
+ : new Error(timeoutMsg);
13938
14114
  }
13939
14115
 
13940
14116
  Object.defineProperty(exports, "x25519", {