mirror of
https://github.com/logos-messaging/rln.waku.org.git
synced 2026-01-07 16:43:05 +00:00
feat: show token spend for rate limit
This commit is contained in:
parent
f7ccf81ba4
commit
a7c1bbbfea
8965
package-lock.json
generated
Normal file
8965
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@
|
|||||||
"@radix-ui/react-toggle": "^1.1.2",
|
"@radix-ui/react-toggle": "^1.1.2",
|
||||||
"@radix-ui/react-toggle-group": "^1.1.2",
|
"@radix-ui/react-toggle-group": "^1.1.2",
|
||||||
"@radix-ui/react-tooltip": "^1.1.8",
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@waku/rln": "0.1.5-a824fff.0",
|
"@waku/rln": "0.1.7-987c6cd.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^12.6.3",
|
"framer-motion": "^12.6.3",
|
||||||
|
|||||||
@ -11,14 +11,13 @@ import { Button } from '../../ui/button';
|
|||||||
import { membershipRegistration, type ContentSegment } from '../../../content/index';
|
import { membershipRegistration, type ContentSegment } from '../../../content/index';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '../../ui/tooltip';
|
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '../../ui/tooltip';
|
||||||
|
|
||||||
interface MembershipRegistrationProps {
|
interface MembershipRegistrationProps {
|
||||||
tabId?: string;
|
tabId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export function MembershipRegistration({ tabId: _tabId }: MembershipRegistrationProps) {
|
export function MembershipRegistration({ tabId: _tabId }: MembershipRegistrationProps) {
|
||||||
const { registerMembership, isInitialized, isStarted, error, isLoading } = useRLN();
|
const { registerMembership, isInitialized, isStarted, error, isLoading, getPriceForRateLimit } = useRLN();
|
||||||
const { isConnected, chainId } = useWallet();
|
const { isConnected, chainId } = useWallet();
|
||||||
|
|
||||||
// Replace slider state with discrete options
|
// Replace slider state with discrete options
|
||||||
@ -37,6 +36,33 @@ export function MembershipRegistration({ tabId: _tabId }: MembershipRegistration
|
|||||||
|
|
||||||
const isLineaSepolia = chainId === 59141;
|
const isLineaSepolia = chainId === 59141;
|
||||||
|
|
||||||
|
const [price, setPrice] = useState<string>('');
|
||||||
|
const [priceLoading, setPriceLoading] = useState(false);
|
||||||
|
const [priceError, setPriceError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isLoading || !isInitialized || !isStarted ) return;
|
||||||
|
let cancelled = false;
|
||||||
|
setPrice('');
|
||||||
|
setPriceError(null);
|
||||||
|
setPriceLoading(true);
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const result = await getPriceForRateLimit(rateLimit);
|
||||||
|
if (!cancelled) {
|
||||||
|
setPrice(result.price.toString());
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
if (!cancelled) {
|
||||||
|
setPriceError('Could not fetch price');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (!cancelled) setPriceLoading(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return () => { cancelled = true; };
|
||||||
|
}, [rateLimit, getPriceForRateLimit, isLoading, isInitialized, isStarted]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (error) {
|
if (error) {
|
||||||
toast.error(error);
|
toast.error(error);
|
||||||
@ -210,6 +236,16 @@ export function MembershipRegistration({ tabId: _tabId }: MembershipRegistration
|
|||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Show calculated token spend for selected rate limit */}
|
||||||
|
<div className="text-xs text-muted-foreground font-mono mt-1">
|
||||||
|
{priceLoading ? (
|
||||||
|
<>Token spend required: <span className="italic">Loading...</span></>
|
||||||
|
) : priceError ? (
|
||||||
|
<>Token spend required: <span className="text-destructive">{priceError}</span></>
|
||||||
|
) : (
|
||||||
|
<>Token spend required: <span>{price}</span> WTT</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
|||||||
@ -33,6 +33,7 @@ interface RLNContextType {
|
|||||||
getRateLimitsBounds: () => Promise<{ success: boolean; rateMinLimit: number; rateMaxLimit: number; error?: string }>;
|
getRateLimitsBounds: () => Promise<{ success: boolean; rateMinLimit: number; rateMaxLimit: number; error?: string }>;
|
||||||
saveCredentialsToKeystore: (credentials: KeystoreEntity, password: string) => Promise<string>;
|
saveCredentialsToKeystore: (credentials: KeystoreEntity, password: string) => Promise<string>;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
getPriceForRateLimit: (rateLimit: number) => Promise<{ price: string }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RLNContext = createContext<RLNContextType | undefined>(undefined);
|
const RLNContext = createContext<RLNContextType | undefined>(undefined);
|
||||||
@ -465,6 +466,20 @@ export function RLNProvider({ children }: { children: ReactNode }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getPriceForRateLimit = async (rateLimit: number): Promise<{ price: string }> => {
|
||||||
|
try {
|
||||||
|
if (!rln || !rln.contract || !isStarted) {
|
||||||
|
throw new Error('RLN not initialized or contract not available');
|
||||||
|
}
|
||||||
|
const result = await rln.contract.getPriceForRateLimit(rateLimit);
|
||||||
|
const formatted = ethers.utils.formatUnits(result.price, 18);
|
||||||
|
return { price: formatted };
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error getting price for rate limit:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RLNContext.Provider
|
<RLNContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@ -483,7 +498,8 @@ export function RLNProvider({ children }: { children: ReactNode }) {
|
|||||||
getCurrentRateLimit,
|
getCurrentRateLimit,
|
||||||
getRateLimitsBounds,
|
getRateLimitsBounds,
|
||||||
saveCredentialsToKeystore: saveToKeystore,
|
saveCredentialsToKeystore: saveToKeystore,
|
||||||
isLoading
|
isLoading,
|
||||||
|
getPriceForRateLimit
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@ -14,4 +14,4 @@ export function cn(...inputs: ClassValue[]) {
|
|||||||
*/
|
*/
|
||||||
export function hslToVar(hsl: string): string {
|
export function hslToVar(hsl: string): string {
|
||||||
return `hsl(var(${hsl}))`;
|
return `hsl(var(${hsl}))`;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user