👨💻 User Story
As a developer I want to easily issue verifiable credentials when users reach a specific goal or action.
More specifically I want to issue a "Proof of Hack" verifiable credential using the Disco credential issuance API.
📜 Disclaimer
To be eligible for the payout you must first get approval to work on the bounty.
It's recommended to share a link to your personal Github account.
🧱 Project
Update the Disco integration to include support for verifiable credential programmatic issuance.
You can reference the public Disco schemas on Github for a full list of potential schemas
https://github.com/discoxyz/disco-schemas
For the integration use the ProofOfHackCredential verifiable credential.
https://github.com/discoxyz/disco-schemas/tree/main/src/schemas/ProofOfHackCredential
Verifiable Credential Schema Snippet
The core credential fields are "eventName", "eventDate" and "projectName", as denoted in the required field, but the form should include support for all of the properties.
credentialSubject: {
type: "object",
required: ["id", "eventName", "eventDate", "projectName"],
properties: {
id: { title: "Recipient DID", type: "string", format: "uri" },
eventName: { title: "Event Name", type: "string" },
eventDate: { title: "Event Date", type: "string", format: "date" },
projectName: { title: "Project Name", type: "string" },
place: { title: "Place", type: "string" },
teamName: { title: "Team Name", type: "string" },
sourceCodeUrl: { title: "Source Code Url", type: "string" },
usageLink: { title: "Usage Link", type: "string" },
},
},
Required Functionality:
- Disco verifiable credential issuance API integration
- Form using shacdn UI
<Form />
components.
- New
app
page to issue verifiable credentials.
Developer Tasks:
Hook
The useDiscoIssueCredential
hook should use useMutation
method exported from the TanStack react-query package.
API
The routeCredentialIssuance.ts
endpoint should limit issuance to admins.
Admins are defined in env
variables using the APP_ADMINS
key.
The isAdmin
key is added to authentication session
during account verification.
https://github.com/turbo-eth/template-web3-app/blob/main/pages/api/siwe/verify.ts#L19
The route
should be re-exported in a pages/api/disco/credential-issue.ts
file.
https://github.com/turbo-eth/template-web3-app/tree/integrations/pages/api/disco
Component
The <FormCredentialIssuanceProofOfHack />
component should use the useDiscoIssueCredential
hook to interact with the API.
The form should be generated using the shacdn UI component library.
Follow the install instructions on https://ui.shadcn.com/docs/forms/react-hook-form
The form should look similar to the code below, but using the verifiable credential schema.
"use client"
import Link from "next/link"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
const formSchema = z.object({
username: z.string().min(2, {
message: "Username must be at least 2 characters.",
}),
})
export function ProfileForm() {
. // 1. Define your form.
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
username: "",
},
})
// 2. Define a submit handler.
function onSubmit(values: z.infer<typeof formSchema>) {
// Do something with the form values.
// ✅ This will be type-safe and validated.
console.log(values)
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}
Potential File Structure
Integration
The Disco integration is located in integrations/disco
folder in the integrations
branch on the template-web3-app
repo.
integrations/disco
├─ routes/
│ ├─ route-credential-issue.tsx
├─ forms/
│ ├─ form-credential-issuance-proof-of-hack.tsx
├─ hooks/
│ ├─ **/*.ts
├─ utils/
│ ├─ **/*.ts
├─ client.ts
├─ README.md
Application
The application pages should be added to the app/(general)/integration/disco
folder.
app/(general)/integration/disco
├─ proof-of-hack
│ ├─ page.tsx
💰 Bounty Reward
The bounty reward is 650 USDC and 50 OP tokens.
TurboETH is the recipient of 18,271.88 OP Tokens from Optimism Retroactive Public Goods Funding. OP tokens earned from RPGF are helping fund TurboETH bounties.
Notice
The final integration may not resemble the proposed integration - that's O.K - a natural part of software development.
During development you might discover an original hypothesis doesn't make sense. No problem. Make a comment and clearly explain why a new approach is better than old one. Get rewarded for thinking out of the box.
The final bounty reward can be increased to match new bounty tasks.
Resources