UNPKG

@ar.io/sdk

Version:

[![codecov](https://codecov.io/gh/ar-io/ar-io-sdk/graph/badge.svg?token=7dXKcT7dJy)](https://codecov.io/gh/ar-io/ar-io-sdk)

175 lines (174 loc) 7.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchAllArNSRecords = exports.ArNSEventEmitter = exports.getANTProcessesOwnedByWallet = void 0; /** * Copyright (C) 2022-2024 Permanent Data Solutions, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const aoconnect_1 = require("@permaweb/aoconnect"); const eventemitter3_1 = require("eventemitter3"); const plimit_lit_1 = require("plimit-lit"); const ant_registry_js_1 = require("../common/ant-registry.js"); const ant_js_1 = require("../common/ant.js"); const index_js_1 = require("../common/index.js"); const io_js_1 = require("../common/io.js"); const logger_js_1 = require("../common/logger.js"); const constants_js_1 = require("../constants.js"); /** * @beta This API is in beta and may change in the future. */ const getANTProcessesOwnedByWallet = async ({ address, registry = ant_registry_js_1.ANTRegistry.init(), }) => { const res = await registry.accessControlList({ address }); return [...new Set([...res.Owned, ...res.Controlled])]; }; exports.getANTProcessesOwnedByWallet = getANTProcessesOwnedByWallet; function timeout(ms, promise) { return new Promise((resolve, reject) => { const timer = setTimeout(() => { reject(new Error('Timeout')); }, ms); promise .then((value) => { clearTimeout(timer); resolve(value); }) .catch((err) => { clearTimeout(timer); reject(err); }); }); } class ArNSEventEmitter extends eventemitter3_1.EventEmitter { contract; timeoutMs; // timeout for each request to 3 seconds throttle; logger; strict; antAoClient; constructor({ contract = io_js_1.ARIO.init({ processId: constants_js_1.ARIO_MAINNET_PROCESS_ID, }), timeoutMs = 60_000, concurrency = 30, logger = logger_js_1.Logger.default, strict = false, antAoClient = (0, aoconnect_1.connect)({ MODE: 'legacy', }), } = {}) { super(); this.contract = contract; this.timeoutMs = timeoutMs; this.throttle = (0, plimit_lit_1.pLimit)(concurrency); this.logger = logger; this.strict = strict; this.antAoClient = antAoClient; } async fetchProcessesOwnedByWallet({ address, pageSize, antRegistry = ant_registry_js_1.ANTRegistry.init(), }) { const uniqueContractProcessIds = {}; const antIdRes = await antRegistry.accessControlList({ address }); const antIds = new Set([...antIdRes.Owned, ...antIdRes.Controlled]); await timeout(this.timeoutMs, (0, exports.fetchAllArNSRecords)({ contract: this.contract, emitter: this, pageSize })) .catch((e) => { this.emit('error', `Error getting ArNS records: ${e}`); this.logger.error(`Error getting ArNS records`, { message: e?.message, stack: e?.stack, }); return {}; }) .then((records) => { Object.entries(records).forEach(([name, arnsRecord]) => { if (antIds.has(arnsRecord.processId)) { if (uniqueContractProcessIds[arnsRecord.processId] == undefined) { uniqueContractProcessIds[arnsRecord.processId] = { state: undefined, names: {}, }; } uniqueContractProcessIds[arnsRecord.processId].names[name] = arnsRecord; } }); }); const idCount = Object.keys(uniqueContractProcessIds).length; this.emit('progress', 0, idCount); // check the contract owner and controllers await Promise.all(Object.keys(uniqueContractProcessIds).map(async (processId, i) => this.throttle(async () => { if (uniqueContractProcessIds[processId].state !== undefined) { this.emit('progress', i + 1, idCount); return; } const ant = ant_js_1.ANT.init({ process: new index_js_1.AOProcess({ processId, ao: this.antAoClient, }), strict: this.strict, }); const state = (await timeout(this.timeoutMs, ant.getState()).catch((e) => { this.emit('error', `Error getting state for process ${processId}: ${e}`); return undefined; })); if (state?.Owner === address || state?.Controllers.includes(address)) { uniqueContractProcessIds[processId].state = state; this.emit('process', processId, uniqueContractProcessIds[processId]); } this.emit('progress', i + 1, idCount); }))); this.emit('end', uniqueContractProcessIds); } } exports.ArNSEventEmitter = ArNSEventEmitter; const fetchAllArNSRecords = async ({ contract = io_js_1.ARIO.init({ processId: constants_js_1.ARIO_MAINNET_PROCESS_ID, }), emitter, logger = logger_js_1.Logger.default, pageSize = 1000, }) => { let cursor; const startTimestamp = Date.now(); const records = {}; do { const pageResult = await contract .getArNSRecords({ cursor, limit: pageSize }) // eslint-disable-next-line @typescript-eslint/no-explicit-any .catch((e) => { logger?.error(`Error getting ArNS records`, { message: e?.message, stack: e?.stack, }); emitter?.emit('arns:error', `Error getting ArNS records: ${e}`); return undefined; }); if (!pageResult) { return {}; } pageResult.items.forEach((record) => { const { name, ...recordDetails } = record; records[name] = recordDetails; }); logger.debug('Fetched page of ArNS records', { totalRecordCount: pageResult.totalItems, fetchedRecordCount: Object.keys(records).length, cursor: pageResult.nextCursor, }); emitter?.emit('arns:pageLoaded', { totalRecordCount: pageResult.totalItems, fetchedRecordCount: Object.keys(records).length, records: pageResult.items, cursor: pageResult.nextCursor, }); cursor = pageResult.nextCursor; } while (cursor !== undefined); emitter?.emit('arns:end', records); logger.debug('Fetched all ArNS records', { totalRecordCount: Object.keys(records).length, durationMs: Date.now() - startTimestamp, }); return records; }; exports.fetchAllArNSRecords = fetchAllArNSRecords;