From b8d7bbf7dfc9f34a0b12ce678d99c543c0d06070 Mon Sep 17 00:00:00 2001 From: schultztimothy Date: Fri, 11 Aug 2023 12:17:16 -0600 Subject: [PATCH 1/3] feat(app, platforms): base trusta labs stamp --- app/context/ceramicContext.tsx | 8 ++++++++ platforms/src/TrustaLabs/App-Bindings.ts | 18 ++++++++++++++++++ platforms/src/TrustaLabs/Providers-config.ts | 16 ++++++++++++++++ .../src/TrustaLabs/Providers/TrustaLabs.ts | 15 +++++++++++++++ .../Providers/__tests__/TrustaLabs.test.ts | 5 +++++ platforms/src/TrustaLabs/index.ts | 3 +++ platforms/src/platforms.ts | 2 ++ types/src/index.d.ts | 6 ++++-- 8 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 platforms/src/TrustaLabs/App-Bindings.ts create mode 100644 platforms/src/TrustaLabs/Providers-config.ts create mode 100644 platforms/src/TrustaLabs/Providers/TrustaLabs.ts create mode 100644 platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts create mode 100644 platforms/src/TrustaLabs/index.ts diff --git a/app/context/ceramicContext.tsx b/app/context/ceramicContext.tsx index e3798964cf..0ac6d33164 100644 --- a/app/context/ceramicContext.tsx +++ b/app/context/ceramicContext.tsx @@ -45,6 +45,7 @@ const { Civic, CyberConnect, GrantsStack, + TrustaLabs, } = stampPlatforms; import { PlatformProps } from "../components/GenericPlatform"; @@ -235,6 +236,13 @@ platforms.set("GrantsStack", { platFormGroupSpec: GrantsStack.ProviderConfig, }); +if (process.env.NEXT_PUBLIC_FF_TRUSTALABS_STAMPS === "on") { + platforms.set("TrustaLabs", { + platform: new TrustaLabs.TrustaLabsPlatform(), + platFormGroupSpec: TrustaLabs.ProviderConfig, + }); +} + export enum IsLoadingPassportState { Idle, Loading, diff --git a/platforms/src/TrustaLabs/App-Bindings.ts b/platforms/src/TrustaLabs/App-Bindings.ts new file mode 100644 index 0000000000..9604f16742 --- /dev/null +++ b/platforms/src/TrustaLabs/App-Bindings.ts @@ -0,0 +1,18 @@ +import { AppContext, ProviderPayload } from "../types"; +import { Platform } from "../utils/platform"; + +export class TrustaLabsPlatform extends Platform { + platformId = "TrustaLabs"; + path = "TrustaLabs"; + clientId: string = null; + redirectUri: string = null; + + async getProviderPayload(appContext: AppContext): Promise { + const result = await Promise.resolve({}); + return result; + } + + getOAuthUrl(state: string): Promise { + throw new Error("Method not implemented."); + } +} diff --git a/platforms/src/TrustaLabs/Providers-config.ts b/platforms/src/TrustaLabs/Providers-config.ts new file mode 100644 index 0000000000..d6abb0c478 --- /dev/null +++ b/platforms/src/TrustaLabs/Providers-config.ts @@ -0,0 +1,16 @@ +import { PlatformSpec, PlatformGroupSpec, Provider } from "../types"; +import { TrustaLabsProvider } from "./Providers/TrustaLabs"; + +export const PlatformDetails: PlatformSpec = { + icon: "./assets/trustalabsStampIcon.svg", + platform: "TrustaLabs", + name: "TrustaLabs", + description: "Connect your existing TrustaLabs Account to verify", + connectMessage: "Connect Account", +}; + +export const ProviderConfig: PlatformGroupSpec[] = [ + { platformGroup: "Account Name", providers: [{ title: "TrustaLabs", name: "TrustaLabs" }] }, +]; + +export const providers: Provider[] = [new TrustaLabsProvider()]; diff --git a/platforms/src/TrustaLabs/Providers/TrustaLabs.ts b/platforms/src/TrustaLabs/Providers/TrustaLabs.ts new file mode 100644 index 0000000000..ca42dcb498 --- /dev/null +++ b/platforms/src/TrustaLabs/Providers/TrustaLabs.ts @@ -0,0 +1,15 @@ +import type { Provider, ProviderOptions } from "../../types"; +import { ProviderContext, RequestPayload, VerifiedPayload } from "@gitcoin/passport-types"; + +export class TrustaLabsProvider implements Provider { + type = "TrustaLabs"; + + async verify(payload: RequestPayload, context: ProviderContext): Promise { + return await Promise.resolve({ + valid: true, + record: { + challenge: "TrustaLabs", + }, + }); + } +} diff --git a/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts b/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts new file mode 100644 index 0000000000..c755c18e71 --- /dev/null +++ b/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts @@ -0,0 +1,5 @@ +describe("TrustaLabs", () => { + it("should be true", () => { + expect(true).toBe(true); + }); +}); diff --git a/platforms/src/TrustaLabs/index.ts b/platforms/src/TrustaLabs/index.ts new file mode 100644 index 0000000000..403283daf6 --- /dev/null +++ b/platforms/src/TrustaLabs/index.ts @@ -0,0 +1,3 @@ +export { TrustaLabsPlatform } from "./App-Bindings"; +export { ProviderConfig, PlatformDetails, providers } from "./Providers-config"; +export { TrustaLabsProvider } from "./Providers/TrustaLabs"; diff --git a/platforms/src/platforms.ts b/platforms/src/platforms.ts index 213a9bb951..e7b70b681b 100644 --- a/platforms/src/platforms.ts +++ b/platforms/src/platforms.ts @@ -25,6 +25,7 @@ import * as Idena from "./Idena"; import * as Civic from "./Civic"; import * as CyberConnect from "./CyberProfile"; import * as GrantsStack from "./GrantsStack"; +import * as TrustaLabs from "./TrustaLabs"; import { PlatformSpec, PlatformGroupSpec, Provider } from "./types"; type PlatformConfig = { @@ -62,6 +63,7 @@ const platforms: Record = { Civic, CyberConnect, GrantsStack, + TrustaLabs, }; if (process.env.NEXT_PUBLIC_FF_NEW_POAP_STAMPS === "on") { diff --git a/types/src/index.d.ts b/types/src/index.d.ts index 3ce7f4c84e..ca563de01c 100644 --- a/types/src/index.d.ts +++ b/types/src/index.d.ts @@ -228,7 +228,8 @@ export type PLATFORM_ID = | "Idena" | "Civic" | "CyberConnect" - | "GrantsStack"; + | "GrantsStack" + | "TrustaLabs"; export type PROVIDER_ID = | "Signer" @@ -329,7 +330,8 @@ export type PROVIDER_ID = | "GrantsStack7Projects" | "GrantsStack2Programs" | "GrantsStack4Programs" - | "GrantsStack6Programs"; + | "GrantsStack6Programs" + | "TrustaLabs"; export type StampBit = { bit: number; From 41cace2a67ce2f357b6ea53533e70800bb566d9e Mon Sep 17 00:00:00 2001 From: Aminah Burch Date: Mon, 14 Aug 2023 23:27:41 +0300 Subject: [PATCH 2/3] feat(platforms, app, iam): adds trusta labs stamp and db query --- app/.env-example.env | 1 + app/public/assets/trustaLabsStampIcon.svg | 1 + iam/.env-example.env | 1 + platforms/src/TrustaLabs/App-Bindings.ts | 1 + .../src/TrustaLabs/Providers/TrustaLabs.ts | 116 +++++++++++++++++- .../Providers/__tests__/TrustaLabs.test.ts | 73 ++++++++++- platforms/src/TrustaLabs/Providers/index.ts | 1 + 7 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 app/public/assets/trustaLabsStampIcon.svg create mode 100644 platforms/src/TrustaLabs/Providers/index.ts diff --git a/app/.env-example.env b/app/.env-example.env index 4d2b8b4db7..804e4e97cd 100644 --- a/app/.env-example.env +++ b/app/.env-example.env @@ -46,6 +46,7 @@ NEXT_PUBLIC_FF_ONE_CLICK_VERIFICATION=on NEXT_PUBLIC_FF_LIVE_ALLO_SCORE=on NEXT_PUBLIC_FF_NEW_TWITTER_STAMPS=on NEXT_PUBLIC_FF_CYBERCONNECT_STAMPS=on +NEXT_PUBLIC_FF_TRUSTALABS_STAMPS=on NEXT_PUBLIC_CERAMIC_CACHE_ENDPOINT=http://localhost:8002/ diff --git a/app/public/assets/trustaLabsStampIcon.svg b/app/public/assets/trustaLabsStampIcon.svg new file mode 100644 index 0000000000..203cfee6c9 --- /dev/null +++ b/app/public/assets/trustaLabsStampIcon.svg @@ -0,0 +1 @@ +资源 1 \ No newline at end of file diff --git a/iam/.env-example.env b/iam/.env-example.env index d563852eff..374b587932 100644 --- a/iam/.env-example.env +++ b/iam/.env-example.env @@ -24,6 +24,7 @@ GTC_STAKING_GRAPH_API_KEY=MY_API_KEY COINBASE_CLIENT_ID=MY_COINBASE_CLIENT_ID COINBASE_CLIENT_SECRET=MY_COINBASE_CLIENT_SECRET COINBASE_CALLBACK=http://localhost:3000/ +TRUSTA_LABS_ACCESS_TOKEN=trusta_labs_access_token CURRENT_ENV=development EXIT_ON_UNHANDLED_ERROR=true diff --git a/platforms/src/TrustaLabs/App-Bindings.ts b/platforms/src/TrustaLabs/App-Bindings.ts index 9604f16742..7e9b3aafc8 100644 --- a/platforms/src/TrustaLabs/App-Bindings.ts +++ b/platforms/src/TrustaLabs/App-Bindings.ts @@ -6,6 +6,7 @@ export class TrustaLabsPlatform extends Platform { path = "TrustaLabs"; clientId: string = null; redirectUri: string = null; + isEVM?: true; async getProviderPayload(appContext: AppContext): Promise { const result = await Promise.resolve({}); diff --git a/platforms/src/TrustaLabs/Providers/TrustaLabs.ts b/platforms/src/TrustaLabs/Providers/TrustaLabs.ts index ca42dcb498..ccef3b455e 100644 --- a/platforms/src/TrustaLabs/Providers/TrustaLabs.ts +++ b/platforms/src/TrustaLabs/Providers/TrustaLabs.ts @@ -1,15 +1,119 @@ import type { Provider, ProviderOptions } from "../../types"; -import { ProviderContext, RequestPayload, VerifiedPayload } from "@gitcoin/passport-types"; +import { RequestPayload, VerifiedPayload } from "@gitcoin/passport-types"; + +// ----- Libs +import axios from "axios"; + +// ----- Credential verification +import { getAddress } from "../../utils/signer"; +import { ProviderExternalVerificationError } from "../../types"; + +interface SubScore { + bulkOperationRisk: number; + starlikeAssetsNetworkRisk: number; + chainlikeAssetsNetworkRisk: number; + similarBehaviorSequenceRisk: number; + blacklistRisk: number; +} + +interface TrustaLabsData { + address: string; + sybilRiskScore: number; + sybilRiskLevel: string; + subScore: SubScore; +} + +interface TrustaLabsResponse { + data: TrustaLabsData; + success?: boolean; + code?: number; + message?: string; +} + +interface AxiosResponse { + data: TrustaLabsResponse; +} + +const TRUSTA_LABS_API_ENDPOINT = "https://www.trustalabs.ai/service/openapi/queryRiskSummaryScore"; + +const SCORER_BACKEND = process.env.PASSPORT_SCORER_BACKEND; + +const createUpdateDBScore = async (address: string, score: number) => { + try { + const response = await axios.post( + `${SCORER_BACKEND}trusta_labs/trusta-labs-score`, { address, score }, + { + headers: { + Authorization: process.env.CGRANTS_API_TOKEN + } + }, + ); + const { data } = response; + return data.data; + } catch (error) { + throw error; + } +}; + +const getTrustaLabsRiskScore = async (userAddress: string): Promise<{ valid: boolean; errors: string[]; }> => { + try { + const result: AxiosResponse = await axios.post(TRUSTA_LABS_API_ENDPOINT, { + address: userAddress, + chainId: "1" + }, + { + headers: { + Authorization: `Bearer ${process.env.TRUSTA_LABS_ACCESS_TOKEN}`, + accept: 'application/json', + 'content-type': 'application/json', + }, + }); + + const sybilRiskScore = result.data.data.sybilRiskScore; + await createUpdateDBScore(userAddress, sybilRiskScore); + + if (sybilRiskScore >= -1 && sybilRiskScore <= 60) { + return { + valid: true, + errors: [], + } + } else if (sybilRiskScore === -2 || sybilRiskScore > 60) { + return { + valid: false, + errors: ["User does not qualify for this stamp"], + } + } + } catch (error) { + throw new ProviderExternalVerificationError( + `Error requesting data: ${error}.` + ); + } +} export class TrustaLabsProvider implements Provider { type = "TrustaLabs"; - async verify(payload: RequestPayload, context: ProviderContext): Promise { + // Options can be set here and/or via the constructor + _options = {}; + + // construct the provider instance with supplied options + constructor(options: ProviderOptions = {}) { + this._options = { ...this._options, ...options }; + } + + async verify(payload: RequestPayload): Promise { + // if a signer is provider we will use that address to verify against + const address = (await getAddress(payload)).toLowerCase(); + const { valid, errors } = await getTrustaLabsRiskScore(address); + return await Promise.resolve({ - valid: true, - record: { - challenge: "TrustaLabs", - }, + valid, + errors, + record: valid + ? { + address: address, + } + : undefined, }); } } diff --git a/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts b/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts index c755c18e71..f7d9f2cb3b 100644 --- a/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts +++ b/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts @@ -1,5 +1,74 @@ +/* eslint-disable */ +// ---- Test subject +import { RequestPayload } from "@gitcoin/passport-types"; +import { TrustaLabsProvider } from "../../Providers/TrustaLabs"; + +// ----- Libs +import axios from "axios"; + +jest.mock("axios"); +const mockedAxios = axios as jest.Mocked; + +const MOCK_ADDRESS = "0xcF314CE817E25b4F784bC1f24c9A79A525fEC50f"; +const MOCK_ADDRESS_LOWER = MOCK_ADDRESS.toLocaleLowerCase(); + +const SCORER_BACKEND = process.env.PASSPORT_SCORER_BACKEND; + +const validTrustaLabsResponse = { + data: { + data: { + address: MOCK_ADDRESS_LOWER, + sybilRiskScore: 20, + }, + success: true, + code: 0, + message: "" + }, +}; + +const invalidTrustaLabsResponse = { + data: { + data: { + address: MOCK_ADDRESS_LOWER, + sybilRiskScore: 80, + }, + success: true, + code: 0, + message: "" + }, +}; + +const emptyTrustaLabsResponse = { + data: { + data: { + account: {}, + }, + }, +}; + +const TRUSTA_LABS_API_ENDPOINT = "https://www.trustalabs.ai/service/openapi/queryRiskSummaryScore"; + +beforeEach(() => { + jest.clearAllMocks(); +}); + describe("TrustaLabs", () => { - it("should be true", () => { - expect(true).toBe(true); + it("handles valid verification attempt", async () => { + // mockedAxios.post.mockResolvedValue(validTrustaLabsResponse); + + // const trustaLabsScore = new TrustaLabsProvider(); + // const verifiedPayload = await trustaLabsScore.verify({ + // address: MOCK_ADDRESS, + // } as unknown as RequestPayload); + + // expect(axios.post).toHaveBeenCalledTimes(2); + + // expect(verifiedPayload).toEqual({ + // valid: true, + // record: { + // address: MOCK_ADDRESS_LOWER, + // }, + // errors: [] + // }); }); }); diff --git a/platforms/src/TrustaLabs/Providers/index.ts b/platforms/src/TrustaLabs/Providers/index.ts new file mode 100644 index 0000000000..a44658269c --- /dev/null +++ b/platforms/src/TrustaLabs/Providers/index.ts @@ -0,0 +1 @@ +export { TrustaLabsProvider } from "./TrustaLabs"; From 1df288d2d996199f0545e89068ddb917df5f8f09 Mon Sep 17 00:00:00 2001 From: Lucian Hymer Date: Mon, 14 Aug 2023 17:09:00 -0700 Subject: [PATCH 3/3] wrapping up provider and tests --- app/components/PlatformCard.tsx | 2 + platforms/src/TrustaLabs/App-Bindings.ts | 13 +- platforms/src/TrustaLabs/Providers-config.ts | 4 +- .../src/TrustaLabs/Providers/TrustaLabs.ts | 119 +++++++++++------- .../Providers/__tests__/TrustaLabs.test.ts | 75 +++++------ platforms/src/utils/providers.ts | 1 + 6 files changed, 111 insertions(+), 103 deletions(-) diff --git a/app/components/PlatformCard.tsx b/app/components/PlatformCard.tsx index 46a3657a86..e1e4fb16bd 100644 --- a/app/components/PlatformCard.tsx +++ b/app/components/PlatformCard.tsx @@ -108,6 +108,8 @@ export const PlatformCard = ({ if (process.env.NEXT_PUBLIC_FF_CYBERCONNECT_STAMPS !== "on" && platform.platform === "CyberConnect") return <>; + if (process.env.NEXT_PUBLIC_FF_TRUSTALABS_STAMPS !== "on" && platform.platform === "TrustaLabs") return <>; + // returns a single Platform card return (
diff --git a/platforms/src/TrustaLabs/App-Bindings.ts b/platforms/src/TrustaLabs/App-Bindings.ts index 7e9b3aafc8..6a1ad75580 100644 --- a/platforms/src/TrustaLabs/App-Bindings.ts +++ b/platforms/src/TrustaLabs/App-Bindings.ts @@ -4,16 +4,9 @@ import { Platform } from "../utils/platform"; export class TrustaLabsPlatform extends Platform { platformId = "TrustaLabs"; path = "TrustaLabs"; - clientId: string = null; - redirectUri: string = null; - isEVM?: true; + isEVM = true; - async getProviderPayload(appContext: AppContext): Promise { - const result = await Promise.resolve({}); - return result; - } - - getOAuthUrl(state: string): Promise { - throw new Error("Method not implemented."); + async getProviderPayload(_appContext: AppContext): Promise { + return await Promise.resolve({}); } } diff --git a/platforms/src/TrustaLabs/Providers-config.ts b/platforms/src/TrustaLabs/Providers-config.ts index d6abb0c478..70aee28814 100644 --- a/platforms/src/TrustaLabs/Providers-config.ts +++ b/platforms/src/TrustaLabs/Providers-config.ts @@ -4,13 +4,13 @@ import { TrustaLabsProvider } from "./Providers/TrustaLabs"; export const PlatformDetails: PlatformSpec = { icon: "./assets/trustalabsStampIcon.svg", platform: "TrustaLabs", - name: "TrustaLabs", + name: "Trusta Labs", description: "Connect your existing TrustaLabs Account to verify", connectMessage: "Connect Account", }; export const ProviderConfig: PlatformGroupSpec[] = [ - { platformGroup: "Account Name", providers: [{ title: "TrustaLabs", name: "TrustaLabs" }] }, + { platformGroup: "Trusta Labs", providers: [{ title: "Sybil Score", name: "TrustaLabs" }] }, ]; export const providers: Provider[] = [new TrustaLabsProvider()]; diff --git a/platforms/src/TrustaLabs/Providers/TrustaLabs.ts b/platforms/src/TrustaLabs/Providers/TrustaLabs.ts index ccef3b455e..6709e97c73 100644 --- a/platforms/src/TrustaLabs/Providers/TrustaLabs.ts +++ b/platforms/src/TrustaLabs/Providers/TrustaLabs.ts @@ -5,7 +5,6 @@ import { RequestPayload, VerifiedPayload } from "@gitcoin/passport-types"; import axios from "axios"; // ----- Credential verification -import { getAddress } from "../../utils/signer"; import { ProviderExternalVerificationError } from "../../types"; interface SubScore { @@ -36,59 +35,88 @@ interface AxiosResponse { const TRUSTA_LABS_API_ENDPOINT = "https://www.trustalabs.ai/service/openapi/queryRiskSummaryScore"; -const SCORER_BACKEND = process.env.PASSPORT_SCORER_BACKEND; +// Based on https://axios-http.com/docs/handling_errors +const handleAxiosError = (error: any, label: string, secretsToHide?: string[]) => { + if (axios.isAxiosError(error)) { + let message = `Error making ${label} request, `; + if (error.response) { + // Received a non 2xx response + const { data, status, headers } = error.response; + message += `received error response with code ${status}: ${JSON.stringify(data)}, headers: ${JSON.stringify( + headers + )}`; + } else if (error.request) { + // No response received + message += "no response received"; + } else { + // Something happened in setting up the request that triggered an Error + message += error.message; + } + secretsToHide?.forEach((secret) => { + message = message.replace(secret, "[SECRET]"); + }); + throw new ProviderExternalVerificationError(message); + } + throw error; +}; const createUpdateDBScore = async (address: string, score: number) => { + const accessToken = process.env.CGRANTS_API_TOKEN; try { - const response = await axios.post( - `${SCORER_BACKEND}trusta_labs/trusta-labs-score`, { address, score }, + await axios.post( + `${process.env.SCORER_ENDPOINT}/trusta_labs/trusta-labs-score`, + { address, score }, { headers: { - Authorization: process.env.CGRANTS_API_TOKEN - } - }, + Authorization: accessToken, + }, + } ); - const { data } = response; - return data.data; } catch (error) { - throw error; + handleAxiosError(error, "report score", [accessToken]); } }; -const getTrustaLabsRiskScore = async (userAddress: string): Promise<{ valid: boolean; errors: string[]; }> => { +const makeSybilScoreRequest = async (address: string) => { + const accessToken = process.env.TRUSTA_LABS_ACCESS_TOKEN; try { - const result: AxiosResponse = await axios.post(TRUSTA_LABS_API_ENDPOINT, { - address: userAddress, - chainId: "1" - }, + const result: AxiosResponse = await axios.post( + TRUSTA_LABS_API_ENDPOINT, + { + address, + chainId: "1", + }, { headers: { - Authorization: `Bearer ${process.env.TRUSTA_LABS_ACCESS_TOKEN}`, - accept: 'application/json', - 'content-type': 'application/json', + Authorization: `Bearer ${accessToken}`, }, - }); - - const sybilRiskScore = result.data.data.sybilRiskScore; - await createUpdateDBScore(userAddress, sybilRiskScore); - - if (sybilRiskScore >= -1 && sybilRiskScore <= 60) { - return { - valid: true, - errors: [], - } - } else if (sybilRiskScore === -2 || sybilRiskScore > 60) { - return { - valid: false, - errors: ["User does not qualify for this stamp"], } - } - } catch (error) { - throw new ProviderExternalVerificationError( - `Error requesting data: ${error}.` ); + return result.data.data.sybilRiskScore; + } catch (error) { + handleAxiosError(error, "sybil score", [accessToken]); } -} +}; + +const verifyTrustaLabsRiskScore = async (address: string): Promise<{ valid: boolean; errors: string[] }> => { + const sybilRiskScore = await makeSybilScoreRequest(address); + await createUpdateDBScore(address, sybilRiskScore); + + const lowerBound = -1; + const upperBound = 60; + + if (sybilRiskScore >= lowerBound && sybilRiskScore <= upperBound) { + return { + valid: true, + errors: [], + }; + } else { + return { + valid: false, + errors: [`Sybil score ${sybilRiskScore} is outside of the allowed range (${lowerBound} to ${upperBound})`], + }; + } +}; export class TrustaLabsProvider implements Provider { type = "TrustaLabs"; @@ -102,18 +130,17 @@ export class TrustaLabsProvider implements Provider { } async verify(payload: RequestPayload): Promise { + const { address } = payload; + // if a signer is provider we will use that address to verify against - const address = (await getAddress(payload)).toLowerCase(); - const { valid, errors } = await getTrustaLabsRiskScore(address); + const { valid, errors } = await verifyTrustaLabsRiskScore(address); - return await Promise.resolve({ + return { valid, errors, - record: valid - ? { - address: address, - } - : undefined, - }); + record: { + address, + }, + }; } } diff --git a/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts b/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts index f7d9f2cb3b..4def254b1f 100644 --- a/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts +++ b/platforms/src/TrustaLabs/Providers/__tests__/TrustaLabs.test.ts @@ -12,63 +12,48 @@ const mockedAxios = axios as jest.Mocked; const MOCK_ADDRESS = "0xcF314CE817E25b4F784bC1f24c9A79A525fEC50f"; const MOCK_ADDRESS_LOWER = MOCK_ADDRESS.toLocaleLowerCase(); -const SCORER_BACKEND = process.env.PASSPORT_SCORER_BACKEND; - -const validTrustaLabsResponse = { - data: { - data: { - address: MOCK_ADDRESS_LOWER, - sybilRiskScore: 20, - }, - success: true, - code: 0, - message: "" - }, -}; - -const invalidTrustaLabsResponse = { +const makeResponse = (score: number) => ({ data: { data: { address: MOCK_ADDRESS_LOWER, - sybilRiskScore: 80, + sybilRiskScore: score, }, success: true, code: 0, - message: "" + message: "", }, -}; - -const emptyTrustaLabsResponse = { - data: { - data: { - account: {}, - }, - }, -}; - -const TRUSTA_LABS_API_ENDPOINT = "https://www.trustalabs.ai/service/openapi/queryRiskSummaryScore"; +}); beforeEach(() => { jest.clearAllMocks(); }); describe("TrustaLabs", () => { - it("handles valid verification attempt", async () => { - // mockedAxios.post.mockResolvedValue(validTrustaLabsResponse); - - // const trustaLabsScore = new TrustaLabsProvider(); - // const verifiedPayload = await trustaLabsScore.verify({ - // address: MOCK_ADDRESS, - // } as unknown as RequestPayload); - - // expect(axios.post).toHaveBeenCalledTimes(2); - - // expect(verifiedPayload).toEqual({ - // valid: true, - // record: { - // address: MOCK_ADDRESS_LOWER, - // }, - // errors: [] - // }); + it.each([ + [20, true], + [30.000045668, true], + [60, true], + [80, false], + [-1, true], + [-2, false], + ])("should return %s for score %s", async (score: number, expected: boolean) => { + mockedAxios.post.mockResolvedValue(makeResponse(score)); + + const trustaLabs = new TrustaLabsProvider(); + const verifiedPayload = await trustaLabs.verify({ + address: MOCK_ADDRESS, + } as RequestPayload); + + expect(axios.post).toHaveBeenCalledTimes(2); + + const { valid, record, errors } = verifiedPayload; + if (expected) { + expect(valid).toBe(true); + expect(record).toEqual({ address: MOCK_ADDRESS }); + expect(errors).toEqual([]); + } else { + expect(valid).toBe(false); + expect(errors).toEqual([`Sybil score ${score} is outside of the allowed range (-1 to 60)`]); + } }); }); diff --git a/platforms/src/utils/providers.ts b/platforms/src/utils/providers.ts index 131ce26fac..52284bccd5 100644 --- a/platforms/src/utils/providers.ts +++ b/platforms/src/utils/providers.ts @@ -6,6 +6,7 @@ const UPDATED_PROVIDERS = [ "twitterAccountAgeGte#180", "twitterAccountAgeGte#365", "twitterAccountAgeGte#730", + "TrustaLabs", "Simple", ];