UNPKG

@agentdao/core

Version:

Core functionality, skills, and ready-made UI components for AgentDAO - Web3 subscriptions, content generation, social media, help support, live chat, RSS fetching, web search, and agent pricing integration

210 lines (209 loc) 9.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TokenGatingSkill = void 0; const ethers_1 = require("ethers"); const Web3SubscriptionSkill_1 = require("./Web3SubscriptionSkill"); const FundAgent_1 = require("./FundAgent"); class TokenGatingSkill { constructor(config) { // Set defaults for gating configuration const defaultFeatures = { chat: { requiredPlan: 'basic', requiredTokens: 0, requireSafeWallet: false }, help: { requiredPlan: 'basic', requiredTokens: 0, requireSafeWallet: false }, content: { requiredPlan: 'pro', requiredTokens: 100, requireSafeWallet: false }, social: { requiredPlan: 'pro', requiredTokens: 100, requireSafeWallet: false }, analytics: { requiredPlan: 'pro', requiredTokens: 100, requireSafeWallet: false } }; this.config = { ...config, gating: { requireSafeWallet: false, // Default to false - Safe wallets are optional autoCreateSafe: false, // Default to false - Don't auto-create Safe wallets minTokenForAccess: 0, // Default to 0 - No minimum token required gracePeriod: 7, // Default 7 days grace period features: { ...defaultFeatures, ...config.gating.features } } }; // Create provider from RPC URL or use provided provider this.provider = config.fundAgent.provider || new ethers_1.ethers.JsonRpcProvider(config.fundAgent.rpcUrl); this.subscriptionSkill = new Web3SubscriptionSkill_1.Web3SubscriptionSkill(config.subscription); this.fundAgent = new FundAgent_1.FundAgent(config.fundAgent); } async checkUserAccess(userAddress) { try { const tokenBalance = await this.getTokenBalance(userAddress); const subscription = await this.subscriptionSkill.checkSubscription(userAddress); const safeWallet = await this.getUserSafeWallet(userAddress); const hasAccess = this.determineAccess(tokenBalance, subscription, safeWallet); const features = await this.checkFeatureAccess(userAddress, tokenBalance, subscription, safeWallet); return { hasAccess, subscription: subscription.hasActiveSubscription ? subscription : null, safeWallet: safeWallet?.address || null, adaoBalance: tokenBalance, features, nextBillingDate: subscription.nextBillingDate, gracePeriodDays: this.calculateGracePeriod(subscription) }; } catch (error) { console.error('Error checking user access:', error); return { hasAccess: false, subscription: null, safeWallet: null, adaoBalance: 0, features: {} }; } } async onboardUser(userAddress, planId, billingPeriod, createSafeWallet = true) { try { const subscription = await this.subscriptionSkill.createSubscription(userAddress, planId, billingPeriod); let safeWallet; if (createSafeWallet && this.config.gating.requireSafeWallet) { const depositAmount = this.config.fundAgent.minDeposit; safeWallet = await this.fundAgent.createSafeWallet(userAddress, depositAmount); await this.fundAgent.addOwner(safeWallet, userAddress); } return { success: true, subscription, safeWallet }; } catch (error) { console.error('Error onboarding user:', error); return { success: false, error: error.message }; } } async verifyPaymentAndCreateSafe(userAddress) { try { const paymentVerified = await this.fundAgent.verifyPayment(userAddress); if (!paymentVerified) { return { success: false, error: `Payment verification failed. Please ensure you have sufficient ${this.config.fundAgent.tokenSymbol} tokens.` }; } const depositAmount = this.config.fundAgent.minDeposit; const safeAddress = await this.fundAgent.createSafeWallet(userAddress, depositAmount); await this.fundAgent.addOwner(safeAddress, userAddress); return { success: true, safeAddress }; } catch (error) { console.error('Error verifying payment and creating Safe:', error); return { success: false, error: error.message }; } } async getTokenBalance(userAddress) { return await this.fundAgent.getTokenBalance(userAddress); } // Keep for backward compatibility async getADaoBalance(userAddress) { return await this.getTokenBalance(userAddress); } async getAvailablePlansForUser(userAddress) { const balance = await this.getTokenBalance(userAddress); const allPlans = await this.subscriptionSkill.getAvailablePlans(); return allPlans.filter(plan => { const minPrice = Math.min(plan.pricing.monthly.price, plan.pricing.quarterly.price, plan.pricing.annually.price); return balance >= minPrice; }); } async getUserSafeWallet(userAddress) { try { // Query database for user's Safe wallet if (!this.config.database || !this.config.database.endpoint) { throw new Error('No database endpoint configured for Safe wallet lookup. Please configure a database endpoint to use this feature.'); } const response = await fetch(`${this.config.database.endpoint}/safe-wallets`, { method: 'GET', headers: { 'Content-Type': 'application/json', ...(this.config.database.apiKey ? { 'Authorization': `Bearer ${this.config.database.apiKey}` } : {}) } }); if (response.ok) { const data = await response.json(); const userSafeWallet = data.safeWallets.find(wallet => wallet.owners && wallet.owners.includes(userAddress.toLowerCase())); if (userSafeWallet) { // Get real status from blockchain const status = await this.fundAgent.getWalletStatus(userSafeWallet.address); return { address: status.address, owners: status.owners, threshold: status.threshold, balance: status.balance, isActive: status.isActive, createdAt: new Date(userSafeWallet.createdAt || Date.now()) }; } } // If no Safe wallet found in database, return null return null; } catch (error) { console.error('Error getting user Safe wallet:', error); return null; } } determineAccess(tokenBalance, subscription, safeWallet) { // Check minimum token requirement if (tokenBalance < this.config.gating.minTokenForAccess) { return false; } // Check subscription requirement if (!subscription.hasActiveSubscription) { return false; } // Safe wallet is optional by default - only required if explicitly configured if (this.config.gating.requireSafeWallet && !safeWallet) { return false; } return true; } async checkFeatureAccess(userAddress, tokenBalance, subscription, safeWallet) { const features = {}; for (const [featureName, featureConfig] of Object.entries(this.config.gating.features)) { let accessible = true; let reason; if (tokenBalance < featureConfig.requiredTokens) { accessible = false; reason = `Insufficient ${this.config.fundAgent.tokenSymbol}. Required: ${featureConfig.requiredTokens}, Available: ${tokenBalance}`; } if (featureConfig.requiredPlan && (!subscription.hasActiveSubscription || subscription.planId !== featureConfig.requiredPlan)) { accessible = false; reason = `Requires ${featureConfig.requiredPlan} subscription`; } if (featureConfig.requireSafeWallet && !safeWallet) { accessible = false; reason = 'Safe wallet required'; } features[featureName] = { accessible, reason }; } return features; } calculateGracePeriod(subscription) { if (!subscription.hasActiveSubscription || subscription.daysLeft === undefined) { return undefined; } if (subscription.daysLeft <= 0) { return Math.max(0, this.config.gating.gracePeriod + subscription.daysLeft); } return undefined; } setSigner(signer) { this.subscriptionSkill.setSigner(signer); } } exports.TokenGatingSkill = TokenGatingSkill;