Presentation Verification
verifyPresentation() runs a 6-step trust chain
to validate a Verifiable Presentation received from a wallet.
The 6-Step Trust Chain
- Extract holder DID — parse the presentation and identify the holder
- Resolve DID Document — fetch the holder's DID Document from the appropriate method handler
- Verify signature — check the presentation proof against the holder's public key
- Validate issuer trust — confirm each credential's issuer is in the trusted set
- Check revocation — query revocation registries for each credential
- Verify wallet trust — optionally confirm the wallet extension itself is trusted
VerifyResult
TypeScript
interface VerifyResult { valid: boolean // Overall pass/fail holderDid: string // Extracted holder DID errors: VerifyError[] // Array of error objects didDocument: DIDDocument // Resolved DID Document }
Error Codes
| Code | Step | Description |
|---|---|---|
NO_HOLDER | 1 | Presentation does not contain a holder DID |
RESOLUTION_FAILED | 2 | Could not resolve the holder's DID Document |
SIGNATURE_INVALID | 3 | Presentation signature does not match holder's public key |
ISSUER_UNTRUSTED | 4 | Credential issuer is not in the trusted issuers list |
CREDENTIAL_REVOKED | 5 | One or more credentials have been revoked |
WALLET_UNTRUSTED | 6 | Wallet extension is not in the trusted wallets list |
Options
| Property | Type | Description |
|---|---|---|
resolverUrl | string | DID resolver endpoint (default: https://resolver.attestto.com) |
trustedIssuers | string[] | Array of trusted issuer DIDs |
trustedWallets | string[] | Array of trusted wallet DIDs (optional) |
checkRevocation | boolean | Whether to check revocation registries (default: true) |
signal | AbortSignal | Abort signal for cancellation |
Full Example
TypeScript
import { pickWallet, verifyPresentation } from '@attestto/id-wallet-adapter' // 1. Pick a wallet and request a Verifiable Presentation const wallet = await pickWallet({ render: 'modal' }) const vp = await wallet.requestPresentation({ challenge: crypto.randomUUID(), }) // 2. Verify the presentation const result = await verifyPresentation(vp, { trustedIssuers: [ 'did:web:gov.example.com', 'did:sns:attestto.sol', ], checkRevocation: true, }) if (result.valid) { console.log('Verified holder:', result.holderDid) } else { console.error('Verification failed:', result.errors) }
Backend Resolver Pattern
Always verify on the backend. Client-side verification is useful for instant feedback, but the authoritative check must happen server-side where the resolver endpoint and trusted issuer list cannot be tampered with.
Send the raw VP to your backend and call verifyPresentation()
there. The same API works in Node.js — the adapter has zero browser-only
dependencies.