QrCodeCnftMint.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { Button, Flex, VStack } from "@chakra-ui/react"
  2. import {
  3. createQR,
  4. encodeURL,
  5. findReference,
  6. FindReferenceError,
  7. TransactionRequestURLFields,
  8. ValidateTransferError,
  9. } from "@solana/pay"
  10. import { clusterApiUrl, Connection, Keypair } from "@solana/web3.js"
  11. import { useEffect, useRef, useState } from "react"
  12. import Confirmed from "./Confirmed"
  13. interface Props {
  14. onClose: () => void
  15. }
  16. const QrModal = ({ onClose }: Props) => {
  17. const [confirmed, setConfirmed] = useState(false)
  18. const connection = new Connection(clusterApiUrl("devnet"))
  19. const qrRef = useRef<HTMLDivElement>(null)
  20. const [reference] = useState(Keypair.generate().publicKey)
  21. const [size, setSize] = useState(() =>
  22. typeof window === "undefined" ? 100 : Math.min(window.outerWidth - 10, 512)
  23. )
  24. useEffect(() => {
  25. const listener = () => setSize(Math.min(window.outerWidth - 10, 512))
  26. window.addEventListener("resize", listener)
  27. return () => window.removeEventListener("resize", listener)
  28. }, [])
  29. useEffect(() => {
  30. const { location } = window
  31. const params = new URLSearchParams()
  32. params.append("reference", reference.toString())
  33. const apiUrl = `${location.protocol}//${
  34. location.host
  35. }/api/mintCnft?${params.toString()}`
  36. const urlParams: TransactionRequestURLFields = {
  37. link: new URL(apiUrl),
  38. label: "Label",
  39. message: "Message",
  40. }
  41. const solanaUrl = encodeURL(urlParams)
  42. console.log(solanaUrl)
  43. const qr = createQR(solanaUrl, size, "white")
  44. if (qrRef.current) {
  45. qrRef.current.innerHTML = ""
  46. qr.append(qrRef.current)
  47. }
  48. }, [window, size, reference])
  49. useEffect(() => {
  50. const interval = setInterval(async () => {
  51. try {
  52. const signatureInfo = await findReference(connection, reference, {
  53. finality: "confirmed",
  54. })
  55. setConfirmed(true)
  56. } catch (e) {
  57. if (e instanceof FindReferenceError) return
  58. if (e instanceof ValidateTransferError) {
  59. console.error("Transaction is invalid", e)
  60. return
  61. }
  62. console.error("Unknown error", e)
  63. }
  64. }, 500)
  65. return () => {
  66. clearInterval(interval)
  67. setConfirmed(false)
  68. }
  69. }, [reference.toString()])
  70. return (
  71. <VStack
  72. position="fixed"
  73. top="50%"
  74. left="50%"
  75. transform="translate(-50%, -50%)"
  76. backgroundColor="white"
  77. padding="10px"
  78. rounded="2xl"
  79. >
  80. {confirmed ? (
  81. <div style={{ width: size }}>
  82. <Confirmed />
  83. </div>
  84. ) : (
  85. <Flex ref={qrRef} />
  86. )}
  87. <Button
  88. color="gray"
  89. onClick={() => {
  90. setConfirmed(false)
  91. onClose()
  92. }}
  93. >
  94. Close
  95. </Button>
  96. </VStack>
  97. )
  98. }
  99. export default QrModal