ChopTreeButton.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import Image from "next/image"
  2. import { useCallback, useState } from "react"
  3. import { Button, HStack, VStack } from "@chakra-ui/react"
  4. import { useConnection, useWallet } from "@solana/wallet-adapter-react"
  5. import { useSessionWallet } from "@magicblock-labs/gum-react-sdk"
  6. import { useGameState } from "@/contexts/GameStateProvider"
  7. import { GAME_DATA_SEED, gameDataPDA, program } from "@/utils/anchor"
  8. import { PublicKey } from "@solana/web3.js"
  9. import { useNftState } from "@/contexts/NftProvider"
  10. import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"
  11. const ChopTreeButton = () => {
  12. const { publicKey, sendTransaction } = useWallet()
  13. const { connection } = useConnection()
  14. const sessionWallet = useSessionWallet()
  15. const { gameState, playerDataPDA } = useGameState()
  16. const [isLoadingSession, setIsLoadingSession] = useState(false)
  17. const [isLoadingMainWallet, setIsLoadingMainWallet] = useState(false)
  18. const [transactionCounter, setTransactionCounter] = useState(0)
  19. const { nftState: nftState } = useNftState()
  20. const onChopClick = useCallback(async () => {
  21. setIsLoadingSession(true)
  22. if (!playerDataPDA || !sessionWallet) return
  23. setTransactionCounter(transactionCounter + 1);
  24. const nftAuthority = await PublicKey.findProgramAddress(
  25. [Buffer.from("nft_authority")],
  26. program.programId
  27. );
  28. let nft = null;
  29. for (var i = 0; i < nftState.items.length; i++) {
  30. try {
  31. const nftData = nftState.items[i];
  32. if (nftData.authorities[0] == nftAuthority[0].toBase58()) {
  33. nft = nftData;
  34. }
  35. console.log("NFT data", nftData);
  36. } catch (error) {
  37. console.log(error);
  38. }
  39. }
  40. console.log("NFT", nft);
  41. if (nft == null) {
  42. window.alert("Mint and NFT character first");
  43. setIsLoadingMainWallet(false);
  44. return;
  45. }
  46. try {
  47. const transaction = await program.methods
  48. .chopTree(GAME_DATA_SEED, transactionCounter)
  49. .accounts({
  50. player: playerDataPDA,
  51. gameData: gameDataPDA,
  52. signer: sessionWallet.publicKey!,
  53. sessionToken: sessionWallet.sessionToken,
  54. nftAuthority: nftAuthority[0],
  55. mint: nft.id,
  56. })
  57. .transaction()
  58. const txids = await sessionWallet.signAndSendTransaction!(transaction)
  59. if (txids && txids.length > 0) {
  60. console.log("Transaction sent:", txids)
  61. } else {
  62. console.error("Failed to send transaction")
  63. }
  64. } catch (error: any) {
  65. console.log("error", `Chopping failed! ${error?.message}`)
  66. } finally {
  67. setIsLoadingSession(false)
  68. }
  69. }, [sessionWallet, nftState])
  70. const onChopMainWalletClick = useCallback(async () => {
  71. if (!publicKey || !playerDataPDA) return
  72. setIsLoadingMainWallet(true)
  73. const nftAuthority = await PublicKey.findProgramAddress(
  74. [Buffer.from("nft_authority")],
  75. program.programId
  76. );
  77. if (nftState == null) {
  78. window.alert("Load NFT state first");
  79. setIsLoadingMainWallet(false);
  80. return;
  81. }
  82. console.log("NFT state", nftState);
  83. let nft = null;
  84. for (var i = 0; i < nftState.items.length; i++) {
  85. try {
  86. const nftData = nftState.items[i];
  87. console.log(nftData.authorities[0].address + " == " + nftAuthority[0].toBase58());
  88. if (nftData.authorities[0].address === nftAuthority[0].toBase58()) {
  89. nft = nftData;
  90. }
  91. console.log("NFT data", nftData);
  92. } catch (error) {
  93. console.log(error);
  94. }
  95. }
  96. console.log("NFT", nft);
  97. if (nft == null) {
  98. window.alert("Mint and NFT character first");
  99. setIsLoadingMainWallet(false);
  100. return;
  101. }
  102. try {
  103. console.log("NFTid", nft.id, "NFT authority", nft.authorities[0].address);
  104. const transaction = await program.methods
  105. .chopTree(GAME_DATA_SEED, transactionCounter)
  106. .accounts({
  107. player: playerDataPDA,
  108. gameData: gameDataPDA,
  109. signer: publicKey,
  110. sessionToken: null,
  111. nftAuthority: nftAuthority[0].toBase58(),
  112. mint: nft.id,
  113. tokenProgram: TOKEN_2022_PROGRAM_ID
  114. })
  115. .transaction()
  116. const txSig = await sendTransaction(transaction, connection, {
  117. skipPreflight: true,
  118. })
  119. console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`)
  120. } catch (error: any) {
  121. console.log("error", `Chopping failed! ${error?.message}`)
  122. } finally {
  123. setIsLoadingMainWallet(false)
  124. }
  125. }, [publicKey, playerDataPDA, connection, nftState])
  126. return (
  127. <>
  128. {publicKey && gameState && (
  129. <VStack>
  130. <Image src="/Beaver.png" alt="Energy Icon" width={64} height={64} />
  131. <HStack>
  132. {sessionWallet && sessionWallet.sessionToken != null && (
  133. <Button
  134. isLoading={isLoadingSession}
  135. onClick={onChopClick}
  136. width="175px"
  137. >
  138. Chop tree Session
  139. </Button>
  140. )}
  141. <Button
  142. isLoading={isLoadingMainWallet}
  143. onClick={onChopMainWalletClick}
  144. width="175px"
  145. >
  146. Chop tree MainWallet
  147. </Button>
  148. </HStack>
  149. </VStack>
  150. )}
  151. </>
  152. )
  153. }
  154. export default ChopTreeButton