Skip to content

Commit

Permalink
feat: verifyCloudProof function (#240)
Browse files Browse the repository at this point in the history
* chore: tidy up

* feat: verifyCloudProof

* feat: nextjs example use verifyCloudProof

non-functional until dev portal v2 api is live, but can test by modifying verifyCloudProof to use v1 api and rebuilding

* add backend-only check

* Update examples/with-next/pages/api/verify.ts

Co-authored-by: Miguel Piedrafita <github@miguel.build>

* fix: isBrowser

* add endpoint param for verifyCloudProof

* update lockfile

* don't modify endpoint if passed

---------

Co-authored-by: Miguel Piedrafita <github@miguel.build>
  • Loading branch information
0xPenryn and m1guelpf committed Mar 28, 2024
1 parent 891c813 commit c4a2821
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 33 deletions.
1 change: 0 additions & 1 deletion examples/with-html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ <h1 id="heading">idkit-js</h1>
signal: 'test_signal',
app_id: 'app_ce4cb73cb75fc3b73b71ffb4de178410',
action: 'test-action',
bridge_url: 'https://wallet-bridge.stage-crypto.worldcoin.org',
action_description: 'Test action description',
handleVerify: response => {
// verify the IDKIt proof, throw an error to show the error screen
Expand Down
10 changes: 10 additions & 0 deletions examples/with-next/pages/api/verify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NextApiRequest, NextApiResponse } from 'next'
import { verifyCloudProof, IVerifyResponse } from '@worldcoin/idkit'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method != 'POST') return res.status(405).json({ message: 'Method Not Allowed' })

const { proof, app_id, action, signal } = req.body
const response = (await verifyCloudProof(proof, app_id, action, signal)) as IVerifyResponse
res.status(response.success ? 200 : 400).json(response)
}
38 changes: 32 additions & 6 deletions examples/with-next/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
import { IDKitWidget, VerificationLevel } from '@worldcoin/idkit'
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
import { IDKitWidget, ISuccessResult, IVerifyResponse, VerificationLevel } from '@worldcoin/idkit'

export const getServerSideProps = (async context => {
return {
props: {
app_id:
(context.query.app_id?.toString() as `app_${string}`) || 'app_staging_45068dca85829d2fd90e2dd6f0bff997',
action: (context.query.action?.toString() as string) || 'test-action',
signal: (context.query.signal?.toString() as string) || 'test_signal',
},
}
}) satisfies GetServerSideProps<{
app_id: `app_${string}`
}>

const Home = ({ app_id }: InferGetServerSidePropsType<typeof getServerSideProps>) => (
async function verify(proof: ISuccessResult, app_id: `app_${string}`, action: string, signal: string) {
const response = await fetch('/api/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
proof,
app_id,
action,
signal,
}),
})

const result = (await response.json()) as IVerifyResponse

if (response.ok) {
console.log('handleVerify Success!')
} else {
throw new Error('handleVerify Error: ' + result.detail)
}
}

const Home = ({ app_id, action, signal }: InferGetServerSidePropsType<typeof getServerSideProps>) => (
<IDKitWidget
action="test-action"
signal="test_signal"
onError={error => console.log(error)}
onSuccess={response => console.log(response)}
action={action}
signal={signal}
onError={error => console.log('onError: ', error)}
onSuccess={response => console.log('onSuccess: ', response)}
handleVerify={proof => verify(proof, app_id, action, signal)}
app_id={app_id}
verification_level={VerificationLevel.Device}
>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"prepublishOnly": "npm run build"
},
"devDependencies": {
"turbo": "^1.11.1"
"turbo": "^1.13.0"
},
"engines": {
"node": ">=18"
Expand Down
9 changes: 9 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@
"import": "./build/lib/hashing.js",
"types": "./build/lib/hashing.d.ts",
"require": "./build/lib/hashing.cjs"
},
"./backend": {
"import": "./build/lib/backend.js",
"types": "./build/lib/backend.d.ts",
"require": "./build/lib/backend.cjs"
}
},
"typesVersions": {
"*": {
"backend": [
"./build/lib/backend.d.ts"
],
"hashing": [
"./build/lib/hashing.d.ts"
],
Expand Down Expand Up @@ -54,6 +62,7 @@
"sybil resistance"
],
"dependencies": {
"browser-or-node": "3.0.0-pre.0",
"buffer": "^6.0.3",
"viem": "^1.19.11",
"zustand": "^4.5"
Expand Down
40 changes: 40 additions & 0 deletions packages/core/src/lib/backend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { hashToField } from './hashing'
import { isBrowser } from 'browser-or-node'
import type { ISuccessResult } from '../types'

export interface IVerifyResponse {
success: boolean
code?: string
detail?: string
attribute?: string | null
}

export async function verifyCloudProof(
proof: ISuccessResult,
app_id: `app_${string}`,
action: string,
signal?: string,
endpoint?: URL | string
): Promise<IVerifyResponse> {
if (isBrowser) {
throw new Error('verifyCloudProof can only be used in the backend.')
}

const response = await fetch(endpoint ?? `https://developer.worldcoin.org/api/v2/verify/${app_id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
...proof,
action,
signal_hash: hashToField(signal ?? '').digest,
}),
})

if (response.ok) {
return { success: true }
} else {
return { success: false, ...(await response.json()) } as IVerifyResponse
}
}
2 changes: 1 addition & 1 deletion packages/core/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export default defineConfig({
outDir: 'build',
format: ['esm', 'cjs'],
external: ['zustand', 'viem'],
entry: ['src/index.ts', 'src/lib/hashing.ts'],
entry: ['src/index.ts', 'src/lib/hashing.ts', 'src/lib/backend.ts'],
define: { 'process.env.NODE_ENV': '"production"' },
})
6 changes: 4 additions & 2 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import IDKitWidget from '@/components/IDKitWidget/index'
import type { WidgetProps, Config } from '@/types/config'
import { VerificationLevel } from '@worldcoin/idkit-core'
import { solidityEncode } from '@worldcoin/idkit-core/hashing'
import { verifyCloudProof } from '@worldcoin/idkit-core/backend'
import type { IVerifyResponse } from '@worldcoin/idkit-core/backend'
import type { ISuccessResult, IErrorState } from '@worldcoin/idkit-core'

export { IDKitWidget, useIDKit, solidityEncode, VerificationLevel }
export type { ISuccessResult, IErrorState, Config, WidgetProps }
export { IDKitWidget, useIDKit, solidityEncode, verifyCloudProof, VerificationLevel }
export type { ISuccessResult, IErrorState, IVerifyResponse, Config, WidgetProps }
51 changes: 29 additions & 22 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c4a2821

Please sign in to comment.