File

src/user/user.controller.ts

Prefix

api/v1/user

Index

Methods

Methods

Async assignInvestorToNewDealer
assignInvestorToNewDealer(id: string, assignNewDealerDto: AssignNewDealerDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@Put('/:id/assign/dealer')
Parameters :
Name Type Optional
id string No
assignNewDealerDto AssignNewDealerDto No
Returns : unknown
Async createWallet
createWallet(id: string, request: AuthRequest, updateWalletDto: UpdateWalletDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@Post('/:id/wallet')
Parameters :
Name Type Optional
id string No
request AuthRequest No
updateWalletDto UpdateWalletDto No
Returns : any
Async findAll
findAll(request: AuthRequest, filterUserDTO: FilterUserDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@Get('/')
Parameters :
Name Type Optional
request AuthRequest No
filterUserDTO FilterUserDto No
Returns : unknown
Async findOne
findOne(request: AuthRequest, id: string)
Decorators :
@UseGuards(new RolesAuthGuard())
@Get('/:id')
Parameters :
Name Type Optional
request AuthRequest No
id string No
Returns : unknown
Async findOneWithOrderBook
findOneWithOrderBook(request: AuthRequest, investorId: string, filterOrderDto: FilterOrderDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@UseInterceptors(CustomCacheInterceptor)
@Get('/:investorId/orderbook')
Parameters :
Name Type Optional
request AuthRequest No
investorId string No
filterOrderDto FilterOrderDto No
Returns : unknown
Async getBalance
getBalance(request: AuthRequest, instrumentId: string)
Decorators :
@UseGuards(new RolesAuthGuard())
@UseInterceptors(CustomCacheInterceptor)
@Get('instrument/:instrumentId/balance')
Parameters :
Name Type Optional
request AuthRequest No
instrumentId string No
Returns : unknown
Async getEditableForm
getEditableForm(request: AuthRequest, dealerConfigDto: DealerConfigDto)
Decorators :
@UseInterceptors(CustomCacheInterceptor)
@UseGuards(new RolesAuthGuard())
@Get('/dealer/editable-form')
Parameters :
Name Type Optional
request AuthRequest No
dealerConfigDto DealerConfigDto No
Returns : unknown
Async getFundDetailsSubscription
getFundDetailsSubscription(request: AuthRequest, userId: string, fundId: string)
Decorators :
@UseInterceptors(CustomCacheInterceptor)
@UseGuards(new RolesAuthGuard())
@Get('/:userId/fund/:fundId')
Parameters :
Name Type Optional
request AuthRequest No
userId string No
fundId string No
Returns : unknown
Async getOnboardConfig
getOnboardConfig(request: AuthRequest, dealerConfigDto: DealerConfigDto)
Decorators :
@UseInterceptors(CustomCacheInterceptor)
@UseGuards(new RolesAuthGuard())
@Get('/dealer/onboard-config')
Parameters :
Name Type Optional
request AuthRequest No
dealerConfigDto DealerConfigDto No
Returns : unknown
Async getOnchainFieldMapping
getOnchainFieldMapping()
Decorators :
@UseInterceptors(CustomCacheInterceptor)
@UseGuards(undefined)
@Get('/dealer/onchain-fields')
Returns : unknown
Async getRegisterForm
getRegisterForm()
Decorators :
@CacheTTL(1000000)
@UseInterceptors(CacheInterceptor)
@Get('register/form')
Returns : unknown
Async getWallets
getWallets(request: AuthRequest, id: string)
Decorators :
@UseGuards(new RolesAuthGuard())
@Get(':id/wallet/')
Parameters :
Name Type Optional
request AuthRequest No
id string No
Returns : unknown
Async getWalletsByAddress
getWalletsByAddress(address: string)
Decorators :
@UseGuards(new RolesAuthGuard())
@Get(':id/wallet/:address')
Parameters :
Name Type Optional
address string No
Returns : unknown
Async myProfile
myProfile(request: AuthRequest)
Decorators :
@UseGuards(undefined)
@UseInterceptors(CustomCacheInterceptor)
@Get('/myprofile')
Parameters :
Name Type Optional
request AuthRequest No
Returns : unknown
Async subscribeUser
subscribeUser(id: string, request: AuthRequest, subscribeUserDto: SubscribeUserDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@Put('/:id/subscribe')
Parameters :
Name Type Optional
id string No
request AuthRequest No
subscribeUserDto SubscribeUserDto No
Returns : unknown
Async update
update(id: string, request: AuthRequest, updateUserDto: UpdateUserDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@Put('/:id')
Parameters :
Name Type Optional
id string No
request AuthRequest No
updateUserDto UpdateUserDto No
Returns : unknown
Async updateOnboardEditableFields
updateOnboardEditableFields(request: AuthRequest, onboardEditableForm: OnboardEditableFormDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@Put('/dealer/editable-form')
Parameters :
Name Type Optional
request AuthRequest No
onboardEditableForm OnboardEditableFormDto No
Returns : unknown
Async updateWalletLabel
updateWalletLabel(request: AuthRequest, id: string, address: string, updateWalletDto: UpdateWalletDto)
Decorators :
@UseGuards(new RolesAuthGuard())
@Put(':id/wallet/:address')
Parameters :
Name Type Optional
request AuthRequest No
id string No
address string No
updateWalletDto UpdateWalletDto No
Returns : unknown
import { UpdateWalletDto } from "./../wallet/dto/update-wallet.dto";
import { OnboardEditableFormDto } from "./dto/onboard-config.dto";
import {
  BadRequestException,
  Body,
  CacheInterceptor,
  CacheTTL,
  Controller,
  Get,
  Inject,
  Param,
  Post,
  Put,
  Query,
  Req,
  ServiceUnavailableException,
  UnauthorizedException,
  UseGuards,
  UseInterceptors,
} from "@nestjs/common";
import { RolesAuthGuard } from "src/auth/guards/roles-auth.guard";
import {
  AuthRequest,
  ContractName,
  EndUserRoles,
  IGetInvestorsIdByInstrumentQuery,
  TransactionNames,
} from "src/common/interfaces";

import { UpdateUserDto } from "./dto/update-user.dto";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { UserService } from "./user.service";
import { WalletService } from "src/wallet/wallet.service";
import { FilterUserDto } from "./dto/filter-user.dto";
import { SubscribeUserDto } from "./dto/subscribe-user.dto";
import { AuthGuard } from "@nestjs/passport";
import {
  apolloClient,
  getContractByName,
  getInvestorsIdByInstrumentQuery,
  transactionSubmitter,
} from "src/common/provider";
import { DEFAULT_LIBRE_DEALER, Roles } from "src/common/constants";
import { AssignNewDealerDto } from "./dto/assign-new-dealer-user.dto";
import { decodeBytes32String, encodeBytes32String, formatEther } from "ethers";
import { ApolloQueryResult } from "@apollo/client";
import { UserCmsService } from "./user.cms.service";
import { UserOrderbookService } from "./user.orderbook.service";
import { FilterOrderDto } from "src/orderbook/dto/filter-order.dto";
import { DealerConfigDto } from "./dto/dealer-config.dto";
import { CustomCacheInterceptor } from "src/interceptor/cache.interceptor";

@Controller("api/v1/user")
export class UserController {
  @Inject(WalletService)
  private readonly walletService: WalletService;
  @Inject(UserCmsService)
  private readonly userCmsService: UserCmsService;
  @Inject(UserOrderbookService)
  private readonly userOrderbookService: UserOrderbookService;

  constructor(private readonly userService: UserService) {}

  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Get("/")
  async findAll(
    @Req() request: AuthRequest,
    @Query() filterUserDTO: FilterUserDto,
  ) {
    try {
      let newFilterUserDto = filterUserDTO;
      if (request.user.role === EndUserRoles.dealer) {
        newFilterUserDto = {
          ...filterUserDTO,
          onboardByEmail: request.user.email,
        };
      }

      if (filterUserDTO.instrumentId) {
        const whitelistInfo: ApolloQueryResult<IGetInvestorsIdByInstrumentQuery> =
          await apolloClient.query({
            query: getInvestorsIdByInstrumentQuery,
            variables: {
              instrumentId: encodeBytes32String(filterUserDTO.instrumentId),
            },
          });

        const unconfirmedRedemptionAmountById: Record<string, string> = {};
        newFilterUserDto = {
          ...newFilterUserDto,
          _id: {
            $in: whitelistInfo.data.whitelistInfos.map(
              ({ id, unConfirmedRedeemedAmount }) => {
                const decodedId = decodeBytes32String(id);
                unconfirmedRedemptionAmountById[decodedId] = formatEther(
                  unConfirmedRedeemedAmount || 0,
                );
                return decodedId;
              },
            ),
          },
        };

        return await this.userService.findUsersByFilterByUsersBalance(
          newFilterUserDto,
          unconfirmedRedemptionAmountById,
        );
      }

      return await this.userService.findUsersByFilter(newFilterUserDto, true);
    } catch (error) {
      console.error(error);
      throw new ServiceUnavailableException(error);
    }
  }

  @UseGuards(AuthGuard("jwt"))
  @UseInterceptors(CustomCacheInterceptor)
  @Get("/myprofile")
  async myProfile(@Req() request: AuthRequest) {
    try {
      return (
        await this.userService.findUsersByFilter(
          { email: request.user.email },
          true,
        )
      )[0];
    } catch (error) {
      console.error(error);
      throw new ServiceUnavailableException(error);
    }
  }

  @UseGuards(new RolesAuthGuard(["investor"]))
  @UseInterceptors(CustomCacheInterceptor)
  @Get("instrument/:instrumentId/balance")
  async getBalance(
    @Req() request: AuthRequest,
    @Param("instrumentId") instrumentId: string,
  ) {
    try {
      const investor = await this.userService.findUserByProperty({
        email: request.user.email,
      });
      return await this.userService.getInvestorBalanceByInstrument({
        investor,
        instrumentId,
      });
    } catch (error) {
      console.error(error);
      if (error.status === 400) {
        throw new BadRequestException(error);
      }
      if (error.status === 401) {
        throw new UnauthorizedException(error);
      }
      throw new ServiceUnavailableException(error);
    }
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Get("/:id")
  async findOne(@Req() request: AuthRequest, @Param("id") id: string) {
    try {
      if (request.user.role === EndUserRoles.dealer) {
        const isAllowed = await this.userService.isDealerAllowed({
          investorId: id,
          dealerEmail: request.user.email,
        });
        if (!isAllowed) {
          throw new UnauthorizedException(
            `Dealer with email ${request.user.email} is unauthorized for this investor`,
          );
        }
      }
      return await this.userService.findOne(id, true);
    } catch (error) {
      console.error(error);
      throw new ServiceUnavailableException(error);
    }
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @UseInterceptors(CustomCacheInterceptor)
  @Get("/:investorId/orderbook")
  async findOneWithOrderBook(
    @Req() request: AuthRequest,
    @Param("investorId") investorId: string,
    @Query() filterOrderDto: FilterOrderDto,
  ) {
    try {
      if (request.user.role === EndUserRoles.dealer) {
        const isAllowed = await this.userService.isDealerAllowed({
          investorId,
          dealerEmail: request.user.email,
        });
        if (!isAllowed) {
          throw new UnauthorizedException(
            `Dealer with email ${request.user.email} is unauthorized for this investor`,
          );
        }
      }
      return await this.userOrderbookService.getInvestorOrders({
        investorId,
        ...filterOrderDto,
      });
    } catch (error) {
      console.error(error);
      if (error.status === 400) {
        throw new BadRequestException(error);
      }
      if (error.status === 401) {
        throw new UnauthorizedException(error);
      }
      throw new ServiceUnavailableException(error);
    }
  }

  @UseInterceptors(CustomCacheInterceptor)
  @UseGuards(new RolesAuthGuard(["admin", "fundAdmin"]))
  @Get("/:userId/fund/:fundId")
  async getFundDetailsSubscription(
    @Req() request: AuthRequest,
    @Param("userId") userId: string,
    @Param("fundId") fundId: string,
  ) {
    try {
      if (request.user.role !== "admin") {
        await this.userService.checkIfUserIsAllowedToFund(request.user, fundId);
      }
      return await this.userService.getFundSubscriptionDetails({
        userId,
        fundId,
      });
    } catch (error) {
      console.error(error);
      throw new ServiceUnavailableException(error);
    }
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Put("/:id")
  async update(
    @Param("id") id: string,
    @Req() request: AuthRequest,
    @Body() updateUserDto: UpdateUserDto,
  ) {
    try {
      if (request.user.role === EndUserRoles.dealer) {
        const isAllowed = await this.userService.isDealerAllowed({
          investorId: id,
          dealerEmail: request.user.email,
        });
        if (!isAllowed) {
          throw new UnauthorizedException(
            "Dealer is Unauthorized for this action",
          );
        }
      }

      return this.userService.update({
        id,
        updateUserDto,
        userJwtPayload: request.user,
      });
    } catch (error) {
      console.error(error);
      throw new ServiceUnavailableException(error);
    }
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Put("/:id/subscribe")
  async subscribeUser(
    @Param("id") id: string,
    @Req() request: AuthRequest,
    @Body() subscribeUserDto: SubscribeUserDto,
  ) {
    if (request.user.role === EndUserRoles.dealer) {
      const isAllowed = await this.userService.isDealerAllowed({
        investorId: id,
        dealerEmail: request.user.email,
        fundId: subscribeUserDto.fundId,
      });
      if (!isAllowed) {
        throw new UnauthorizedException(
          "Dealer is Unauthorized for this action",
        );
      }
    }
    const updateResult = await this.userService.userSubscribeToNewFund({
      userId: id,
      userJwt: request.user,
      ...subscribeUserDto,
    });
    if (!updateResult) {
      throw new ServiceUnavailableException("Tx didn't pass");
    }
    if (updateResult) {
      return {
        message: `User ${
          subscribeUserDto.isSubscribed ? "subscribed" : "unsubscribed"
        } to fund ${subscribeUserDto.fundId} successfully!`,
      };
    }
    throw new BadRequestException(
      `Incorrect Id for fund ${subscribeUserDto.fundId}`,
    );
  }

  @UseGuards(new RolesAuthGuard(["admin"]))
  @Put("/:id/assign/dealer")
  async assignInvestorToNewDealer(
    @Param("id") id: string,
    @Body() assignNewDealerDto: AssignNewDealerDto,
  ) {
    const user = await this.userService.findOne(id);

    if (!user) {
      throw new BadRequestException("User not found");
    }
    if (user.endUserRole !== EndUserRoles.investor) {
      throw new BadRequestException(`${user.email} is not an investor`);
    }
    try {
      return await transactionSubmitter({
        signerKey: process.env.RELAYER_KEY,
        contractAddress: getContractByName["InvestorRegistry"].address,
        transactionName: TransactionNames.assignInvestorToNewDealer,
        contractName: ContractName.InvestorRegistry,
        args: [
          Roles.Dealer,
          encodeBytes32String(id),
          encodeBytes32String(assignNewDealerDto.dealerId),
        ],
      });
    } catch (error) {
      throw new ServiceUnavailableException(error);
    }
  }

  // Creating new wallets will be supported once we depend on multiple custodial
  @UseGuards(new RolesAuthGuard(["admin"]))
  @Post("/:id/wallet")
  async createWallet(
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    @Param("id") id: string,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    @Req() request: AuthRequest,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    @Body() updateWalletDto: UpdateWalletDto,
  ) {
    throw new BadRequestException(
      "Only one wallet per user is supported until adding other external custodial and external wallets",
    );
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer", "investor"]))
  @Get(":id/wallet/")
  async getWallets(@Req() request: AuthRequest, @Param("id") id: string) {
    if (request.user.role === EndUserRoles.dealer) {
      const isAllowed = await this.userService.isDealerAllowed({
        investorId: id,
        dealerEmail: request.user.email,
      });
      if (!isAllowed) {
        throw new UnauthorizedException("Role Unauthorized for this action");
      }
    }
    const user = await this.userService.findOne(id);
    if (!user) {
      throw new BadRequestException(`No user exist with id ${id}`);
    }

    if (request.user.role === EndUserRoles.investor) {
      if (user.email !== request.user.email) {
        throw new UnauthorizedException("Role Unauthorized for this action");
      }
    }

    const wallets = await this.walletService.findByIds(user.wallets);
    return wallets;
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Get(":id/wallet/:address")
  async getWalletsByAddress(@Param("address") address: string) {
    const wallet = await this.walletService.findByAddress(address);
    if (!wallet) {
      throw new BadRequestException(`No wallet found with address ${address}`);
    }
    return wallet;
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer", "investor"]))
  @Put(":id/wallet/:address")
  async updateWalletLabel(
    @Req() request: AuthRequest,
    @Param("id") id: string,
    @Param("address") address: string,
    @Body() updateWalletDto: UpdateWalletDto,
  ) {
    if (request.user.role === EndUserRoles.dealer) {
      const isAllowed = await this.userService.isDealerAllowed({
        investorId: id,
        dealerEmail: request.user.email,
      });
      if (!isAllowed) {
        throw new UnauthorizedException("Role Unauthorized for this action");
      }
    }

    if (
      request.user.role !== EndUserRoles.dealer &&
      request.user.role === "admin"
    ) {
      const user = await this.userService.findOne(id);
      const isAllowed =
        user.wallets.findIndex((wallet) => wallet.address === address) !== -1;
      if (!isAllowed) {
        throw new UnauthorizedException("Role Unauthorized for this action");
      }
    }
    const wallet = await this.walletService.findByAddress(address);
    if (!wallet) {
      throw new BadRequestException(`No wallet exist with id ${address}`);
    }
    const updatedWallet = await this.walletService.update(
      wallet._id,
      updateWalletDto,
    );
    if (updatedWallet.id) {
      return { ...updatedWallet.toObject(), ...updateWalletDto };
    }
  }

  @CacheTTL(1000000)
  @UseInterceptors(CacheInterceptor)
  @Get("register/form")
  async getRegisterForm() {
    try {
      return await this.userCmsService.getOnboardConfigOfDealer(
        DEFAULT_LIBRE_DEALER,
      );
    } catch (err) {
      console.error(err);
      if (err.status === 400) {
        throw new BadRequestException(err);
      }
      throw new ServiceUnavailableException(err.message);
    }
  }
  //  add delete & transfer wallet once we have the smart contracts
  @UseInterceptors(CustomCacheInterceptor)
  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Get("/dealer/onboard-config")
  async getOnboardConfig(
    @Req() request: AuthRequest,
    @Query() dealerConfigDto: DealerConfigDto,
  ) {
    try {
      if (request.user.role === "admin" && !dealerConfigDto) {
        throw new BadRequestException("Admin should send the dealer email");
      }
      return await this.userCmsService.getOnboardConfigOfDealer(
        request.user.role === "admin"
          ? dealerConfigDto.dealerEmail
          : request.user.email,
      );
    } catch (err) {
      console.error(err);
      if (err.status === 400) {
        throw new BadRequestException(err);
      }
      throw new ServiceUnavailableException(err.message);
    }
  }

  @UseInterceptors(CustomCacheInterceptor)
  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Get("/dealer/editable-form")
  async getEditableForm(
    @Req() request: AuthRequest,
    @Query() dealerConfigDto: DealerConfigDto,
  ) {
    try {
      if (request.user.role === "admin" && !dealerConfigDto) {
        throw new BadRequestException("Admin should send the dealer email");
      }
      return await this.userCmsService.getEditableFormOfDealer(
        request.user.role === "admin"
          ? dealerConfigDto.dealerEmail
          : request.user.email,
      );
    } catch (err) {
      console.error(err);
      if (err.status === 400) {
        throw new BadRequestException(err);
      }
      throw new ServiceUnavailableException(err.message);
    }
  }

  @UseInterceptors(CustomCacheInterceptor)
  @UseGuards(AuthGuard("jwt"))
  @Get("/dealer/onchain-fields")
  async getOnchainFieldMapping() {
    try {
      return await this.userCmsService.getOnboardOnchainFields();
    } catch (err) {
      console.error(err);
      throw new ServiceUnavailableException(err.message);
    }
  }

  @UseGuards(new RolesAuthGuard(["admin", "dealer"]))
  @Put("/dealer/editable-form")
  async updateOnboardEditableFields(
    @Req() request: AuthRequest,
    @Body() onboardEditableForm: OnboardEditableFormDto,
  ) {
    try {
      return await this.userCmsService.updateOnboardEditableFields(
        request.user.email,
        onboardEditableForm.onboardEditableFields,
        onboardEditableForm.id,
      );
    } catch (err) {
      console.error(err);
      throw new ServiceUnavailableException(err.message);
    }
  }
}

results matching ""

    No results matching ""