File

src/profile/profile.service.ts

Index

Properties
Methods

Methods

Async createRole
createRole(createRoleDto)
Parameters :
Name Optional
createRoleDto No
Returns : unknown
Async getMyProfile
getMyProfile(userJwtPayload: UserJwtPayload)
Parameters :
Name Type Optional
userJwtPayload UserJwtPayload No
Async grantRole
grantRole(grantRoleDto)
Parameters :
Name Optional
grantRoleDto No
Returns : unknown
Async manageRoleAccess
manageRoleAccess(action: "revoke" | "grant", manageRoleAccessDto)
Parameters :
Name Type Optional
action "revoke" | "grant" No
manageRoleAccessDto No
Returns : unknown
Async resetAccess
resetAccess(restRoleDto)
Parameters :
Name Optional
restRoleDto No
Returns : unknown
Async setInvestorRestriction
setInvestorRestriction(undefined: ISetInvestorRestriction)
Parameters :
Name Type Optional
ISetInvestorRestriction No
Returns : unknown
Async setSanction
setSanction(investorSanctionDto: ISetSanction)
Parameters :
Name Type Optional
investorSanctionDto ISetSanction No
Returns : unknown
Async userDeleteModule
userDeleteModule(undefined: IUserModule)
Parameters :
Name Type Optional
IUserModule No
Returns : unknown
Async userEnableDisableModule
userEnableDisableModule(undefined: IUserModuleEnableDisable)
Parameters :
Name Type Optional
IUserModuleEnableDisable No
Returns : unknown
Async userRegisterModule
userRegisterModule(undefined: IUserModule)
Parameters :
Name Type Optional
IUserModule No
Returns : unknown
Async verifyInvestor
verifyInvestor(undefined: Omit<ISetInvestorRestriction | "isRestricted" | "userJwtPayload">)
Returns : unknown

Properties

Private Readonly adminProfileService
Type : AdminProfileService
Decorators :
@Inject(AdminProfileService)
Private Readonly emailService
Type : EmailService
Decorators :
@Inject(EmailService)
Private Readonly fundService
Type : FundService
Decorators :
@Inject(FundService)
Private Readonly instrumentService
Type : InstrumentService
Decorators :
@Inject(InstrumentService)
Private Readonly internalCustodialService
Type : InternalCustodialService
Decorators :
@Inject(InternalCustodialService)
Private Readonly userService
Type : UserService
Decorators :
@Inject(UserService)
import { CustodialDocument } from "./../shared/custodial/schemas/custodial.schema";
import {
  BatchRegistry,
  ContractName,
  EndUserRoles,
  IGetOrdersQuery,
  QueryNames,
  RegistryName,
  TransactionNames,
  UserJwtPayload,
} from "src/common/interfaces";
import { Inject, Injectable } from "@nestjs/common";
import { FundService } from "src/security/fund.service";
import { UserService } from "src/user/user.service";
import type {
  IUserModule,
  IDealerModuleEnableDisable as IUserModuleEnableDisable,
  IOrderWithDbFundInstrument,
  ISetInvestorRestriction,
  ISetSanction,
  IUserProfile,
} from "./profile.interface";
import { ApolloQueryResult } from "@apollo/client";
import { encodeBytes32String } from "ethers";
import {
  apolloClient,
  getAllOrdersByDealerIdQuery,
  getAllOrdersByInvestorIdQuery,
  getAllOrdersBySubscribedFundsIdQuery,
  getAllOrdersByTypeQuery,
  getContractByName,
  getRoleAndContractAddressByNameOrAddress,
  getTxSelector,
  transactionQuery,
  transactionSubmitter,
} from "src/common/provider";
import { UserDocument } from "src/user/schemas/user.schema";
import { InternalCustodialService } from "src/shared/custodial/internalCustodial.service";
import { JurisdictionDefaultValues, Roles } from "src/common/constants";
import { RoleRegistry } from "src/shared/artifacts/RoleRegistry";
import { CreateRoleDto } from "./dto/create-role.dto";
import { GrantRoleDto } from "./dto/grant-role.dto";
import { ResetRoleDto } from "./dto/reset-role.dto";
import { ManageRoleAccessDto } from "./dto/manage-role.dto";
import { OnChainDataField } from "src/shared/onchainDataFields/entities/onChainDataField.entity";
import { LeanDocument } from "mongoose";
import { InstrumentDocument } from "src/security/schemas/instrument.schema";
import { InstrumentService } from "src/security/instrument.service";
import { EmailService } from "src/common/provider/mail/email.service";
import { AllowInstrumentAccessTemplate } from "src/common/provider/mail/templates/allowInstrumentAccess";
import { RejectInstrumentAccessTemplate } from "src/common/provider/mail/templates/rejectInstrumentAccess";
import { AdminProfileService } from "src/admin-profile/admin-profile.service";

@Injectable()
export class ProfileService {
  @Inject(FundService)
  private readonly fundService: FundService;
  @Inject(EmailService)
  private readonly emailService: EmailService;
  @Inject(UserService)
  private readonly userService: UserService;
  @Inject(InstrumentService)
  private readonly instrumentService: InstrumentService;
  @Inject(InternalCustodialService)
  private readonly internalCustodialService: InternalCustodialService;
  @Inject(AdminProfileService)
  private readonly adminProfileService: AdminProfileService;

  async getMyProfile(userJwtPayload: UserJwtPayload): Promise<IUserProfile> {
    const { email, role } = userJwtPayload;
    const user: LeanDocument<UserDocument> =
      await this.userService.findUserByProperty({
        email,
      });
    const funds = await this.fundService.findByIdsAndInstrument({
      ids: user.subscribedFunds.map((currentFund) => currentFund.toString()),
    });
    let subgraphOrderBook: ApolloQueryResult<IGetOrdersQuery>;
    if (role === EndUserRoles.dealer) {
      subgraphOrderBook = await apolloClient.query({
        query: getAllOrdersByDealerIdQuery,
        variables: {
          dealerId: encodeBytes32String(user._id.toString()),
          type: "",
        },
      });
    }

    if (role === EndUserRoles.investor) {
      subgraphOrderBook = await apolloClient.query({
        query: getAllOrdersByInvestorIdQuery,
        variables: {
          investorId: encodeBytes32String(user._id.toString()),
          type: "",
        },
      });
    }
    if (role === EndUserRoles.fundAdmin) {
      subgraphOrderBook = await apolloClient.query({
        query: getAllOrdersBySubscribedFundsIdQuery,
        variables: {
          fundsId: user.subscribedFunds.map((subscribedFund) =>
            encodeBytes32String(String(subscribedFund)),
          ),
          type: "",
        },
      });
    }
    if (role === "admin") {
      subgraphOrderBook = await apolloClient.query({
        query: getAllOrdersByTypeQuery,
        variables: {
          type: "",
        },
      });
    }

    if (!subgraphOrderBook.data) {
      return {
        ...user,
        orders: [],
      };
    }
    const orders: IOrderWithDbFundInstrument[] = subgraphOrderBook.data.orders
      .map((order) => {
        const fund = funds.find((currentFund) => {
          return (
            encodeBytes32String(currentFund._id.toString()) ===
            order.orderBook.fund.id
          );
        });
        if (!fund) {
          return null;
        }
        const instrument = fund.instruments.find(
          (currentInstrument) =>
            currentInstrument.subgraphInstrument.id ===
            order.orderBook.instrument.id,
        );
        return {
          ...order,
          orderBook: {
            ...order.orderBook,
            fund: { ...fund, instruments: [] },
            instrument,
          },
        };
      })
      .filter((orderBook) => orderBook);
    return { ...user, orders };
  }

  async setInvestorRestriction({
    investorId,
    instrumentId,
    isRestricted,
    userJwtPayload,
  }: ISetInvestorRestriction) {
    const isPlatformAdmin = userJwtPayload.role === "admin";

    let signerKey: CustodialDocument;
    let dealer: LeanDocument<UserDocument>;
    if (isPlatformAdmin) {
      signerKey = await this.adminProfileService.getCustodial(
        userJwtPayload.email,
      );
    } else {
      dealer = await this.userService.findUserByProperty({
        email: userJwtPayload.email,
      });
      signerKey = await this.internalCustodialService.findOne(
        dealer.wallets[0].address,
      );
    }

    const { contractAddress, role } =
      await getRoleAndContractAddressByNameOrAddress({
        contractName: ContractName.InvestorRegistry,
        transactionName: TransactionNames.setInvestorRestriction,
        userAddress:
          userJwtPayload.role !== "admin"
            ? dealer.wallets[0].address
            : signerKey.address,
      });
    const txResponse = await transactionSubmitter({
      signerKey: signerKey.privateKey,
      contractAddress,
      contractName: ContractName.InvestorRegistry,
      transactionName: TransactionNames.setInvestorRestriction,
      args: [
        role,
        encodeBytes32String(investorId),
        encodeBytes32String(instrumentId),
        isRestricted,
      ],
    });

    const [instrument, investor]: [
      LeanDocument<InstrumentDocument>,
      LeanDocument<UserDocument>,
    ] = await Promise.all([
      this.instrumentService.findOne(instrumentId),
      this.userService.findOne(investorId),
    ]);

    let subject;
    let htmlTemplate;

    if (isRestricted) {
      subject = `Access to ${instrument.name} is denied for the investor ${investor.name}`;
      htmlTemplate = RejectInstrumentAccessTemplate({
        instrumentName: instrument.name,
        investor: investor,
      });
    } else {
      subject = `Access to ${instrument.name} is approved for the investor ${investor.name}`;
      htmlTemplate = AllowInstrumentAccessTemplate({
        instrumentName: instrument.name,
        investor: investor,
      });
    }
    await this.emailService.sendEmail({
      from: "yehia@nethermind.io",
      to: [investor.email],
      subject,
      html: htmlTemplate,
    });
    return txResponse;
  }

  async verifyInvestor({
    investorId,
    instrumentId,
  }: Omit<ISetInvestorRestriction, "isRestricted" | "userJwtPayload">) {
    try {
      await transactionQuery({
        contractAddress: getContractByName["InvestorRegistry"].address,
        contractName: ContractName.InvestorRegistry,
        queryName: QueryNames.checkInvestorAllowed,
        args: [
          encodeBytes32String(investorId),
          encodeBytes32String(instrumentId),
        ],
      });
      return {
        isAllowed: true,
        message: "Investor is allowed to use this instrument",
      };
    } catch (error) {
      return {
        isAllowed: false,
        message: error.toString(),
      };
    }
  }

  async setSanction(investorSanctionDto: ISetSanction) {
    const { investorSanction, userJwtPayload } = investorSanctionDto;
    const onchainFields: OnChainDataField[] = [];
    const investorIdInBytes = encodeBytes32String(
      investorSanctionDto.investorId,
    );
    const sanctionRegistriesToSet: BatchRegistry[] = Object.keys(
      investorSanction,
    ).map((investor) => {
      onchainFields.push({
        name: JurisdictionDefaultValues[investor].dataFieldCol,
        hash: JurisdictionDefaultValues[investor].dataFieldColHash,
        linkedName: "",
        linkedHash: "",
        linkedType: JurisdictionDefaultValues[investor].type,
      });
      return {
        id: investorIdInBytes,
        dataFieldType: JurisdictionDefaultValues[investor].type,
        dataFieldName: JurisdictionDefaultValues[investor].dataFieldCol,
        dataFieldValue: investorSanction[investor],
      };
    });
    return await this.userService.setRegistryData({
      registries: sanctionRegistriesToSet,
      registryName: RegistryName.InvestorRegistry,
      userJwtPayload,
      onchainFields,
    });
  }

  async userRegisterModule({ contractAddress, userJwtPayload }: IUserModule) {
    const user = await this.userService.findUserByProperty({
      email: userJwtPayload.email,
    });
    const signerKey = (
      await this.internalCustodialService.findOne(user.wallets[0].address)
    ).privateKey;
    return await transactionSubmitter({
      signerKey,
      contractName: ContractName.DealerRulesEngine,
      contractAddress:
        userJwtPayload.role === EndUserRoles.dealer
          ? getContractByName["DealerRulesEngine"].address
          : getContractByName["RulesEngine"].address,
      transactionName: TransactionNames.registerModule,
      args: [contractAddress],
    });
  }

  async userEnableDisableModule({
    contractAddress,
    userJwtPayload,
    status,
  }: IUserModuleEnableDisable) {
    const user = await this.userService.findUserByProperty({
      email: userJwtPayload.email,
    });
    const signerKey = (
      await this.internalCustodialService.findOne(user.wallets[0].address)
    ).privateKey;

    return await transactionSubmitter({
      signerKey,
      contractName: ContractName.DealerRulesEngine,
      contractAddress:
        userJwtPayload.role === EndUserRoles.dealer
          ? getContractByName["DealerRulesEngine"].address
          : getContractByName["RulesEngine"].address,
      transactionName: TransactionNames.editModule,
      args: [contractAddress, status],
    });
  }

  async userDeleteModule({ contractAddress, userJwtPayload }: IUserModule) {
    const dealer = await this.userService.findUserByProperty({
      email: userJwtPayload.email,
    });
    const signerKey = (
      await this.internalCustodialService.findOne(dealer.wallets[0].address)
    ).privateKey;
    return await transactionSubmitter({
      signerKey,
      contractName: ContractName.DealerRulesEngine,
      contractAddress:
        userJwtPayload.role === EndUserRoles.dealer
          ? getContractByName["DealerRulesEngine"].address
          : getContractByName["RulesEngine"].address,
      transactionName: TransactionNames.deleteModule,
      args: [contractAddress],
    });
  }

  async createRole(createRoleDto: CreateRoleDto & { user: UserJwtPayload }) {
    const { user } = createRoleDto;
    const signerKey =
      user.role === "admin"
        ? (await this.adminProfileService.getCustodial(user.email)).privateKey
        : (await this.userService.getCustodial(user.email)).privateKey;
    const createdRole = encodeBytes32String(createRoleDto.newRoleName);
    await transactionSubmitter({
      signerKey,
      contractAddress: RoleRegistry.address,
      transactionName: TransactionNames.createRole,
      contractName: ContractName.RoleRegistry,
      args: [Roles.Admin, createdRole],
    });
    return {
      createdRole,
    };
  }

  async grantRole(grantRoleDto: GrantRoleDto & { user: UserJwtPayload }) {
    const roleBytes = encodeBytes32String(grantRoleDto.roleName);
    const userWithGrantedRole = await this.userService.findOne(
      grantRoleDto.userId,
    );
    const { user } = grantRoleDto;
    const signerKey =
      user.role === "admin"
        ? (await this.adminProfileService.getCustodial(user.email)).privateKey
        : (await this.userService.getCustodial(user.email)).privateKey;

    return await transactionSubmitter({
      signerKey,
      contractAddress: RoleRegistry.address,
      transactionName: TransactionNames.grantRole,
      contractName: ContractName.RoleRegistry,
      args: [roleBytes, userWithGrantedRole.wallets[0].address],
    });
  }

  async manageRoleAccess(
    action: "revoke" | "grant",
    manageRoleAccessDto: ManageRoleAccessDto & { user: UserJwtPayload },
  ) {
    const { contractName, transactionName, user } = manageRoleAccessDto;
    const selector = getTxSelector({ contractName, transactionName });
    const transactionNameToSubmit =
      action === "revoke"
        ? TransactionNames.revokeAccess
        : TransactionNames.grantAccess;

    const signerKey =
      user.role === "admin"
        ? (await this.adminProfileService.getCustodial(user.email)).privateKey
        : (await this.userService.getCustodial(user.email)).privateKey;

    return transactionSubmitter({
      signerKey,
      contractAddress: RoleRegistry.address,
      transactionName: transactionNameToSubmit,
      contractName: ContractName.RoleRegistry,
      args: [
        getContractByName[contractName].address,
        selector,
        encodeBytes32String(manageRoleAccessDto.roleName),
      ],
    });
  }

  async resetAccess(restRoleDto: ResetRoleDto & { user: UserJwtPayload }) {
    const { contractName, transactionName, user } = restRoleDto;
    const selector = getTxSelector({ contractName, transactionName });
    const signerKey =
      user.role === "admin"
        ? (await this.adminProfileService.getCustodial(user.email)).privateKey
        : (await this.userService.getCustodial(user.email)).privateKey;
    return transactionSubmitter({
      signerKey,
      contractAddress: RoleRegistry.address,
      transactionName: TransactionNames.resetAccess,
      contractName: ContractName.RoleRegistry,
      args: [
        restRoleDto.contractAddress || getContractByName[contractName].address,
        selector,
      ],
    });
  }
}

results matching ""

    No results matching ""