diff --git a/app/components/CardListV2.tsx b/app/components/CardListV2.tsx
index 3a48fe049e..9ce49e6fe5 100644
--- a/app/components/CardListV2.tsx
+++ b/app/components/CardListV2.tsx
@@ -24,8 +24,7 @@ import {
// --- Components
import { LoadingCard } from "./LoadingCard";
-import { GenericOauthPlatform, PlatformProps } from "./GenericOauthPlatform";
-import { GenericEVMPlatform } from "./GenericEVMPlatform";
+import { GenericPlatform, PlatformProps } from "./GenericPlatform";
// --- Identity Providers
import { SideBarContent } from "./SideBarContent";
@@ -165,7 +164,7 @@ export const CardList = ({ isLoading = false }: CardListProps): JSX.Element => {
const platformProps = providers.get(currentPlatform.platform);
if (platformProps) {
return (
-
+
);
}
}
@@ -180,110 +179,6 @@ export const CardList = ({ isLoading = false }: CardListProps): JSX.Element => {
verifyButton={undefined}
/>
);
-
- // switch (currentPlatform?.platform) {
- // case "Twitter":
- // return (
- //
- // );
- // case "GitPOAP":
- // return (
- //
- // );
- // case "Ens":
- // return ;
- // case "NFT":
- // return ;
- // case "Facebook":
- // const facebook = new Facebook.FacebookPlatform();
- // return ;
- // case "Github":
- // return (
- //
- // );
- // case "Gitcoin":
- // const platformProps = providers.get("Github");
- // if (platformProps) {
- // return (
- //
- // );
- // }
- // // case "Facebook":
- // // return ;
- // case "Snapshot":
- // return (
- //
- // );
- // // case "Google":
- // // return ;
- // // case "Linkedin":
- // // return ;
- // // case "ETH":
- // // return ;
- // // case "Discord":
- // // return ;
- // // case "POAP":
- // // return ;
- // // case "Ens":
- // // return ;
- // // case "Brightid":
- // // return ;
- // case "Poh":
- // return ;
- // // case "GTC":
- // // return ;
- // // case "GtcStaking":
- // // return ;
- // // case "NFT":
- // // return ;
- // case "ZkSync":
- // return (
- //
- // );
- // case "Lens":
- // return ;
- // // case "Lens":
- // // return ;
- // case "GnosisSafe":
- // return (
- //
- // );
- // default:
- // return (
- //
- // );
- // }
};
useEffect(() => {
diff --git a/app/components/GenericOauthPlatform.tsx b/app/components/GenericOauthPlatform.tsx
deleted file mode 100644
index ad726f465a..0000000000
--- a/app/components/GenericOauthPlatform.tsx
+++ /dev/null
@@ -1,218 +0,0 @@
-// --- Methods
-import React, { useContext, useEffect, useMemo, useState } from "react";
-
-// --- Datadog
-import { datadogLogs } from "@datadog/browser-logs";
-
-import { debounce } from "ts-debounce";
-import { BroadcastChannel } from "broadcast-channel";
-
-// --- Identity tools
-import {
- Stamp,
- VerifiableCredential,
- CredentialResponseBody,
- VerifiableCredentialRecord,
-} from "@gitcoin/passport-types";
-import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
-
-// --- Style Components
-import { SideBarContent } from "./SideBarContent";
-import { DoneToastContent } from "./DoneToastContent";
-import { useToast } from "@chakra-ui/react";
-
-// --- Context
-import { CeramicContext } from "../context/ceramicContext";
-import { UserContext } from "../context/userContext";
-
-// --- Types
-import { PlatformGroupSpec } from "@gitcoin/passport-platforms/dist/commonjs/src/types";
-import {
- Platform,
- AccessTokenResult,
- Proofs,
- AppContext,
- ProviderPayload,
-} from "@gitcoin/passport-platforms/dist/commonjs/src/types";
-import { getPlatformSpec, PROVIDER_ID } from "@gitcoin/passport-platforms/dist/commonjs/src/platforms-config";
-
-export type PlatformProps = {
- // platformId: string;
- platformgroupspec: PlatformGroupSpec[];
- platform: Platform;
-};
-
-function generateUID(length: number) {
- return window
- .btoa(
- Array.from(window.crypto.getRandomValues(new Uint8Array(length * 2)))
- .map((b) => String.fromCharCode(b))
- .join("")
- )
- .replace(/[+/]/g, "")
- .substring(0, length);
-}
-
-export const GenericOauthPlatform = ({ platformgroupspec, platform }: PlatformProps): JSX.Element => {
- const { address, signer } = useContext(UserContext);
- const { handleAddStamps, allProvidersState } = useContext(CeramicContext);
- const [isLoading, setLoading] = useState(false);
- const [canSubmit, setCanSubmit] = useState(false);
-
- // find all providerIds
- const providerIds = useMemo(
- () =>
- platformgroupspec?.reduce((all, stamp) => {
- return all.concat(stamp.providers?.map((provider) => provider.name as PROVIDER_ID));
- }, [] as PROVIDER_ID[]) || [],
- // eslint-disable-next-line react-hooks/exhaustive-deps
- []
- );
-
- // SelectedProviders will be passed in to the sidebar to be filled there...
- const [verifiedProviders, setVerifiedProviders] = useState(
- providerIds.filter((providerId) => {
- return typeof allProvidersState[providerId]?.stamp?.credential !== "undefined";
- })
- );
- // SelectedProviders will be passed in to the sidebar to be filled there...
- const [selectedProviders, setSelectedProviders] = useState([...verifiedProviders]);
-
- // any time we change selection state...
- useEffect(() => {
- if (selectedProviders.length !== verifiedProviders.length) {
- setCanSubmit(true);
- }
- if (selectedProviders.length === 0) {
- setCanSubmit(false);
- }
- }, [selectedProviders, verifiedProviders]);
-
- // --- Chakra functions
- const toast = useToast();
-
- async function fetchCredential(proofs: Proofs): Promise {
- // fetch VCs for only the selectedProviders
- const vcs = await fetchVerifiableCredential(
- process.env.NEXT_PUBLIC_PASSPORT_IAM_URL || "",
- {
- type: platform.platformId,
- types: selectedProviders,
- version: "0.0.0",
- address: address || "",
- proofs,
- },
- signer as { signMessage: (message: string) => Promise }
- );
- await setVerifiedCredentialState(vcs);
- }
-
- async function setVerifiedCredentialState(verified: VerifiableCredentialRecord) {
- // because we provided a types array in the params we expect to receive a credentials array in the response...
- const vcs =
- verified.credentials
- ?.map((cred: CredentialResponseBody): Stamp | undefined => {
- if (!cred.error) {
- // add each of the requested/received stamps to the passport...
- return {
- provider: cred.record?.type as PROVIDER_ID,
- credential: cred.credential as VerifiableCredential,
- };
- }
- })
- .filter((v: Stamp | undefined) => v) || [];
- // Add all the stamps to the passport at once
- await handleAddStamps(vcs as Stamp[]);
- // report success to datadog
- datadogLogs.logger.info("Successfully saved Stamp", { platform: platform.platformId });
- // grab all providers who are verified from the verify response
- const actualVerifiedProviders = providerIds.filter(
- (providerId: string | undefined) =>
- !!vcs.find((vc: Stamp | undefined) => vc?.credential?.credentialSubject?.provider === providerId)
- );
- // both verified and selected should look the same after save
- setVerifiedProviders([...actualVerifiedProviders]);
- setSelectedProviders([...actualVerifiedProviders]);
- // reset can submit state
- setCanSubmit(false);
-
- toast({
- duration: 5000,
- isClosable: true,
- render: (result: any) => (
-
- ),
- });
- }
-
- const state = `${platform.path}-` + generateUID(10);
-
- const waitForRedirect = (timeout?: number): Promise => {
- const channel = new BroadcastChannel(`${platform.path}_oauth_channel`);
- const waitForRedirect = new Promise((resolve, reject) => {
- // Listener to watch for oauth redirect response on other windows (on the same host)
- function listenForRedirect(e: { target: string; data: { code: string; state: string } }) {
- // when receiving oauth response from a spawned child run fetchVerifiableCredential
- if (e.target === platform.path) {
- // pull data from message
- const queryCode = e.data.code;
- const queryState = e.data.state;
- datadogLogs.logger.info("Saving Stamp", { platform: platform.platformId });
- try {
- resolve({ code: queryCode, state: queryState });
- } catch (e) {
- datadogLogs.logger.error("Error saving Stamp", { platform: platform.platformId });
- console.error(e);
- reject(e);
- }
- }
- }
- // event handler will listen for messages from the child (debounced to avoid multiple submissions)
- channel.onmessage = debounce(listenForRedirect, 300);
- }).finally(() => {
- channel.close();
- });
- return waitForRedirect;
- };
-
- async function initiateFetchCredential() {
- try {
- // fetch and store credential
- setLoading(true);
- const providerPayload = await platform.getProviderPayload({ state, window, screen, waitForRedirect });
- // TODO: use only one of Proofs or ProfiderPayload and drop the other
- await fetchCredential(providerPayload as unknown as Proofs);
- } catch (e) {
- datadogLogs.logger.error("Error saving Stamp", { platform: platform.platformId });
- console.error(e);
- }
- setLoading(false);
- }
-
- return (
-
- Verify
-
- }
- />
- );
-};
diff --git a/app/components/GenericEVMPlatform.tsx b/app/components/GenericPlatform.tsx
similarity index 78%
rename from app/components/GenericEVMPlatform.tsx
rename to app/components/GenericPlatform.tsx
index ccc70691d8..aa008779fb 100644
--- a/app/components/GenericEVMPlatform.tsx
+++ b/app/components/GenericPlatform.tsx
@@ -11,6 +11,7 @@ import {
CredentialResponseBody,
VerifiableCredentialRecord,
} from "@gitcoin/passport-types";
+import { ProviderPayload } from "@gitcoin/passport-platforms/dist/commonjs/src/types";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
// --- Style Components
@@ -29,7 +30,10 @@ import { getPlatformSpec } from "@gitcoin/passport-platforms/dist/commonjs/platf
// --- Helpers
import { difference } from "../utils/helpers";
-type PlatformProps = {
+import { debounce } from "ts-debounce";
+import { BroadcastChannel } from "broadcast-channel";
+
+export type PlatformProps = {
platFormGroupSpec: PlatformGroupSpec[];
platform: Platform;
};
@@ -37,7 +41,18 @@ type PlatformProps = {
const iamUrl = process.env.NEXT_PUBLIC_PASSPORT_IAM_URL || "";
const rpcUrl = process.env.NEXT_PUBLIC_RPC_URL;
-export const GenericEVMPlatform = ({ platFormGroupSpec, platform }: PlatformProps): JSX.Element => {
+function generateUID(length: number) {
+ return window
+ .btoa(
+ Array.from(window.crypto.getRandomValues(new Uint8Array(length * 2)))
+ .map((b) => String.fromCharCode(b))
+ .join("")
+ )
+ .replace(/[+/]/g, "")
+ .substring(0, length);
+}
+
+export const GenericPlatform = ({ platFormGroupSpec, platform }: PlatformProps): JSX.Element => {
const { address, signer } = useContext(UserContext);
const { handleAddStamps, handleDeleteStamps, allProvidersState } = useContext(CeramicContext);
const [isLoading, setLoading] = useState(false);
@@ -74,12 +89,43 @@ export const GenericEVMPlatform = ({ platFormGroupSpec, platform }: PlatformProp
}
}, [selectedProviders, verifiedProviders]);
+ const waitForRedirect = (timeout?: number): Promise => {
+ const channel = new BroadcastChannel(`${platform.path}_oauth_channel`);
+ const waitForRedirect = new Promise((resolve, reject) => {
+ // Listener to watch for oauth redirect response on other windows (on the same host)
+ function listenForRedirect(e: { target: string; data: { code: string; state: string } }) {
+ // when receiving oauth response from a spawned child run fetchVerifiableCredential
+ if (e.target === platform.path) {
+ // pull data from message
+ const queryCode = e.data.code;
+ const queryState = e.data.state;
+ datadogLogs.logger.info("Saving Stamp", { platform: platform.platformId });
+ try {
+ resolve({ code: queryCode, state: queryState });
+ } catch (e) {
+ datadogLogs.logger.error("Error saving Stamp", { platform: platform.platformId });
+ console.error(e);
+ reject(e);
+ }
+ }
+ }
+ // event handler will listen for messages from the child (debounced to avoid multiple submissions)
+ channel.onmessage = debounce(listenForRedirect, 300);
+ }).finally(() => {
+ channel.close();
+ });
+ return waitForRedirect;
+ };
+
// fetch VCs from IAM server
const handleFetchCredential = async (): Promise => {
datadogLogs.logger.info("Saving Stamp", { platform: platform.platformId });
setLoading(true);
setVerificationAttempted(true);
try {
+ const state = `${platform.path}-` + generateUID(10);
+ const providerPayload = (await platform.getProviderPayload({ state, window, screen, waitForRedirect })) as {};
+
const verified: VerifiableCredentialRecord = await fetchVerifiableCredential(
iamUrl,
{
@@ -87,7 +133,7 @@ export const GenericEVMPlatform = ({ platFormGroupSpec, platform }: PlatformProp
types: selectedProviders,
version: "0.0.0",
address: address || "",
- proofs: {},
+ proofs: providerPayload,
rpcUrl,
},
signer as { signMessage: (message: string) => Promise }
diff --git a/platforms/src/Gitcoin/App-Bindings.ts b/platforms/src/Gitcoin/App-Bindings.ts
index 174fb7d854..d83232b6fb 100644
--- a/platforms/src/Gitcoin/App-Bindings.ts
+++ b/platforms/src/Gitcoin/App-Bindings.ts
@@ -7,19 +7,37 @@ export class GitcoinPlatform implements Platform {
clientId: string = null;
redirectUri: string = null;
- async getProviderPayload(appContext: AppContext): Promise {
- return {};
- }
-
-
constructor(options: PlatformOptions = {}) {
this.clientId = options.clientId as string;
this.redirectUri = options.redirectUri as string;
}
+ async getProviderPayload(appContext: AppContext): Promise {
+ const authUrl: string = await this.getOAuthUrl(appContext.state);
+ const width = 600;
+ const height = 800;
+ const left = appContext.screen.width / 2 - width / 2;
+ const top = appContext.screen.height / 2 - height / 2;
+
+ // Pass data to the page via props
+ appContext.window.open(
+ authUrl,
+ "_blank",
+ "toolbar=no, location=no, directories=no, status=no, menubar=no, resizable=no, copyhistory=no, width=" +
+ width +
+ ", height=" +
+ height +
+ ", top=" +
+ top +
+ ", left=" +
+ left
+ );
+
+ return appContext.waitForRedirect();
+ }
+
async getOAuthUrl(state: string): Promise {
const githubUrl = `https://github.com/login/oauth/authorize?client_id=${this.clientId}&redirect_uri=${this.redirectUri}&state=${state}`;
-
return githubUrl;
}
}
diff --git a/platforms/src/Github/App-Bindings.ts b/platforms/src/Github/App-Bindings.ts
index 8b2be9cec6..62169b7f75 100644
--- a/platforms/src/Github/App-Bindings.ts
+++ b/platforms/src/Github/App-Bindings.ts
@@ -13,9 +13,6 @@ export class GithubPlatform implements Platform {
}
async getProviderPayload(appContext: AppContext): Promise {
- // TODO: open the BroadCastChannel
- // TODO: register the event handler - onmessage
-
const authUrl: string = await this.getOAuthUrl(appContext.state);
const width = 600;
const height = 800;
diff --git a/platforms/src/GnosisSafe/App-Bindings.ts b/platforms/src/GnosisSafe/App-Bindings.ts
index a7003da562..15d8264133 100644
--- a/platforms/src/GnosisSafe/App-Bindings.ts
+++ b/platforms/src/GnosisSafe/App-Bindings.ts
@@ -2,16 +2,16 @@
import { AppContext, Platform, PlatformOptions, ProviderPayload } from "../types";
export class GnosisSafePlatform implements Platform {
+ platformId = "GnosisSafe";
+ path = "GnosisSafe";
+ clientId: string = null;
+ redirectUri: string = null;
+
getOAuthUrl(state: string): Promise {
throw new Error("Method not implemented.");
}
+
async getProviderPayload(appContext: AppContext): Promise {
return {};
}
-
-
- platformId = "GnosisSafe";
- path = "GnosisSafe";
- clientId: string = null;
- redirectUri: string = null;
}
diff --git a/platforms/src/NFT/App-Bindings.ts b/platforms/src/NFT/App-Bindings.ts
index f356370262..32879ebdd1 100644
--- a/platforms/src/NFT/App-Bindings.ts
+++ b/platforms/src/NFT/App-Bindings.ts
@@ -2,16 +2,16 @@
import { AppContext, Platform, PlatformOptions, ProviderPayload } from "../types";
export class NFTPlatform implements Platform {
+ platformId = "NFT";
+ path = "NFT";
+ clientId: string = null;
+ redirectUri: string = null;
+
async getProviderPayload(appContext: AppContext): Promise {
return {};
}
-
getOAuthUrl(state: string): Promise {
throw new Error("Method not implemented.");
}
- platformId = "NFT";
- path = "NFT";
- clientId: string = null;
- redirectUri: string = null;
-};
+}