Web proofs from javascript

Actively in Development

Our team is currently working on this feature. If you experience any bugs, please let us know on our Discord. We appreciate your patience.

Web Proofs

On top of access to vlayer JSON-RPC proving API, vlayer client provides functionality to generate and prove Web Proofs.

vlayer browser extension

vlayer provides a browser extension which can be launched (once installed in user's browser) from vlayer SDK and used to generate a Web Proof of a 3rd party website.
vlayer extension is compatible with Chrome and Brave browsers.

We start by instantiating vlayer client.

import { createVlayerClient } from '@vlayer/sdk'

const vlayer = createVlayerClient()

We can configure a Web Proof provider which uses vlayer browser extension and enables configuring custom Notary server and custom WebSocket proxy (see section WebSocket proxy below for more details).

import { createExtensionWebProofProvider } from '@vlayer/sdk/web_proof'

const webProofProvider = createExtensionWebProofProvider({
    notaryUrl: 'https://...',
    wsProxyUrl: 'wss://...',
})

Both notaryUrl and wsProxyUrl have default values, so the provider can be initialized without any configuration as:

const webProofProvider = createExtensionWebProofProvider();

In the future, vlayer is planning to provide additional Web Proof provider implementations, which can be e.g. ran server-side and don't require vlayer browser extension for the purpose of Web Proof generation.

The Web Proof provider exposes a low-level API to directly define proverCallCommitment (commitment to use the generated Web Proof only with the specified prover contract call details, so it's not possible to submit it in a different context) and to explicitly generate the Web Proof by calling getWebProof.

import {
  startPage,
  expectUrl,
  notarize,
} from '@vlayer/sdk/web_proof'

// all args required by prover contract function except webProof itself
const commitmentArgs = ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045']

const proverCallCommitment = {
  address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
  functionName: 'main',
  commitmentArgs,
  chainId: sepolia,
  proverAbi,
}

const webProof = await webProofProvider.getWebProof({
  proverCallCommitment,
  logoUrl: 'http://twitterswap.com/logo.png',
  steps: [
    startPage('https://x.com/i/flow/login', 'Go to x.com login page'),
    expectUrl('https://x.com/home', 'Log in'),
    notarize('https://api.x.com/1.1/account/settings.json', 'GET', 'Generate Proof of Twitter profile'),
  ],
})

The above snippet defines a Web Proof, which is generated by the following steps:

  1. startPage - redirects the user's browser to https://x.com/i/flow/login.
  2. expectUrl - ensures that the user is logged in and visiting https://x.com/home URL.
  3. notarize - prompts the user to generate a Web Proof, i.e. to notarize an HTTP GET request sent to https://api.x.com/1.1/account/settings.json URL.

Each step also accepts a human-readable message which the user will see. We can also optionally pass a link to custom logo to display in the extension.

The call to webProofProvider.getWebProof opens vlayer browser extension and guides the user through the steps passed as an argument.

Once we have the Web Proof available we can directly call vlayer client prove method, adding the Web Proof to previously created proverCallCommitment.

import { sepolia } from 'viem/chains'
import { proverAbi } from './proverAbi'

const { hash } = await vlayer.prove({
    ...proverCallCommitment,
    args: [webProof, ...commitmentArgs],
})

To learn more details about the Web Proof feature, please see the Web Proof section.

WebSocket proxy

The WebSocket proxy is required in the Web Proofs setup to allow the vlayer extension to access the low-level TLS connection of the HTTPS request for which we are generating a Web Proof (browsers do not provide this access by default). The default WebSocket proxy, wss://notary.pse.dev/proxy, used in our SDK and hosted by the TLSN team, supports a limited number of domains (you can view the list here).

If you'd like to notarize a request for a different domain, you can run your own proxy server. To do this locally, install and run websocat:

cargo install websocat
websocat --binary -v ws-l:0.0.0.0:55688 tcp:api.x.com:443

Replace api.x.com with the domain you'd like to use. Then, configure your Web Proof provider to use your local WebSocket proxy (running on port 55688):

import { createExtensionWebProofProvider } from '@vlayer/sdk/web_proof'

const webProofProvider = createExtensionWebProofProvider({
  wsProxyUrl: "ws://localhost:55688",
})

Now the notarized HTTPS request will be routed through your local proxy server.