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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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";