OrderbookTransferController.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <?php
  2. namespace Controllers;
  3. use Libs\ResponseLib;
  4. use Models\OrderbookModel;
  5. use Models\OrderbookTransferModel;
  6. use Models\PaymentModel;
  7. use Models\WalletModel;
  8. use Psr\Http\Message\ServerRequestInterface;
  9. use Respect\Validation\Exceptions\ValidationException;
  10. use Respect\Validation\Validator as val;
  11. use Services\TokenTransferService;
  12. class OrderbookTransferController
  13. {
  14. private PaymentModel $paymentModel;
  15. private WalletModel $walletModel;
  16. private OrderbookTransferModel $orderbookTransferModel;
  17. private TokenTransferService $tokenTransferService;
  18. public function __construct()
  19. {
  20. $this->paymentModel = new PaymentModel();
  21. $this->walletModel = new WalletModel();
  22. $this->orderbookTransferModel = new OrderbookTransferModel();
  23. $this->tokenTransferService = new TokenTransferService();
  24. }
  25. public function __invoke(ServerRequestInterface $request)
  26. {
  27. $body = json_decode((string)$request->getBody(), true) ?? [];
  28. try {
  29. val::key('external_id', val::stringType()->notEmpty())
  30. ->key('token_external_id', val::stringType()->notEmpty())
  31. ->assert($body);
  32. } catch (ValidationException $e) {
  33. return ResponseLib::sendFail('Validation failed: ' . $e->getFullMessage(), [], 'E_VALIDATE')->withStatus(400);
  34. }
  35. $externalId = trim((string)$body['external_id']);
  36. $tokenExternalId = trim((string)$body['token_external_id']);
  37. $companyId = (int)($request->getAttribute('api_company_id') ?? 0);
  38. if ($companyId <= 0) {
  39. return ResponseLib::sendFail('Empresa autenticada não encontrada', [], 'E_VALIDATE')->withStatus(401);
  40. }
  41. try {
  42. $payment = $this->paymentModel->findByExternalId($externalId);
  43. } catch (\Throwable $e) {
  44. return ResponseLib::sendFail('Falha ao consultar pagamento: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
  45. }
  46. if (!$payment) {
  47. return ResponseLib::sendFail('Pagamento não encontrado', ['external_id' => $externalId], 'E_NOT_FOUND')->withStatus(404);
  48. }
  49. if ((int)$payment['status_id'] !== PaymentModel::STATUS_COMPLETED) {
  50. return ResponseLib::sendFail('Pagamento ainda não concluído', ['external_id' => $externalId, 'status_id' => $payment['status_id']], 'E_PAYMENT_PENDING')->withStatus(409);
  51. }
  52. try {
  53. $orderbook = $this->orderbookTransferModel->getByTokenExternalId($tokenExternalId);
  54. } catch (\Throwable $e) {
  55. return ResponseLib::sendFail('Falha ao consultar orderbook: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
  56. }
  57. if (!$orderbook) {
  58. return ResponseLib::sendFail('Orderbook não encontrado', ['token_external_id' => $tokenExternalId], 'E_NOT_FOUND')->withStatus(404);
  59. }
  60. if ((int)$orderbook['company_id'] !== $companyId) {
  61. return ResponseLib::sendFail('Orderbook não pertence à empresa autenticada', [], 'E_FORBIDDEN')->withStatus(403);
  62. }
  63. if ((int)$orderbook['status_id'] === OrderbookModel::STATUS_COMPLETED) {
  64. return ResponseLib::sendOk([
  65. 'orderbook_id' => (int)$orderbook['orderbook_id'],
  66. 'token_external_id' => $tokenExternalId,
  67. 'message' => 'Orderbook já transferido anteriormente',
  68. ], 'S_TOKEN_ALREADY_TRANSFERRED');
  69. }
  70. try {
  71. $wallet = $this->walletModel->getPrimaryWalletByCompanyId($companyId);
  72. } catch (\Throwable $e) {
  73. return ResponseLib::sendFail('Falha ao consultar carteira da empresa: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
  74. }
  75. if (!$wallet || empty($wallet['wallet_address'])) {
  76. return ResponseLib::sendFail('Carteira da empresa não encontrada', [], 'E_WALLET_NOT_FOUND')->withStatus(404);
  77. }
  78. $serverAddress = $this->resolveServerAddress();
  79. try {
  80. $transferResult = $this->tokenTransferService->transferFrom($serverAddress, (string)$wallet['wallet_address'], $tokenExternalId);
  81. $this->orderbookTransferModel->markCompleted((int)$orderbook['orderbook_id']);
  82. } catch (\Throwable $e) {
  83. return ResponseLib::sendFail('Falha ao transferir token: ' . $e->getMessage(), [], 'E_TRANSFER')->withStatus(500);
  84. }
  85. return ResponseLib::sendOk([
  86. 'orderbook_id' => (int)$orderbook['orderbook_id'],
  87. 'token_external_id' => $tokenExternalId,
  88. 'destination_address' => (string)$wallet['wallet_address'],
  89. 'transfer_output' => $transferResult['output'] ?? '',
  90. 'transfer_error' => $transferResult['error'] ?? '',
  91. ], 'S_TOKEN_TRANSFERRED');
  92. }
  93. private function resolveServerAddress(): string
  94. {
  95. $address = $_ENV['SERVER_WALLET_ADDRESS'] ?? $_ENV['EASY_ADMIM_PUBLIC_KEY'] ?? '';
  96. $trimmed = trim((string)$address);
  97. if ($trimmed === '') {
  98. throw new \RuntimeException('Endereço do servidor (SERVER_WALLET_ADDRESS) não configurado.');
  99. }
  100. return $trimmed;
  101. }
  102. }