@inkwell.ar/sdk
Version:
SDK for interacting with the Inkwell Blog CRUD AO process using aoconnect for deployment and interactions
207 lines • 9.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.InkwellRegistrySDK = void 0;
const aoconnect_1 = require("@permaweb/aoconnect");
const registry_1 = require("../config/registry");
const types_1 = require("../types");
const logger_1 = require("../utils/logger");
class InkwellRegistrySDK {
constructor(config) {
this.aoconnect = config?.aoconnect || (0, aoconnect_1.connect)({ MODE: 'legacy' });
this.registryProcessId =
config?.registryProcessId || registry_1.BLOG_REGISTRY_PROCESS_ID;
this.logger = new logger_1.Logger({ level: config?.logLevel || types_1.LogLevel.WARN });
if (this.registryProcessId === 'YOUR_REGISTRY_PROCESS_ID_HERE') {
this.logger.error(logger_1.LogGroup.REGISTRY, 'Registry process ID not configured');
throw new Error('Registry process ID not configured. Please run the deployment script first: npm run deploy:registry');
}
this.logger.info(logger_1.LogGroup.REGISTRY, `Initialized InkwellRegistrySDK with process ID: ${this.registryProcessId}`);
}
/**
* Note: Write operations (register, remove, update) are only available to blog processes
* for security reasons. The registry uses msg.From as the blog ID to ensure only
* the actual blog process can modify its own permissions.
*/
/**
* Get all blogs a wallet has permissions for
*/
async getWalletBlogs(wallet) {
try {
this.logger.debug(logger_1.LogGroup.REGISTRY, `Getting blogs for wallet: ${wallet}`);
const result = await this.aoconnect.dryrun({
process: this.registryProcessId,
data: '',
tags: [
{ name: 'Action', value: 'Get-Wallet-Blogs' },
{ name: 'Wallet-Address', value: wallet },
],
});
this.logger.debug(logger_1.LogGroup.REGISTRY, 'Parsing wallet blogs response', result.Messages[0].Data);
const response = JSON.parse(result.Messages[0].Data);
if (!response.success) {
this.logger.error(logger_1.LogGroup.REGISTRY, `Failed to get wallet blogs: ${response.data}`);
throw new Error(response.data);
}
this.logger.debug(logger_1.LogGroup.REGISTRY, `Found ${response.data.length} blogs for wallet`);
return response.data;
}
catch (error) {
this.logger.error(logger_1.LogGroup.REGISTRY, `Error getting wallet blogs for ${wallet}`, error);
throw error;
}
}
/**
* Get all wallets with permissions for a specific blog
*/
async getBlogWallets(blogId) {
try {
this.logger.debug(logger_1.LogGroup.REGISTRY, `Getting wallets for blog: ${blogId}`);
const result = await this.aoconnect.dryrun({
process: this.registryProcessId,
data: '',
tags: [
{ name: 'Action', value: 'Get-Blog-Wallets' },
{ name: 'Blog-ID', value: blogId },
],
});
this.logger.debug(logger_1.LogGroup.REGISTRY, 'Parsing blog wallets response', result.Messages[0].Data);
const response = JSON.parse(result.Messages[0].Data);
if (!response.success) {
this.logger.error(logger_1.LogGroup.REGISTRY, `Failed to get blog wallets: ${response.data}`);
throw new Error(response.data);
}
this.logger.debug(logger_1.LogGroup.REGISTRY, `Found ${response.data.length} wallets for blog`);
return response.data;
}
catch (error) {
this.logger.error(logger_1.LogGroup.REGISTRY, `Error getting blog wallets for ${blogId}`, error);
throw error;
}
}
/**
* Check if a wallet has a specific role for a blog
*/
async checkWalletRole(wallet, blogId, role) {
try {
this.logger.debug(logger_1.LogGroup.AUTH, `Checking if wallet ${wallet} has role ${role} for blog ${blogId}`);
const result = await this.aoconnect.dryrun({
process: this.registryProcessId,
data: '',
tags: [
{ name: 'Action', value: 'Check-Wallet-Role' },
{ name: 'Wallet-Address', value: wallet },
{ name: 'Blog-ID', value: blogId },
{ name: 'Role', value: role },
],
});
this.logger.debug(logger_1.LogGroup.AUTH, 'Parsing role check response', result.Messages[0].Data);
const response = JSON.parse(result.Messages[0].Data);
if (!response.success) {
this.logger.error(logger_1.LogGroup.AUTH, `Role check failed: ${response.data.error}`);
throw new Error(response.data.error);
}
this.logger.debug(logger_1.LogGroup.AUTH, `Role check result: ${response.data.has_role}`);
return response.data.has_role;
}
catch (error) {
this.logger.error(logger_1.LogGroup.AUTH, `Error checking wallet role for ${wallet}`, error);
throw error;
}
}
/**
* Get registry statistics
*/
async getRegistryStats() {
try {
this.logger.debug(logger_1.LogGroup.REGISTRY, 'Getting registry statistics');
const result = await this.aoconnect.dryrun({
process: this.registryProcessId,
data: '',
tags: [{ name: 'Action', value: 'Get-Registry-Stats' }],
});
this.logger.debug(logger_1.LogGroup.REGISTRY, 'Parsing registry stats response', result.Messages[0].Data);
const response = JSON.parse(result.Messages[0].Data);
if (!response.success) {
this.logger.error(logger_1.LogGroup.REGISTRY, `Failed to get registry stats: ${response.data}`);
throw new Error(response.data);
}
this.logger.info(logger_1.LogGroup.REGISTRY, `Registry stats: ${response.data.blog_count} blogs, ${response.data.wallet_count} wallets`);
return response.data;
}
catch (error) {
this.logger.error(logger_1.LogGroup.REGISTRY, 'Error getting registry statistics', error);
throw error;
}
}
/**
* Note: Bulk operations and sync operations are only available to blog processes
* for security reasons. The registry uses msg.From as the blog ID to ensure only
* the actual blog process can modify its own permissions.
*/
/**
* Get all blogs that a wallet can admin
*/
async getAdminBlogs(wallet) {
try {
this.logger.debug(logger_1.LogGroup.AUTH, `Getting admin blogs for wallet: ${wallet}`);
const allBlogs = await this.getWalletBlogs(wallet);
const adminBlogs = allBlogs.filter((blog) => blog.roles.includes(types_1.Role.ADMIN));
this.logger.info(logger_1.LogGroup.AUTH, `Found ${adminBlogs.length} admin blogs for wallet`);
return adminBlogs;
}
catch (error) {
this.logger.error(logger_1.LogGroup.AUTH, `Error getting admin blogs for ${wallet}`, error);
throw error;
}
}
/**
* Get all blogs that a wallet can edit
*/
async getEditableBlogs(wallet) {
try {
this.logger.debug(logger_1.LogGroup.AUTH, `Getting editable blogs for wallet: ${wallet}`);
const allBlogs = await this.getWalletBlogs(wallet);
const editableBlogs = allBlogs.filter((blog) => blog.roles.includes(types_1.Role.EDITOR) || blog.roles.includes(types_1.Role.ADMIN));
this.logger.info(logger_1.LogGroup.AUTH, `Found ${editableBlogs.length} editable blogs for wallet`);
return editableBlogs;
}
catch (error) {
this.logger.error(logger_1.LogGroup.AUTH, `Error getting editable blogs for ${wallet}`, error);
throw error;
}
}
/**
* Check if a wallet can admin a specific blog
*/
async canAdminBlog(wallet, blogId) {
try {
this.logger.debug(logger_1.LogGroup.AUTH, `Checking admin permission for wallet ${wallet} on blog ${blogId}`);
const canAdmin = await this.checkWalletRole(wallet, blogId, types_1.Role.ADMIN);
this.logger.debug(logger_1.LogGroup.AUTH, `Admin check result: ${canAdmin}`);
return canAdmin;
}
catch (error) {
this.logger.error(logger_1.LogGroup.AUTH, `Error checking admin permission for ${wallet}`, error);
throw error;
}
}
/**
* Check if a wallet can edit a specific blog
*/
async canEditBlog(wallet, blogId) {
try {
this.logger.debug(logger_1.LogGroup.AUTH, `Checking edit permission for wallet ${wallet} on blog ${blogId}`);
const canEdit = await this.checkWalletRole(wallet, blogId, types_1.Role.EDITOR);
const canAdmin = await this.checkWalletRole(wallet, blogId, types_1.Role.ADMIN);
const result = canEdit || canAdmin;
this.logger.debug(logger_1.LogGroup.AUTH, `Edit check result: ${result} (editor: ${canEdit}, admin: ${canAdmin})`);
return result;
}
catch (error) {
this.logger.error(logger_1.LogGroup.AUTH, `Error checking edit permission for ${wallet}`, error);
throw error;
}
}
}
exports.InkwellRegistrySDK = InkwellRegistrySDK;
//# sourceMappingURL=registry-sdk.js.map