Skip to content

Commit

Permalink
fix(app): resolve merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-schultz committed Jan 26, 2023
2 parents 6a55fb6 + 0f831f4 commit 75b5369
Show file tree
Hide file tree
Showing 15 changed files with 370 additions and 271 deletions.
3 changes: 2 additions & 1 deletion app/__test-fixtures__/contextTestHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,15 @@ export const makeTestCeramicContext = (initialState?: Partial<CeramicContextStat
stamp: undefined,
},
},
ceramicErrors: { error: false },
passportLoadResponse: undefined,
handleAddStamp: jest.fn(),
handleAddStamps: jest.fn(),
handleCreatePassport: jest.fn(),
handleDeleteStamp: jest.fn(),
handleDeleteStamps: jest.fn(),
handleCheckRefreshPassport: () => Promise.resolve(true),
expiredProviders: [],
passportHasCacaoError: () => false,
...initialState,
};
};
Expand Down
2 changes: 1 addition & 1 deletion app/__tests__/components/NoStampModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("NoStampModal", () => {
describe("linking another account", () => {
it("opens", () => {
render(<NoStampModal {...props} />);
expect(screen.getByText("No Stamp Found")).toBeInTheDocument();
expect(screen.getByText("You do not meet the eligibility criteria")).toBeInTheDocument();
});
it("initiates account change when requested", async () => {
(fetchAdditionalSigner as jest.Mock).mockResolvedValue({ cool: true });
Expand Down
15 changes: 3 additions & 12 deletions app/__tests__/components/RefreshModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ describe("RefreshStampModal", () => {
mockUserContext,
{
...mockCeramicContext,
ceramicErrors: {
error: true,
stamps: ["streamid"],
},
passportHasCacaoError: () => true,
},
<RefreshStampModal isOpen={true} onClose={jest.fn()} />
);
Expand All @@ -48,10 +45,7 @@ describe("RefreshStampModal", () => {
mockUserContext,
{
...mockCeramicContext,
ceramicErrors: {
error: true,
stamps: ["streamid"],
},
passportHasCacaoError: () => true,
},
<RefreshStampModal isOpen={true} onClose={jest.fn()} />
);
Expand All @@ -65,10 +59,7 @@ describe("RefreshStampModal", () => {
mockUserContext,
{
...mockCeramicContext,
ceramicErrors: {
error: true,
stamps: ["streamid"],
},
passportHasCacaoError: () => true,
},
<RefreshStampModal isOpen={true} onClose={jest.fn()} />
);
Expand Down
12 changes: 3 additions & 9 deletions app/__tests__/pages/Dashboard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,7 @@ describe("when a user clicks on the Passport logo", () => {
mockUserContext,
{
...mockCeramicContext,
ceramicErrors: {
error: true,
stamps: ["streamid"],
},
passportHasCacaoError: () => true,
},
<Router>
<Dashboard />
Expand All @@ -246,17 +243,14 @@ describe("when a user clicks on the Passport logo", () => {
mockUserContext,
{
...mockCeramicContext,
ceramicErrors: {
error: true,
stamps: ["streamid"],
},
passportHasCacaoError: () => true,
},
<Router>
<Dashboard />
</Router>
);

await fireEvent.click(screen.getByText("Reset Passport"));
fireEvent.click(screen.getByText("Reset Passport"));
await waitFor(() => {
expect(screen.getByText("Refresh Modal")).toBeInTheDocument();
});
Expand Down
4 changes: 2 additions & 2 deletions app/components/NoStampModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const NoStampModal = ({ isOpen, onClose }: NoStampModalProps) => {
<div className="mt-2 w-fit rounded-full bg-pink-500/25">
<img className="m-2" alt="shield-exclamation-icon" src="./assets/shield-exclamation-icon-warning.svg" />
</div>
<p className="m-1 text-sm font-bold">No Stamp Found</p>
<p className="m-1 text-sm font-bold">You do not meet the eligibility criteria</p>
<p className="m-1 mb-4 text-center">
The stamp you are trying to verify could not be associated with your current Ethereum wallet address.
</p>
Expand Down Expand Up @@ -102,7 +102,7 @@ export const NoStampModal = ({ isOpen, onClose }: NoStampModalProps) => {
className="my-auto mr-2"
/>
)}
Try another wallet
Try another stamp
</button>
</div>
</>
Expand Down
8 changes: 5 additions & 3 deletions app/components/PlatformCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const PlatformCard = ({
getUpdatedPlatforms,
}: PlatformCardProps): JSX.Element => {
// import all providers
const { allProvidersState, ceramicErrors, handleDeleteStamps } = useContext(CeramicContext);
const { allProvidersState, passportHasCacaoError, handleDeleteStamps } = useContext(CeramicContext);

// useDisclosure to control JSON modal
const {
Expand All @@ -57,6 +57,8 @@ export const PlatformCard = ({
onClose: onCloseRemoveStampModal,
} = useDisclosure();

const disabled = passportHasCacaoError();

// returns a single Platform card
return (
<div className="w-1/2 p-2 md:w-1/2 xl:w-1/4" key={`${platform.name}${i}`}>
Expand Down Expand Up @@ -93,7 +95,7 @@ export const PlatformCard = ({
{selectedProviders[platform.platform].length > 0 ? (
<>
<Menu>
<MenuButton disabled={ceramicErrors?.error} className="verify-btn flex" data-testid="card-menu-button">
<MenuButton disabled={disabled} className="verify-btn flex" data-testid="card-menu-button">
<div className="m-auto flex justify-center">
<svg
className="m-1 mr-2"
Expand Down Expand Up @@ -179,7 +181,7 @@ export const PlatformCard = ({
) : (
<button
className="verify-btn"
disabled={ceramicErrors?.error}
disabled={disabled}
ref={btnRef.current}
onClick={(e) => {
if (platform.enablePlatformCardUpdate) {
Expand Down
111 changes: 49 additions & 62 deletions app/context/ceramicContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { createContext, useContext, useEffect, useMemo, useState } from "react";
import { Passport, PassportWithErrors, PassportError, PLATFORM_ID, PROVIDER_ID, Stamp } from "@gitcoin/passport-types";
import {
Passport,
PassportLoadResponse,
PassportLoadStatus,
PLATFORM_ID,
PROVIDER_ID,
Stamp,
} from "@gitcoin/passport-types";
import { ProviderSpec, STAMP_PROVIDERS } from "../config/providers";
import { CeramicDatabase } from "@gitcoin/passport-database-client";
import { useViewerConnection } from "@self.id/framework";
Expand Down Expand Up @@ -45,8 +52,9 @@ export interface CeramicContextState {
handleDeleteStamps: (providerIds: PROVIDER_ID[]) => Promise<void>;
handleCheckRefreshPassport: () => Promise<boolean>;
userDid: string | undefined;
ceramicErrors: PassportError | undefined;
expiredProviders: PROVIDER_ID[];
passportHasCacaoError: () => boolean;
passportLoadResponse?: PassportLoadResponse;
}

export const platforms = new Map<PLATFORM_ID, PlatformProps>();
Expand Down Expand Up @@ -442,9 +450,10 @@ const startingState: CeramicContextState = {
handleDeleteStamp: async (streamId: string) => {},
handleDeleteStamps: async () => {},
handleCheckRefreshPassport: async () => false,
passportHasCacaoError: () => false,
userDid: undefined,
ceramicErrors: undefined,
expiredProviders: [],
passportLoadResponse: undefined,
};

export const CeramicContext = createContext(startingState);
Expand All @@ -455,8 +464,8 @@ export const CeramicContextProvider = ({ children }: { children: any }) => {
const [isLoadingPassport, setIsLoadingPassport] = useState<IsLoadingPassportState>(IsLoadingPassportState.Loading);
const [passport, setPassport] = useState<Passport | undefined>(undefined);
const [userDid, setUserDid] = useState<string | undefined>();
const [ceramicErrors, setCeramicErrors] = useState<PassportError | undefined>();
const [expiredProviders, setExpiredProviders] = useState<PROVIDER_ID[]>([]);
const [passportLoadResponse, setPassportLoadResponse] = useState<PassportLoadResponse | undefined>();
const [viewerConnection] = useViewerConnection();

const { address } = useContext(UserContext);
Expand All @@ -467,7 +476,7 @@ export const CeramicContextProvider = ({ children }: { children: any }) => {
setCeramicDatabase(undefined);
setPassport(undefined);
setUserDid(undefined);
setCeramicErrors(undefined);
setPassportLoadResponse(undefined);
};
}, [address]);

Expand Down Expand Up @@ -505,63 +514,34 @@ export const CeramicContextProvider = ({ children }: { children: any }) => {
}, [ceramicDatabase]);

const fetchPassport = async (database: CeramicDatabase, skipLoadingState?: boolean): Promise<void> => {
let passportHasError = false;
let failedStamps: string[] = [];

if (!skipLoadingState) setIsLoadingPassport(IsLoadingPassportState.Loading);
// fetch, clean and set the new Passport state
const passportResponse = (await database.getPassport()) as PassportWithErrors | undefined | false;

// Ceramic error being thrown relies on the false response from getPassport. This is a temporary fix
let passport;
if (passportResponse === undefined || passportResponse === false) {
passport = passportResponse;
} else {
passport = passportResponse.passport;
}

if (passportResponse && passportResponse?.errors?.passport) {
const passportCacaoError = await database.checkPassportCACAOError();
if (passportCacaoError) {
datadogRum.addError("Passport CACAO error -- error thrown on initial fetch within getPassport", { address });
passportHasError = true;
}
}
if (passportResponse && passportResponse?.errors?.stamps) failedStamps = passportResponse.errors.stamps;

if (passport) {
passport = cleanPassport(passport, database) as Passport;
hydrateAllProvidersState(passport);
setPassport(passport);
if (!skipLoadingState) setIsLoadingPassport(IsLoadingPassportState.Idle);
} else if (passportResponse === false) {
const passportCacaoError = await database.checkPassportCACAOError();
if (passportCacaoError) {
datadogRum.addError(
"Passport CACAO error -- undefined or null return while fetching getPassport from ceramic",
{ address }
);
passportHasError = true;
} else {
// fetch, clean and set the new Passport state
const { status, errorDetails, passport } = await database.getPassport();

switch (status) {
case "Success":
case "StampCacaoError":
const cleanedPassport = cleanPassport(passport, database) as Passport;
hydrateAllProvidersState(cleanedPassport);
setPassport(cleanedPassport);
if (!skipLoadingState) setIsLoadingPassport(IsLoadingPassportState.Idle);
break;
case "PassportCacaoError":
datadogRum.addError("Passport CACAO error -- error thrown on initial fetch", { address });
break;
case "DoesNotExist":
handleCreatePassport();
}
} else {
const passportCacaoError = await database.checkPassportCACAOError();
if (passportCacaoError) {
datadogRum.addError("Passport CACAO error -- checking before throwing IsLoadingPassportState.FailedToConnect", {
address,
});
passportHasError = true;
} else {
break;
case "ExceptionRaised":
// something is wrong with Ceramic...
datadogRum.addError("Ceramic connection failed", { address });
setPassport(undefined);
if (!skipLoadingState) setIsLoadingPassport(IsLoadingPassportState.FailedToConnect);
}
break;
}
const error = passportHasError || failedStamps.length > 0;

setCeramicErrors({ passport: passportHasError, stamps: failedStamps, error });
setPassportLoadResponse({ passport, status, errorDetails });
};

const cleanPassport = (
Expand Down Expand Up @@ -592,22 +572,22 @@ export const CeramicContextProvider = ({ children }: { children: any }) => {

const handleCheckRefreshPassport = async (): Promise<boolean> => {
let success = true;
if (ceramicDatabase && ceramicErrors) {
let passportHasError = ceramicErrors.passport;
let failedStamps = ceramicErrors.stamps || [];
if (ceramicDatabase && passportLoadResponse) {
let passportHasError = passportLoadResponse.status === "PassportCacaoError";
let failedStamps = passportLoadResponse.errorDetails?.stampStreamIds || [];
try {
if (ceramicErrors.passport) {
if (passportHasError) {
passportHasError = !(await ceramicDatabase.refreshPassport());
}

if (ceramicErrors.stamps && ceramicErrors.stamps.length) {
if (failedStamps && failedStamps.length) {
try {
await ceramicDatabase.deleteStampIDs(ceramicErrors.stamps);
await ceramicDatabase.deleteStampIDs(failedStamps);
failedStamps = [];
} catch {}
}

// fetchpassport to reset passport state
// fetchPassport to reset passport state
await fetchPassport(ceramicDatabase);

success = !passportHasError && !failedStamps.length;
Expand Down Expand Up @@ -663,7 +643,7 @@ export const CeramicContextProvider = ({ children }: { children: any }) => {
if (passport) {
// set stamps into allProvidersState
let newAllProviderState = { ...startingAllProvidersState };
passport.stamps.forEach((stamp: Stamp, index: number) => {
passport.stamps.forEach((stamp: Stamp) => {
const { provider } = stamp;
const providerState = allProvidersState[provider];
if (providerState) {
Expand All @@ -684,6 +664,12 @@ export const CeramicContextProvider = ({ children }: { children: any }) => {
setAllProviderState(startingAllProvidersState);
};

const passportHasCacaoError = (): boolean => {
const errorStatuses: PassportLoadStatus[] = ["PassportCacaoError", "StampCacaoError"];
if (passportLoadResponse) return errorStatuses.includes(passportLoadResponse.status);
else return false;
};

const stateMemo = useMemo(
() => ({
passport,
Expand Down Expand Up @@ -712,8 +698,9 @@ export const CeramicContextProvider = ({ children }: { children: any }) => {
handleDeleteStamp,
handleCheckRefreshPassport,
userDid,
ceramicErrors,
expiredProviders,
passportLoadResponse,
passportHasCacaoError,
};

return <CeramicContext.Provider value={providerProps}>{children}</CeramicContext.Provider>;
Expand Down
10 changes: 5 additions & 5 deletions app/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ import { UserContext } from "../context/userContext";
import { useViewerConnection } from "@self.id/framework";
import { EthereumAuthProvider } from "@self.id/web";
import { Banner } from "../components/Banner";
import { getExpiredStamps } from "../utils/helpers";
import { RefreshStampModal } from "../components/RefreshStampModal";
import { ExpiredStampModal } from "../components/ExpiredStampModal";

export default function Dashboard() {
const { passport, isLoadingPassport, ceramicErrors, expiredProviders } = useContext(CeramicContext);
const { passport, isLoadingPassport, passportHasCacaoError, expiredProviders } = useContext(CeramicContext);
const { wallet, toggleConnection, handleDisconnection } = useContext(UserContext);

const { isOpen, onOpen, onClose } = useDisclosure();
Expand Down Expand Up @@ -84,8 +83,9 @@ export default function Dashboard() {
<div className="flex flex-col" data-testid="retry-modal-content">
<p className="text-lg font-bold">Ceramic Network Error</p>
<p>
The Gitcoin Passport relies on the Ceramic Network which currently is having network issues. Please try
again later.
Gitcoin Passport relies on the Ceramic Network to load your stamp details. We cannot reach the Ceramic
Network right now. There are a number of reasons this could be happening, but there is no action you
need to take. Please try again.
</p>
</div>
</div>
Expand Down Expand Up @@ -131,7 +131,7 @@ export default function Dashboard() {
</div>
)}

{ceramicErrors && ceramicErrors.error && (
{passportHasCacaoError() && (
<Banner>
<div className="flex w-full justify-center">
We have detected some broken stamps in your passport. Your passport is currently locked because of this. We
Expand Down
Loading

0 comments on commit 75b5369

Please sign in to comment.