src/Controller/Api/ApiWalletController.php line 261

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Api;
  3. use App\Entity\WEB3\NFT;
  4. use App\Entity\User\User;
  5. use App\Entity\WEB3\TX;
  6. use App\Entity\WEB3\Wallet;
  7. use App\Service\NFT\QRCodeGenerator;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  10. use Symfony\Component\HttpFoundation\JsonResponse;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\Routing\Annotation\Route;
  14. use Symfony\Component\Security\Core\Security;
  15. class ApiWalletController extends AbstractController
  16. {
  17.     private Security $security;
  18.     private EntityManagerInterface $em;
  19.     private QRCodeGenerator $qr;
  20.     public function __construct(Security $securityEntityManagerInterface $emQRCodeGenerator $qr)
  21.     {
  22.         $this->security $security;
  23.         $this->em $em;
  24.         $this->qr $qr;
  25.     }
  26.     #[Route('/web3api/wallet/history'name'web3api_wallet_history'methods: ['GET'])]
  27.     public function walletHistory(Request $request): JsonResponse
  28.     {
  29.         // 1. Get the currently logged-in user
  30.         $user $this->security->getUser();
  31.         if (!$user) {
  32.             return new JsonResponse(['error' => 'User is not logged in'], 403);
  33.         }
  34.         // 2. Get pagination, sorting, and search parameters
  35.         $page $request->query->getInt('page'1);
  36.         $limit $request->query->getInt('limit'20);
  37.         $sortField $request->query->get('sortField''id');
  38.         $sortOrder $request->query->get('sortOrder''desc');
  39.         $search $request->query->get('search'null);
  40.         // 3. Build query for TXs for this user
  41.         $qb $this->em->createQueryBuilder();
  42.         $qb->select('tx')
  43.             ->from(TX::class, 'tx')
  44.             ->where('tx.userId = :userId')
  45.             ->setParameter('userId'$user->getId())
  46.             ->orderBy('tx.' $sortField$sortOrder)
  47.             ->setFirstResult(($page 1) * $limit)
  48.             ->setMaxResults($limit);
  49.         if ($search) {
  50.             $qb->andWhere(
  51.                 $qb->expr()->orX(
  52.                     $qb->expr()->like('tx.txHash'':search'),
  53.                     $qb->expr()->like('tx.action'':search')
  54.                 )
  55.             )->setParameter('search''%' $search '%');
  56.         }
  57.         $txs $qb->getQuery()->getResult();
  58.         $countQb = clone $qb;
  59.         $countQb->select('COUNT(tx.id)');
  60.         $countQb->setFirstResult(null)->setMaxResults(null);
  61.         $total = (int) $countQb->getQuery()->getSingleScalarResult();
  62.         $txArray = [];
  63.         foreach ($txs as $tx) {
  64.             $txArray[] = [
  65.                 'id'        => $tx->getId(),
  66.                 'action'    => $tx->getAction(),
  67.                 'txHash'    => $tx->getTxHash(),
  68.                 'txStatus'  => $tx->getTxStatus(),
  69.                 'createdAt' => $tx->getCreatedAt()?->format('Y-m-d H:i:s'),
  70.                 'error'     => $tx->getError(),
  71.             ];
  72.         }
  73.         return $this->json([
  74.             'data' => $txArray,
  75.             'meta' => [
  76.                 'total' => $total,
  77.                 'page'  => $page,
  78.                 'limit' => $limit,
  79.                 'pages' => ceil($total $limit),
  80.             ],
  81.         ]);
  82.     }
  83.     #[Route('/web3api/wallet/nft'name'web3api_wallet_nft'methods: ['GET'])]
  84.     public function walletNFT(): JsonResponse
  85.     {
  86.         // 1) Auth check (your pattern)
  87.         $user $this->security->getUser();
  88.         if (!$user) {
  89.             return new JsonResponse(['error' => 'User is not logged in'], 403);
  90.         }
  91.         $nfts $this->em->getRepository(NFT::class)->findBy(['user' => $user]);
  92.         if (empty($nfts)) {
  93.             return new JsonResponse(['message' => 'No NFTs found for this user'], 404);
  94.         }
  95.         $nftData = [];
  96.         foreach ($nfts as $nft) {
  97.             $collection $nft->getCollection();
  98.             $brand      $collection?->getBrand();
  99.             $brandUser  $brand?->getUser();
  100.             $token      $collection?->getCashbackToken();
  101.             $nftData[] = [
  102.                 'collection' => $collection ? [
  103.                     'collectionId'    => $collection->getId(),
  104.                     'name'            => $collection->getName(),
  105.                     'baseUri'         => $collection->getIpfsBaseUri(),
  106.                     'contractAddress' => $collection->getContractAddress(),
  107.                 ] : null,
  108.                 'brand' => $brand ? [
  109.                     'name'     => $brand->getName(),
  110.                     'logo'     => $brand->getLogo(),
  111.                     'user'     => $brandUser?->getUsername(),
  112.                     'verified' => method_exists($brand'isVerified') ? $brand->isVerified() : null,
  113.                 ] : null,
  114.                 'cashbackToken' => $token ? [
  115.                     'name'            => $token->getName(),
  116.                     'symbol'          => $token->getSymbol(),
  117.                     'contractAddress' => $token->getContractAddress(),
  118.                     'decimals'        => $token->getDecimals(),
  119.                     'logo'            => $token->getLogo(),
  120.                 ] : null,
  121.                 'tokenId'     => $nft->getTokenId(),
  122.                 'id'          => $nft->getId(),
  123.                 'ipfs'        => $nft->getIpfs(),
  124.                 'isClaimed'   => $nft->isIsClaimed(),
  125.                 'claimStatus' => $nft->isClaimStatus(),
  126.                 'claimedAt'   => $nft->getClaimedAt()?->format(\DateTimeInterface::ATOM),
  127.                 'claimTx'     => $nft->getClaimTx(),
  128.                 'priceUSD'    => $nft->getPrice(),
  129.                 'tokens'      => $nft->getTokens(),
  130.                 'type'        => $nft->getType() ? ucfirst(strtolower($nft->getType())) : null,
  131.             ];
  132.         }
  133.         return new JsonResponse(['nfts' => $nftData]);
  134.     }
  135.     /**
  136.      * GET /web3api/wallet/addressqr
  137.      *
  138.      * Authenticated. If 'address' omitted, uses the user's first wallet address.
  139.      *
  140.      * Query:
  141.      *  - address?: string
  142.      *  - theme?: light|dark (default light)
  143.      *  - size?: int [128..2048] (default 512)
  144.      *  - margin?: int [0..64] (default 8)
  145.      *  - logo?: 0|1 (default 1)
  146.      *  - ecl?: high|medium|quartile|low (default high)
  147.      *
  148.      * Returns: image/png
  149.      */
  150.     #[Route('/web3api/wallet/addressqr'name'addressqr'methods: ['GET'])]
  151.     public function addressQr(Request $request): Response
  152.     {
  153.         // 1) Auth check
  154.         $user $this->security->getUser();
  155.         if (!$user) {
  156.             return $this->json(['success' => false'error' => 'User is not logged in'], 403);
  157.         }
  158.         // 2) Re-attach user via injected EM (no getDoctrine in Symfony 6)
  159.         $managedUser $this->em->getReference(User::class, $user->getId());
  160.         // 3) Query wallets (don’t rely on collection; avoids detached issues)
  161.         $walletRepo $this->em->getRepository(Wallet::class);
  162.         $wallets    $walletRepo->findBy(['user' => $managedUser], ['id' => 'ASC'], 1);
  163.         if (!$wallets || count($wallets) === 0) {
  164.             return $this->json(['success' => false'error' => 'User wallet not found'], 404);
  165.         }
  166.         $userWallet  $wallets[0];
  167.         $userAddress $userWallet->getWalletAddress();
  168.         if (!$userAddress) {
  169.             return $this->json(['success' => false'error' => 'Wallet address not set'], 404);
  170.         }
  171.         $address trim((string)$request->query->get('address'''));
  172.         if ($address === '')
  173.         {
  174.         }
  175.         else
  176.         {
  177.             $userAddress $address;
  178.         }
  179.         // --- QR options ---
  180.         $theme  strtolower((string)$request->query->get('theme''light'));
  181.         $logoOn = (int)$request->query->get('logo'1) === 1;
  182.         $size   max(128min(2048, (int)$request->query->get('size'512)));
  183.         $margin max(0,   min(64,   (int)$request->query->get('margin'8)));
  184.         $ecl    = (string)$request->query->get('ecl''high');
  185.         $projectDir   $this->getParameter('kernel.project_dir');
  186.         $logoPath     $projectDir '/public_html/qr-logo.png';
  187.         $logoPathDark $projectDir '/public_html/qr-logo-dark.png';
  188.         if ($theme === 'dark') {
  189.             $fg = [255255255];
  190.             $bg = [181818];
  191.             $logo $logoOn ? (is_file($logoPathDark) ? $logoPathDark : (is_file($logoPath) ? $logoPath null)) : null;
  192.         } else {
  193.             $fg = [000];
  194.             $bg = [255255255];
  195.             $logo $logoOn ? (is_file($logoPath) ? $logoPath : (is_file($logoPathDark) ? $logoPathDark null)) : null;
  196.         }
  197.         // Build QR with service (use $userAddress, not $address)
  198.         $png $this->qr->generateToString(
  199.             data$userAddress,
  200.             logoPath$logo,
  201.             size$size,
  202.             margin$margin,
  203.             errorCorrection$ecl,
  204.             foregroundRgb$fg,
  205.             backgroundRgb$bg
  206.         );
  207.         return new Response($png200, [
  208.             'Content-Type'  => 'image/png',
  209.             'Cache-Control' => 'private, max-age=60',
  210.         ]);
  211.     }
  212.     /**
  213.      * GET /web3api/wallet/addressqr
  214.      *
  215.      * Authenticated. If 'address' omitted, uses the user's first wallet address.
  216.      *
  217.      * Query:
  218.      *  - address?: string
  219.      *  - theme?: light|dark (default light)
  220.      *  - size?: int [128..2048] (default 512)
  221.      *  - margin?: int [0..64] (default 8)
  222.      *  - logo?: 0|1 (default 1)
  223.      *  - ecl?: high|medium|quartile|low (default high)
  224.      *
  225.      * Returns: image/png
  226.      */
  227.     #[Route('/papi/wallet/addressqr'name'addressqr'methods: ['GET'])]
  228.     public function publicAddressQr(Request $request): Response
  229.     {
  230.         $address trim((string)$request->query->get('address'''));
  231.         if ($address === '')
  232.         {
  233.             return $this->json(['success' => false'error' => 'Wallet address not set'], 404);
  234.         }
  235.         else
  236.         {
  237.             $userAddress $address;
  238.         }
  239.         // --- QR options ---
  240.         $theme  strtolower((string)$request->query->get('theme''light'));
  241.         $logoOn = (int)$request->query->get('logo'1) === 1;
  242.         $size   max(128min(2048, (int)$request->query->get('size'512)));
  243.         $margin max(0,   min(64,   (int)$request->query->get('margin'8)));
  244.         $ecl    = (string)$request->query->get('ecl''high');
  245.         $projectDir   $this->getParameter('kernel.project_dir');
  246.         $logoPath     $projectDir '/public_html/qr-logo.png';
  247.         $logoPathDark $projectDir '/public_html/qr-logo-dark.png';
  248.         if ($theme === 'dark') {
  249.             $fg = [255255255];
  250.             $bg = [181818];
  251.             $logo $logoOn ? (is_file($logoPathDark) ? $logoPathDark : (is_file($logoPath) ? $logoPath null)) : null;
  252.         } else {
  253.             $fg = [000];
  254.             $bg = [255255255];
  255.             $logo $logoOn ? (is_file($logoPath) ? $logoPath : (is_file($logoPathDark) ? $logoPathDark null)) : null;
  256.         }
  257.         // Build QR with service (use $userAddress, not $address)
  258.         $png $this->qr->generateToString(
  259.             data$userAddress,
  260.             logoPath$logo,
  261.             size$size,
  262.             margin$margin,
  263.             errorCorrection$ecl,
  264.             foregroundRgb$fg,
  265.             backgroundRgb$bg
  266.         );
  267.         return new Response($png200, [
  268.             'Content-Type'  => 'image/png',
  269.             'Cache-Control' => 'private, max-age=60',
  270.         ]);
  271.     }
  272. }