UNPKG

@wasserstoff/tribes-sdk

Version:

SDK for integrating with Tribes by Astrix platform on any EVM compatible chain

501 lines (500 loc) 19.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TribesModule = void 0; const ethers_1 = require("ethers"); const BaseModule_1 = require("../core/BaseModule"); const core_1 = require("../types/core"); const tribes_1 = require("../types/tribes"); const validation_1 = require("../utils/validation"); // Import TribeController ABI const TribeController_json_1 = __importDefault(require("../../abis/TribeController.json")); /** * Module for managing tribes and tribe membership */ class TribesModule extends BaseModule_1.BaseModule { /** * Get the TribeController contract * @param useSigner Whether to use the signer */ getTribeControllerContract(useSigner = false) { // eslint-disable-next-line @typescript-eslint/no-explicit-any return this. // eslint-disable-next-line @typescript-eslint/no-explicit-any getContract(this.config.contracts.tribeController, TribeController_json_1.default, useSigner); } /** * Create a new tribe * @param params Tribe creation parameters * @returns Tribe ID of the newly created tribe */ async createTribe(params) { try { // Validate input (0, validation_1.validateNonEmptyString)(params.name, 'name'); (0, validation_1.validateNonEmptyString)(params.metadata, 'metadata'); if (params.admins) { params.admins.forEach((admin, index) => { (0, validation_1.validateAddress)(admin, `admins[${index}]`); }); } if (params.entryFee) { (0, validation_1.validatePositiveBigInt)(params.entryFee, 'entryFee'); } const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.createTribe(params.name, params.metadata, params.admins || [], params.joinType !== undefined ? params.joinType : tribes_1.JoinType.PUBLIC, params.entryFee || 0n, params.nftRequirements || []); const receipt = await tx.wait(); // Extract tribeId from event const event = receipt.logs.find((log) => { return log.topics && log.topics[0] === ethers_1.ethers.id("TribeCreated(uint256,address,string)"); }); if (!event || !event.args) { throw new Error('Tribe creation event not found or args undefined'); } const tribeId = Number(event.args[0]); this.log(`Created tribe`, { tribeId, name: params.name, txHash: receipt.hash }); return tribeId; } catch (error) { return this.handleError(error, 'Failed to create tribe', core_1.ErrorType.CONTRACT_ERROR); } } /** * Update tribe configuration * @param params Tribe configuration update parameters * @returns Transaction hash */ async updateTribeConfig(params) { try { if (params.entryFee) { (0, validation_1.validatePositiveBigInt)(params.entryFee, 'entryFee'); } const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.updateTribeConfig(params.tribeId, params.joinType, params.entryFee, params.nftRequirements || []); const receipt = await tx.wait(); this.log(`Updated tribe configuration`, { tribeId: params.tribeId, joinType: params.joinType, entryFee: params.entryFee?.toString(), txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to update tribe configuration', core_1.ErrorType.CONTRACT_ERROR); } } /** * Update tribe metadata and whitelist * @param params Tribe update parameters * @returns Transaction hash */ async updateTribe(params) { try { (0, validation_1.validateNonEmptyString)(params.newMetadata, 'newMetadata'); if (params.updatedWhitelist) { params.updatedWhitelist.forEach((address, index) => { (0, validation_1.validateAddress)(address, `updatedWhitelist[${index}]`); }); } const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.updateTribe(params.tribeId, params.newMetadata, params.updatedWhitelist || []); const receipt = await tx.wait(); this.log(`Updated tribe`, { tribeId: params.tribeId, txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to update tribe', core_1.ErrorType.CONTRACT_ERROR); } } /** * Join a tribe * @param params Join tribe parameters * @returns Transaction hash */ async joinTribe(params) { try { const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.joinTribe(params.tribeId); const receipt = await tx.wait(); this.log(`Joined tribe`, { tribeId: params.tribeId, txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to join tribe', core_1.ErrorType.CONTRACT_ERROR); } } /** * Request to join a private tribe * @param params Request to join parameters * @returns Transaction hash */ async requestToJoinTribe(params) { try { if (params.entryFee) { (0, validation_1.validatePositiveBigInt)(params.entryFee, 'entryFee'); } const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.requestToJoinTribe(params.tribeId, { value: params.entryFee || 0n }); const receipt = await tx.wait(); this.log(`Requested to join tribe`, { tribeId: params.tribeId, entryFee: params.entryFee?.toString(), txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to request to join tribe', core_1.ErrorType.CONTRACT_ERROR); } } /** * Join a tribe using an invite code * @param params Join with code parameters * @returns Transaction hash */ async joinTribeWithCode(params) { try { (0, validation_1.validateNonEmptyString)(params.inviteCode, 'inviteCode'); const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.joinTribeWithCode(params.tribeId, params.inviteCode); const receipt = await tx.wait(); this.log(`Joined tribe with code`, { tribeId: params.tribeId, txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to join tribe with code', core_1.ErrorType.CONTRACT_ERROR); } } /** * Approve a member's request to join * @param params Manage member parameters * @returns Transaction hash */ async approveMember(params) { try { (0, validation_1.validateAddress)(params.memberAddress, 'memberAddress'); const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.approveMember(params.tribeId, params.memberAddress); const receipt = await tx.wait(); this.log(`Approved member`, { tribeId: params.tribeId, member: params.memberAddress, txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to approve member', core_1.ErrorType.CONTRACT_ERROR); } } /** * Remove a member from a tribe * @param params Manage member parameters * @returns Transaction hash */ async removeMember(params) { try { (0, validation_1.validateAddress)(params.memberAddress, 'memberAddress'); const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.removeMember(params.tribeId, params.memberAddress); const receipt = await tx.wait(); this.log(`Removed member`, { tribeId: params.tribeId, member: params.memberAddress, txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to remove member', core_1.ErrorType.CONTRACT_ERROR); } } /** * Ban a member from a tribe * @param params Manage member parameters * @returns Transaction hash */ async banMember(params) { try { (0, validation_1.validateAddress)(params.memberAddress, 'memberAddress'); const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.banMember(params.tribeId, params.memberAddress); const receipt = await tx.wait(); this.log(`Banned member`, { tribeId: params.tribeId, member: params.memberAddress, txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to ban member', core_1.ErrorType.CONTRACT_ERROR); } } /** * Create an invite code for a tribe * @param params Create invite code parameters * @returns Transaction hash */ async createInviteCode(params) { try { (0, validation_1.validateNonEmptyString)(params.code, 'code'); const tribeController = this.getTribeControllerContract(true); const tx = await tribeController.createInviteCode(params.tribeId, params.code, params.maxUses, params.expiryTime || 0); const receipt = await tx.wait(); this.log(`Created invite code`, { tribeId: params.tribeId, code: params.code, maxUses: params.maxUses, expiryTime: params.expiryTime, txHash: receipt.hash }); return receipt.hash; } catch (error) { return this.handleError(error, 'Failed to create invite code', core_1.ErrorType.CONTRACT_ERROR); } } /** * Get tribe details * @param tribeId Tribe ID * @returns Tribe details object */ async getTribeDetails(tribeId) { try { const tribeController = this.getTribeControllerContract(); const tribeData = await tribeController.getTribeDetails(tribeId); return { id: tribeId, name: tribeData.name, admin: tribeData.admin, metadata: tribeData.metadata, joinType: tribeData.joinType, entryFee: tribeData.entryFee, memberCount: Number(tribeData.memberCount), creationTime: Number(tribeData.creationTime) || 0, nftRequirements: tribeData.nftRequirements || [], organization: tribeData.organization || undefined, isActive: tribeData.isActive || true, canMerge: tribeData.canMerge || false }; } catch (error) { return this.handleError(error, 'Failed to get tribe details', core_1.ErrorType.CONTRACT_ERROR); } } /** * Check if an address is a member of a tribe * @param tribeId Tribe ID * @param address Address to check * @returns Member status */ async getMemberStatus(tribeId, address) { try { (0, validation_1.validateAddress)(address, 'address'); const tribeController = this.getTribeControllerContract(); const status = await tribeController.getMemberStatus(tribeId, address); return status; } catch (error) { return this.handleError(error, 'Failed to get member status', core_1.ErrorType.CONTRACT_ERROR); } } /** * Get all members of a tribe * @param tribeId Tribe ID * @returns Array of member addresses */ async getMembers(tribeId) { try { // This function is a placeholder until the contract adds support for it this.log(`Warning: getMembers function is not yet supported by the contract`, { tribeId }); // Return an empty array for now return []; // Original implementation (commented out until contract supports it) // const tribeController = this.getTribeControllerContract(); // const members = await tribeController.getMembers(tribeId); // return members; } catch (error) { return this.handleError(error, 'Failed to get tribe members', core_1.ErrorType.CONTRACT_ERROR); } } /** * Get all tribes a user is a member of * @param address User address * @returns Array of tribe IDs */ async getUserTribes(address) { try { (0, validation_1.validateAddress)(address, 'address'); const tribeController = this.getTribeControllerContract(); const tribes = await tribeController.getUserTribes(address); return tribes.map((tribeId) => Number(tribeId)); } catch (error) { return this.handleError(error, 'Failed to get user tribes', core_1.ErrorType.CONTRACT_ERROR); } } /** * Check if an invite code is valid * @param tribeId Tribe ID * @param code Invite code * @returns True if the code is valid */ async isInviteCodeValid(tribeId, code) { try { (0, validation_1.validateNonEmptyString)(code, 'code'); const tribeController = this.getTribeControllerContract(); return await tribeController.isInviteCodeValid(tribeId, code); } catch (error) { return this.handleError(error, 'Failed to check invite code validity', core_1.ErrorType.CONTRACT_ERROR); } } /** * Get all tribes with pagination * @param offset The starting index for pagination * @param limit The maximum number of tribes to return * @returns Object containing tribe IDs and total count */ async getAllTribes(offset = 0, limit = 100) { try { const tribeController = this.getTribeControllerContract(); const result = await tribeController.getAllTribes(offset, limit); return { tribeIds: result.tribeIds.map((id) => Number(id)), total: Number(result.total) }; } catch (error) { return this.handleError(error, 'Failed to get all tribes', core_1.ErrorType.CONTRACT_ERROR); } } /** * Check if a tribe exists * @param tribeId Tribe ID to check * @returns True if the tribe exists */ async tribeExists(tribeId) { try { const tribeController = this.getTribeControllerContract(); // Check if the method exists if (typeof tribeController.tribeExists !== 'function') { this.log('Warning: tribeExists method not available in contract', {}); // Try to get tribe details as a fallback try { await tribeController.getTribeDetails(tribeId); return true; // If no error, tribe exists } catch (detailsError) { return false; // Error getting details, tribe doesn't exist } } return await tribeController.tribeExists(tribeId); } catch (error) { this.log(`Error checking if tribe ${tribeId} exists, assuming it doesn't`, { error }); return false; } } /** * Get the total number of tribes * @returns Total number of tribes */ async getTribeCount() { try { const tribeController = this.getTribeControllerContract(); // Check if the method exists if (typeof tribeController.getTribeCount !== 'function') { this.log('Warning: getTribeCount method not available in contract', {}); return 0; } const count = await tribeController.getTribeCount(); return Number(count); } catch (error) { // Return 0 for any errors, indicating no tribes available this.log('Error in getTribeCount, returning 0', { error }); return 0; } } /** * Check if a user is an active member of a tribe * @param tribeId Tribe ID * @param address User address * @returns True if the user is an active member */ async isActiveMember(tribeId, address) { try { const status = await this.getMemberStatus(tribeId, address); // MemberStatus.ACTIVE = 2 return status === tribes_1.MemberStatus.ACTIVE; } catch (error) { return this.handleError(error, `Failed to check if ${address} is an active member of tribe ${tribeId}`, core_1.ErrorType.CONTRACT_ERROR); } } /** * Find the first tribe the user is a member of, useful for testing * @param address User address * @returns Tribe ID of the first tribe the user is a member of, or 0 if none */ async findFirstActiveTribe(address) { try { const tribes = await this.getUserTribes(address); if (tribes.length === 0) { return 0; } // Find the first tribe where the user is an active member for (const tribeId of tribes) { const isActive = await this.isActiveMember(tribeId, address); if (isActive) { return tribeId; } } return 0; } catch (error) { return this.handleError(error, `Failed to find first active tribe for ${address}`, core_1.ErrorType.CONTRACT_ERROR); } } /** * Check if a user can post in a tribe * @param tribeId Tribe ID * @param address User address * @returns True if the user can post in the tribe */ async canPostInTribe(tribeId, address) { try { // First check if the tribe exists const exists = await this.tribeExists(tribeId); if (!exists) { return false; } // Then check if the user is an active member return await this.isActiveMember(tribeId, address); } catch (error) { return this.handleError(error, `Failed to check if ${address} can post in tribe ${tribeId}`, core_1.ErrorType.CONTRACT_ERROR); } } } exports.TribesModule = TribesModule;