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(embed): retrieve stamps via metadata endpoint #11

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
11 changes: 6 additions & 5 deletions example/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ const appQueryClient = new QueryClient({
const passportEmbedParams = {
apiKey: import.meta.env.VITE_API_KEY,
scorerId: import.meta.env.VITE_SCORER_ID,
overrideIamUrl: "https://embed.review.passport.xyz",
challengeSignatureUrl: "https://iam.review.passport.xyz/api/v0.0.0/challenge",
// challengeSignatureUrl: "http://localhost:8003/api/v0.0.0/challenge",
// overrideIamUrl: "https://embed.review.passport.xyz",
overrideIamUrl: "http://localhost:8004",
// challengeSignatureUrl: "https://iam.review.passport.xyz/api/v0.0.0/challenge",
challengeSignatureUrl: "http://localhost:8003/api/v0.0.0/challenge",
// oAuthPopUpUrl: "http://localhost:3010",
oAuthPopUpUrl:
"http://passport-embed-popup-review.s3-website-us-west-2.amazonaws.com",
// oAuthPopUpUrl:
// "http://passport-embed-popup-review.s3-website-us-west-2.amazonaws.com",
};

const connectWallet = async () => {
Expand Down
1 change: 1 addition & 0 deletions example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
dependencies:
"@tanstack/react-query" "^5.62.11"
axios "^1.7.7"
buffer "^6.0.3"

"@rollup/[email protected]":
version "4.24.0"
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
},
"dependencies": {
"@tanstack/react-query": "^5.62.11",
"axios": "^1.7.7"
"axios": "^1.7.7",
"buffer": "^6.0.3"
}
}
}
11 changes: 5 additions & 6 deletions src/components/Body/PlatformVerification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import utilStyles from "../../utilStyles.module.css";
import { useEffect, useState } from "react";
import { Buffer } from "buffer";
import { Button } from "../Button";
import { Hyperlink, Platform, usePlatformStatus } from "./ScoreTooLowBody";
import { Hyperlink, usePlatformStatus } from "./ScoreTooLowBody";
import { Platform } from "../../hooks/useStampPages";
import { ScrollableDiv } from "../ScrollableDiv";
import {
useWidgetIsQuerying,
Expand All @@ -14,8 +15,6 @@ import { useQueryContext } from "../../contexts/QueryContext";
const DEFAULT_CHALLENGE_URL =
"https://iam.review.passport.xyz/api/v0.0.0/challenge";

const DEFAULT_OAUTH_POPUP = "https://embed-popup.passport.xyz";

const CloseIcon = () => (
<svg
width="12"
Expand Down Expand Up @@ -116,7 +115,7 @@ export const PlatformVerification = ({
and come back after.
</div>
) : (
platform.description
<div dangerouslySetInnerHTML={{ __html: platform.description}} />
)}
</ScrollableDiv>
<Button
Expand Down Expand Up @@ -158,10 +157,10 @@ export const PlatformVerification = ({
signature = await generateSignatureCallback(challengeToSign);
}

if (platform.oAuthPopup) {
if (platform.requiresPopup && platform.popUpUrl) {
// open the popup
const oAuthPopUpUrl = `${
queryProps.oAuthPopUpUrl || DEFAULT_OAUTH_POPUP
platform.popUpUrl
}?address=${encodeURIComponent(
queryProps.address || ""
)}&platform=${encodeURIComponent(
Expand Down
201 changes: 19 additions & 182 deletions src/components/Body/ScoreTooLowBody.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
import { QueryClient } from "@tanstack/react-query";
import styles from "./Body.module.css";
import utilStyles from "../../utilStyles.module.css";
import { Button } from "../Button";
import { useEffect, useMemo, useState } from "react";
import { useHeaderControls } from "../../contexts/HeaderContext";
import { useWidgetPassportScore } from "../../hooks/usePassportScore";
import { usePaginatedStampPages, Platform } from "../../hooks/useStampPages";
import { TextButton } from "../TextButton";
import { displayNumber } from "../../utils";
import { RightArrow } from "../../assets/rightArrow";
import { ScrollableDiv } from "../ScrollableDiv";
import { PlatformVerification } from "./PlatformVerification";

// TODO should probably load this data from an API endpoint, so that
// if we need to add/change/remove stamps, integrators don't need to
// update the package and re-release their apps
// Also at least weights could be scorer-specific
import { useQueryContext } from "../../contexts/QueryContext";

type Credential = {
id: string;
weight: string;
};

export type Platform = {
name: string;
description: JSX.Element;
documentationLink: string;
credentials: Credential[];
displayWeight: string; // calculated
requireSignature?: boolean;
oAuthPopup?: boolean;
};

type StampPage = {
header: string;
platforms: Platform[];
Expand All @@ -56,151 +43,6 @@ export const Hyperlink = ({

const VISIT_PASSPORT_HEADER = "More Options";

const STAMP_PAGES: StampPage[] = [
{
header: "KYC verification",
platforms: [
{
name: "Binance",
description: (
<div>
If you do not have the Binance Account Bound Token (BABT), obtain it{" "}
<a
href="http://google.com"
style={{
color: "inherit",
fontWeight: "700",
textDecoration: "none",
}}
rel="noopener noreferrer"
target="_blank"
>
here
</a>{" "}
 by verifying your identity and logging into your Binance account.
Then return here and click Verify to claim this Stamp.
</div>
),
documentationLink: "https://google.com",
credentials: [
{
// id: "BinanceBABT2",
id: "NFT",
weight: "16",
},
],
},
{
name: "Holonym",
description: <div>TODO</div>,
documentationLink: "https://google.com",
credentials: [
{
id: "HolonymGovIdProvider",
weight: "16",
},
],
},
],
},
{
header: "Biometrics verification",
platforms: [
{
name: "Civic",
description: <div>TODO</div>,
documentationLink: "https://google.com",
credentials: [
{
id: "CivicCaptchaPass",
weight: "1",
},
{
id: "CivicUniquenessPass",
weight: "2",
},
{
id: "CivicLivenessPass",
weight: "3",
},
],
},
],
},
{
header: "Social & Professional Platforms",
platforms: [
{
name: "LinkedIn",
description: <div>Claim Linkedin stamp</div>,
documentationLink: "https://google.com",
requireSignature: true,
oAuthPopup: true,
credentials: [
{
id: "LinkedIn",
weight: "1",
},
],
},
{
name: "Discord",
description: <div>Coming soon</div>,
documentationLink: "https://google.com",
requireSignature: true,
oAuthPopup: true,
credentials: [
{
id: "Discord",
weight: "1",
},
],
},
// {
// name: "Github",
// description: <div>Coming soon</div>,
// documentationLink: "https://google.com",
// requireSignature: true,
// oAuthPopup: true,
// credentials: [
// {
// id: "Github",
// weight: "1",
// },
// ],
// },
{
name: "Google",
description: <div>Coming soon</div>,
documentationLink: "https://google.com",
requireSignature: true,
oAuthPopup: true,
credentials: [
{
id: "Google",
weight: "1",
},
],
},
],
},
{
header: VISIT_PASSPORT_HEADER,
platforms: [],
},
].map((page) => ({
...page,
platforms: page.platforms.map((platform) => ({
...platform,
displayWeight: displayNumber(
platform.credentials.reduce(
(acc, credential) => acc + parseFloat(credential.weight),
0
)
),
})),
}));

export const ScoreTooLowBody = ({
generateSignatureCallback,
}: {
Expand All @@ -215,20 +57,6 @@ export const ScoreTooLowBody = ({
);
};

const usePages = <T,>(pages: T[]) => {
const [idx, setIdx] = useState(0);

const nextPage = () => setIdx((prev) => Math.min(prev + 1, pages.length - 1));
const prevPage = () => setIdx((prev) => Math.max(prev - 1, 0));

const isFirstPage = idx === 0;
const isLastPage = idx === pages.length - 1;

const page = pages[idx];

return { page, nextPage, prevPage, isFirstPage, isLastPage };
};

const ClaimedIcon = () => (
<svg
width="16"
Expand Down Expand Up @@ -300,19 +128,28 @@ const AddStamps = ({
generateSignatureCallback: (message: string) => Promise<string | undefined>;
}) => {
const { setSubtitle } = useHeaderControls();
const { page, nextPage, prevPage, isFirstPage, isLastPage } =
usePages(STAMP_PAGES);

const queryProps = useQueryContext();
const { scorerId, apiKey, queryClient, overrideIamUrl } = queryProps;
const { page, nextPage, prevPage, isFirstPage, isLastPage, loading, error } =
usePaginatedStampPages({
apiKey: apiKey,
scorerId: scorerId,
overrideIamUrl: overrideIamUrl,
queryClient: queryClient,
});
const [openPlatform, setOpenPlatform] = useState<Platform | null>(null);

const { header, platforms } = page;

useEffect(() => {
setSubtitle("VERIFY STAMPS");
});
}, [setSubtitle]);

if (loading) return <div>Loading Stamps Metadata...</div>;
if (error) return <div>{error}</div>;
if (!page) return <div>No stamp metadata available</div>;

const { header, platforms } = page;

if (openPlatform) {
console.log("LARISA HELLO openPlatform", openPlatform);
return (
<PlatformVerification
platform={openPlatform}
Expand Down
4 changes: 0 additions & 4 deletions src/contexts/QueryContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ type QueryContextValue = Pick<
| "scorerId"
| "overrideIamUrl"
| "challengeSignatureUrl"
| "oAuthPopUpUrl"
> & {
queryClient: QueryClient; // This makes queryClient required
};
Expand All @@ -28,7 +27,6 @@ export const QueryContextProvider = ({
scorerId,
overrideIamUrl,
challengeSignatureUrl,
oAuthPopUpUrl,
queryClient,
}: {
children: React.ReactNode;
Expand All @@ -40,7 +38,6 @@ export const QueryContextProvider = ({
scorerId,
overrideIamUrl,
challengeSignatureUrl,
oAuthPopUpUrl,
// Use override if passed in, otherwise use the widget query client
queryClient: queryClient || widgetQueryClient,
}),
Expand All @@ -50,7 +47,6 @@ export const QueryContextProvider = ({
scorerId,
overrideIamUrl,
challengeSignatureUrl,
oAuthPopUpUrl,
queryClient,
]
);
Expand Down
3 changes: 1 addition & 2 deletions src/hooks/usePassportScore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import axios from "axios";
import { useQueryContext } from "../contexts/QueryContext";
import { useCallback } from "react";

const DEFAULT_IAM_URL = "https://embed.passport.xyz";
export const DEFAULT_IAM_URL = "https://embed.passport.xyz";

export type PassportEmbedProps = {
apiKey: string;
Expand All @@ -21,7 +21,6 @@ export type PassportEmbedProps = {
address?: string;
overrideIamUrl?: string;
challengeSignatureUrl?: string;
oAuthPopUpUrl?: string;
// Optional, allows you to share a queryClient between the
// widget(s) and the wider app
queryClient?: QueryClient;
Expand Down
Loading