companyModel = new CompanyModel(); $this->userModel = new UserModel(); } public function __invoke(ServerRequestInterface $request) { $body = json_decode((string)$request->getBody(), true) ?? []; try { val::key('company_name', val::stringType()->notEmpty()->length(1, 255)) ->key('username', val::stringType()->notEmpty()->length(1, 100)) ->key('email', val::email()) ->key('password', val::stringType()->length(8, null)) ->key('phone', val::stringType()->notEmpty()->length(1, 50)) ->key('address', val::stringType()->notEmpty()->length(1, 255)) ->key('city', val::stringType()->notEmpty()->length(1, 100)) ->key('state', val::stringType()->notEmpty()->length(1, 100)) ->key('zip', val::stringType()->notEmpty()->length(1, 20)) ->key('country', val::stringType()->notEmpty()->length(1, 100)) ->key('kyc', val::intType()) ->key('birthdate', val::intType()) ->key('cpf', val::stringType()->notEmpty()->length(1, 11)) ->key('cnpj', val::stringType()->notEmpty()->length(1, 14)) ->assert($body); } catch (ValidationException $e) { return ResponseLib::sendFail("Validation failed: " . $e->getFullMessage(), [], "E_VALIDATE")->withStatus(400); } try { $pdo = $GLOBALS['pdo']; $pdo->beginTransaction(); $companyId = $this->companyModel->createCompany($body['company_name'], $body['cnpj'], 'a'); $roleId = 1; $chk = $pdo->prepare('SELECT 1 FROM "role" WHERE role_id = :rid'); $chk->execute(['rid' => $roleId]); if (!$chk->fetchColumn()) { $pdo->rollBack(); return ResponseLib::sendFail('Default role_id 1 not found', [], 'E_DATABASE')->withStatus(500); } $userPayload = [ 'username' => $body['username'], 'email' => $body['email'], 'password' => $body['password'], 'phone' => $body['phone'], 'address' => $body['address'], 'city' => $body['city'], 'state' => $body['state'], 'zip' => $body['zip'], 'country' => $body['country'], 'kyc' => (int)$body['kyc'], 'birthdate' => (int)$body['birthdate'], 'cpf' => $body['cpf'], 'company_id' => $companyId, 'role_id' => $roleId ]; $userData = $this->userModel->createUser($userPayload); if (!$userData) { $pdo->rollBack(); return ResponseLib::sendFail("Email already exists or creation failed", [], "E_VALIDATE")->withStatus(400); } $bin = dirname(__DIR__) . '/bin/easycli'; $result = BashExecutor::run($bin . ' polygon create-new-address'); if ((int)($result['exitCode'] ?? 1) !== 0) { $cliOutput = trim((string)($result['output'] ?? '')); $cliError = trim((string)($result['error'] ?? '')); error_log('[CompanyWithUserController] easycli wallet generation failed. Output: ' . $cliOutput . ' | Error: ' . $cliError); $pdo->rollBack(); return ResponseLib::sendFail("Wallet generation failed", ['error' => $result['error'] ?? ''], "E_INTERNAL")->withStatus(500); } $output = trim((string)($result['output'] ?? '')); $parsed = []; foreach (preg_split('/\r?\n/', $output) as $line) { $line = trim($line); if ($line === '' || strpos($line, '=') === false) { continue; } [$k, $v] = explode('=', $line, 2); $parsed[trim($k)] = trim($v); } if (!isset($parsed['privateKey'], $parsed['publicKey'], $parsed['address'])) { $pdo->rollBack(); return ResponseLib::sendFail("Wallet parsing failed", ['raw' => $output], "E_INTERNAL")->withStatus(500); } $stmt = $pdo->prepare('SELECT chain_id FROM "chain" WHERE chain_name = :name'); $stmt->execute(['name' => 'polygon']); $chainId = $stmt->fetchColumn(); if (!$chainId) { $pdo->rollBack(); return ResponseLib::sendFail("Chain not found", [], "E_DATABASE")->withStatus(500); } $stmt = $pdo->prepare('INSERT INTO "wallet" (company_id, wallet_public_key, wallet_address, wallet_private_key, wallet_flag, chain_id) VALUES (:company_id, :public_key, :address, :private_key, :flag, :chain_id) RETURNING wallet_id'); $stmt->execute([ 'company_id' => $companyId, 'public_key' => $parsed['publicKey'], 'address' => $parsed['address'], 'private_key' => $parsed['privateKey'], 'flag' => 'a', 'chain_id' => (int)$chainId ]); $walletId = (int)$stmt->fetchColumn(); $pdo->commit(); return ResponseLib::sendOk([ 'company_id' => $companyId, 'role_id' => $roleId, 'user' => $userData, 'wallet_id' => $walletId, 'wallet_address' => $parsed['address'] ], 'S_CREATED'); } catch (\Throwable $e) { if (isset($pdo) && $pdo->inTransaction()) { $pdo->rollBack(); } return ResponseLib::sendFail($e->getMessage(), [], 'E_DATABASE')->withStatus(500); } } }