UNPKG

@arcium-hq/reader

Version:

Reader SDK for fetching onchain data for Arcium network programs

303 lines (295 loc) 11.4 kB
'use strict'; var client = require('@arcium-hq/client'); var anchor = require('@coral-xyz/anchor'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var anchor__namespace = /*#__PURE__*/_interopNamespaceDefault(anchor); const ARCIUM_PROGRAM_ID_STRING = 'BKck65TgoKRokMjQM3datB9oRwJ8rAj2jxPXvHXUvcL6'; /** * Discriminator for the ArxNode account type. Used to filter and identify ArxNode accounts on-chain. */ const ARX_NODE_ACC_DISCRIMINATOR = [2, 207, 122, 223, 93, 97, 231, 199]; /** * Discriminator for the Cluster account type. Used to filter and identify Cluster accounts on-chain. */ const CLUSTER_ACC_DISCRIMINATOR = [236, 225, 118, 228, 173, 106, 18, 60]; /** * Discriminator for the MXE account type. Used to filter and identify MXE accounts on-chain. */ const MXE_ACC_DISCRIMINATOR = [103, 26, 85, 250, 179, 159, 17, 117]; /** * The public key of the deployed Arcium program on Solana. */ const ARCIUM_PROGRAM_ID = new anchor__namespace.web3.PublicKey(ARCIUM_PROGRAM_ID_STRING); /** * Anchor coder for encoding and decoding Arcium program instructions. */ new anchor__namespace.BorshInstructionCoder(client.ARCIUM_IDL); /** * Anchor event parser for parsing Arcium program events from transaction logs. */ const ARCIUM_EVENT_CODER = new anchor__namespace.EventParser(ARCIUM_PROGRAM_ID, new anchor__namespace.BorshCoder(client.ARCIUM_IDL)); /** * Returns all MXE account addresses. * @param conn - The Solana connection object. * @returns Array of MXE account public keys. */ async function getMXEAccAddresses(conn) { return getArciumAccPubkeys(conn, MXE_ACC_DISCRIMINATOR); } /** * Returns all Cluster account addresses. * @param conn - The Solana connection object. * @returns Array of Cluster account public keys. */ async function getClusterAccAddresses(conn) { return getArciumAccPubkeys(conn, CLUSTER_ACC_DISCRIMINATOR); } /** * Returns all ArxNode account addresses. * @param conn - The Solana connection object. * @returns Array of ArxNode account public keys. */ async function getArxNodeAccAddresses(conn) { return getArciumAccPubkeys(conn, ARX_NODE_ACC_DISCRIMINATOR); } /** * Fetches and parses a given MXE account. * @param arciumProgram - The Anchor program instance. * @param address - The public key of the MXE account. * @param commitment - (Optional) RPC commitment level. * @returns The MXEAccount object. */ async function getMXEAccInfo(arciumProgram, address, commitment) { return arciumProgram.account.mxeAccount.fetch(address, commitment); } /** * Fetches and parses a given Cluster account. * @param arciumProgram - The Anchor program instance. * @param address - The public key of the Cluster account. * @param commitment - (Optional) RPC commitment level. * @returns The ClusterAccount object. */ async function getClusterAccInfo(arciumProgram, address, commitment) { return arciumProgram.account.cluster.fetch(address, commitment); } /** * Fetches and parses a given ArxNode account. * @param arciumProgram - The Anchor program instance. * @param address - The public key of the ArxNode account. * @param commitment - (Optional) RPC commitment level. * @returns The ArxNodeAccount object. */ async function getArxNodeAccInfo(arciumProgram, address, commitment) { return arciumProgram.account.arxNode.fetch(address, commitment); } /** * Fetches and parses a given ComputationDefinition account. * @param arciumProgram - The Anchor program instance. * @param address - The public key of the ComputationDefinition account. * @param commitment - (Optional) RPC commitment level. * @returns The ComputationDefinitionAccount object. */ async function getCompDefAccInfo(arciumProgram, address, commitment) { return arciumProgram.account.computationDefinitionAccount.fetch(address, commitment); } /** * Returns all computation references in the mempool for a given account. * Only non-stake computations are included. * @param arciumProgram - The Anchor program instance. * @param address - The public key of the mempool account. * @returns Array of ComputationReference objects. */ async function getComputationsInMempool(arciumProgram, address) { const mempool = await client.getMempoolAccData(arciumProgram.provider, address); const startIndex = mempool.inner.computations.startIndex; const length = mempool.inner.computations.length; const elems = mempool.inner.computations.elems; function isValid(validBits, idx) { const byte = idx >>> 3; const bit = idx & 7; if (byte >= validBits.length) { // This should never happen, so we'll want to know about it throw new Error(`isValid: byte ${byte} >= validBits.length ${validBits.length}`); } return (validBits[byte] & (1 << bit)) !== 0; } // Handle circular buffer wraparound const refs = []; for (let i = 0; i < length; i++) { const idx = (startIndex + i) % elems.length; // Only save non-stake computations if (isValid(mempool.inner.computations.validBits, idx)) { refs.push(...elems[idx].entries); } } return refs .flat() .filter((ref) => !isNullRef(ref)); } /** * Fetches and parses a given Computation account. * @param arciumProgram - The Anchor program instance. * @param address - The public key of the Computation account. * @param commitment - (Optional) RPC commitment level. * @returns The Computation object. */ async function getComputationAccInfo(arciumProgram, address, commitment) { return arciumProgram.account.computationAccount.fetch(address, commitment); } async function getArciumAccPubkeys(conn, discriminator) { const accs = await conn.getProgramAccounts(ARCIUM_PROGRAM_ID, { dataSlice: { offset: 0, length: 0 }, filters: [ { memcmp: { offset: 0, encoding: 'base64', bytes: Buffer.from(discriminator).toString('base64'), }, }, ], }); return accs.map((acc) => acc.pubkey); } function isNullRef(ref) { const bigZero = new anchor__namespace.BN(0); return (ref.computationDefinitionOffset === 0 && ref.computationOffset === bigZero && ref.priorityFee === bigZero); } const ArciumEventNames = [ 'QueueComputationEvent', 'InitComputationEvent', 'CallbackComputationEvent', 'FinalizeComputationEvent', ]; /** * Subscribes to computation-related events for a given MXE program ID. * @param conn - The Solana connection object. * @param mxeProgramId - The public key of the MXE program. * @param callback - Callback function to handle each computation event and its name. * @returns The subscription ID for the logs listener. */ async function subscribeComputations(conn, mxeProgramId, callback) { return conn.onLogs(mxeProgramId, (logs) => { const events = getComputationEventsFromLogs(logs.logs); for (const event of events) { callback(event.event, event.name); } }); } /** * Unsubscribes from computation-related events using the subscription ID. * @param conn - The Solana connection object. * @param subscriptionId - The subscription ID returned by subscribeComputations. */ async function unsubscribeComputations(conn, subscriptionId) { conn.removeOnLogsListener(subscriptionId); } /** * Gets the computation offset from a transaction. * @param tx - The transaction to get the computation offset from. * @returns The computation offset if one is found, otherwise undefined. * @throws Error if multiple computation offsets are found in the transaction. */ function getComputationOffset(tx) { const events = getComputationEventsFromLogs(tx.meta?.logMessages ?? []); if (events.length === 0) { return undefined; } const computationOffsets = events.map((e) => e.event.computationOffset); const computationOffset = computationOffsets[0]; if (computationOffsets.some((offset) => !offset.eq(computationOffset))) { throw new Error(`Multiple computation offsets found in computation: ${JSON.stringify(computationOffsets)}`); } return computationOffset; } /** * Get the events related to arcium computations from a transaction's logs * @param logs - The logs to get the events from * @returns The events in the logs. */ function getComputationEventsFromLogs(logs) { return Array.from(ARCIUM_EVENT_CODER.parseLogs(logs)) .filter((e) => ArciumEventNames.includes(e.name)) .map((e) => { const eventData = { computationOffset: e.data.computation_offset, ...e.data, }; if (e.data.mxe_program_id) { eventData.mxeProgramId = e.data.mxe_program_id; } return { event: eventData, name: e.name, }; }); } Object.defineProperty(exports, "getArciumProgramReadonly", { enumerable: true, get: function () { return client.getArciumProgramReadonly; } }); Object.defineProperty(exports, "getArxNodeAccAddress", { enumerable: true, get: function () { return client.getArxNodeAccAddress; } }); Object.defineProperty(exports, "getClockAccAddress", { enumerable: true, get: function () { return client.getClockAccAddress; } }); Object.defineProperty(exports, "getClusterAccAddress", { enumerable: true, get: function () { return client.getClusterAccAddress; } }); Object.defineProperty(exports, "getCompDefAccAddress", { enumerable: true, get: function () { return client.getCompDefAccAddress; } }); Object.defineProperty(exports, "getComputationAccAddress", { enumerable: true, get: function () { return client.getComputationAccAddress; } }); Object.defineProperty(exports, "getExecutingPoolAccAddress", { enumerable: true, get: function () { return client.getExecutingPoolAccAddress; } }); Object.defineProperty(exports, "getMXEAccAddress", { enumerable: true, get: function () { return client.getMXEAccAddress; } }); Object.defineProperty(exports, "getMempoolAccAddress", { enumerable: true, get: function () { return client.getMempoolAccAddress; } }); Object.defineProperty(exports, "getStakingPoolAccAddress", { enumerable: true, get: function () { return client.getStakingPoolAccAddress; } }); exports.getArxNodeAccAddresses = getArxNodeAccAddresses; exports.getArxNodeAccInfo = getArxNodeAccInfo; exports.getClusterAccAddresses = getClusterAccAddresses; exports.getClusterAccInfo = getClusterAccInfo; exports.getCompDefAccInfo = getCompDefAccInfo; exports.getComputationAccInfo = getComputationAccInfo; exports.getComputationOffset = getComputationOffset; exports.getComputationsInMempool = getComputationsInMempool; exports.getMXEAccAddresses = getMXEAccAddresses; exports.getMXEAccInfo = getMXEAccInfo; exports.subscribeComputations = subscribeComputations; exports.unsubscribeComputations = unsubscribeComputations;