@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
336 lines (335 loc) • 24.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Web3SubscriptionWidget = Web3SubscriptionWidget;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const theme_1 = require("./theme");
const Web3SubscriptionSkill_1 = require("../Web3SubscriptionSkill");
function Web3SubscriptionWidget({ config, className, style }) {
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
const [currentStep, setCurrentStep] = (0, react_1.useState)('plans');
const [selectedPlan, setSelectedPlan] = (0, react_1.useState)(null);
const [userAddress, setUserAddress] = (0, react_1.useState)('');
const [paymentMethods, setPaymentMethods] = (0, react_1.useState)([]);
const [selectedPaymentMethod, setSelectedPaymentMethod] = (0, react_1.useState)(null);
const [loading, setLoading] = (0, react_1.useState)(false);
const [error, setError] = (0, react_1.useState)(null);
const [subscription, setSubscription] = (0, react_1.useState)(null);
const theme = (0, theme_1.getTheme)(config.theme || 'auto');
(0, react_1.useEffect)(() => {
// Inject CSS variables
const styleElement = document.createElement('style');
styleElement.textContent = `
.agentdao-widget {
${(0, theme_1.generateCSSVariables)(theme)}
}
`;
document.head.appendChild(styleElement);
return () => {
document.head.removeChild(styleElement);
};
}, [theme]);
const handlePlanSelect = (plan) => {
setSelectedPlan(plan);
setCurrentStep('payment');
};
const handlePaymentMethodSelect = (method) => {
setSelectedPaymentMethod(method);
};
const handleSubscribe = async () => {
if (!selectedPlan || !selectedPaymentMethod || !userAddress) {
setError('Please fill in all required fields');
return;
}
setLoading(true);
setError(null);
try {
// Convert SubscriptionPlan to the format expected by Web3SubscriptionSkill
const plansConfig = config.plans.reduce((acc, plan) => {
acc[plan.id] = {
name: plan.name,
description: plan.description,
features: plan.features,
pricing: {
monthly: { price: plan.price, discount: 0 },
quarterly: { price: plan.price * 3 * 0.9, discount: 10 },
annually: { price: plan.price * 12 * 0.8, discount: 20 }
},
billing: {
allowTrial: plan.trialDays ? true : false,
trialDays: plan.trialDays || 0,
gracePeriodDays: 3
}
};
return acc;
}, {});
const subscriptionSkill = new Web3SubscriptionSkill_1.Web3SubscriptionSkill({
agentId: config.agentId,
agentName: config.agentName,
domain: config.domain,
plans: plansConfig,
adaoToken: {
address: selectedPaymentMethod.address,
decimals: selectedPaymentMethod.decimals,
network: 'base'
},
provider: {
rpcUrl: config.provider?.rpcUrl || 'https://mainnet.base.org',
chainId: config.provider?.chainId || 8453,
explorer: config.provider?.explorer || 'https://basescan.org'
},
payment: {
autoApprove: true,
requireConfirmation: false,
refundPolicy: {
enabled: true,
gracePeriod: 7
},
billing: {
allowTrial: true,
trialDays: 7,
gracePeriodDays: 3
}
},
integration: {
webhookUrl: config.onSubscriptionCreated ? undefined : undefined,
redirectUrl: undefined,
successMessage: 'Subscription created successfully!',
errorMessage: 'Failed to create subscription'
},
analytics: {
trackRevenue: true,
trackUsage: true,
exportData: false
}
});
const newSubscription = await subscriptionSkill.createSubscription(userAddress, selectedPlan.id, selectedPlan.billingPeriod);
setSubscription(newSubscription);
setCurrentStep('success');
if (config.onSubscriptionCreated) {
config.onSubscriptionCreated(newSubscription);
}
}
catch (err) {
setError(err instanceof Error ? err.message : 'Failed to create subscription');
if (config.onError) {
config.onError(err instanceof Error ? err : new Error('Unknown error'));
}
}
finally {
setLoading(false);
}
};
const getPositionStyles = () => {
const baseStyles = {
position: 'fixed',
zIndex: 9999,
...style
};
switch (config.position) {
case 'bottom-right':
return { ...baseStyles, bottom: '20px', right: '20px' };
case 'bottom-left':
return { ...baseStyles, bottom: '20px', left: '20px' };
case 'top-right':
return { ...baseStyles, top: '20px', right: '20px' };
case 'top-left':
return { ...baseStyles, top: '20px', left: '20px' };
case 'center':
return { ...baseStyles, top: '50%', left: '50%', transform: 'translate(-50%, -50%)' };
default:
return { ...baseStyles, bottom: '20px', right: '20px' };
}
};
return ((0, jsx_runtime_1.jsxs)("div", { className: `agentdao-widget ${className || ''}`, style: getPositionStyles(), children: [!isOpen && ((0, jsx_runtime_1.jsx)("button", { onClick: () => setIsOpen(true), style: {
width: '60px',
height: '60px',
borderRadius: '50%',
backgroundColor: theme.colors.primary,
color: 'white',
border: 'none',
cursor: 'pointer',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
fontSize: '24px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}, children: "\uD83D\uDCB0" })), isOpen && ((0, jsx_runtime_1.jsx)("div", { style: {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 10000,
}, onClick: () => setIsOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { style: {
backgroundColor: theme.colors.surface,
borderRadius: theme.borderRadius.lg,
padding: theme.spacing.lg,
maxWidth: '500px',
width: '90%',
maxHeight: '80vh',
overflow: 'auto',
boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1)',
}, onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: theme.spacing.lg }, children: [(0, jsx_runtime_1.jsxs)("h2", { style: {
color: theme.colors.text,
fontSize: theme.typography.fontSize.lg,
margin: 0,
fontFamily: theme.typography.fontFamily
}, children: ["Subscribe to ", config.agentName] }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setIsOpen(false), style: {
background: 'none',
border: 'none',
fontSize: '24px',
cursor: 'pointer',
color: theme.colors.textSecondary,
}, children: "\u00D7" })] }), currentStep === 'plans' && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { style: {
color: theme.colors.text,
fontSize: theme.typography.fontSize.md,
marginBottom: theme.spacing.md,
fontFamily: theme.typography.fontFamily
}, children: "Choose a Plan" }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md }, children: config.plans.map((plan) => ((0, jsx_runtime_1.jsxs)("div", { style: {
border: `1px solid ${theme.colors.border}`,
borderRadius: theme.borderRadius.md,
padding: theme.spacing.md,
cursor: 'pointer',
backgroundColor: plan.popular ? theme.colors.primary + '10' : 'transparent',
position: 'relative',
}, onClick: () => handlePlanSelect(plan), children: [plan.popular && ((0, jsx_runtime_1.jsx)("div", { style: {
position: 'absolute',
top: '-8px',
right: '16px',
backgroundColor: theme.colors.primary,
color: 'white',
padding: '4px 8px',
borderRadius: theme.borderRadius.sm,
fontSize: theme.typography.fontSize.xs,
}, children: "Popular" })), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h4", { style: {
color: theme.colors.text,
margin: '0 0 4px 0',
fontSize: theme.typography.fontSize.md,
fontFamily: theme.typography.fontFamily
}, children: plan.name }), (0, jsx_runtime_1.jsx)("p", { style: {
color: theme.colors.textSecondary,
margin: '0 0 8px 0',
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily
}, children: plan.description }), (0, jsx_runtime_1.jsx)("ul", { style: {
margin: '0 0 8px 0',
paddingLeft: '20px',
fontSize: theme.typography.fontSize.sm,
color: theme.colors.textSecondary,
fontFamily: theme.typography.fontFamily
}, children: plan.features.map((feature, index) => ((0, jsx_runtime_1.jsx)("li", { children: feature }, index))) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'right' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
fontSize: theme.typography.fontSize.lg,
fontWeight: 'bold',
color: theme.colors.text,
fontFamily: theme.typography.fontFamily
}, children: ["$", plan.price] }), (0, jsx_runtime_1.jsxs)("div", { style: {
fontSize: theme.typography.fontSize.sm,
color: theme.colors.textSecondary,
fontFamily: theme.typography.fontFamily
}, children: ["per ", plan.billingPeriod] }), plan.trialDays && ((0, jsx_runtime_1.jsxs)("div", { style: {
fontSize: theme.typography.fontSize.xs,
color: theme.colors.success,
fontFamily: theme.typography.fontFamily
}, children: [plan.trialDays, " days free trial"] }))] })] })] }, plan.id))) })] })), currentStep === 'payment' && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { style: {
color: theme.colors.text,
fontSize: theme.typography.fontSize.md,
marginBottom: theme.spacing.md,
fontFamily: theme.typography.fontFamily
}, children: "Payment Details" }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: theme.spacing.md }, children: [(0, jsx_runtime_1.jsx)("label", { style: {
display: 'block',
marginBottom: '4px',
color: theme.colors.text,
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily
}, children: "Wallet Address" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: userAddress, onChange: (e) => setUserAddress(e.target.value), placeholder: "0x...", style: {
width: '100%',
padding: theme.spacing.sm,
border: `1px solid ${theme.colors.border}`,
borderRadius: theme.borderRadius.sm,
backgroundColor: theme.colors.background,
color: theme.colors.text,
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily,
boxSizing: 'border-box',
} })] }), paymentMethods.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: theme.spacing.md }, children: [(0, jsx_runtime_1.jsx)("label", { style: {
display: 'block',
marginBottom: '4px',
color: theme.colors.text,
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily
}, children: "Payment Method" }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.sm }, children: paymentMethods.map((method) => ((0, jsx_runtime_1.jsx)("div", { style: {
border: `1px solid ${selectedPaymentMethod?.address === method.address ? theme.colors.primary : theme.colors.border}`,
borderRadius: theme.borderRadius.sm,
padding: theme.spacing.sm,
cursor: 'pointer',
backgroundColor: selectedPaymentMethod?.address === method.address ? theme.colors.primary + '10' : 'transparent',
}, onClick: () => handlePaymentMethodSelect(method), children: (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
fontWeight: 'bold',
color: theme.colors.text,
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily
}, children: method.symbol }), (0, jsx_runtime_1.jsxs)("div", { style: {
color: theme.colors.textSecondary,
fontSize: theme.typography.fontSize.xs,
fontFamily: theme.typography.fontFamily
}, children: ["Balance: ", method.balance, " ", method.symbol] })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
color: theme.colors.textSecondary,
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily
}, children: ["$", method.priceUSD?.toFixed(2)] })] }) }, method.address))) })] })), error && ((0, jsx_runtime_1.jsx)("div", { style: {
backgroundColor: theme.colors.error + '10',
color: theme.colors.error,
padding: theme.spacing.sm,
borderRadius: theme.borderRadius.sm,
marginBottom: theme.spacing.md,
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily
}, children: error })), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: theme.spacing.sm }, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setCurrentStep('plans'), style: {
padding: `${theme.spacing.sm} ${theme.spacing.md}`,
border: `1px solid ${theme.colors.border}`,
borderRadius: theme.borderRadius.sm,
backgroundColor: 'transparent',
color: theme.colors.text,
cursor: 'pointer',
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily,
flex: 1,
}, children: "Back" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleSubscribe, disabled: loading || !userAddress || !selectedPaymentMethod, style: {
padding: `${theme.spacing.sm} ${theme.spacing.md}`,
border: 'none',
borderRadius: theme.borderRadius.sm,
backgroundColor: loading ? theme.colors.secondary : theme.colors.primary,
color: 'white',
cursor: loading ? 'not-allowed' : 'pointer',
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily,
flex: 2,
}, children: loading ? 'Processing...' : `Subscribe for $${selectedPlan?.price}` })] })] })), currentStep === 'success' && ((0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center' }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
fontSize: '48px',
marginBottom: theme.spacing.md
}, children: "\u2705" }), (0, jsx_runtime_1.jsx)("h3", { style: {
color: theme.colors.text,
fontSize: theme.typography.fontSize.lg,
marginBottom: theme.spacing.sm,
fontFamily: theme.typography.fontFamily
}, children: "Subscription Created!" }), (0, jsx_runtime_1.jsxs)("p", { style: {
color: theme.colors.textSecondary,
fontSize: theme.typography.fontSize.sm,
marginBottom: theme.spacing.lg,
fontFamily: theme.typography.fontFamily
}, children: ["You now have access to ", selectedPlan?.name, " features."] }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setIsOpen(false), style: {
padding: `${theme.spacing.sm} ${theme.spacing.lg}`,
border: 'none',
borderRadius: theme.borderRadius.sm,
backgroundColor: theme.colors.primary,
color: 'white',
cursor: 'pointer',
fontSize: theme.typography.fontSize.sm,
fontFamily: theme.typography.fontFamily,
}, children: "Close" })] }))] }) }))] }));
}