Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OnboardingAPI: fix-ups for algol #1560

Merged
merged 7 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import { useWallet } from '@centrifuge/centrifuge-react'
import { useCentrifuge, useWallet } from '@centrifuge/centrifuge-react'
import { encodeAddress } from '@polkadot/util-crypto'
import { useQuery } from 'react-query'
import { getSelectedWallet } from '../../../utils/getSelectedWallet'

export const useGlobalOnboardingStatus = () => {
const wallet = useWallet()
const cent = useCentrifuge()

const selectedWallet = getSelectedWallet(wallet)

const query = useQuery(
['global-onboarding-status', selectedWallet?.address],
async () => {
if (selectedWallet) {
if (selectedWallet && selectedWallet.address) {
const chainId = await cent.getChainId()
const address =
selectedWallet.network === 'substrate'
? encodeAddress(selectedWallet.address, chainId)
: selectedWallet.address
const response = await fetch(
`${import.meta.env.REACT_APP_ONBOARDING_API_URL}/getGlobalOnboardingStatus?address=${
selectedWallet.address
}&network=${selectedWallet.network}`,
`${import.meta.env.REACT_APP_ONBOARDING_API_URL}/getGlobalOnboardingStatus?address=${address}&network=${
selectedWallet.network
}&chainId=${wallet.connectedNetwork}`,
{
method: 'GET',
headers: {
Expand Down
4 changes: 3 additions & 1 deletion centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@
// @ts-expect-error
blockNumber = result.blockNumber.toString()
}
const chainId = connectedNetwork === 'centrifuge' ? await centrifuge.getChainId() : connectedNetwork

await sendDocumentsToIssuer({
txHash,
blockNumber,
isEvmOnSubstrate,
chainId: connectedNetwork || 'centrifuge',
chainId: chainId || 136,
})
setIsSubstrateTxLoading(false)
} catch (e) {
Expand Down Expand Up @@ -149,7 +151,7 @@
}
}
executePaymentInfo()
}, [centrifuge, selectedAccount])

Check warning on line 154 in centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts

View workflow job for this annotation

GitHub Actions / build-app

React Hook useEffect has missing dependencies: 'evmChainId', 'evmProvider', 'evmSelectedAddress', and 'isEvmOnSubstrate'. Either include them or remove the dependency array

const signEvmRemark = async (args: [message: string]) => {
const txId = Math.random().toString(36).substr(2)
Expand Down
16 changes: 13 additions & 3 deletions onboarding-api/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# VARIABLES
REDIRECT_URL=http://localhost:3000
MEMBERLIST_ADMIN_PURE_PROXY=kAM1ELFDHdHeLDAkAdwEnfufoCL5hpUycGs4ZQkSQKVpHFoXm
COLLATOR_WSS_URL=wss://fullnode.algol.cntrfg.com/public-ws
RELAY_WSS_URL=wss://fullnode-relay.algol.cntrfg.com
INFURA_KEY=bf808e7d3d924fbeb74672d9341d0550
EVM_NETWORK=goerli
ONBOARDING_STORAGE_BUCKET=centrifuge-onboarding-api-dev
# SECRETS
SHUFTI_PRO_SECRET_KEY=
SHUFTI_PRO_CLIENT_ID=
NODE_ENV=development
JWT_SECRET=
REDIRECT_URL=http://localhost:3000
SENDGRID_API_KEY=
SENDGRID_API_KEY=
COOKIE_SECRET=
EVM_MEMBERLIST_ADMIN_PRIVATE_KEY=
PURE_PROXY_CONTROLLER_SEED=
12 changes: 3 additions & 9 deletions onboarding-api/src/controllers/user/getGlobalOnboardingStatus.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import { Request, Response } from 'express'
import { InferType, mixed, object, string } from 'yup'
import { SupportedNetworks } from '../../database'
import { walletSchema } from '../../database'
import { fetchUser } from '../../utils/fetchUser'
import { reportHttpError } from '../../utils/httpError'
import { validateInput } from '../../utils/validateInput'

const getGlobalOnboardingStatusInput = object({
address: string().required(),
network: mixed<SupportedNetworks>().required().oneOf(['evm', 'substrate']),
})

export const getGlobalOnboardingStatusController = async (
req: Request<{}, {}, {}, InferType<typeof getGlobalOnboardingStatusInput>>,
req: Request<{}, {}, {}, Request['wallet']>,
res: Response
) => {
try {
await validateInput(req.query, getGlobalOnboardingStatusInput)
await validateInput(req.query, walletSchema)

const user = await fetchUser(req.query, { suppressError: true })

Expand Down
4 changes: 2 additions & 2 deletions onboarding-api/src/controllers/user/updateInvestorStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,13 @@ export const updateInvestorStatusController = async (
metadata,
countersignedAgreementPDF
),
sendApproveIssuerMessage(wallet.address, metadata, tranche as Pool['tranches'][0], countersignedAgreementPDF),
sendApproveIssuerMessage(wallet, metadata, tranche as Pool['tranches'][0], countersignedAgreementPDF),
validateAndWriteToFirestore(wallet, updatedUser, user.investorType, ['poolSteps']),
])
return res.status(200).send({ status: 'approved', poolId, trancheId, txHash })
} else if (user?.email && status === 'rejected') {
await Promise.all([
sendRejectInvestorMessage(user.email, metadata),
sendRejectInvestorMessage(user.email, tranche as Pool['tranches'][0], metadata),
validateAndWriteToFirestore(wallet, updatedUser, user.investorType, ['poolSteps']),
])
return res.status(200).send({ status: 'rejected', poolId, trancheId })
Expand Down
4 changes: 2 additions & 2 deletions onboarding-api/src/database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const uboSchema = object({
countryOfCitizenship: string().required(),
})

const walletSchema = object({
export const walletSchema = object({
evm: array().of(string()),
substrate: array().of(string()),
evmOnSubstrate: array().of(string()),
Expand Down Expand Up @@ -115,7 +115,7 @@ export const individualUserSchema = object({
investorType: string().default('individual') as StringSchema<Individual>,
wallets: walletSchema,
kycReference: string().optional(),
email: string().default(null).nullable(), // TODO: coming soon
email: string().default(null).nullable(),
name: string().required(),
dateOfBirth: string().required(),
countryOfCitizenship: string().required(), // TODO: validate with list of countries
Expand Down
1 change: 0 additions & 1 deletion onboarding-api/src/emails/sendApproveInvestorMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const sendApproveInvestorMessage = async (
},
],
dynamic_template_data: {
poolName: poolMetadata?.pool.name,
trancheName: tranche?.currency.name,
poolUrl: `${process.env.REDIRECT_URL}/pools/${poolId}`,
},
Expand Down
10 changes: 7 additions & 3 deletions onboarding-api/src/emails/sendApproveIssuerMessage.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Pool } from '@centrifuge/centrifuge-js'
import { Request } from 'express'
import { sendEmail, templateIds } from '.'
import { fetchUser } from '../utils/fetchUser'

export const sendApproveIssuerMessage = async (
walletAddress: string,
wallet: Request['wallet'],
metadata: Record<string, any>,
tranche: Pool['tranches'][0],
countersignedAgreementPDF: Uint8Array
) => {
const user = await fetchUser(wallet)
const message = {
personalizations: [
{
Expand All @@ -16,7 +19,8 @@ export const sendApproveIssuerMessage = async (
},
],
dynamic_template_data: {
tokenName: tranche.currency.name,
trancheName: tranche.currency.name,
investorEmail: user.email,
},
},
],
Expand All @@ -28,7 +32,7 @@ export const sendApproveIssuerMessage = async (
attachments: [
{
content: Buffer.from(countersignedAgreementPDF).toString('base64'),
filename: `${walletAddress}-${tranche.currency.name?.replaceAll(' ', '-')}-subscription-agreement.pdf`,
filename: `${wallet.address}-${tranche.currency.name?.replaceAll(' ', '-')}-subscription-agreement.pdf`,
type: 'application/pdf',
disposition: 'attachment',
},
Expand Down
6 changes: 6 additions & 0 deletions onboarding-api/src/emails/sendDocumentsMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Request } from 'express'
import * as jwt from 'jsonwebtoken'
import { sendEmail, templateIds } from '.'
import { onboardingBucket } from '../database'
import { fetchUser } from '../utils/fetchUser'
import { HttpError } from '../utils/httpError'
import { NetworkSwitch } from '../utils/networks/networkSwitch'

Expand All @@ -11,6 +12,7 @@ export type UpdateInvestorStatusPayload = {
trancheId: string
}

// send documents to issuer to approve or reject the prospective investor
export const sendDocumentsMessage = async (
wallet: Request['wallet'],
poolId: string,
Expand All @@ -19,6 +21,8 @@ export const sendDocumentsMessage = async (
debugEmail?: string
) => {
const { metadata, pool } = await new NetworkSwitch(wallet.network).getPoolById(poolId)
const tranche = pool?.tranches.find((t) => t.id === trancheId)
const investorEmail = (await fetchUser(wallet)).email
const payload: UpdateInvestorStatusPayload = { wallet, poolId, trancheId }
const token = jwt.sign(payload, process.env.JWT_SECRET, {
expiresIn: '14d',
Expand Down Expand Up @@ -48,6 +52,8 @@ export const sendDocumentsMessage = async (
token
)}&status=approved&metadata=${pool?.metadata}&network=${wallet.network}`,
disclaimerLink: `${process.env.REDIRECT_URL}/disclaimer`,
trancheName: tranche?.currency.name,
investorEmail,
},
},
],
Expand Down
9 changes: 7 additions & 2 deletions onboarding-api/src/emails/sendRejectInvestorMessage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Pool } from '@centrifuge/centrifuge-js'
import { sendEmail, templateIds } from '.'

export const sendRejectInvestorMessage = async (to: string, metadata: Record<string, any>) => {
export const sendRejectInvestorMessage = async (
to: string,
tranche: Pool['tranches'][0],
metadata: Record<string, any>
) => {
const message = {
personalizations: [
{
Expand All @@ -10,8 +15,8 @@ export const sendRejectInvestorMessage = async (to: string, metadata: Record<str
},
],
dynamic_template_data: {
poolName: metadata?.pool.name,
issuerEmail: metadata.pool.issuer.email,
trancheName: tranche?.currency.name,
},
},
],
Expand Down
2 changes: 1 addition & 1 deletion onboarding-api/src/utils/envCheck.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
const devEnvs = ['demo', 'development', 'catalyst']
const devEnvs = ['algol', 'development', 'catalyst']
export const IS_DEV_ENV = devEnvs.some((env) => process.env.COLLATOR_WSS_URL.includes(env))
2 changes: 1 addition & 1 deletion onboarding-api/src/utils/fetchUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function fetchUser<T>(wallet: Request['wallet'], options?: OptionsO
if (!userSnapshotOnOtherNetwork.empty) {
const { user, id } = userSnapshotOnOtherNetwork.docs.map((doc) => ({ user: doc.data(), id: doc.id }))[0]
await validateAndWriteToFirestore(
{ address: id, network },
{ address: id, network, chainId: wallet.chainId },
{
wallets: {
...user.wallets,
Expand Down
Loading