@arcium-hq/reader 0.3.0 → 0.5.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 CHANGED
@@ -18,12 +18,12 @@ pnpm add @arcium-hq/reader
18
18
 
19
19
  ```typescript
20
20
  import * as anchor from "@coral-xyz/anchor";
21
- import { getArciumProgramReadonly } from "@arcium-hq/reader";
21
+ import { getArciumProgram } from "@arcium-hq/reader";
22
22
 
23
23
  // Setup connection (no wallet required)
24
24
  const connection = new anchor.web3.Connection("https://api.mainnet-beta.solana.com");
25
25
  const provider = new anchor.AnchorProvider(connection, null, {});
26
- const arciumProgram = getArciumProgramReadonly(provider);
26
+ const arciumProgram = getArciumProgram(provider);
27
27
  ```
28
28
 
29
29
  ### 2. Query Account Information
@@ -288,6 +288,6 @@ if (tx) {
288
288
 
289
289
  ## API Reference
290
290
 
291
- <!-- TODO: Add API reference url -->
292
-
293
- For detailed API documentation, please refer to the [Arcium TypeScript SDK API reference](https://github.com/arcium-hq).
291
+ - **[API Reference](https://ts.arcium.com/api)** - Complete API documentation
292
+ - **[Developer Docs](https://docs.arcium.com/developers/js-client-library)** - Guides and tutorials
293
+ - **[Examples](https://github.com/arcium-hq/examples)** - Code examples
package/build/index.cjs CHANGED
@@ -22,7 +22,26 @@ function _interopNamespaceDefault(e) {
22
22
 
23
23
  var anchor__namespace = /*#__PURE__*/_interopNamespaceDefault(anchor);
24
24
 
25
- const ARCIUM_PROGRAM_ID_STRING = 'BKck65TgoKRokMjQM3datB9oRwJ8rAj2jxPXvHXUvcL6';
25
+ /**
26
+ * Prefix for program data logs in Solana transaction logs.
27
+ * @constant {string}
28
+ */
29
+ const PROGRAM_DATA_PREFIX = 'Program data: ';
30
+ /**
31
+ * Prefix for program log messages in Solana transaction logs.
32
+ * @constant {string}
33
+ */
34
+ const PROGRAM_LOG_PREFIX = 'Program log: ';
35
+ /**
36
+ * Valid Arcium event names for computation lifecycle tracking.
37
+ * @constant {ArciumEventName[]}
38
+ */
39
+ const ARCIUM_EVENT_NAMES = [
40
+ 'QueueComputationEvent',
41
+ 'InitComputationEvent',
42
+ 'CallbackComputationEvent',
43
+ 'FinalizeComputationEvent',
44
+ ];
26
45
  /**
27
46
  * Discriminator for the ArxNode account type. Used to filter and identify ArxNode accounts on-chain.
28
47
  */
@@ -38,7 +57,7 @@ const MXE_ACC_DISCRIMINATOR = [103, 26, 85, 250, 179, 159, 17, 117];
38
57
  /**
39
58
  * The public key of the deployed Arcium program on Solana.
40
59
  */
41
- const ARCIUM_PROGRAM_ID = new anchor__namespace.web3.PublicKey(ARCIUM_PROGRAM_ID_STRING);
60
+ const ARCIUM_PROGRAM_ID = new anchor__namespace.web3.PublicKey(client.ARCIUM_ADDR);
42
61
  /**
43
62
  * Anchor coder for encoding and decoding Arcium program instructions.
44
63
  */
@@ -46,7 +65,12 @@ new anchor__namespace.BorshInstructionCoder(client.ARCIUM_IDL);
46
65
  /**
47
66
  * Anchor event parser for parsing Arcium program events from transaction logs.
48
67
  */
49
- const ARCIUM_EVENT_CODER = new anchor__namespace.EventParser(ARCIUM_PROGRAM_ID, new anchor__namespace.BorshCoder(client.ARCIUM_IDL));
68
+ new anchor__namespace.EventParser(ARCIUM_PROGRAM_ID, new anchor__namespace.BorshCoder(client.ARCIUM_IDL));
69
+ /**
70
+ * BorshCoder instance for decoding Arcium events.
71
+ * Used directly instead of accessing EventParser's private coder property.
72
+ */
73
+ const ARCIUM_BORSH_CODER = new anchor__namespace.BorshCoder(client.ARCIUM_IDL);
50
74
 
51
75
  /**
52
76
  * Returns all MXE account addresses.
@@ -112,40 +136,6 @@ async function getArxNodeAccInfo(arciumProgram, address, commitment) {
112
136
  async function getCompDefAccInfo(arciumProgram, address, commitment) {
113
137
  return arciumProgram.account.computationDefinitionAccount.fetch(address, commitment);
114
138
  }
115
- /**
116
- * Returns all computation references in the mempool for a given account.
117
- * Only non-stake computations are included.
118
- * @param arciumProgram - The Anchor program instance.
119
- * @param address - The public key of the mempool account.
120
- * @returns Array of ComputationReference objects.
121
- */
122
- async function getComputationsInMempool(arciumProgram, address) {
123
- const mempool = await client.getMempoolAccData(arciumProgram.provider, address);
124
- const startIndex = mempool.inner.computations.startIndex;
125
- const length = mempool.inner.computations.length;
126
- const elems = mempool.inner.computations.elems;
127
- function isValid(validBits, idx) {
128
- const byte = idx >>> 3;
129
- const bit = idx & 7;
130
- if (byte >= validBits.length) {
131
- // This should never happen, so we'll want to know about it
132
- throw new Error(`isValid: byte ${byte} >= validBits.length ${validBits.length}`);
133
- }
134
- return (validBits[byte] & (1 << bit)) !== 0;
135
- }
136
- // Handle circular buffer wraparound
137
- const refs = [];
138
- for (let i = 0; i < length; i++) {
139
- const idx = (startIndex + i) % elems.length;
140
- // Only save non-stake computations
141
- if (isValid(mempool.inner.computations.validBits, idx)) {
142
- refs.push(...elems[idx].entries);
143
- }
144
- }
145
- return refs
146
- .flat()
147
- .filter((ref) => !isNullRef(ref));
148
- }
149
139
  /**
150
140
  * Fetches and parses a given Computation account.
151
141
  * @param arciumProgram - The Anchor program instance.
@@ -171,19 +161,7 @@ async function getArciumAccPubkeys(conn, discriminator) {
171
161
  });
172
162
  return accs.map((acc) => acc.pubkey);
173
163
  }
174
- function isNullRef(ref) {
175
- const bigZero = new anchor__namespace.BN(0);
176
- return (ref.computationDefinitionOffset === 0
177
- && ref.computationOffset === bigZero
178
- && ref.priorityFee === bigZero);
179
- }
180
164
 
181
- const ArciumEventNames = [
182
- 'QueueComputationEvent',
183
- 'InitComputationEvent',
184
- 'CallbackComputationEvent',
185
- 'FinalizeComputationEvent',
186
- ];
187
165
  /**
188
166
  * Subscribes to computation-related events for a given MXE program ID.
189
167
  * @param conn - The Solana connection object.
@@ -227,13 +205,53 @@ function getComputationOffset(tx) {
227
205
  }
228
206
  /**
229
207
  * Get the events related to arcium computations from a transaction's logs
208
+ *
209
+ * Note: This implements a direct decode approach instead of using Anchor's EventParser.parseLogs().
210
+ *
211
+ * BREAKING CHANGE IN ANCHOR v0.32.0 (PR #3657, commit 34b6d19):
212
+ * EventParser.parseLogs was hardened to prevent malicious log injection attacks. It now:
213
+ * 1. Requires the first log to match "Program X invoke [1]" (root invocation)
214
+ * 2. Pre-seeds the execution stack with program X from the first log
215
+ * 3. Only parses events when execution.program() === EventParser.programId
216
+ *
217
+ * This breaks our use case:
218
+ * - We subscribe to MXE program logs (line 29) via conn.onLogs(mxeProgramId, ...)
219
+ * - But we need to parse Arcium events emitted during MXE→Arcium CPI calls
220
+ * - When MXE is the root program, execution.program() = MXE_PROGRAM_ID
221
+ * - EventParser expects execution.program() = ARCIUM_PROGRAM_ID
222
+ * - Result: All Arcium events are silently skipped
223
+ *
224
+ * Our discriminator-based approach:
225
+ * - Scans all logs for "Program data:" and "Program log:" prefixes
226
+ * - Uses event discriminators to identify valid Arcium events (no program context check)
227
+ * - Works regardless of which program is root or subscription target
228
+ * - Handles both MXE→Arcium and Arcium→MXE CPI patterns
229
+ *
230
230
  * @param logs - The logs to get the events from
231
231
  * @returns The events in the logs.
232
232
  */
233
233
  function getComputationEventsFromLogs(logs) {
234
- return Array.from(ARCIUM_EVENT_CODER.parseLogs(logs))
235
- .filter((e) => ArciumEventNames.includes(e.name))
236
- .map((e) => {
234
+ const events = [];
235
+ // Scan all event logs and rely on discriminators to identify valid Arcium events.
236
+ // This works for both MXE→Arcium CPI and Arcium→MXE CPI transactions.
237
+ for (const log of logs) {
238
+ if (log.startsWith(PROGRAM_DATA_PREFIX)) {
239
+ const eventData = log.slice(PROGRAM_DATA_PREFIX.length);
240
+ const decoded = ARCIUM_BORSH_CODER.events.decode(eventData);
241
+ if (decoded && ARCIUM_EVENT_NAMES.includes(decoded.name)) {
242
+ events.push(decoded);
243
+ }
244
+ }
245
+ else if (log.startsWith(PROGRAM_LOG_PREFIX)) {
246
+ const eventData = log.slice(PROGRAM_LOG_PREFIX.length);
247
+ const decoded = ARCIUM_BORSH_CODER.events.decode(eventData);
248
+ if (decoded && ARCIUM_EVENT_NAMES.includes(decoded.name)) {
249
+ events.push(decoded);
250
+ }
251
+ }
252
+ }
253
+ // Map to existing return format
254
+ return events.map((e) => {
237
255
  const eventData = {
238
256
  computationOffset: e.data.computation_offset,
239
257
  ...e.data,
@@ -248,9 +266,9 @@ function getComputationEventsFromLogs(logs) {
248
266
  });
249
267
  }
250
268
 
251
- Object.defineProperty(exports, "getArciumProgramReadonly", {
269
+ Object.defineProperty(exports, "getArciumProgram", {
252
270
  enumerable: true,
253
- get: function () { return client.getArciumProgramReadonly; }
271
+ get: function () { return client.getArciumProgram; }
254
272
  });
255
273
  Object.defineProperty(exports, "getArxNodeAccAddress", {
256
274
  enumerable: true,
@@ -272,10 +290,18 @@ Object.defineProperty(exports, "getComputationAccAddress", {
272
290
  enumerable: true,
273
291
  get: function () { return client.getComputationAccAddress; }
274
292
  });
293
+ Object.defineProperty(exports, "getComputationsInMempool", {
294
+ enumerable: true,
295
+ get: function () { return client.getComputationsInMempool; }
296
+ });
275
297
  Object.defineProperty(exports, "getExecutingPoolAccAddress", {
276
298
  enumerable: true,
277
299
  get: function () { return client.getExecutingPoolAccAddress; }
278
300
  });
301
+ Object.defineProperty(exports, "getFeePoolAccAddress", {
302
+ enumerable: true,
303
+ get: function () { return client.getFeePoolAccAddress; }
304
+ });
279
305
  Object.defineProperty(exports, "getMXEAccAddress", {
280
306
  enumerable: true,
281
307
  get: function () { return client.getMXEAccAddress; }
@@ -284,9 +310,9 @@ Object.defineProperty(exports, "getMempoolAccAddress", {
284
310
  enumerable: true,
285
311
  get: function () { return client.getMempoolAccAddress; }
286
312
  });
287
- Object.defineProperty(exports, "getStakingPoolAccAddress", {
313
+ Object.defineProperty(exports, "getMempoolPriorityFeeStats", {
288
314
  enumerable: true,
289
- get: function () { return client.getStakingPoolAccAddress; }
315
+ get: function () { return client.getMempoolPriorityFeeStats; }
290
316
  });
291
317
  exports.getArxNodeAccAddresses = getArxNodeAccAddresses;
292
318
  exports.getArxNodeAccInfo = getArxNodeAccInfo;
@@ -295,7 +321,6 @@ exports.getClusterAccInfo = getClusterAccInfo;
295
321
  exports.getCompDefAccInfo = getCompDefAccInfo;
296
322
  exports.getComputationAccInfo = getComputationAccInfo;
297
323
  exports.getComputationOffset = getComputationOffset;
298
- exports.getComputationsInMempool = getComputationsInMempool;
299
324
  exports.getMXEAccAddresses = getMXEAccAddresses;
300
325
  exports.getMXEAccInfo = getMXEAccInfo;
301
326
  exports.subscribeComputations = subscribeComputations;
package/build/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ArciumIdlType } from '@arcium-hq/client';
2
- export { getArciumProgramReadonly, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getComputationAccAddress, getExecutingPoolAccAddress, getMXEAccAddress, getMempoolAccAddress, getStakingPoolAccAddress } from '@arcium-hq/client';
2
+ export { getArciumProgram, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getFeePoolAccAddress, getMXEAccAddress, getMempoolAccAddress, getMempoolPriorityFeeStats } from '@arcium-hq/client';
3
3
  import * as anchor from '@coral-xyz/anchor';
4
4
 
5
5
  /**
@@ -7,9 +7,21 @@ import * as anchor from '@coral-xyz/anchor';
7
7
  * Many types are derived from the Anchor-generated IDL and are used throughout the reader package.
8
8
  */
9
9
 
10
+ /**
11
+ * Solana PublicKey type alias for convenience.
12
+ */
10
13
  type PublicKey = anchor.web3.PublicKey;
14
+ /**
15
+ * Solana Connection type alias for convenience.
16
+ */
11
17
  type Connection = anchor.web3.Connection;
18
+ /**
19
+ * Anchor Program type alias with generic IDL support.
20
+ */
12
21
  type Program<T extends anchor.Idl> = anchor.Program<T>;
22
+ /**
23
+ * Arcium IDL types derived from the Arcium program interface.
24
+ */
13
25
  type ArciumTypes = anchor.IdlTypes<ArciumIdlType>;
14
26
  /**
15
27
  * All events emitted by the Arcium program, keyed by event name.
@@ -23,15 +35,42 @@ type ArciumEventName = Capitalize<keyof ArciumEvent>;
23
35
  * Data structure for any Arcium event, as parsed from logs.
24
36
  */
25
37
  type ArciumEventData = ArciumEvent[keyof ArciumEvent];
38
+ /**
39
+ * MXE (Multi-party eXecution Environment) account data structure.
40
+ */
26
41
  type MXEAccount = ArciumTypes['mxeAccount'];
42
+ /**
43
+ * Cluster account data structure containing node information.
44
+ */
27
45
  type ClusterAccount = ArciumTypes['cluster'];
46
+ /**
47
+ * ArxNode account data structure for individual computation nodes.
48
+ */
28
49
  type ArxNodeAccount = ArciumTypes['arxNode'];
50
+ /**
51
+ * Computation account data structure tracking computation state.
52
+ */
29
53
  type ComputationAccount = ArciumTypes['computationAccount'];
54
+ /**
55
+ * Reference to a computation in a mempool or executing pool.
56
+ */
30
57
  type ComputationReference = ArciumTypes['computationReference'];
58
+ /**
59
+ * Computation definition account containing circuit configuration.
60
+ */
31
61
  type ComputationDefinitionAccount = ArciumTypes['computationDefinitionAccount'];
32
- type QueueComputationIx = ArciumIdlType['instructions']['23'];
62
+ /**
63
+ * Queue computation instruction type from the Arcium IDL.
64
+ */
65
+ type QueueComputationIx = ArciumIdlType['instructions']['26'];
66
+ /**
67
+ * Callback computation instruction type from the Arcium IDL.
68
+ */
33
69
  type CallbackComputationIx = ArciumIdlType['instructions']['3'];
34
- type FinalizeComputationIx = ArciumIdlType['instructions']['8'];
70
+ /**
71
+ * Valid instruction names from the Arcium IDL.
72
+ */
73
+ type ArciumInstructionName = ArciumIdlType['instructions'][number]['name'];
35
74
  /**
36
75
  * Status values for a computation, as defined by the Arcium protocol.
37
76
  */
@@ -87,14 +126,6 @@ declare function getArxNodeAccInfo(arciumProgram: anchor.Program<ArciumIdlType>,
87
126
  * @returns The ComputationDefinitionAccount object.
88
127
  */
89
128
  declare function getCompDefAccInfo(arciumProgram: anchor.Program<ArciumIdlType>, address: PublicKey, commitment?: anchor.web3.Commitment): Promise<ComputationDefinitionAccount>;
90
- /**
91
- * Returns all computation references in the mempool for a given account.
92
- * Only non-stake computations are included.
93
- * @param arciumProgram - The Anchor program instance.
94
- * @param address - The public key of the mempool account.
95
- * @returns Array of ComputationReference objects.
96
- */
97
- declare function getComputationsInMempool(arciumProgram: anchor.Program<ArciumIdlType>, address: PublicKey): Promise<ComputationReference[]>;
98
129
  /**
99
130
  * Fetches and parses a given Computation account.
100
131
  * @param arciumProgram - The Anchor program instance.
@@ -126,5 +157,5 @@ declare function unsubscribeComputations(conn: Connection, subscriptionId: numbe
126
157
  */
127
158
  declare function getComputationOffset(tx: anchor.web3.VersionedTransactionResponse): anchor.BN | undefined;
128
159
 
129
- export { getArxNodeAccAddresses, getArxNodeAccInfo, getClusterAccAddresses, getClusterAccInfo, getCompDefAccInfo, getComputationAccInfo, getComputationOffset, getComputationsInMempool, getMXEAccAddresses, getMXEAccInfo, subscribeComputations, unsubscribeComputations };
130
- export type { ArciumEvent, ArciumEventData, ArciumEventName, ArciumTypes, ArxNodeAccount, CallbackComputationIx, ClusterAccount, ComputationAccount, ComputationDefinitionAccount, ComputationReference, ComputationStatus, Connection, FinalizeComputationIx, MXEAccount, Program, PublicKey, QueueComputationIx };
160
+ export { getArxNodeAccAddresses, getArxNodeAccInfo, getClusterAccAddresses, getClusterAccInfo, getCompDefAccInfo, getComputationAccInfo, getComputationOffset, getMXEAccAddresses, getMXEAccInfo, subscribeComputations, unsubscribeComputations };
161
+ export type { ArciumEvent, ArciumEventData, ArciumEventName, ArciumInstructionName, ArciumTypes, ArxNodeAccount, CallbackComputationIx, ClusterAccount, ComputationAccount, ComputationDefinitionAccount, ComputationReference, ComputationStatus, Connection, MXEAccount, Program, PublicKey, QueueComputationIx };
package/build/index.mjs CHANGED
@@ -1,8 +1,27 @@
1
- import { ARCIUM_IDL, getMempoolAccData } from '@arcium-hq/client';
2
- export { getArciumProgramReadonly, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getComputationAccAddress, getExecutingPoolAccAddress, getMXEAccAddress, getMempoolAccAddress, getStakingPoolAccAddress } from '@arcium-hq/client';
1
+ import { ARCIUM_ADDR, ARCIUM_IDL } from '@arcium-hq/client';
2
+ export { getArciumProgram, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getFeePoolAccAddress, getMXEAccAddress, getMempoolAccAddress, getMempoolPriorityFeeStats } from '@arcium-hq/client';
3
3
  import * as anchor from '@coral-xyz/anchor';
4
4
 
5
- const ARCIUM_PROGRAM_ID_STRING = 'BKck65TgoKRokMjQM3datB9oRwJ8rAj2jxPXvHXUvcL6';
5
+ /**
6
+ * Prefix for program data logs in Solana transaction logs.
7
+ * @constant {string}
8
+ */
9
+ const PROGRAM_DATA_PREFIX = 'Program data: ';
10
+ /**
11
+ * Prefix for program log messages in Solana transaction logs.
12
+ * @constant {string}
13
+ */
14
+ const PROGRAM_LOG_PREFIX = 'Program log: ';
15
+ /**
16
+ * Valid Arcium event names for computation lifecycle tracking.
17
+ * @constant {ArciumEventName[]}
18
+ */
19
+ const ARCIUM_EVENT_NAMES = [
20
+ 'QueueComputationEvent',
21
+ 'InitComputationEvent',
22
+ 'CallbackComputationEvent',
23
+ 'FinalizeComputationEvent',
24
+ ];
6
25
  /**
7
26
  * Discriminator for the ArxNode account type. Used to filter and identify ArxNode accounts on-chain.
8
27
  */
@@ -18,7 +37,7 @@ const MXE_ACC_DISCRIMINATOR = [103, 26, 85, 250, 179, 159, 17, 117];
18
37
  /**
19
38
  * The public key of the deployed Arcium program on Solana.
20
39
  */
21
- const ARCIUM_PROGRAM_ID = new anchor.web3.PublicKey(ARCIUM_PROGRAM_ID_STRING);
40
+ const ARCIUM_PROGRAM_ID = new anchor.web3.PublicKey(ARCIUM_ADDR);
22
41
  /**
23
42
  * Anchor coder for encoding and decoding Arcium program instructions.
24
43
  */
@@ -26,7 +45,12 @@ new anchor.BorshInstructionCoder(ARCIUM_IDL);
26
45
  /**
27
46
  * Anchor event parser for parsing Arcium program events from transaction logs.
28
47
  */
29
- const ARCIUM_EVENT_CODER = new anchor.EventParser(ARCIUM_PROGRAM_ID, new anchor.BorshCoder(ARCIUM_IDL));
48
+ new anchor.EventParser(ARCIUM_PROGRAM_ID, new anchor.BorshCoder(ARCIUM_IDL));
49
+ /**
50
+ * BorshCoder instance for decoding Arcium events.
51
+ * Used directly instead of accessing EventParser's private coder property.
52
+ */
53
+ const ARCIUM_BORSH_CODER = new anchor.BorshCoder(ARCIUM_IDL);
30
54
 
31
55
  /**
32
56
  * Returns all MXE account addresses.
@@ -92,40 +116,6 @@ async function getArxNodeAccInfo(arciumProgram, address, commitment) {
92
116
  async function getCompDefAccInfo(arciumProgram, address, commitment) {
93
117
  return arciumProgram.account.computationDefinitionAccount.fetch(address, commitment);
94
118
  }
95
- /**
96
- * Returns all computation references in the mempool for a given account.
97
- * Only non-stake computations are included.
98
- * @param arciumProgram - The Anchor program instance.
99
- * @param address - The public key of the mempool account.
100
- * @returns Array of ComputationReference objects.
101
- */
102
- async function getComputationsInMempool(arciumProgram, address) {
103
- const mempool = await getMempoolAccData(arciumProgram.provider, address);
104
- const startIndex = mempool.inner.computations.startIndex;
105
- const length = mempool.inner.computations.length;
106
- const elems = mempool.inner.computations.elems;
107
- function isValid(validBits, idx) {
108
- const byte = idx >>> 3;
109
- const bit = idx & 7;
110
- if (byte >= validBits.length) {
111
- // This should never happen, so we'll want to know about it
112
- throw new Error(`isValid: byte ${byte} >= validBits.length ${validBits.length}`);
113
- }
114
- return (validBits[byte] & (1 << bit)) !== 0;
115
- }
116
- // Handle circular buffer wraparound
117
- const refs = [];
118
- for (let i = 0; i < length; i++) {
119
- const idx = (startIndex + i) % elems.length;
120
- // Only save non-stake computations
121
- if (isValid(mempool.inner.computations.validBits, idx)) {
122
- refs.push(...elems[idx].entries);
123
- }
124
- }
125
- return refs
126
- .flat()
127
- .filter((ref) => !isNullRef(ref));
128
- }
129
119
  /**
130
120
  * Fetches and parses a given Computation account.
131
121
  * @param arciumProgram - The Anchor program instance.
@@ -151,19 +141,7 @@ async function getArciumAccPubkeys(conn, discriminator) {
151
141
  });
152
142
  return accs.map((acc) => acc.pubkey);
153
143
  }
154
- function isNullRef(ref) {
155
- const bigZero = new anchor.BN(0);
156
- return (ref.computationDefinitionOffset === 0
157
- && ref.computationOffset === bigZero
158
- && ref.priorityFee === bigZero);
159
- }
160
144
 
161
- const ArciumEventNames = [
162
- 'QueueComputationEvent',
163
- 'InitComputationEvent',
164
- 'CallbackComputationEvent',
165
- 'FinalizeComputationEvent',
166
- ];
167
145
  /**
168
146
  * Subscribes to computation-related events for a given MXE program ID.
169
147
  * @param conn - The Solana connection object.
@@ -207,13 +185,53 @@ function getComputationOffset(tx) {
207
185
  }
208
186
  /**
209
187
  * Get the events related to arcium computations from a transaction's logs
188
+ *
189
+ * Note: This implements a direct decode approach instead of using Anchor's EventParser.parseLogs().
190
+ *
191
+ * BREAKING CHANGE IN ANCHOR v0.32.0 (PR #3657, commit 34b6d19):
192
+ * EventParser.parseLogs was hardened to prevent malicious log injection attacks. It now:
193
+ * 1. Requires the first log to match "Program X invoke [1]" (root invocation)
194
+ * 2. Pre-seeds the execution stack with program X from the first log
195
+ * 3. Only parses events when execution.program() === EventParser.programId
196
+ *
197
+ * This breaks our use case:
198
+ * - We subscribe to MXE program logs (line 29) via conn.onLogs(mxeProgramId, ...)
199
+ * - But we need to parse Arcium events emitted during MXE→Arcium CPI calls
200
+ * - When MXE is the root program, execution.program() = MXE_PROGRAM_ID
201
+ * - EventParser expects execution.program() = ARCIUM_PROGRAM_ID
202
+ * - Result: All Arcium events are silently skipped
203
+ *
204
+ * Our discriminator-based approach:
205
+ * - Scans all logs for "Program data:" and "Program log:" prefixes
206
+ * - Uses event discriminators to identify valid Arcium events (no program context check)
207
+ * - Works regardless of which program is root or subscription target
208
+ * - Handles both MXE→Arcium and Arcium→MXE CPI patterns
209
+ *
210
210
  * @param logs - The logs to get the events from
211
211
  * @returns The events in the logs.
212
212
  */
213
213
  function getComputationEventsFromLogs(logs) {
214
- return Array.from(ARCIUM_EVENT_CODER.parseLogs(logs))
215
- .filter((e) => ArciumEventNames.includes(e.name))
216
- .map((e) => {
214
+ const events = [];
215
+ // Scan all event logs and rely on discriminators to identify valid Arcium events.
216
+ // This works for both MXE→Arcium CPI and Arcium→MXE CPI transactions.
217
+ for (const log of logs) {
218
+ if (log.startsWith(PROGRAM_DATA_PREFIX)) {
219
+ const eventData = log.slice(PROGRAM_DATA_PREFIX.length);
220
+ const decoded = ARCIUM_BORSH_CODER.events.decode(eventData);
221
+ if (decoded && ARCIUM_EVENT_NAMES.includes(decoded.name)) {
222
+ events.push(decoded);
223
+ }
224
+ }
225
+ else if (log.startsWith(PROGRAM_LOG_PREFIX)) {
226
+ const eventData = log.slice(PROGRAM_LOG_PREFIX.length);
227
+ const decoded = ARCIUM_BORSH_CODER.events.decode(eventData);
228
+ if (decoded && ARCIUM_EVENT_NAMES.includes(decoded.name)) {
229
+ events.push(decoded);
230
+ }
231
+ }
232
+ }
233
+ // Map to existing return format
234
+ return events.map((e) => {
217
235
  const eventData = {
218
236
  computationOffset: e.data.computation_offset,
219
237
  ...e.data,
@@ -228,4 +246,4 @@ function getComputationEventsFromLogs(logs) {
228
246
  });
229
247
  }
230
248
 
231
- export { getArxNodeAccAddresses, getArxNodeAccInfo, getClusterAccAddresses, getClusterAccInfo, getCompDefAccInfo, getComputationAccInfo, getComputationOffset, getComputationsInMempool, getMXEAccAddresses, getMXEAccInfo, subscribeComputations, unsubscribeComputations };
249
+ export { getArxNodeAccAddresses, getArxNodeAccInfo, getClusterAccAddresses, getClusterAccInfo, getCompDefAccInfo, getComputationAccInfo, getComputationOffset, getMXEAccAddresses, getMXEAccInfo, subscribeComputations, unsubscribeComputations };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcium-hq/reader",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Reader SDK for fetching onchain data for Arcium network programs",
5
5
  "author": "Arcium",
6
6
  "license": "GPL-3.0-only",
@@ -31,10 +31,7 @@
31
31
  "require": "./build/index.cjs"
32
32
  }
33
33
  ],
34
- "repository": {
35
- "type": "git",
36
- "url": "https://github.com/arcium-hq/arcium-tooling.git"
37
- },
34
+ "homepage": "https://ts.arcium.com",
38
35
  "devDependencies": {
39
36
  "@rollup/plugin-json": "^6.1.0",
40
37
  "@rollup/plugin-typescript": "^12.1.1",
@@ -57,10 +54,10 @@
57
54
  "typescript-eslint": "^8.15.0"
58
55
  },
59
56
  "dependencies": {
60
- "@coral-xyz/anchor": "^0.31.1",
57
+ "@coral-xyz/anchor": "^0.32.1",
61
58
  "@noble/curves": "^1.9.5",
62
59
  "@noble/hashes": "^1.7.1",
63
- "@arcium-hq/client": "0.3.0"
60
+ "@arcium-hq/client": "0.5.0"
64
61
  },
65
62
  "keywords": [
66
63
  "Cryptography",