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

feat(NftStamp): update nft stamp, include nft model #2387

Merged
merged 5 commits into from
Apr 19, 2024
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
40 changes: 36 additions & 4 deletions platforms/src/NFT/Providers-config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PlatformSpec, PlatformGroupSpec, Provider } from "../types";
import { NFTProvider } from "./Providers";
import { NFTProvider, DigitalCollectorProvider, ArtAficionadoProvider, NftVisionaryProvider} from "./Providers";

export const PlatformDetails: PlatformSpec = {
icon: "./assets/nftStampIcon.svg",
Expand All @@ -14,9 +14,41 @@ export const PlatformDetails: PlatformSpec = {

export const ProviderConfig: PlatformGroupSpec[] = [
{
platformGroup: "NFT Holder",
providers: [{ title: "Holds at least 1 NFT", name: "NFT" }],
platformGroup: "Collector's Journey",
providers: [
{
name: "DigitalCollector",
title: "Digital Collector",
description:
"Recognizes users beginning to explore the NFT space with a budding collection.",
},
{
name: "ArtAficionado",
title: "Art Aficionado",
description:
"Highlights users with a significant, more curated NFT portfolio that demonstrates their deeper involvement and appreciation for digital art and assets.",
},
{
name: "NftVisionary",
title: "NFT Visionary",
description:
"Distinguishes users at the forefront of the NFT movement, showcasing exceptional collections that set trends within the community.",
},
],
},
{
platformGroup: "NFT Ownership Verification",
providers: [{
name: "NFT",
title: "NFT Holder",
description: "Verifies users possessing at least one NFT on the Ethereum mainnet, serving as the foundational credential within the NFT stamp category."
},],
},
];

export const providers: Provider[] = [new NFTProvider()];
export const providers: Provider[] = [
new NFTProvider(),
new DigitalCollectorProvider(),
new ArtAficionadoProvider(),
new NftVisionaryProvider()
];
301 changes: 301 additions & 0 deletions platforms/src/NFT/Providers/__tests__/collectors_journey.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
/* eslint-disable */
// ---- Test subject
import {
DigitalCollectorProvider,
ArtAficionadoProvider,
NftVisionaryProvider,
NftCollectorBaseProvider,
} from "../collectors_journey";

import { RequestPayload } from "@gitcoin/passport-types";

// ----- Libs
import axios, { AxiosError } from "axios";
import { ProviderExternalVerificationError } from "../../../types";
jest.mock("axios");

const mockedAxios = axios as jest.Mocked<typeof axios>;
const MOCK_ADDRESS = "0xcF314CE817E25b4F784bC1f24c9A79A525fEC50f";
const MOCK_ADDRESS_LOWER = MOCK_ADDRESS.toLocaleLowerCase();

describe("Valid stamp verification Collector's Journey", function () {
beforeEach(() => {
jest.clearAllMocks();
});

it("Should return valid stamp for DigitalCollector (50)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 50,
},
},
});
});

const digitalCollectorProvider = new DigitalCollectorProvider();
const digitalCollectorPayload = await digitalCollectorProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(digitalCollectorPayload).toEqual({
valid: true,
record: {
address: MOCK_ADDRESS_LOWER,
human_probability: "50",
},
});
});

it("Should return valid stamp for DigitalCollector (60)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 60,
},
},
});
});

const digitalCollectorProvider = new DigitalCollectorProvider();
const digitalCollectorPayload = await digitalCollectorProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(digitalCollectorPayload).toEqual({
valid: true,
record: {
address: MOCK_ADDRESS_LOWER,
human_probability: "60",
},
});
});

it("Should return valid stamp for ArtAficionado (75)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 75,
},
},
});
});

const artAficionadoProvider = new ArtAficionadoProvider();
const artAficionadoPayload = await artAficionadoProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(artAficionadoPayload).toEqual({
valid: true,
record: {
address: MOCK_ADDRESS_LOWER,
human_probability: "75",
},
});
});

it("Should return valid stamp for ArtAficionado (80)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 80,
},
},
});
});

const artAficionadoProvider = new ArtAficionadoProvider();
const artAficionadoPayload = await artAficionadoProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(artAficionadoPayload).toEqual({
valid: true,
record: {
address: MOCK_ADDRESS_LOWER,
human_probability: "80",
},
});
});

it("Should return valid stamp for NftVisionary (90)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 90,
},
},
});
});

const nftVisionaryProvider = new NftVisionaryProvider();
const nftVisionaryPayload = await nftVisionaryProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(nftVisionaryPayload).toEqual({
valid: true,
record: {
address: MOCK_ADDRESS_LOWER,
human_probability: "90",
},
});
});

it("Should return valid stamp for NftVisionary (100)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 100,
},
},
});
});

const nftVisionaryProvider = new NftVisionaryProvider();
const nftVisionaryPayload = await nftVisionaryProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(nftVisionaryPayload).toEqual({
valid: true,
record: {
address: MOCK_ADDRESS_LOWER,
human_probability: "100",
},
});
});
});

describe("Invalid stamp verification Collector's Journey", function () {
beforeEach(() => {
jest.clearAllMocks();
});

it("Should return invalid stamp for DigitalCollector (45)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 45,
},
},
});
});

const digitalCollectorProvider = new DigitalCollectorProvider();
const digitalCollectorPayload = await digitalCollectorProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(digitalCollectorPayload).toEqual({
valid: false,
errors: ["Your internal NFTScore is 45. You need a minimum of 50 to claim this stamp"],
});
});

it("Should return invalid stamp for ArtAficionado (65)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 65,
},
},
});
});

const artAficionadoProvider = new ArtAficionadoProvider();
const artAficionadoPayload = await artAficionadoProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(artAficionadoPayload).toEqual({
valid: false,
errors: ["Your internal NFTScore is 65. You need a minimum of 75 to claim this stamp"],
});
});

it("Should return invalid stamp for NftVisionary (85)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {
human_probability: 85,
},
},
});
});

const nftVisionaryProvider = new NftVisionaryProvider();
const nftVisionaryPayload = await nftVisionaryProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(nftVisionaryPayload).toEqual({
valid: false,
errors: ["Your internal NFTScore is 85. You need a minimum of 90 to claim this stamp"],
});
});

it("Should return invalid stamp for NftVisionary (undefined)", async () => {
(axios.post as jest.Mock).mockImplementation((url) => {
return Promise.resolve({
data: {
data: {},
},
});
});

const nftVisionaryProvider = new NftVisionaryProvider();
const nftVisionaryPayload = await nftVisionaryProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload);

expect(nftVisionaryPayload).toEqual({
valid: false,
errors: ["Your internal NFTScore is undefined. You need a minimum of 90 to claim this stamp"],
});
});
});

describe("Test Error cases for stamp verification", function () {
beforeEach(() => {
jest.clearAllMocks();
});
it.each([
["DigitalCollectorProvider", new DigitalCollectorProvider()],
["ArtAficionadoProvider", new ArtAficionadoProvider()],
["NftVisionaryProvider", new NftVisionaryProvider()],
])(
"%p should throw Provider External Verification error when unable to access nft stamp api",
async (nftProviderName: string, nftProvider: NftCollectorBaseProvider) => {
const mockAxiosError = new Error("Network error") as AxiosError;
mockedAxios.isAxiosError.mockReturnValueOnce(true);
mockAxiosError.response = {
status: 500,
data: {},
headers: {},
statusText: "Internal Server Error",
config: {},
};

mockedAxios.post.mockRejectedValueOnce(mockAxiosError);

await expect(
nftProvider.verify({
address: MOCK_ADDRESS_LOWER,
} as unknown as RequestPayload)
).rejects.toThrow(
"Error making queryNftStampApi request, received error response with code 500: {}, headers: {}"
);
}
);
});
Loading
Loading