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

No gasless vouches removal #28

Merged
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
27 changes: 4 additions & 23 deletions src/app/[pohid]/[chain]/[request]/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -297,12 +297,12 @@ export default withClientConnected<ActionBarProps>(function ActionBar({
) : (
!isVouchGranted.didIVouchFor ?
<Vouch pohId={pohId} claimer={requester} />
:
: isVouchGranted.isVouchOnchain ?
<RemoveVouch
requester={requester}
pohId={pohId}
isOnchain={isVouchGranted.isVouchOnchain}
/>
: null
)}
</div>
</>
Expand All @@ -324,12 +324,12 @@ export default withClientConnected<ActionBarProps>(function ActionBar({
) : (
!isVouchGranted.didIVouchFor ?
<Vouch pohId={pohId} claimer={requester} />
:
: isVouchGranted.isVouchOnchain ?
<RemoveVouch
requester={requester}
pohId={pohId}
isOnchain={isVouchGranted.isVouchOnchain}
/>
: null
)}
<button
disabled={pending}
Expand All @@ -345,15 +345,6 @@ export default withClientConnected<ActionBarProps>(function ActionBar({
<>
<span className="text-slate-400">Ready to finalize.</span>
<div className="flex flex-col md:flex-row md:items-center justify-between font-normal gap-4">
{isVouchGranted.didIVouchFor ?
<RemoveVouch
requester={requester}
pohId={pohId}
isOnchain={isVouchGranted.isVouchOnchain}
/>
: null
}

<button
disabled={pending}
className="btn-main mb-2"
Expand Down Expand Up @@ -419,16 +410,6 @@ export default withClientConnected<ActionBarProps>(function ActionBar({
/>
.
</span>
<div className="flex flex-col md:flex-row md:items-center justify-between font-normal gap-4">
{isVouchGranted.didIVouchFor ?
<RemoveVouch
requester={requester}
pohId={pohId}
isOnchain={isVouchGranted.isVouchOnchain}
/>
: null
}
</div>
</>
)}

Expand Down
67 changes: 2 additions & 65 deletions src/app/[pohid]/[chain]/[request]/RemoveVouch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,17 @@ import { useLoading } from "hooks/useLoading";
import { enableReactUse } from "@legendapp/state/config/enableReactUse";
import { toast } from "react-toastify";
import { useEffectOnce } from "@legendapp/state/react";
import axios from "axios";
import useChainParam from "hooks/useChainParam";
import { useAccount, useSignTypedData } from "wagmi";
import { Contract } from "contracts";

enableReactUse();

interface RemoveVouchProps {
pohId: Hash;
requester: Address;
isOnchain: boolean;
}

export default function RemoveVouch({ pohId, requester, isOnchain }: RemoveVouchProps) {
export default function RemoveVouch({ pohId, requester }: RemoveVouchProps) {
const loading = useLoading();
const [pending] = loading.use();
const chain = useChainParam()!;

const [prepareRemoveVouch, removeOnchainVouch] = usePoHWrite(
"removeVouch",
Expand All @@ -46,69 +40,12 @@ export default function RemoveVouch({ pohId, requester, isOnchain }: RemoveVouch
prepareRemoveVouch({ args: [requester, pohId] });
});

const { address } = useAccount();
const voucher = address!.toLowerCase();
const expiration = useMemo(
() => Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30 * 6,
[]
);

const { signTypedData } = useSignTypedData({
onSuccess: async (signature) => {
try {
await axios.delete(`/api/vouch/${chain.name}/remove`, {
data: {
pohId: pohId,
voucher: voucher,
claimer: requester,
expiration: expiration,
signature
}
});
toast.success("Vouch removed successfully");
} catch (err) {
console.error(err);
toast.error("Some error occurred");
}
},
});

const removeOffchainVouch = () => {
signTypedData({
domain: {
name: "Proof of Humanity",
chainId: chain.id,
verifyingContract: Contract.ProofOfHumanity[chain.id],
},
types: {
IsHumanVoucher: [
{ name: "vouched", type: "address" },
{ name: "humanityId", type: "bytes20" },
{ name: "expirationTimestamp", type: "uint256" },
],
},
primaryType: "IsHumanVoucher",
message: {
vouched: requester,
humanityId: pohId,
expirationTimestamp: BigInt(expiration),
},
});
};

const removeVouch = () => {
if (isOnchain)
removeOnchainVouch()
else
removeOffchainVouch()
}

return (
<div className="flex gap-4">
<button
disabled={pending}
className="btn-main mb-2"
onClick={removeVouch}
onClick={removeOnchainVouch}
>
Remove Vouch
</button>
Expand Down
3 changes: 2 additions & 1 deletion src/app/[pohid]/[chain]/[request]/Vouch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ export default function Vouch({ pohId, claimer }: VouchButtonProps) {
(Sybil attack) or (Identity theft), all people who had vouched for it get
removed as well. Profiles that do not follow the Policy risk being
challenged and removed. Make sure you read and understand the Policy
before proceeding.
before proceeding. Also take into account that although a gasless vouch is possible,
it cannot be removed. Gasless vouches expire after one year.
</span>
<button
className={cn(
Expand Down
48 changes: 36 additions & 12 deletions src/app/[pohid]/[chain]/[request]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EvidenceFile, RegistrationFile } from "types/docs";
import { ipfs, ipfsFetch } from "utils/ipfs";
import { paramToChain, supportedChains } from "config/chains";
import { SupportedChain, getChainRpc, paramToChain, supportedChains } from "config/chains";
import ActionBar from "./ActionBar";
import Evidence from "./Evidence";
import { getOffChainVouches, getRequestData } from "data/request";
Expand All @@ -19,10 +19,12 @@ import Link from "next/link";
import Attachment from "components/Attachment";
import ChainLogo from "components/ChainLogo";
import Info from "./Info";
import { Address } from "viem";
import { Address, createPublicClient, getContract, http } from "viem";
import { Hash } from "@wagmi/core";
import { getClaimerData } from "data/claimer";
import { Request } from "generated/graphql";
import abis from "contracts/abis";
import { Contract } from "contracts";

interface PageProps {
params: { pohid: string; chain: string; request: string };
Expand Down Expand Up @@ -149,6 +151,22 @@ export default async function Request({ params }: PageProps) {
// advanceRequests.offChain =
// }

const getProofOfHumanity = (chain: SupportedChain) =>
getContract({
abi: abis.ProofOfHumanity,
address: Contract.ProofOfHumanity[chain.id],
publicClient: createPublicClient({
chain,
transport: http(getChainRpc(chain.id)),
}),
});

const isVoucherHuman = async (voucher: `0x${string}`, chain: SupportedChain): Promise<boolean> => {
const poh = getProofOfHumanity(chain);
const result = await poh.read.isHuman([voucher]);
return result;
}

const vouchersData = await Promise.all(
(
await Promise.all([
Expand All @@ -161,29 +179,34 @@ export default async function Request({ params }: PageProps) {
(chain) =>
voucher[chain.id].claimer?.registration?.humanity.winnerClaim
);
if (voucherEvidenceChain)

if (voucherEvidenceChain) {
return {
pohId:
voucher[voucherEvidenceChain.id].claimer!.registration!.humanity
.id,
pohId: voucher[voucherEvidenceChain.id].claimer!.registration!.humanity.id,
uri: voucher[voucherEvidenceChain.id]
.claimer!.registration!.humanity.winnerClaim.at(0)
?.evidenceGroup.evidence.at(0)?.uri,
};
chain: voucherEvidenceChain,
voucherId: voucher[voucherEvidenceChain.id].claimer!.registration!.humanity.id,
}
};
return {
voucher: voucher[chain.id].claimer?.id as Address,
pohId: undefined,
uri: undefined,
chain: chain,
voucherId: voucher[chain.id].claimer!.registration!.humanity.id,
};
})
.map(async ({ voucher, pohId, uri }) => {
.map(async ({ voucher, pohId, uri, voucherId, chain }) => {
if (!uri || !pohId) return { voucher };
try {
const evFile = await ipfsFetch<EvidenceFile>(uri);
if (!evFile?.fileURI) return { pohId };
return {
pohId,
photo: (await ipfsFetch<RegistrationFile>(evFile.fileURI)).photo,
isHuman: await isVoucherHuman(voucherId, chain),
};
} catch {
return { pohId };
Expand Down Expand Up @@ -351,11 +374,12 @@ export default async function Request({ params }: PageProps) {
Vouched by

<div className="flex gap-2">
{vouchersData.map(({ photo, pohId, voucher }, idx) =>
photo ? (
{vouchersData.map(({ photo, pohId, voucher, isHuman }, idx) => {
const className = `w-8 h-8 rounded-full cursor-pointer ${!isHuman? 'opacity-25' : ''}`
return photo ? (
<Link key={idx} href={`/${prettifyId(pohId)}`}>
<Image
className="w-8 h-8 rounded-full cursor-pointer"
className={className}
alt="image"
src={ipfs(photo)}
width={64}
Expand All @@ -367,7 +391,7 @@ export default async function Request({ params }: PageProps) {
<Identicon key={idx} address={voucher} diameter={32} />
</Link>
)
)}
})}
</div>
</div>
)}
Expand Down
4 changes: 2 additions & 2 deletions src/app/api/vouch/[chain]/add/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ export async function POST(

if (!validSignature) throw new Error("Invalid signature");

await datalake
/* await datalake
.from("poh-vouchdb")
.delete()
.eq("pohId", pohId.toLowerCase())
.eq("voucher", voucher.toLowerCase());

*/
await datalake
.from("poh-vouchdb")
.upsert({
Expand Down
101 changes: 0 additions & 101 deletions src/app/api/vouch/[chain]/remove/route.ts

This file was deleted.

Loading
Loading