@ar.io/sdk
Version:
[](https://codecov.io/gh/ar-io/ar-io-sdk)
175 lines (174 loc) • 7.26 kB
JavaScript
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;
;