@vlayer/sdk 0.1.0-nightly-20241001-aa0406f → 0.1.0-nightly-20241002-4630acc

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -2,7 +2,8 @@
2
2
  "name": "@vlayer/sdk",
3
3
  "type": "module",
4
4
  "module": "src/index.ts",
5
- "version": "0.1.0-nightly-20241001-aa0406f",
5
+ "version": "0.1.0-nightly-20241002-4630acc",
6
+ "types": "src/index.ts",
6
7
  "scripts": {
7
8
  "build": "npm run gen:types",
8
9
  "test": "vitest --run",
@@ -11,7 +12,6 @@
11
12
  "devDependencies": {
12
13
  "@changesets/cli": "^2.27.7",
13
14
  "@types/bun": "latest",
14
- "@types/mailparser": "^3.4.4",
15
15
  "abitype": "^1.0.6",
16
16
  "vitest": "^2.1.1"
17
17
  },
@@ -19,7 +19,9 @@
19
19
  "typescript": "^5.0.0"
20
20
  },
21
21
  "dependencies": {
22
- "mailparser": "^3.7.1",
23
- "viem": "^2.21.0"
22
+ "dns-over-http-resolver": "^3.0.3",
23
+ "postal-mime": "^2.3.2",
24
+ "viem": "^2.21.0",
25
+ "zod": "^3.23.8"
24
26
  }
25
27
  }
@@ -1,14 +1,7 @@
1
- import dns from "node:dns";
1
+ import DnsResolver from "dns-over-http-resolver";
2
2
 
3
3
  export async function resolveDkimDns(domain: string, selector: string) {
4
- return new Promise<string>((resolve, reject) => {
5
- dns.resolveTxt(`${selector}._domainkey.${domain}`, (err, addresses) => {
6
- if (err) {
7
- reject(err);
8
- return;
9
- }
10
-
11
- resolve(addresses.flat()[0]);
12
- });
13
- });
4
+ const resolver = new DnsResolver();
5
+ const address = await resolver.resolveTxt(`${selector}._domainkey.${domain}`);
6
+ return address.flat()[0];
14
7
  }
@@ -1,7 +1,5 @@
1
- import assert from "node:assert";
2
1
  import { describe, expect, test } from "vitest";
3
- import { getDkimSigners, parseEmail } from "./parseEmail.ts";
4
- import { StructuredHeader } from "mailparser";
2
+ import { getDkimSigners, parseEmail, parseParams } from "./parseEmail.ts";
5
3
 
6
4
  const emailHeaders = `From: "John Doe" <john@d.oe>
7
5
  To: "Jane Doe" <jane@d.oe>
@@ -17,18 +15,12 @@ const body = "Hello, World!";
17
15
  const emailFixture = `${emailHeaders}${dkimHeader}\n\n${body}`;
18
16
 
19
17
  describe("parseEmail", () => {
20
- test("should get dkim header from email", async () => {
21
- const email = await parseEmail(emailFixture);
22
- const dkim = email.headers.get("dkim-signature")!;
23
- assert(typeof dkim === "object" && "params" in dkim);
24
- expect(dkim.params.d).toBe("example.com");
25
- expect(dkim.params.s).toBe("selector1");
26
- });
18
+ test("should get dkim header from email", async () => {});
27
19
 
28
20
  test("correctly parses untrimmed email", async () => {
29
21
  const untrimmed = `\n ${emailFixture} \n`;
30
22
  const email = await parseEmail(untrimmed);
31
- expect(email.headers.get("dkim-signature")).toBeDefined();
23
+ expect(email.headers.find((h) => h.key === "dkim-signature")).toBeDefined();
32
24
  });
33
25
 
34
26
  test("works well with multiple dkim headers", async () => {
@@ -38,12 +30,11 @@ describe("parseEmail", () => {
38
30
  const email = await parseEmail(
39
31
  `${emailHeaders}${dkimHeader}\n${dkimHeader2}\n\n${body}`,
40
32
  );
41
- const dkim = email.headers.get(
42
- "dkim-signature",
43
- )! as unknown as StructuredHeader[];
33
+ const dkim = email.headers.filter((h) => h.key === "dkim-signature")!;
34
+
44
35
  expect(dkim).toHaveLength(2);
45
- expect(dkim[0].params.s).toBe("selector1");
46
- expect(dkim[1].params.s).toBe("selector2");
36
+ expect(parseParams(dkim[0].value).s).toBe("selector1");
37
+ expect(parseParams(dkim[1].value).s).toBe("selector2");
47
38
  });
48
39
  });
49
40
 
@@ -103,3 +94,40 @@ describe("getDkimSigners", () => {
103
94
  );
104
95
  });
105
96
  });
97
+
98
+ describe("parseParams", () => {
99
+ test("should parse single parameter", () => {
100
+ const params = parseParams("a=b");
101
+ expect(params).toEqual({ a: "b" });
102
+ });
103
+
104
+ test("should parse multiple parameters", () => {
105
+ const params = parseParams("a=b; c=d; e=f");
106
+ expect(params).toEqual({ a: "b", c: "d", e: "f" });
107
+ });
108
+
109
+ test("should trim spaces around parameters", () => {
110
+ const params = parseParams(" a = b ; c = d ; e = f ");
111
+ expect(params).toEqual({ a: "b", c: "d", e: "f" });
112
+ });
113
+
114
+ test("should handle empty values", () => {
115
+ const params = parseParams("a=; b=c");
116
+ expect(params).toEqual({ a: "", b: "c" });
117
+ });
118
+
119
+ test("should handle missing values", () => {
120
+ const params = parseParams("a; b=c");
121
+ expect(params).toEqual({ a: undefined, b: "c" });
122
+ });
123
+
124
+ test("should handle empty string", () => {
125
+ const params = parseParams("");
126
+ expect(params).toEqual({});
127
+ });
128
+
129
+ test("should handle parameters with extra semicolons", () => {
130
+ const params = parseParams("a=b;; c=d;");
131
+ expect(params).toEqual({ a: "b", c: "d" });
132
+ });
133
+ });
@@ -1,4 +1,4 @@
1
- import { simpleParser, HeaderValue, type ParsedMail } from "mailparser";
1
+ import PostalMime, { Email, Header } from "postal-mime";
2
2
 
3
3
  export class DkimParsingError extends Error {
4
4
  constructor(message: string) {
@@ -8,38 +8,42 @@ export class DkimParsingError extends Error {
8
8
  }
9
9
 
10
10
  export async function parseEmail(mime: string) {
11
- return simpleParser(mime.trim(), {
12
- skipHtmlToText: true,
13
- skipTextToHtml: true,
14
- skipTextLinks: true,
15
- skipImageLinks: true,
16
- });
11
+ return await PostalMime.parse(mime.trim());
17
12
  }
18
13
 
19
- export function getDkimSigners(mail: ParsedMail) {
20
- const dkimHeader = mail.headers.get("dkim-signature");
21
- if (!dkimHeader) throw new DkimParsingError("No DKIM header found");
22
- if (Array.isArray(dkimHeader)) {
23
- return dkimHeader.map(parseHeader);
24
- }
25
- return [parseHeader(dkimHeader)];
14
+ export function getDkimSigners(mail: Email) {
15
+ const dkimHeader = mail.headers.filter((h) => h.key === "dkim-signature");
16
+ if (dkimHeader.length === 0)
17
+ throw new DkimParsingError("No DKIM header found");
18
+ return dkimHeader.map(parseHeader);
19
+ }
20
+
21
+ export function parseParams(str: string) {
22
+ return Object.fromEntries(
23
+ str.split(";").map((s) =>
24
+ s
25
+ .trim()
26
+ .split("=")
27
+ .map((v) => v && v.trim()),
28
+ ),
29
+ );
26
30
  }
27
31
 
28
- function parseHeader(header: HeaderValue) {
29
- if (typeof header === "string" || !("params" in header)) {
32
+ function parseHeader(header: Header) {
33
+ const params = parseParams(header.value);
34
+ if (!params) {
30
35
  throw new DkimParsingError(`Invalid DKIM header ${header}`);
31
36
  }
32
37
 
33
- if (!header.params.d) {
38
+ if (!params.d) {
34
39
  throw new DkimParsingError("DKIM header missing domain");
35
40
  }
36
41
 
37
- if (!header.params.s) {
42
+ if (!params.s) {
38
43
  throw new DkimParsingError("DKIM header missing selector");
39
44
  }
40
-
41
45
  return {
42
- domain: header.params.d,
43
- selector: header.params.s,
46
+ domain: params.d,
47
+ selector: params.s,
44
48
  };
45
49
  }
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from "vitest";
2
2
  import { preverifyEmail } from "./preverify.ts";
3
- import { readFile } from "testHelpers/readFile";
3
+ import { readFile } from "../../testHelpers/readFile";
4
4
 
5
5
  describe("Preverify email: integration", () => {
6
6
  test("adds dns record to email mime", async () => {
@@ -18,14 +18,10 @@ import { foundry } from "viem/chains";
18
18
  import type { ContractSpec, ContractArg } from "types/ethereum";
19
19
 
20
20
  export const testChainId1 = 100001;
21
- export const testChainId2 = 100002;
22
21
 
23
- const rpcUrls: Map<number, HttpTransport> = new Map([
24
- [testChainId1, http()],
25
- [testChainId2, http("http://127.0.0.1:8546")],
26
- ]);
22
+ const rpcUrls: Map<number, HttpTransport> = new Map([[testChainId1, http()]]);
27
23
 
28
- export const chainIds = [testChainId1, testChainId2];
24
+ export const chainIds = [testChainId1];
29
25
 
30
26
  export function client(
31
27
  chainId: number = testChainId1,
@@ -1,6 +1,7 @@
1
1
  import { VlayerClient } from "types/vlayer";
2
- import { WebProofProvider } from "types/webProof";
2
+ import { WebProofProvider } from "types/webProofProvider";
3
3
 
4
+ import { prove } from "../prover";
4
5
  export const createVlayerClient = ({
5
6
  url,
6
7
  webProofProvider,
@@ -8,11 +9,11 @@ export const createVlayerClient = ({
8
9
  url: string;
9
10
  webProofProvider: WebProofProvider;
10
11
  }): VlayerClient => {
12
+ // TODO : implement high level api
13
+ console.log("createVlayerClient with", url, webProofProvider);
11
14
  return {
12
- prove: async () => {
13
- console.log("prove");
14
- console.log("url", url);
15
- console.log("webProofProvider", webProofProvider);
15
+ prove: async ({ address, functionName, chainId, proverAbi, args }) => {
16
+ return prove(address, proverAbi, functionName, args, chainId);
16
17
  },
17
18
  };
18
19
  };
@@ -1,2 +1,5 @@
1
1
  export * from "./ethereum";
2
2
  export * from "./webProof";
3
+ export * from "./utils";
4
+ export * from "./vlayer";
5
+ export * from "./webProofProvider";
@@ -0,0 +1,28 @@
1
+ import { Abi, ContractFunctionName } from "viem";
2
+ import { AbiParametersToPrimitiveTypes, ExtractAbiFunction } from "abitype";
3
+
4
+ type Without<T extends readonly unknown[], P> = T extends readonly [
5
+ infer F,
6
+ ...infer R,
7
+ ]
8
+ ? F extends P
9
+ ? Without<R, P>
10
+ : readonly [F, ...Without<R, P>]
11
+ : [];
12
+
13
+ export type ContractFunctionArgsWithout<
14
+ abi extends Abi,
15
+ functionName extends ContractFunctionName<abi>,
16
+ without,
17
+ > =
18
+ AbiParametersToPrimitiveTypes<
19
+ Without<
20
+ ExtractAbiFunction<abi extends Abi ? abi : Abi, functionName>["inputs"],
21
+ without
22
+ >,
23
+ "inputs"
24
+ > extends infer args
25
+ ? [args] extends [never]
26
+ ? readonly unknown[]
27
+ : args
28
+ : readonly unknown[];
@@ -1,4 +1,14 @@
1
- import { Address, Hex } from "viem";
1
+ import {
2
+ Abi,
3
+ AbiFunction,
4
+ AbiStateMutability,
5
+ Address,
6
+ ContractFunctionArgs,
7
+ ContractFunctionName,
8
+ Hex,
9
+ } from "viem";
10
+
11
+ import { type ProverCallCommitment } from "types/webProofProvider.ts";
2
12
 
3
13
  type Calldata = string;
4
14
 
@@ -30,7 +40,7 @@ export interface Proof {
30
40
  bigint,
31
41
  bigint,
32
42
  ];
33
- commitment: {
43
+ assumptions: {
34
44
  proverContractAddress: Address;
35
45
  functionSelector: Hex;
36
46
  settleBlockHash: Hex;
@@ -51,5 +61,17 @@ export interface VCallResponse {
51
61
 
52
62
  // Add more methods here
53
63
  export type VlayerClient = {
54
- prove: () => void;
64
+ prove: <
65
+ T extends readonly [AbiFunction, ...Abi[number][]],
66
+ F extends ContractFunctionName<T>,
67
+ >(
68
+ args: VlayerClientProveArgs<T, F>,
69
+ ) => void;
70
+ };
71
+
72
+ export type VlayerClientProveArgs<
73
+ T extends readonly [AbiFunction, ...Abi[number][]],
74
+ F extends ContractFunctionName<T>,
75
+ > = ProverCallCommitment<T, F> & {
76
+ args: ContractFunctionArgs<T, AbiStateMutability, F>;
55
77
  };
@@ -1,6 +1,6 @@
1
- //NOTE : this is copied from tlsn-js 5.4
2
- // for some reason newest vertsions doesnt not export this type (clarification is in progress)
3
- // probaly it should be reexported from tlsn-js
1
+ // NOTE : this is copied from tlsn-js 5.4
2
+ // for some reason newest versions doesn't export this type (clarification is in progress)
3
+ // probably it should be reexported from tlsn-js
4
4
 
5
5
  export interface WebProof {
6
6
  session: Session;
@@ -100,7 +100,12 @@ export interface Range {
100
100
  start: number;
101
101
  end: number;
102
102
  }
103
-
104
- export type WebProofProvider = {
105
- requestProof: (url: string) => Promise<WebProof>;
103
+ export const assertWebProof = function (candidate: {
104
+ notaryUrl?: string;
105
+ }): asserts candidate is WebProof {
106
+ //for now only thing we check is notary url
107
+ //TODO: implement later once we known the conteact with tlsn-js
108
+ if (!candidate.notaryUrl) {
109
+ throw new Error("Missing required parameter");
110
+ }
106
111
  };
@@ -0,0 +1,93 @@
1
+ import { WebProof } from "types/webProof.ts";
2
+ import { AbiFunction, Hex, Abi, ContractFunctionName } from "viem";
3
+ import { Branded } from "types/utils.ts";
4
+ import type { ContractFunctionArgsWithout } from "./viem";
5
+
6
+ export const EXTENSION_STEP = {
7
+ expectUrl: "expectUrl",
8
+ startPage: "startPage",
9
+ notarize: "notarize",
10
+ } as const;
11
+
12
+ export const EXTENSION_ACTION = {
13
+ requestWebProof: "requestWebProof",
14
+ } as const;
15
+
16
+ export const EXTENSION_MESSAGE = {
17
+ proofDone: "proofDone",
18
+ proofError: "proofError",
19
+ } as const;
20
+
21
+ export type ExtensionStep =
22
+ (typeof EXTENSION_STEP)[keyof typeof EXTENSION_STEP];
23
+
24
+ export type WebProofStepNotarize = Branded<
25
+ {
26
+ url: string;
27
+ method: string;
28
+ label: string;
29
+ step: typeof EXTENSION_STEP.notarize;
30
+ },
31
+ "notarize"
32
+ >;
33
+
34
+ export type WebProofStepExpectUrl = Branded<
35
+ {
36
+ url: string;
37
+ label: string;
38
+ step: typeof EXTENSION_STEP.expectUrl;
39
+ },
40
+ "expectUrl"
41
+ >;
42
+
43
+ export type WebProofStepStartPage = Branded<
44
+ {
45
+ url: string;
46
+ label: string;
47
+ step: typeof EXTENSION_STEP.startPage;
48
+ },
49
+ "startPage"
50
+ >;
51
+
52
+ export type WebProofSetupInput = {
53
+ logoUrl: string;
54
+ steps: [WebProofStepExpectUrl, WebProofStepStartPage, WebProofStepStartPage];
55
+ };
56
+
57
+ export type WebProofSetup = Branded<
58
+ WebProofSetupInput & {
59
+ isWebProof: true;
60
+ },
61
+ "webProof"
62
+ >;
63
+
64
+ export type ProverCallCommitment<
65
+ T extends readonly [AbiFunction, ...Abi[number][]],
66
+ F extends ContractFunctionName<T>,
67
+ > = {
68
+ address: Hex;
69
+ proverAbi: T;
70
+ functionName: F;
71
+ commitmentArgs: ContractFunctionArgsWithout<T, F, { name: "webProof" }>;
72
+ chainId: number;
73
+ };
74
+ export type GetWebProofArgs<
75
+ T extends readonly [AbiFunction, ...Abi[number][]],
76
+ F extends ContractFunctionName<T>,
77
+ > = {
78
+ proverCallCommitment: ProverCallCommitment<T, F>;
79
+ } & WebProofSetupInput;
80
+
81
+ export type WebProofProvider = {
82
+ getWebProof: <
83
+ T extends readonly [AbiFunction, ...Abi[number][]],
84
+ F extends ContractFunctionName<T>,
85
+ >(
86
+ args: GetWebProofArgs<T, F>,
87
+ ) => Promise<WebProof>;
88
+ };
89
+
90
+ export type WebProofProviderSetup = {
91
+ notaryUrl?: string;
92
+ wsProxyUrl?: string;
93
+ };
package/src/api/prover.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  encodeFunctionData,
10
10
  } from "viem";
11
11
 
12
- import { type CallContext, type CallParams, Proof } from "types/vlayer";
12
+ import { type CallContext, type CallParams } from "types/vlayer";
13
13
  import { v_call } from "./v_call";
14
14
  import { testChainId1 } from "./helpers";
15
15
  import { ContractSpec } from "types/ethereum";
@@ -43,31 +43,12 @@ export async function prove<
43
43
  result: { proof, evm_call_result },
44
44
  } = await v_call(call, context);
45
45
 
46
- const returnValue = decodeFunctionResult({
46
+ const [, ...returnValue] = decodeFunctionResult({
47
47
  abi: abi as Abi,
48
48
  data: evm_call_result,
49
49
  functionName: functionName as string,
50
- });
51
-
52
- addDynamicParamsOffsets(abi, functionName, proof);
53
-
54
- return { proof, returnValue: returnValue as `0x${string}`[] };
55
- }
56
-
57
- function addDynamicParamsOffsets(
58
- abi: Abi,
59
- functionName: string | undefined,
60
- proof: Proof,
61
- ) {
62
- const proverFunction = abi.find(
63
- (f) => f.type === "function" && f.name === functionName,
64
- ) as AbiFunction;
65
-
66
- if (proverFunction?.outputs && proverFunction.outputs.length > 0) {
67
- const secondVerifyMethodParamType = proverFunction.outputs[0].type;
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ }) as any[];
68
52
 
69
- if (secondVerifyMethodParamType === "string") {
70
- proof.dynamicParamsOffsets[0] = BigInt(32);
71
- }
72
- }
53
+ return { proof, returnValue };
73
54
  }
@@ -0,0 +1,9 @@
1
+ import { WebProofSetup, WebProofSetupInput } from "types/webProofProvider.ts";
2
+
3
+ export const createWebProof = ({ logoUrl, steps }: WebProofSetupInput) => {
4
+ return {
5
+ logoUrl,
6
+ steps,
7
+ isWebProof: true,
8
+ } as WebProofSetup;
9
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./createWebProof";
2
+ export * from "./steps";
3
+ export * from "./providers";
@@ -0,0 +1,73 @@
1
+ import {
2
+ EXTENSION_ACTION,
3
+ EXTENSION_MESSAGE,
4
+ type WebProofProvider,
5
+ type WebProofProviderSetup,
6
+ type WebProofSetupInput,
7
+ } from "../../lib/types/webProofProvider";
8
+
9
+ import { WebProof } from "../../lib/types/webProof";
10
+
11
+ // NOTE @types/chrome and webextension-polyfill work only in the extension context
12
+ // and looks that there is no community driven package providing typings for chrome.runtime
13
+ // or polyfill logic for the browser APIs available in the browser context
14
+ // we intentionally use chrome here instead of browser as we support only chrome for now
15
+ // and there could be some differences in the API between browsers
16
+
17
+ declare const chrome: {
18
+ runtime: {
19
+ sendMessage: (extensionId: string | undefined, message: unknown) => void;
20
+ connect: (extensionId: string) => {
21
+ onMessage: {
22
+ addListener: (message: unknown) => void;
23
+ };
24
+ };
25
+ };
26
+ };
27
+
28
+ export const createExtensionWebProofProvider = ({
29
+ notaryUrl = "https://notary.pse.dev/v0.1.0-alpha.5/",
30
+ wsProxyUrl = "wss://notary.pse.dev/proxy",
31
+ }: WebProofProviderSetup): WebProofProvider => {
32
+ return {
33
+ getWebProof: async function (webProofSetup: WebProofSetupInput) {
34
+ // TODO: we cant assume that developer is using vite
35
+ // EXTESION_ID value should be injected by the build system
36
+
37
+ return new Promise<WebProof>((resolve, reject) => {
38
+ chrome.runtime.sendMessage(import.meta.env.VITE_EXTENSION_ID, {
39
+ action: EXTENSION_ACTION.requestWebProof,
40
+ payload: {
41
+ notaryUrl,
42
+ wsProxyUrl,
43
+ logoUrl: webProofSetup.logoUrl,
44
+ steps: webProofSetup.steps,
45
+ },
46
+ });
47
+ const EXTENSION_ID = import.meta.env.VITE_EXTENSION_ID as string;
48
+ const port = chrome.runtime.connect(EXTENSION_ID);
49
+ //TODO : validate message in runtime
50
+ port.onMessage.addListener(
51
+ (
52
+ message:
53
+ | {
54
+ type: typeof EXTENSION_MESSAGE.proofDone;
55
+ proof: WebProof;
56
+ }
57
+ | {
58
+ type: typeof EXTENSION_MESSAGE.proofError;
59
+ error: { message: string };
60
+ },
61
+ ) => {
62
+ if (message.type === EXTENSION_MESSAGE.proofDone) {
63
+ resolve(message.proof);
64
+ }
65
+ if (message.type === EXTENSION_MESSAGE.proofError) {
66
+ reject(message.error);
67
+ }
68
+ },
69
+ );
70
+ });
71
+ },
72
+ };
73
+ };
@@ -0,0 +1 @@
1
+ export * from "./extension";
@@ -0,0 +1,12 @@
1
+ import {
2
+ EXTENSION_STEP,
3
+ WebProofStepExpectUrl,
4
+ } from "../../../api/lib/types/webProofProvider";
5
+
6
+ export const expectUrl = (url: string, label: string) => {
7
+ return {
8
+ url,
9
+ label,
10
+ step: EXTENSION_STEP.expectUrl,
11
+ } as WebProofStepExpectUrl;
12
+ };
@@ -0,0 +1,11 @@
1
+ import { expectUrl } from "./expectUrl.ts";
2
+ import { startPage } from "./startPage.ts";
3
+ import { notarize } from "./notarize.ts";
4
+
5
+ const steps = {
6
+ expectUrl,
7
+ startPage,
8
+ notarize,
9
+ };
10
+
11
+ export { expectUrl, startPage, notarize, steps };
@@ -0,0 +1,17 @@
1
+ import {
2
+ EXTENSION_STEP,
3
+ WebProofStepNotarize,
4
+ } from "../../../api/lib/types/webProofProvider";
5
+
6
+ export const notarize = (
7
+ url: string,
8
+ method: string = "GET",
9
+ label: string,
10
+ ) => {
11
+ return {
12
+ url,
13
+ method,
14
+ label,
15
+ step: EXTENSION_STEP.notarize,
16
+ } as WebProofStepNotarize;
17
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ EXTENSION_STEP,
3
+ WebProofStepStartPage,
4
+ } from "../../../api/lib/types/webProofProvider";
5
+
6
+ export const startPage = (url: string, label: string) => {
7
+ return {
8
+ url,
9
+ label,
10
+ step: EXTENSION_STEP.startPage,
11
+ } as WebProofStepStartPage;
12
+ };
package/src/index.ts CHANGED
@@ -6,3 +6,6 @@ export { getContractSpec, prove } from "./api/prover";
6
6
  export * as testHelpers from "./api/helpers";
7
7
  export { client as createTestClient } from "./api/helpers";
8
8
  export { preverifyEmail } from "./api/email/preverify.ts";
9
+
10
+ export * from "./api/webProof";
11
+ export * from "./api/lib/types";