Skip to content

Commit

Permalink
[OTE-420]: Deprecate ONBOARD from Indexer (#1728)
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher-Li authored Jun 19, 2024
1 parent a56105b commit 2039998
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ describe('ComplianceV2Controller', () => {
const body: any = {
address: testConstants.defaultAddress,
message: 'Test message',
action: ComplianceAction.ONBOARD,
action: ComplianceAction.CONNECT,
signedMessage: 'signedmessage123',
pubkey: 'asdfasdf',
timestamp: 1620000000,
Expand Down Expand Up @@ -340,10 +340,11 @@ describe('ComplianceV2Controller', () => {
expect(response.body.status).toEqual(ComplianceStatus.COMPLIANT);
});

it('should set status to BLOCKED for ONBOARD action from a restricted country with no existing compliance status', async () => {
it('should set status to BLOCKED for CONNECT action from a restricted country with no existing compliance status and no wallet', async () => {
(Secp256k1.verifySignature as jest.Mock).mockResolvedValueOnce(true);
getGeoComplianceReasonSpy.mockReturnValueOnce(ComplianceReason.US_GEO);
isRestrictedCountryHeadersSpy.mockReturnValue(true);
await dbHelpers.clearData();

const response: any = await sendRequest({
type: RequestMethod.POST,
Expand All @@ -365,7 +366,7 @@ describe('ComplianceV2Controller', () => {
expect(response.body.updatedAt).toBeDefined();
});

it('should set status to FIRST_STRIKE_CLOSE_ONLY for CONNECT action from a restricted country with no existing compliance status', async () => {
it('should set status to FIRST_STRIKE_CLOSE_ONLY for CONNECT action from a restricted country with no existing compliance status and a wallet', async () => {
(Secp256k1.verifySignature as jest.Mock).mockResolvedValueOnce(true);
getGeoComplianceReasonSpy.mockReturnValueOnce(ComplianceReason.US_GEO);
isRestrictedCountryHeadersSpy.mockReturnValue(true);
Expand Down Expand Up @@ -446,59 +447,6 @@ describe('ComplianceV2Controller', () => {
expect(response.body.updatedAt).toBeDefined();
});

it('should be a no-op for ONBOARD action with existing COMPLIANT status', async () => {
await ComplianceStatusTable.create({
address: testConstants.defaultAddress,
status: ComplianceStatus.COMPLIANT,
});
(Secp256k1.verifySignature as jest.Mock).mockResolvedValueOnce(true);
isRestrictedCountryHeadersSpy.mockReturnValue(true);

const response: any = await sendRequest({
type: RequestMethod.POST,
path: '/v4/compliance/geoblock',
body,
expectedStatus: 200,
});

const data: ComplianceStatusFromDatabase[] = await ComplianceStatusTable.findAll({}, [], {});
expect(data).toHaveLength(1);
expect(data[0]).toEqual(expect.objectContaining({
address: testConstants.defaultAddress,
status: ComplianceStatus.COMPLIANT,
}));
expect(response.body.status).toEqual(ComplianceStatus.COMPLIANT);
});

it('should be a no-op for ONBOARD action with existing FIRST_STRIKE_CLOSE_ONLY status', async () => {
await ComplianceStatusTable.create({
address: testConstants.defaultAddress,
status: ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY,
reason: ComplianceReason.US_GEO,
});
(Secp256k1.verifySignature as jest.Mock).mockResolvedValueOnce(true);
isRestrictedCountryHeadersSpy.mockReturnValue(true);

const response: any = await sendRequest({
type: RequestMethod.POST,
path: '/v4/compliance/geoblock',
body,
expectedStatus: 200,
});

const data: ComplianceStatusFromDatabase[] = await ComplianceStatusTable.findAll({}, [], {});
expect(data).toHaveLength(1);
expect(data[0]).toEqual(expect.objectContaining({
address: testConstants.defaultAddress,
status: ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY,
reason: ComplianceReason.US_GEO,
}));

expect(response.body.status).toEqual(ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY);
expect(response.body.reason).toEqual(ComplianceReason.US_GEO);
expect(response.body.updatedAt).toBeDefined();
});

it('should update status to CLOSE_ONLY for CONNECT action from a restricted country with existing FIRST_STRIKE status', async () => {
await ComplianceStatusTable.create({
address: testConstants.defaultAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import {
ComplianceStatus,
ComplianceStatusFromDatabase,
ComplianceStatusTable,
WalletFromDatabase,
WalletTable,
} from '@dydxprotocol-indexer/postgres';
import express from 'express';
import { matchedData } from 'express-validator';
import _ from 'lodash';
import { DateTime } from 'luxon';
import {
Controller, Get, Path, Route,
Expand All @@ -28,14 +31,15 @@ import { getIpAddr } from '../../../lib/utils';
import { CheckAddressSchema } from '../../../lib/validation/schemas';
import { handleValidationErrors } from '../../../request-helpers/error-handler';
import ExportResponseCodeStats from '../../../request-helpers/export-response-code-stats';
import { ComplianceRequest, ComplianceV2Response, SetComplianceStatusRequest } from '../../../types';
import {
ComplianceRequest, ComplianceV2Response, SetComplianceStatusRequest,
} from '../../../types';
import { ComplianceControllerHelper } from './compliance-controller';

const router: express.Router = express.Router();
const controllerName: string = 'compliance-v2-controller';

export enum ComplianceAction {
ONBOARD = 'ONBOARD',
CONNECT = 'CONNECT',
VALID_SURVEY = 'VALID_SURVEY',
INVALID_SURVEY = 'INVALID_SURVEY',
Expand Down Expand Up @@ -235,98 +239,31 @@ router.post(
);
}

/**
* If the address doesn't exist in the compliance table:
* - if the request is from a restricted country:
* - if the action is ONBOARD, set the status to BLOCKED
* - if the action is CONNECT, set the status to FIRST_STRIKE_CLOSE_ONLY
* - else if the request is from a non-restricted country:
* - set the status to COMPLIANT
*
* if the address is COMPLIANT:
* - the ONLY action should be CONNECT. ONBOARD/VALID_SURVEY/INVALID_SURVEY are no-ops.
* - if the request is from a restricted country:
* - set the status to FIRST_STRIKE_CLOSE_ONLY
*
* if the address is FIRST_STRIKE_CLOSE_ONLY:
* - the ONLY actions should be VALID_SURVEY/INVALID_SURVEY/CONNECT. ONBOARD/CONNECT
* are no-ops.
* - if the action is VALID_SURVEY:
* - set the status to FIRST_STRIKE
* - if the action is INVALID_SURVEY:
* - set the status to CLOSE_ONLY
*
* if the address is FIRST_STRIKE:
* - the ONLY action should be CONNECT. ONBOARD/VALID_SURVEY/INVALID_SURVEY are no-ops.
* - if the request is from a restricted country:
* - set the status to CLOSE_ONLY
*/
const complianceStatus: ComplianceStatusFromDatabase[] = await
ComplianceStatusTable.findAll(
{ address: [address] },
[],
);
let complianceStatusFromDatabase: ComplianceStatusFromDatabase | undefined;
const [
complianceStatus,
wallet,
]: [
ComplianceStatusFromDatabase[],
WalletFromDatabase | undefined,
] = await Promise.all([
ComplianceStatusTable.findAll(
{ address: [address] },
[],
),
WalletTable.findById(address),
]);

const updatedAt: string = DateTime.utc().toISO();
if (complianceStatus.length === 0) {
if (isRestrictedCountryHeaders(req.headers as CountryHeaders)) {
if (action === ComplianceAction.ONBOARD) {
complianceStatusFromDatabase = await ComplianceStatusTable.upsert({
address,
status: ComplianceStatus.BLOCKED,
reason: getGeoComplianceReason(req.headers as CountryHeaders)!,
updatedAt,
});
} else if (action === ComplianceAction.CONNECT) {
complianceStatusFromDatabase = await ComplianceStatusTable.upsert({
address,
status: ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY,
reason: getGeoComplianceReason(req.headers as CountryHeaders)!,
updatedAt,
});
}
} else {
complianceStatusFromDatabase = await ComplianceStatusTable.upsert({
address,
status: ComplianceStatus.COMPLIANT,
updatedAt,
});
}
} else {
complianceStatusFromDatabase = complianceStatus[0];
if (
complianceStatus[0].status === ComplianceStatus.FIRST_STRIKE ||
complianceStatus[0].status === ComplianceStatus.COMPLIANT
) {
if (
isRestrictedCountryHeaders(req.headers as CountryHeaders) &&
action === ComplianceAction.CONNECT
) {
complianceStatusFromDatabase = await ComplianceStatusTable.update({
address,
status: COMPLIANCE_PROGRESSION[complianceStatus[0].status],
reason: getGeoComplianceReason(req.headers as CountryHeaders)!,
updatedAt,
});
}
} else if (
complianceStatus[0].status === ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY
) {
if (action === ComplianceAction.VALID_SURVEY) {
complianceStatusFromDatabase = await ComplianceStatusTable.update({
address,
status: ComplianceStatus.FIRST_STRIKE,
updatedAt,
});
} else if (action === ComplianceAction.INVALID_SURVEY) {
complianceStatusFromDatabase = await ComplianceStatusTable.update({
address,
status: ComplianceStatus.CLOSE_ONLY,
updatedAt,
});
}
}
}
const complianceStatusFromDatabase:
ComplianceStatusFromDatabase | undefined = await upsertComplianceStatus(
req,
action,
address,
wallet,
complianceStatus,
updatedAt,
);

const response = {
status: complianceStatusFromDatabase!.status,
reason: complianceStatusFromDatabase!.reason,
Expand Down Expand Up @@ -360,6 +297,102 @@ function generateAddress(pubkeyArray: Uint8Array): string {
return toBech32('dydx', ripemd160(sha256(pubkeyArray)));
}

/**
* If the address doesn't exist in the compliance table:
* - if the request is from a restricted country:
* - if the action is CONNECT and no wallet, set the status to BLOCKED
* - if the action is CONNECT and wallet exists, set the status to FIRST_STRIKE_CLOSE_ONLY
* - else if the request is from a non-restricted country:
* - set the status to COMPLIANT
*
* if the address is COMPLIANT:
* - the ONLY action should be CONNECT. VALID_SURVEY/INVALID_SURVEY are no-ops.
* - if the request is from a restricted country:
* - set the status to FIRST_STRIKE_CLOSE_ONLY
*
* if the address is FIRST_STRIKE_CLOSE_ONLY:
* - the ONLY actions should be VALID_SURVEY/INVALID_SURVEY/CONNECT. CONNECT
* are no-ops.
* - if the action is VALID_SURVEY:
* - set the status to FIRST_STRIKE
* - if the action is INVALID_SURVEY:
* - set the status to CLOSE_ONLY
*
* if the address is FIRST_STRIKE:
* - the ONLY action should be CONNECT. VALID_SURVEY/INVALID_SURVEY are no-ops.
* - if the request is from a restricted country:
* - set the status to CLOSE_ONLY
*/
// eslint-disable-next-line @typescript-eslint/require-await
async function upsertComplianceStatus(
req: express.Request,
action: ComplianceAction,
address: string,
wallet: WalletFromDatabase | undefined,
complianceStatus: ComplianceStatusFromDatabase[],
updatedAt: string,
): Promise<ComplianceStatusFromDatabase | undefined> {
if (complianceStatus.length === 0) {
if (!isRestrictedCountryHeaders(req.headers as CountryHeaders)) {
return ComplianceStatusTable.upsert({
address,
status: ComplianceStatus.COMPLIANT,
updatedAt,
});
}

// If address is restricted and is not onboarded then block
if (_.isUndefined(wallet)) {
return ComplianceStatusTable.upsert({
address,
status: ComplianceStatus.BLOCKED,
reason: getGeoComplianceReason(req.headers as CountryHeaders)!,
updatedAt,
});
}

return ComplianceStatusTable.upsert({
address,
status: ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY,
reason: getGeoComplianceReason(req.headers as CountryHeaders)!,
updatedAt,
});
}

if (
complianceStatus[0].status === ComplianceStatus.FIRST_STRIKE ||
complianceStatus[0].status === ComplianceStatus.COMPLIANT
) {
if (
isRestrictedCountryHeaders(req.headers as CountryHeaders) &&
action === ComplianceAction.CONNECT
) {
return ComplianceStatusTable.update({
address,
status: COMPLIANCE_PROGRESSION[complianceStatus[0].status],
reason: getGeoComplianceReason(req.headers as CountryHeaders)!,
updatedAt,
});
}
} else if (complianceStatus[0].status === ComplianceStatus.FIRST_STRIKE_CLOSE_ONLY) {
if (action === ComplianceAction.VALID_SURVEY) {
return ComplianceStatusTable.update({
address,
status: ComplianceStatus.FIRST_STRIKE,
updatedAt,
});
} else if (action === ComplianceAction.INVALID_SURVEY) {
return ComplianceStatusTable.update({
address,
status: ComplianceStatus.CLOSE_ONLY,
updatedAt,
});
}
}

return complianceStatus[0];
}

if (config.EXPOSE_SET_COMPLIANCE_ENDPOINT) {
router.post(
'/setStatus',
Expand Down

0 comments on commit 2039998

Please sign in to comment.