Skip to content

Commit

Permalink
feat: Switch from credential types to verification level (#202)
Browse files Browse the repository at this point in the history
Co-authored-by: Paolo <[email protected]>
  • Loading branch information
m1guelpf and pdtfh authored Dec 10, 2023
1 parent fe7d166 commit 9cbae6e
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 35 deletions.
1 change: 0 additions & 1 deletion examples/with-html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ <h1 id="heading">idkit-js</h1>
action: 'test-action',
bridge_url: 'https://wallet-bridge.stage-crypto.worldcoin.org',
action_description: 'Test action description',
credential_types: ['phone', 'device'],
handleVerify: response => {
// verify the IDKIt proof, throw an error to show the error screen
},
Expand Down
10 changes: 8 additions & 2 deletions examples/with-next/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { IDKitWidget } from '@worldcoin/idkit'
import { IDKitWidget, VerificationLevel } from '@worldcoin/idkit'
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'

export const getServerSideProps = (async context => {
return { props: { app_id: context.query.app_id?.toString() as `app_${string}` || 'app_staging_45068dca85829d2fd90e2dd6f0bff997' } }
return {
props: {
app_id:
(context.query.app_id?.toString() as `app_${string}`) || 'app_staging_45068dca85829d2fd90e2dd6f0bff997',
},
}
}) satisfies GetServerSideProps<{
app_id: `app_${string}`
}>
Expand All @@ -14,6 +19,7 @@ const Home = ({ app_id }: InferGetServerSidePropsType<typeof getServerSideProps>
onError={error => console.log(error)}
onSuccess={response => console.log(response)}
app_id={app_id}
verification_level={VerificationLevel.Lite}
>
{({ open }) => <button onClick={open}>Open IDKit</button>}
</IDKitWidget>
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/bridge.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { create } from 'zustand'
import { DEFAULT_VERIFICATION_LEVEL, buffer_decode, verification_level_to_credential_types } from './lib/utils'
import { type IDKitConfig } from '@/types/config'
import { VerificationState } from '@/types/bridge'
import type { ISuccessResult } from '@/types/result'
import { encodeAction, generateSignal } from '@/lib/hashing'
import { AppErrorCodes, ResponseStatus } from '@/types/bridge'
import { buffer_decode, credential_types_or_default } from './lib/utils'
import { decryptResponse, encryptRequest, exportKey, generateKey } from '@/lib/crypto'

const DEFAULT_BRIDGE_URL = 'https://bridge.worldcoin.org'
Expand Down Expand Up @@ -44,7 +44,7 @@ export const useWorldBridgeStore = create<WorldBridgeStore>((set, get) => ({
bridge_url: DEFAULT_BRIDGE_URL,
verificationState: VerificationState.PreparingClient,

createClient: async ({ bridge_url, app_id, credential_types, action_description, action, signal }) => {
createClient: async ({ bridge_url, app_id, verification_level, action_description, action, signal }) => {
const { key, iv } = await generateKey()

const res = await fetch(`${bridge_url ?? DEFAULT_BRIDGE_URL}/request`, {
Expand All @@ -56,10 +56,10 @@ export const useWorldBridgeStore = create<WorldBridgeStore>((set, get) => ({
iv,
JSON.stringify({
app_id,
credential_types: credential_types_or_default(credential_types),
action_description,
action: encodeAction(action),
signal: generateSignal(signal).digest,
credential_types: verification_level_to_credential_types(verification_level ?? DEFAULT_VERIFICATION_LEVEL),
})
)
),
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ export {
VerificationState,
AbiEncodedValue,
CredentialType,
VerificationLevel,
IDKitConfig,
} from '@/types'

export { useWorldBridgeStore, WorldBridgeStore } from '@/bridge'

export { DEFAULT_CREDENTIAL_TYPES } from '@/lib/utils'
export { DEFAULT_VERIFICATION_LEVEL, verification_level_to_credential_types } from '@/lib/utils'
21 changes: 16 additions & 5 deletions packages/core/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { CredentialType } from '..'
import type { IDKitConfig } from '..'
import { Buffer } from 'buffer/index.js'
import { CredentialType, VerificationLevel } from '@/types/config'

export const DEFAULT_CREDENTIAL_TYPES = [CredentialType.Orb]
export const DEFAULT_VERIFICATION_LEVEL = VerificationLevel.Orb

export const buffer_encode = (buffer: ArrayBuffer): string => {
return Buffer.from(buffer).toString('base64')
Expand All @@ -12,6 +11,18 @@ export const buffer_decode = (encoded: string): ArrayBuffer => {
return Buffer.from(encoded, 'base64')
}

export const credential_types_or_default = (credential_types: IDKitConfig['credential_types']): CredentialType[] => {
return credential_types?.length ? credential_types : DEFAULT_CREDENTIAL_TYPES
/**
* @deprecated use to transition to verification levels from credential types
* @param verification_level
* @returns
*/
export const verification_level_to_credential_types = (verification_level: VerificationLevel): string[] => {
switch (verification_level) {
case VerificationLevel.Lite:
return [CredentialType.Orb, CredentialType.Device]
case VerificationLevel.Orb:
return [CredentialType.Orb]
default:
throw new Error(`Unknown verification level: ${verification_level}`)
}
}
12 changes: 10 additions & 2 deletions packages/core/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ type Brand<T, TBrand extends string> = T & { [brand]: TBrand }

export type AbiEncodedValue = Brand<{ types: string[]; values: unknown[] }, 'AbiEncodedValue'>

/**
* @deprecated in [email protected], use VerificationLevel instead
*/
export enum CredentialType {
Orb = 'orb',
Device = 'device',
}

export enum VerificationLevel {
Lite = 'lite',
Orb = 'orb',
}

export type IDKitConfig = {
/** Unique identifier for the app verifying the action. This should be the app ID obtained from the Developer Portal. */
app_id: `app_${string}`
Expand All @@ -19,6 +27,6 @@ export type IDKitConfig = {
action?: AbiEncodedValue | string
/** URL to a third-party bridge to use when connecting to the World App. Optional. */
bridge_url?: string
/** An array of credential types to allow for verification. Will accept any combination of "orb" & "device". Defaults to orb. TypeScript apps can use the `CredentialType` enum. */
credential_types?: CredentialType[] // Accepted credentials for verification by the host app
/** The minimum required level of verification. Defaults to "orb". */
verification_level?: VerificationLevel
}
2 changes: 1 addition & 1 deletion packages/core/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { ISuccessResult, IErrorState } from '@/types/result'
export { AppErrorCodes, VerificationState } from '@/types/bridge'
export { AbiEncodedValue, CredentialType, IDKitConfig } from '@/types/config'
export { AbiEncodedValue, VerificationLevel, CredentialType, IDKitConfig } from '@/types/config'
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import AboutWorldID from '@/components/AboutWorldID'
import { useWorldBridge } from '@/services/wld-bridge'
import LoadingIcon from '@/components/Icons/LoadingIcon'
import WorldcoinIcon from '@/components/Icons/WorldcoinIcon'
import { AppErrorCodes, VerificationState } from '@worldcoin/idkit-core'
import { AppErrorCodes, VerificationState, verification_level_to_credential_types } from '@worldcoin/idkit-core'

const getOptions = (store: IDKitStore) => ({
signal: store.signal,
Expand All @@ -20,7 +20,7 @@ const getOptions = (store: IDKitStore) => ({
bridge_url: store.bridge_url,
handleVerify: store.handleVerify,
setErrorState: store.setErrorState,
credential_types: store.credential_types,
verification_level: store.verification_level,
action_description: store.action_description,
})

Expand All @@ -35,7 +35,7 @@ const WorldIDState = () => {
handleVerify,
bridge_url,
action_description,
credential_types,
verification_level,
setErrorState,
} = useIDKitStore(getOptions, shallow)

Expand All @@ -44,7 +44,7 @@ const WorldIDState = () => {
action,
signal,
bridge_url,
credential_types,
verification_level,
action_description
)

Expand All @@ -57,6 +57,7 @@ const WorldIDState = () => {
}

if (result) {
const credential_types = verification_level_to_credential_types(verification_level)
if (!credential_types.includes(result.credential_type)) {
console.error(
'Credential type received from wallet does not match configured credential_types. This should only happen when manually selecting disallowed credentials in the Worldcoin Simulator.'
Expand All @@ -67,7 +68,7 @@ const WorldIDState = () => {
}
return handleVerify(result)
}
}, [result, handleVerify, verificationState, setStage, errorCode, setErrorState, credential_types])
}, [result, handleVerify, verificationState, setStage, errorCode, setErrorState, verification_level])

return (
<div className="-mt-6 space-y-10">
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import useIDKit from './hooks/useIDKit'
import SignInButton from './components/SignInButton'
import { CredentialType } from '@worldcoin/idkit-core'
import IDKitWidget from '@/components/IDKitWidget/index'
import type { WidgetProps, Config } from '@/types/config'
import { solidityEncode } from '@worldcoin/idkit-core/hashing'
import SignInWithWorldID from './components/SignInWithWorldID'
import type { ISuccessResult, IErrorState } from '@worldcoin/idkit-core'
import { CredentialType, VerificationLevel } from '@worldcoin/idkit-core'

export { IDKitWidget, useIDKit, solidityEncode, SignInWithWorldID, CredentialType, SignInButton }
export { IDKitWidget, useIDKit, solidityEncode, SignInWithWorldID, CredentialType, SignInButton, VerificationLevel }
export type { ISuccessResult, IErrorState, Config, WidgetProps }
8 changes: 4 additions & 4 deletions packages/react/src/services/wld-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ export const useWorldBridge = (
action: IDKitConfig['action'],
signal?: IDKitConfig['signal'],
bridge_url?: IDKitConfig['bridge_url'],
credential_types?: IDKitConfig['credential_types'],
verification_level?: IDKitConfig['verification_level'],
action_description?: IDKitConfig['action_description']
): UseAppBridgeResponse => {
const ref_credential_types = useRef(credential_types)
const ref_verification_level = useRef(verification_level)
const { reset, result, connectorURI, createClient, pollForUpdates, verificationState, errorCode } =
useWorldBridgeStore()

Expand All @@ -29,11 +29,11 @@ export const useWorldBridge = (
action,
signal,
bridge_url,
credential_types: ref_credential_types.current,
action_description,
verification_level: ref_verification_level.current,
})
}
}, [app_id, action, signal, action_description, createClient, ref_credential_types, bridge_url, connectorURI])
}, [app_id, action, signal, action_description, createClient, ref_verification_level, bridge_url, connectorURI])

useEffect(() => {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
Expand Down
14 changes: 5 additions & 9 deletions packages/react/src/store/idkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import type { Config, ConfigSource } from '@/types/config'
import { createWithEqualityFn } from 'zustand/traditional'
import {
AppErrorCodes,
CredentialType,
DEFAULT_CREDENTIAL_TYPES,
DEFAULT_VERIFICATION_LEVEL,
type IErrorState,
type IDKitConfig,
type ISuccessResult,
Expand All @@ -21,7 +20,7 @@ export type IDKitStore = {
signal: IDKitConfig['signal']
bridge_url?: IDKitConfig['bridge_url']
action_description?: IDKitConfig['action_description']
credential_types: NonNullable<IDKitConfig['credential_types']>
verification_level: NonNullable<IDKitConfig['verification_level']>

open: boolean
stage: IDKITStage
Expand Down Expand Up @@ -57,7 +56,7 @@ const useIDKitStore = createWithEqualityFn<IDKitStore>()(
action: '',
action_description: '',
bridge_url: '',
credential_types: DEFAULT_CREDENTIAL_TYPES,
verification_level: DEFAULT_VERIFICATION_LEVEL,

open: false,
result: null,
Expand Down Expand Up @@ -113,7 +112,7 @@ const useIDKitStore = createWithEqualityFn<IDKitStore>()(
action,
app_id,
onError,
credential_types,
verification_level,
action_description,
bridge_url,
autoClose,
Expand All @@ -122,18 +121,15 @@ const useIDKitStore = createWithEqualityFn<IDKitStore>()(
}: Config,
source: ConfigSource
) => {
const sanitizedCredentialTypes =
credential_types?.filter(type => Object.values(CredentialType).includes(type)) ?? []

set({
theme,
signal,
action,
autoClose,
bridge_url,
action_description,
credential_types: sanitizedCredentialTypes.length ? sanitizedCredentialTypes : DEFAULT_CREDENTIAL_TYPES,
app_id: advanced?.self_hosted ? SELF_HOSTED_APP_ID : app_id,
verification_level: verification_level ?? DEFAULT_VERIFICATION_LEVEL,
})

get().addSuccessCallback(onSuccess, source)
Expand Down

0 comments on commit 9cbae6e

Please sign in to comment.