Presentation Verification

verifyPresentation() runs a 6-step trust chain to validate a Verifiable Presentation received from a wallet.

The 6-Step Trust Chain

  1. Extract holder DID — parse the presentation and identify the holder
  2. Resolve DID Document — fetch the holder's DID Document from the appropriate method handler
  3. Verify signature — check the presentation proof against the holder's public key
  4. Validate issuer trust — confirm each credential's issuer is in the trusted set
  5. Check revocation — query revocation registries for each credential
  6. 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

CodeStepDescription
NO_HOLDER1Presentation does not contain a holder DID
RESOLUTION_FAILED2Could not resolve the holder's DID Document
SIGNATURE_INVALID3Presentation signature does not match holder's public key
ISSUER_UNTRUSTED4Credential issuer is not in the trusted issuers list
CREDENTIAL_REVOKED5One or more credentials have been revoked
WALLET_UNTRUSTED6Wallet extension is not in the trusted wallets list

Options

PropertyTypeDescription
resolverUrlstringDID resolver endpoint (default: https://resolver.attestto.com)
trustedIssuersstring[]Array of trusted issuer DIDs
trustedWalletsstring[]Array of trusted wallet DIDs (optional)
checkRevocationbooleanWhether to check revocation registries (default: true)
signalAbortSignalAbort 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.