22
33import { useState } from "react"
44import { motion , AnimatePresence } from "framer-motion"
5- import { Zap , CheckCircle , Clock , Wallet , Settings , AlertTriangle , Activity , XCircle , Info } from "lucide-react"
5+ import { Zap , CheckCircle , Clock , Wallet , Settings , AlertTriangle , Activity , XCircle , Info , ExternalLink } from "lucide-react"
66import { Button } from "@/components/ui/button"
77import { Input } from "@/components/ui/input"
88import { Label } from "@/components/ui/label"
@@ -33,7 +33,7 @@ const NFT_CONFIGS: Record<NFTSize, NFTConfig> = {
3333 } ,
3434 big : {
3535 size : "big" ,
36- minGas : 150000 ,
36+ minGas : 550000 ,
3737 description : "Complex NFT with rich metadata and attributes" ,
3838 } ,
3939}
@@ -71,6 +71,78 @@ export default function PythentropyNFTDemo() {
7171 NFT Minting with Enhanced Callback Status Monitoring
7272 </ p >
7373
74+ { /* What You'll Learn Section */ }
75+ < div className = "max-w-4xl mx-auto mb-6" >
76+ < Card className = "bg-gradient-to-r from-blue-50 to-purple-50 dark:from-blue-900/20 dark:to-purple-900/20 border-blue-200 dark:border-blue-800" >
77+ < CardHeader className = "text-center pb-4" >
78+ < CardTitle className = "text-2xl text-blue-900 dark:text-blue-100" > 🎓 What You'll Learn</ CardTitle >
79+ < CardDescription className = "text-blue-800 dark:text-blue-200 text-lg" >
80+ Understand the complete Pyth Entropy v2 flow from your contract to the provider and back
81+ </ CardDescription >
82+ </ CardHeader >
83+ < CardContent className = "space-y-4" >
84+ < div className = "grid md:grid-cols-2 gap-6" >
85+ < div className = "space-y-3" >
86+ < h3 className = "font-semibold text-blue-900 dark:text-blue-100 text-lg" > 📚 Learning Objectives</ h3 >
87+ < ul className = "space-y-2 text-sm text-blue-800 dark:text-blue-200" >
88+ < li className = "flex items-start gap-2" >
89+ < span className = "w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0" > </ span >
90+ How your contract requests entropy from Pyth Entropy v2
91+ </ li >
92+ < li className = "flex items-start gap-2" >
93+ < span className = "w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0" > </ span >
94+ How Entropy processes requests and sends to providers
95+ </ li >
96+ < li className = "flex items-start gap-2" >
97+ < span className = "w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0" > </ span >
98+ How callbacks return results and handle failures
99+ </ li >
100+ </ ul >
101+ </ div >
102+ < div className = "space-y-3" >
103+ < h3 className = "font-semibold text-blue-900 dark:text-blue-100 text-lg" > 🧪 Demo Steps</ h3 >
104+ < div className = "space-y-3" >
105+ < div className = "p-3 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg" >
106+ < div className = "font-medium text-green-800 dark:text-green-200" > Step 1: Success Scenario</ div >
107+ < div className = "text-sm text-green-700 dark:text-green-300" > Mint a small NFT with default gas to see successful callback</ div >
108+ </ div >
109+ < div className = "p-3 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800 rounded-lg" >
110+ < div className = "font-medium text-orange-800 dark:text-orange-200" > Step 2: Failure Scenario</ div >
111+ < div className = "text-sm text-orange-700 dark:text-orange-300" > Mint a big NFT with only 10 gas to see callback failure</ div >
112+ </ div >
113+ </ div >
114+ </ div >
115+ </ div >
116+
117+ { /* Base Sepolia Faucet Button */ }
118+ < div className = "pt-4 border-t border-blue-200 dark:border-blue-800" >
119+ < div className = "text-center" >
120+ < p className = "text-sm text-blue-700 dark:text-blue-300 mb-3" >
121+ 💡 Need testnet ETH to try this demo?
122+ </ p >
123+ < Button
124+ asChild
125+ className = "bg-orange-500 hover:bg-orange-600 text-white"
126+ >
127+ < a
128+ href = "https://faucet.quicknode.com/base/sepolia"
129+ target = "_blank"
130+ rel = "noopener noreferrer"
131+ className = "inline-flex items-center gap-2"
132+ >
133+ 🚰 Get Base Sepolia Testnet ETH
134+ < ExternalLink className = "w-4 h-4" />
135+ </ a >
136+ </ Button >
137+ < p className = "text-xs text-blue-600 dark:text-blue-400 mt-2" >
138+ QuickNode faucet provides 0.05 ETH every 12 hours
139+ </ p >
140+ </ div >
141+ </ div >
142+ </ CardContent >
143+ </ Card >
144+ </ div >
145+
74146 { /* Contract Status */ }
75147 < div className = "max-w-2xl mx-auto mb-4 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg" >
76148 < div className = "flex justify-between items-center" >
@@ -148,6 +220,44 @@ export default function PythentropyNFTDemo() {
148220 < CardDescription > Configure your NFT size and gas settings below</ CardDescription >
149221 </ CardHeader >
150222 < CardContent className = "space-y-6" >
223+ { /* Guided Demo Buttons */ }
224+ < div className = "space-y-3" >
225+ < Label className = "text-sm font-medium text-gray-700 dark:text-gray-300" > 🎯 Quick Demo Actions</ Label >
226+ < div className = "grid grid-cols-2 gap-3" >
227+ < Button
228+ onClick = { ( ) => {
229+ setNftSize ( "small" )
230+ setGasLimit ( "50000" )
231+ } }
232+ disabled = { isMinting }
233+ variant = "outline"
234+ className = "text-sm h-auto py-3 px-4"
235+ >
236+ < div className = "text-left" >
237+ < div className = "font-medium" > ✅ Success Demo</ div >
238+ < div className = "text-xs text-gray-500" > Small NFT + 50k gas</ div >
239+ </ div >
240+ </ Button >
241+ < Button
242+ onClick = { ( ) => {
243+ setNftSize ( "big" )
244+ setGasLimit ( "10" )
245+ } }
246+ disabled = { isMinting }
247+ variant = "outline"
248+ className = "text-sm h-auto py-3 px-4"
249+ >
250+ < div className = "text-left" >
251+ < div className = "font-medium" > ❌ Failure Demo</ div >
252+ < div className = "text-xs text-gray-500" > Big NFT + 10 gas</ div >
253+ </ div >
254+ </ Button >
255+ </ div >
256+ < p className = "text-xs text-gray-500 dark:text-gray-400" >
257+ Click these buttons to quickly set up the recommended demo scenarios
258+ </ p >
259+ </ div >
260+
151261 < div className = "space-y-2" >
152262 < Label htmlFor = "nft-size" > NFT Size</ Label >
153263 < Select value = { nftSize } onValueChange = { handleNFTSizeChange } disabled = { isMinting } >
@@ -230,7 +340,9 @@ export default function PythentropyNFTDemo() {
230340 < Activity className = "w-5 h-5" />
231341 Event Details
232342 </ CardTitle >
233- < CardDescription > Returned event from Beast Minted</ CardDescription >
343+ < CardDescription >
344+ Returned event from Pyth Entropy v2 Contract - This shows the callback result
345+ </ CardDescription >
234346 </ CardHeader >
235347 < CardContent className = "space-y-4" >
236348 { callbackCompleted ? (
@@ -245,48 +357,65 @@ export default function PythentropyNFTDemo() {
245357 </ p >
246358 </ div >
247359
360+ { /* Event Source Info */ }
361+ < div className = "p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg" >
362+ < div className = "flex items-center gap-2 text-blue-800 dark:text-blue-200" >
363+ < Info className = "w-4 h-4" />
364+ < span className = "font-medium" > Event Source</ span >
365+ </ div >
366+ < p className = "text-sm text-blue-700 dark:text-blue-300 mt-1" >
367+ This event comes from the Pyth Entropy v2 contract, not your NFT contract. It shows the callback execution result.
368+ </ p >
369+ </ div >
370+
248371 { revealedEvent && (
249372 < div className = "space-y-3" >
250373 < div className = "space-y-2" >
251374 < Label className = "text-sm font-medium" > Provider Address</ Label >
252375 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm break-all" >
253376 { revealedEvent . args . provider }
254377 </ div >
378+ < p className = "text-xs text-gray-500 dark:text-gray-400" > The Fortuna provider that generated the entropy</ p >
255379 </ div >
256380
257381 < div className = "space-y-2" >
258382 < Label className = "text-sm font-medium" > Caller Address</ Label >
259383 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm break-all" >
260384 { revealedEvent . args . caller }
261385 </ div >
386+ < p className = "text-xs text-gray-500 dark:text-gray-400" > Your contract address that requested the entropy</ p >
262387 </ div >
263388
264389 < div className = "space-y-2" >
265390 < Label className = "text-sm font-medium" > Sequence Number</ Label >
266391 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm" >
267392 { revealedEvent . args . sequenceNumber ?. toString ( ) }
268393 </ div >
394+ < p className = "text-xs text-gray-500 dark:text-gray-400" > Unique identifier for this entropy request</ p >
269395 </ div >
270396
271397 < div className = "space-y-2" >
272398 < Label className = "text-sm font-medium" > Random Number</ Label >
273399 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm break-all" >
274400 { revealedEvent . args . randomNumber }
275401 </ div >
402+ < p className = "text-xs text-gray-500 dark:text-gray-400" > The entropy value generated by the provider</ p >
276403 </ div >
277404
278405 < div className = "space-y-2" >
279406 < Label className = "text-sm font-medium" > User Contribution</ Label >
280407 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm break-all" >
281408 { revealedEvent . args . userContribution }
282409 </ div >
410+ < p className = "text-xs text-gray-500 dark:text-gray-400" > Your contribution to the entropy generation</ p >
283411 </ div >
284412
285413 < div className = "space-y-2" >
286414 < Label className = "text-sm font-medium" > Provider Contribution</ Label >
287415 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm break-all" >
288416 { revealedEvent . args . providerContribution }
289417 </ div >
418+ < p className = "text-xs text-gray-500 dark:text-gray-400" > Provider's contribution to the entropy generation</ p >
290419 </ div >
291420
292421 < div className = "space-y-2" >
@@ -298,27 +427,36 @@ export default function PythentropyNFTDemo() {
298427 } `} >
299428 { revealedEvent . args . callbackFailed ? 'Failed ❌' : 'Success ✅' }
300429 </ div >
430+ < p className = "text-xs text-gray-500 dark:text-gray-400" >
431+ { revealedEvent . args . callbackFailed
432+ ? 'Your contract callback failed (likely due to insufficient gas)'
433+ : 'Your contract callback executed successfully'
434+ }
435+ </ p >
301436 </ div >
302437
303438 < div className = "space-y-2" >
304439 < Label className = "text-sm font-medium" > Callback Return Value</ Label >
305440 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm break-all" >
306441 { revealedEvent . args . callbackReturnValue || '0x' }
307442 </ div >
443+ < p className = "text-xs text-gray-500 dark:text-gray-400" > Return value from your contract's callback function</ p >
308444 </ div >
309445
310446 < div className = "space-y-2" >
311447 < Label className = "text-sm font-medium" > Callback Gas Used</ Label >
312448 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm" >
313449 { revealedEvent . args . callbackGasUsed ?. toString ( ) || '0' }
314450 </ div >
451+ < p className = "text-xs text-gray-500 dark:text-gray-400" > Gas consumed by your contract's callback execution</ p >
315452 </ div >
316453
317454 < div className = "space-y-2" >
318455 < Label className = "text-sm font-medium" > Extra Args</ Label >
319456 < div className = "p-2 bg-gray-50 dark:bg-gray-800 rounded border font-mono text-sm break-all" >
320457 { revealedEvent . args . extraArgs || '0x' }
321458 </ div >
459+ < p className = "text-xs text-gray-500 dark:text-gray-400" > Additional arguments passed to your callback function</ p >
322460 </ div >
323461 </ div >
324462 ) }
@@ -378,9 +516,9 @@ export default function PythentropyNFTDemo() {
378516 < div className = "w-12 h-12 bg-blue-100 dark:bg-blue-900/30 rounded-lg flex items-center justify-center mx-auto mb-3" >
379517 < Settings className = "w-6 h-6 text-blue-600 dark:text-blue-400" />
380518 </ div >
381- < h3 className = "font-semibold mb-2 dark:text-white" > Smart Gas Management </ h3 >
519+ < h3 className = "font-semibold mb-2 dark:text-white" > Configurable Gas Limits </ h3 >
382520 < p className = "text-sm text-gray-600 dark:text-gray-300" >
383- Automatic gas estimation with size-based requirements
521+ Configurable Gas Limits for Callbacks
384522 </ p >
385523 </ div >
386524 < div className = "text-center" >
@@ -396,75 +534,14 @@ export default function PythentropyNFTDemo() {
396534 < div className = "w-12 h-12 bg-green-100 dark:bg-green-900/30 rounded-lg flex items-center justify-center mx-auto mb-3" >
397535 < Activity className = "w-6 h-6 text-green-600 dark:text-green-400" />
398536 </ div >
399- < h3 className = "font-semibold mb-2 dark:text-white" > Real-time Event Monitoring </ h3 >
537+ < h3 className = "font-semibold mb-2 dark:text-white" > Public Entropy Explorer </ h3 >
400538 < p className = "text-sm text-gray-600 dark:text-gray-300" >
401- Live event logs showing the complete transaction lifecycle
539+ Public Entropy Explorer for all Pyth Entropy requests at < a href = "https://entropy-explorer.pyth.network/" target = "_blank" rel = "noopener noreferrer" className = "text-blue-600 dark:text-blue-400 hover:underline" > entropy-explorer.pyth.network </ a >
402540 </ p >
403541 </ div >
404542 </ div >
405543 </ CardContent >
406544 </ Card >
407-
408- { /* Usage Notes */ }
409- < Card className = "mt-8" >
410- < CardHeader >
411- < CardTitle > How to Use This Demo</ CardTitle >
412- </ CardHeader >
413- < CardContent >
414- < div className = "grid md:grid-cols-2 gap-6" >
415- < div >
416- < h3 className = "font-semibold mb-3 text-gray-900 dark:text-white" > Getting Started</ h3 >
417- < ul className = "space-y-2 text-sm text-gray-600 dark:text-gray-300" >
418- < li className = "flex items-start gap-2" >
419- < span className = "w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0" > </ span >
420- Connect your wallet using the button above (optional for demo)
421- </ li >
422- < li className = "flex items-start gap-2" >
423- < span className = "w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0" > </ span >
424- Choose between Small or Big NFT to see different gas requirements
425- </ li >
426- < li className = "flex items-start gap-2" >
427- < span className = "w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0" > </ span >
428- Adjust gas limit to trigger different callback scenarios
429- </ li >
430- < li className = "flex items-start gap-2" >
431- < span className = "w-2 h-2 bg-blue-500 rounded-full mt-2 flex-shrink-0" > </ span >
432- Watch the flow visualization and event logs in real-time
433- </ li >
434- </ ul >
435- </ div >
436- < div >
437- < h3 className = "font-semibold mb-3 text-gray-900 dark:text-white" > What You'll Learn</ h3 >
438- < ul className = "space-y-2 text-sm text-gray-600 dark:text-gray-300" >
439- < li className = "flex items-start gap-2" >
440- < span className = "w-2 h-2 bg-green-500 rounded-full mt-2 flex-shrink-0" > </ span >
441- How Pyth Entropy v2 handles custom gas limits
442- </ li >
443- < li className = "flex items-start gap-2" >
444- < span className = "w-2 h-2 bg-green-500 rounded-full mt-2 flex-shrink-0" > </ span >
445- Enhanced callback status detection and error handling
446- </ li >
447- < li className = "flex items-start gap-2" >
448- < span className = "w-2 h-2 bg-green-500 rounded-full mt-2 flex-shrink-0" > </ span >
449- Real-time event monitoring and transaction lifecycle
450- </ li >
451- < li className = "flex items-start gap-2" >
452- < span className = "w-2 h-2 bg-green-500 rounded-full mt-2 flex-shrink-0" > </ span >
453- Out-of-gas detection and failure reason analysis
454- </ li >
455- </ ul >
456- </ div >
457- </ div >
458-
459- < div className = "mt-6 p-4 bg-gray-50 dark:bg-gray-900 rounded-lg" >
460- < h4 className = "font-medium text-gray-900 dark:text-white mb-2" > 💡 Pro Tip</ h4 >
461- < p className = "text-sm text-gray-600 dark:text-gray-300" >
462- Try setting the gas limit below the minimum requirement for your selected NFT size to see how Entropy v2
463- detects and reports out-of-gas failures in the callback status.
464- </ p >
465- </ div >
466- </ CardContent >
467- </ Card >
468545 </ div >
469546 </ div >
470547 )
0 commit comments