@vlayer/sdk 0.1.0-nightly-20241028-74b5b0d → 0.1.0-nightly-202410292-42360cf

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. package/dist/api/email/dnsResolver.d.ts +1 -0
  2. package/dist/api/email/dnsResolver.js +6 -0
  3. package/dist/api/email/dnsResolver.test.d.ts +1 -0
  4. package/dist/api/email/dnsResolver.test.js +12 -0
  5. package/dist/api/email/parseEmail.d.ts +10 -0
  6. package/dist/api/email/parseEmail.js +38 -0
  7. package/dist/api/email/parseEmail.test.d.ts +1 -0
  8. package/dist/api/email/parseEmail.test.js +91 -0
  9. package/dist/api/email/preverify.d.ts +4 -0
  10. package/dist/api/email/preverify.js +18 -0
  11. package/dist/api/email/preverify.test.d.ts +1 -0
  12. package/dist/api/email/preverify.test.js +25 -0
  13. package/dist/api/helpers.d.ts +38 -0
  14. package/dist/api/helpers.js +72 -0
  15. package/dist/api/lib/client.d.ts +6 -0
  16. package/dist/api/lib/client.js +45 -0
  17. package/dist/api/lib/types/ethereum.d.ts +14 -0
  18. package/dist/api/lib/types/ethereum.js +12 -0
  19. package/dist/api/lib/types/index.js +3 -0
  20. package/dist/api/lib/types/viem.d.ts +8 -0
  21. package/dist/api/lib/types/viem.js +1 -0
  22. package/dist/api/lib/types/vlayer.d.ts +47 -0
  23. package/dist/api/lib/types/vlayer.js +1 -0
  24. package/dist/api/lib/types/webProofProvider.d.ts +29 -0
  25. package/dist/api/lib/types/webProofProvider.js +1 -0
  26. package/dist/api/prover.d.ts +2 -0
  27. package/dist/api/prover.js +15 -0
  28. package/dist/api/v_call.d.ts +2 -0
  29. package/dist/api/v_call.js +30 -0
  30. package/dist/api/webProof/createWebProof.d.ts +2 -0
  31. package/dist/api/webProof/createWebProof.js +7 -0
  32. package/dist/api/webProof/index.js +3 -0
  33. package/dist/api/webProof/providers/extension.d.ts +2 -0
  34. package/dist/api/webProof/providers/extension.js +32 -0
  35. package/dist/api/webProof/providers/index.js +1 -0
  36. package/dist/api/webProof/steps/expectUrl.d.ts +2 -0
  37. package/dist/api/webProof/steps/expectUrl.js +8 -0
  38. package/dist/api/webProof/steps/index.d.ts +9 -0
  39. package/dist/api/webProof/steps/index.js +9 -0
  40. package/dist/api/webProof/steps/notarize.d.ts +2 -0
  41. package/dist/api/webProof/steps/notarize.js +9 -0
  42. package/dist/api/webProof/steps/startPage.d.ts +2 -0
  43. package/dist/api/webProof/steps/startPage.js +8 -0
  44. package/dist/index.d.ts +7 -0
  45. package/dist/index.js +7 -0
  46. package/dist/testHelpers/readFile.d.ts +1 -0
  47. package/dist/testHelpers/readFile.js +2 -0
  48. package/dist/web-proof-commons/index.d.ts +3 -0
  49. package/dist/web-proof-commons/index.js +3 -0
  50. package/dist/web-proof-commons/types/message.d.ts +56 -0
  51. package/dist/web-proof-commons/types/message.js +5 -0
  52. package/dist/web-proof-commons/types/webProof.d.ts +86 -0
  53. package/dist/web-proof-commons/types/webProof.js +10 -0
  54. package/dist/web-proof-commons/utils.d.ts +7 -0
  55. package/dist/web-proof-commons/utils.js +5 -0
  56. package/package.json +16 -7
  57. package/.changeset/config.json +0 -11
  58. package/CHANGELOG.md +0 -7
  59. package/eslint.config.ts +0 -22
  60. package/src/api/email/dnsResolver.test.ts +0 -18
  61. package/src/api/email/dnsResolver.ts +0 -7
  62. package/src/api/email/parseEmail.test.ts +0 -133
  63. package/src/api/email/parseEmail.ts +0 -49
  64. package/src/api/email/preverify.test.ts +0 -37
  65. package/src/api/email/preverify.ts +0 -19
  66. package/src/api/email/testdata/test_email.txt +0 -21
  67. package/src/api/email/testdata/test_email_multiple_dkims.txt +0 -28
  68. package/src/api/email/testdata/test_email_unknown_domain.txt +0 -21
  69. package/src/api/helpers.ts +0 -173
  70. package/src/api/lib/client.ts +0 -76
  71. package/src/api/lib/types/ethereum.ts +0 -43
  72. package/src/api/lib/types/viem.ts +0 -28
  73. package/src/api/lib/types/vlayer.ts +0 -60
  74. package/src/api/lib/types/webProofProvider.ts +0 -44
  75. package/src/api/prover.ts +0 -34
  76. package/src/api/v_call.ts +0 -45
  77. package/src/api/webProof/createWebProof.ts +0 -9
  78. package/src/api/webProof/providers/extension.ts +0 -72
  79. package/src/api/webProof/steps/expectUrl.ts +0 -12
  80. package/src/api/webProof/steps/index.ts +0 -11
  81. package/src/api/webProof/steps/notarize.ts +0 -17
  82. package/src/api/webProof/steps/startPage.ts +0 -12
  83. package/src/index.ts +0 -9
  84. package/src/testHelpers/readFile.ts +0 -3
  85. package/src/web-proof-commons/index.ts +0 -3
  86. package/src/web-proof-commons/types/message.ts +0 -73
  87. package/src/web-proof-commons/types/webProof.ts +0 -111
  88. package/src/web-proof-commons/utils.ts +0 -12
  89. package/tsconfig.json +0 -24
  90. package/vite.config.ts +0 -7
  91. /package/{src/api/lib/types/index.ts → dist/api/lib/types/index.d.ts} +0 -0
  92. /package/{src/api/webProof/index.ts → dist/api/webProof/index.d.ts} +0 -0
  93. /package/{src/api/webProof/providers/index.ts → dist/api/webProof/providers/index.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ export declare function resolveDkimDns(domain: string, selector: string): Promise<string>;
@@ -0,0 +1,6 @@
1
+ import DnsResolver from "dns-over-http-resolver";
2
+ export async function resolveDkimDns(domain, selector) {
3
+ const resolver = new DnsResolver();
4
+ const address = await resolver.resolveTxt(`${selector}._domainkey.${domain}`);
5
+ return address.flat()[0];
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { resolveDkimDns } from "./dnsResolver";
3
+ describe("resolveDkimDns Integration", () => {
4
+ test("resolves VLayer DNS", async () => {
5
+ const resolved = await resolveDkimDns("vlayer-xyz.20230601.gappssmtp.com", "20230601");
6
+ const expected = "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3gWcOhCm99qzN+h7/2+LeP3CLsJkQQ4EP/2mrceXle5pKq8uZmBl1U4d2Vxn4w+pWFANDLmcHolLboESLFqEL5N6ae7u9b236dW4zn9AFkXAGenTzQEeif9VUFtLAZ0Qh2eV7OQgz/vPj5IaNqJ7h9hpM9gO031fe4v+J0DLCE8Rgo7hXbNgJavctc0983DaCDQaznHZ44LZ6TtZv9TBs+QFvsy4+UCTfsuOtHzoEqOOuXsVXZKLP6B882XbEnBpXEF8QzV4J26HiAJFUbO3mAqZL2UeKC0hhzoIZqZXNG0BfuzOF0VLpDa18GYMUiu+LhEJPJO9D8zhzvQIHNrpGwIDAQAB";
7
+ expect(resolved).toBe(expected);
8
+ });
9
+ test("throws error if dns not found", async () => {
10
+ await expect(resolveDkimDns("not-a-domain.com", "abcd")).rejects.toThrow();
11
+ });
12
+ });
@@ -0,0 +1,10 @@
1
+ import { Email } from "postal-mime";
2
+ export declare class DkimParsingError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare function parseEmail(mime: string): Promise<Email>;
6
+ export declare function getDkimSigners(mail: Email): {
7
+ domain: string;
8
+ selector: string;
9
+ }[];
10
+ export declare function parseParams(str: string): Record<string, string>;
@@ -0,0 +1,38 @@
1
+ import PostalMime from "postal-mime";
2
+ export class DkimParsingError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "DkimParsingError";
6
+ }
7
+ }
8
+ export async function parseEmail(mime) {
9
+ return await PostalMime.parse(mime.trim());
10
+ }
11
+ export function getDkimSigners(mail) {
12
+ const dkimHeader = mail.headers.filter((h) => h.key === "dkim-signature");
13
+ if (dkimHeader.length === 0)
14
+ throw new DkimParsingError("No DKIM header found");
15
+ return dkimHeader.map(parseHeader);
16
+ }
17
+ export function parseParams(str) {
18
+ return Object.fromEntries(str.split(";").map((s) => s
19
+ .trim()
20
+ .split("=")
21
+ .map((v) => v && v.trim())));
22
+ }
23
+ function parseHeader(header) {
24
+ const params = parseParams(header.value);
25
+ if (!params) {
26
+ throw new DkimParsingError(`Invalid DKIM header ${header.value}`);
27
+ }
28
+ if (!params.d) {
29
+ throw new DkimParsingError("DKIM header missing domain");
30
+ }
31
+ if (!params.s) {
32
+ throw new DkimParsingError("DKIM header missing selector");
33
+ }
34
+ return {
35
+ domain: params.d,
36
+ selector: params.s,
37
+ };
38
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,91 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { getDkimSigners, parseEmail, parseParams } from "./parseEmail";
3
+ const emailHeaders = `From: "John Doe" <john@d.oe>
4
+ To: "Jane Doe" <jane@d.oe>
5
+ Subject: Hello World
6
+ Date: Thu, 1 Jan 1970 00:00:00 +0000
7
+ `;
8
+ const dkimHeader = "DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; h=from:to:subject; s=selector1; b=abcdef;";
9
+ const body = "Hello, World!";
10
+ const emailFixture = `${emailHeaders}${dkimHeader}\n\n${body}`;
11
+ describe("parseEmail", () => {
12
+ test("should get dkim header from email", async () => { });
13
+ test("correctly parses untrimmed email", async () => {
14
+ const untrimmed = `\n ${emailFixture} \n`;
15
+ const email = await parseEmail(untrimmed);
16
+ expect(email.headers.find((h) => h.key === "dkim-signature")).toBeDefined();
17
+ });
18
+ test("works well with multiple dkim headers", async () => {
19
+ const dkimHeader2 = "DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=second.signer; h=from:to:subject; s=selector2; b=abcdef;";
20
+ const email = await parseEmail(`${emailHeaders}${dkimHeader}\n${dkimHeader2}\n\n${body}`);
21
+ const dkim = email.headers.filter((h) => h.key === "dkim-signature");
22
+ expect(dkim).toHaveLength(2);
23
+ expect(parseParams(dkim[0].value).s).toBe("selector1");
24
+ expect(parseParams(dkim[1].value).s).toBe("selector2");
25
+ });
26
+ });
27
+ describe("getDkimSigners", () => {
28
+ test("should get dkim signers from email", async () => {
29
+ const email = await parseEmail(emailFixture);
30
+ const dkim = getDkimSigners(email);
31
+ expect(dkim).toHaveLength(1);
32
+ expect(dkim[0].domain).toBe("example.com");
33
+ expect(dkim[0].selector).toBe("selector1");
34
+ });
35
+ test("should get multiple dkim signers from email", async () => {
36
+ const dkimHeader2 = "DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=second.signer; h=from:to:subject; s=selector2; b=abcdef;";
37
+ const email = await parseEmail(`${emailHeaders}${dkimHeader}\n${dkimHeader2}\n\n${body}`);
38
+ const dkim = getDkimSigners(email);
39
+ expect(dkim).toHaveLength(2);
40
+ expect(dkim[0].domain).toBe("example.com");
41
+ expect(dkim[0].selector).toBe("selector1");
42
+ expect(dkim[1].domain).toBe("second.signer");
43
+ expect(dkim[1].selector).toBe("selector2");
44
+ });
45
+ test("should throw if no dkim header found", async () => {
46
+ const email = await parseEmail(emailHeaders);
47
+ expect(() => getDkimSigners(email)).toThrowError("No DKIM header found");
48
+ });
49
+ test("should throw if dkim header is invalid", async () => {
50
+ const email = await parseEmail(`${emailHeaders}DKIM-Signature: invalid\n\n${body}`);
51
+ expect(() => getDkimSigners(email)).toThrowError("DKIM header missing domain");
52
+ });
53
+ test("should throw if dkim header is missing domain", async () => {
54
+ const email = await parseEmail(`${emailHeaders}DKIM-Signature: v=1; s=selector\n\n${body}`);
55
+ expect(() => getDkimSigners(email)).toThrowError("DKIM header missing domain");
56
+ });
57
+ test("should throw if dkim header is missing selector", async () => {
58
+ const email = await parseEmail(`${emailHeaders}DKIM-Signature: v=1; d=example.com\n\n${body}`);
59
+ expect(() => getDkimSigners(email)).toThrowError("DKIM header missing selector");
60
+ });
61
+ });
62
+ describe("parseParams", () => {
63
+ test("should parse single parameter", () => {
64
+ const params = parseParams("a=b");
65
+ expect(params).toEqual({ a: "b" });
66
+ });
67
+ test("should parse multiple parameters", () => {
68
+ const params = parseParams("a=b; c=d; e=f");
69
+ expect(params).toEqual({ a: "b", c: "d", e: "f" });
70
+ });
71
+ test("should trim spaces around parameters", () => {
72
+ const params = parseParams(" a = b ; c = d ; e = f ");
73
+ expect(params).toEqual({ a: "b", c: "d", e: "f" });
74
+ });
75
+ test("should handle empty values", () => {
76
+ const params = parseParams("a=; b=c");
77
+ expect(params).toEqual({ a: "", b: "c" });
78
+ });
79
+ test("should handle missing values", () => {
80
+ const params = parseParams("a; b=c");
81
+ expect(params).toEqual({ a: undefined, b: "c" });
82
+ });
83
+ test("should handle empty string", () => {
84
+ const params = parseParams("");
85
+ expect(params).toEqual({});
86
+ });
87
+ test("should handle parameters with extra semicolons", () => {
88
+ const params = parseParams("a=b;; c=d;");
89
+ expect(params).toEqual({ a: "b", c: "d" });
90
+ });
91
+ });
@@ -0,0 +1,4 @@
1
+ export declare function preverifyEmail(mimeEmail: string): Promise<{
2
+ email: string;
3
+ dnsRecords: string[];
4
+ }>;
@@ -0,0 +1,18 @@
1
+ import { parseEmail, getDkimSigners } from "./parseEmail";
2
+ import { resolveDkimDns } from "./dnsResolver";
3
+ export async function preverifyEmail(mimeEmail) {
4
+ const parsedEmail = await parseEmail(mimeEmail);
5
+ const signers = getDkimSigners(parsedEmail);
6
+ if (signers.length === 0) {
7
+ throw new Error("No DKIM header found");
8
+ }
9
+ if (signers.length > 1) {
10
+ throw new Error("Multiple DKIM headers found");
11
+ }
12
+ const [{ domain, selector }] = signers;
13
+ const dnsRecord = await resolveDkimDns(domain, selector);
14
+ return {
15
+ email: mimeEmail,
16
+ dnsRecords: [dnsRecord],
17
+ };
18
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { preverifyEmail } from "./preverify";
3
+ import { readFile } from "../../testHelpers/readFile";
4
+ describe("Preverify email: integration", () => {
5
+ test("adds dns record to email mime", async () => {
6
+ const rawEmail = readFile("./src/api/email/testdata/test_email.txt");
7
+ const preverifiedEmail = await preverifyEmail(rawEmail);
8
+ expect(preverifiedEmail).toMatchObject({
9
+ email: rawEmail,
10
+ dnsRecords: [expect.stringContaining("v=DKIM1; k=rsa; p=")],
11
+ });
12
+ });
13
+ test("throws error if DKIM not found", async () => {
14
+ const emailWithNoDkimHeader = 'From: "Alice"\n\nBody';
15
+ await expect(preverifyEmail(emailWithNoDkimHeader)).rejects.toThrow("No DKIM header found");
16
+ });
17
+ test("throws error if DNS could not be resolved", async () => {
18
+ const emailWithNoDkimHeader = readFile("./src/api/email/testdata/test_email_unknown_domain.txt");
19
+ await expect(preverifyEmail(emailWithNoDkimHeader)).rejects.toThrow();
20
+ });
21
+ test("throws error if multiple DNS records found", async () => {
22
+ const emailWithNoDkimHeader = readFile("./src/api/email/testdata/test_email_multiple_dkims.txt");
23
+ await expect(preverifyEmail(emailWithNoDkimHeader)).rejects.toThrow("Multiple DKIM headers found");
24
+ });
25
+ });
@@ -0,0 +1,38 @@
1
+ import { type Abi, type Address, type Chain, type ContractFunctionArgs, type ContractFunctionName, type Hex, PublicClient, walletActions } from "viem";
2
+ import type { ContractSpec, ContractArg } from "types/ethereum";
3
+ export declare const chainIds: 31337[];
4
+ export declare function createAnvilClient(chainId?: number): ReturnType<typeof walletActions> & PublicClient;
5
+ export declare function deployContract(contractSpec: ContractSpec, args?: ContractArg[], chainId?: number): Promise<Address>;
6
+ type DeploySpec<T extends Abi> = {
7
+ abi: T;
8
+ bytecode: {
9
+ object: Hex;
10
+ };
11
+ };
12
+ type Tail<T> = T extends readonly [unknown, ...infer U] ? U : [];
13
+ export declare function deployProverVerifier<P extends Abi, V extends Abi>(proverSpec: DeploySpec<P>, verifierSpec: DeploySpec<V>, args?: {
14
+ prover?: ContractArg[];
15
+ verifier?: Tail<ContractArg>[];
16
+ }, chainId?: number): Promise<`0x${string}`[]>;
17
+ export declare function call<T extends Abi, F extends ContractFunctionName<T, "pure" | "view">>(abi: T, address: Address, functionName: F, args?: ContractFunctionArgs<T, "pure" | "view", F>, chainId?: number): Promise<import("viem").ContractFunctionReturnType<T, "pure" | "view", F, ContractFunctionArgs<T, "pure" | "view", F>>>;
18
+ export declare function writeContract<T extends Abi, F extends ContractFunctionName<T, "payable" | "nonpayable">>(address: Address, abi: T, functionName: F, args: ContractFunctionArgs<T, "payable" | "nonpayable", F>, sender?: Address, chain?: Chain): Promise<import("viem").TransactionReceipt>;
19
+ export declare const getTestAccount: () => {
20
+ address: Address;
21
+ nonceManager?: import("viem").NonceManager | undefined;
22
+ sign: (parameters: {
23
+ hash: import("viem").Hash;
24
+ }) => Promise<Hex>;
25
+ experimental_signAuthorization: (parameters: import("viem/experimental").Authorization) => Promise<import("viem/accounts").SignAuthorizationReturnType>;
26
+ signMessage: ({ message }: {
27
+ message: import("viem").SignableMessage;
28
+ }) => Promise<Hex>;
29
+ signTransaction: <serializer extends import("viem").SerializeTransactionFn<import("viem").TransactionSerializable> = import("viem").SerializeTransactionFn<import("viem").TransactionSerializable>, transaction extends Parameters<serializer>[0] = Parameters<serializer>[0]>(transaction: transaction, options?: {
30
+ serializer?: serializer | undefined;
31
+ } | undefined) => Promise<import("viem").IsNarrowable<import("viem").TransactionSerialized<import("viem").GetTransactionType<transaction>>, Hex> extends true ? import("viem").TransactionSerialized<import("viem").GetTransactionType<transaction>> : Hex>;
32
+ signTypedData: <const typedData extends import("viem").TypedData | Record<string, unknown>, primaryType extends keyof typedData | "EIP712Domain" = keyof typedData>(parameters: import("viem").TypedDataDefinition<typedData, primaryType>) => Promise<Hex>;
33
+ publicKey: Hex;
34
+ source: "privateKey";
35
+ type: "local";
36
+ };
37
+ export declare const getTestAddresses: (chainId?: number) => Promise<Address[]>;
38
+ export {};
@@ -0,0 +1,72 @@
1
+ import { createTestClient, http, publicActions, walletActions, } from "viem";
2
+ import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
3
+ import { foundry } from "viem/chains";
4
+ const rpcUrls = new Map([[foundry.id, http()]]);
5
+ export const chainIds = [foundry.id];
6
+ export function createAnvilClient(chainId = foundry.id) {
7
+ const transport = rpcUrls.get(chainId);
8
+ if (transport == undefined) {
9
+ throw Error(`No url for chainId ${chainId}`);
10
+ }
11
+ return createTestClient({
12
+ chain: foundry,
13
+ mode: "anvil",
14
+ transport: transport,
15
+ })
16
+ .extend(publicActions)
17
+ .extend(walletActions);
18
+ }
19
+ export async function deployContract(contractSpec, args = [], chainId = foundry.id) {
20
+ const ethClient = createAnvilClient(chainId);
21
+ const [deployer] = await ethClient.getAddresses();
22
+ const txHash = await ethClient.deployContract({
23
+ abi: contractSpec.abi,
24
+ bytecode: contractSpec.bytecode.object,
25
+ account: deployer,
26
+ args,
27
+ chain: foundry,
28
+ });
29
+ const receipt = await ethClient.waitForTransactionReceipt({ hash: txHash });
30
+ if (receipt.status != "success") {
31
+ throw new Error(`Contract deployment failed with status: ${receipt.status}`);
32
+ }
33
+ return receipt.contractAddress;
34
+ }
35
+ export async function deployProverVerifier(proverSpec, verifierSpec, args = {}, chainId = foundry.id) {
36
+ console.log("Deploying prover");
37
+ const proverAddress = await deployContract(proverSpec, args.prover ?? [], chainId);
38
+ console.log(`Prover has been deployed on ${proverAddress} address`);
39
+ console.log("Deploying verifier");
40
+ const verifierAddress = await deployContract(verifierSpec, [proverAddress, ...(args.verifier ?? [])], chainId);
41
+ console.log(`Verifier has been deployed on ${verifierAddress} address`);
42
+ return [proverAddress, verifierAddress];
43
+ }
44
+ export async function call(abi, address, functionName, args, chainId = foundry.id) {
45
+ const ethClient = createAnvilClient(chainId);
46
+ return ethClient.readContract({
47
+ abi,
48
+ address,
49
+ functionName,
50
+ args,
51
+ });
52
+ }
53
+ export async function writeContract(address, abi, functionName, args, sender, chain = foundry) {
54
+ const ethClient = createAnvilClient(chain.id);
55
+ const selectedSender = sender || (await ethClient.getAddresses())[0];
56
+ const txHash = await ethClient.writeContract({
57
+ address,
58
+ abi: abi,
59
+ functionName,
60
+ args: args,
61
+ chain,
62
+ account: selectedSender,
63
+ chainOverride: undefined,
64
+ });
65
+ const txReceipt = await ethClient.waitForTransactionReceipt({ hash: txHash });
66
+ if (txReceipt.status != "success") {
67
+ throw new Error(`Transaction failed with status: ${txReceipt.status}`);
68
+ }
69
+ return txReceipt;
70
+ }
71
+ export const getTestAccount = () => privateKeyToAccount(generatePrivateKey());
72
+ export const getTestAddresses = (chainId = foundry.id) => createAnvilClient(chainId).getAddresses();
@@ -0,0 +1,6 @@
1
+ import { VlayerClient } from "types/vlayer";
2
+ import { WebProofProvider } from "types/webProofProvider";
3
+ export declare const createVlayerClient: ({ url, webProofProvider, }?: {
4
+ url?: string;
5
+ webProofProvider?: WebProofProvider;
6
+ }) => VlayerClient;
@@ -0,0 +1,45 @@
1
+ import { prove } from "../prover";
2
+ import { createExtensionWebProofProvider } from "../webProof";
3
+ import { decodeFunctionResult } from "viem";
4
+ function dropEmptyProofFromArgs(args) {
5
+ if (Array.isArray(args)) {
6
+ return args.slice(1);
7
+ }
8
+ return [];
9
+ }
10
+ function generateRandomHash() {
11
+ let hash = "0x";
12
+ for (let i = 0; i < 40; ++i) {
13
+ hash += Math.floor(Math.random() * 16).toString(16);
14
+ }
15
+ return hash;
16
+ }
17
+ export const createVlayerClient = ({ url = "http://127.0.0.1:3000", webProofProvider = createExtensionWebProofProvider(), } = {
18
+ url: "http://127.0.0.1:3000",
19
+ webProofProvider: createExtensionWebProofProvider(),
20
+ }) => {
21
+ console.log("createVlayerClient with", url, webProofProvider);
22
+ const resultHashMap = new Map();
23
+ return {
24
+ // eslint-disable-next-line @typescript-eslint/require-await
25
+ prove: async ({ address, functionName, chainId, proverAbi, args }) => {
26
+ const result_promise = prove(address, proverAbi, functionName, args, chainId, url);
27
+ const hash = generateRandomHash();
28
+ resultHashMap.set(hash, [result_promise, proverAbi, functionName]);
29
+ return { hash };
30
+ },
31
+ waitForProvingResult: async ({ hash }) => {
32
+ const savedProvingData = resultHashMap.get(hash);
33
+ if (!savedProvingData) {
34
+ throw new Error("No result found for hash " + hash);
35
+ }
36
+ const { result: { proof, evm_call_result }, } = await savedProvingData[0];
37
+ const result = dropEmptyProofFromArgs(decodeFunctionResult({
38
+ abi: savedProvingData[1],
39
+ data: evm_call_result,
40
+ functionName: savedProvingData[2],
41
+ }));
42
+ return [proof, ...result];
43
+ },
44
+ };
45
+ };
@@ -0,0 +1,14 @@
1
+ import { Abi, Address, Hex } from "viem";
2
+ import { Branded } from "../../../web-proof-commons";
3
+ export type Bytecode = {
4
+ object: Hex;
5
+ };
6
+ export type ContractSpec = {
7
+ abi: Abi;
8
+ bytecode: Bytecode;
9
+ };
10
+ export type ContractArg = number | string | boolean | bigint | number[] | string[] | boolean[] | bigint[] | Address[];
11
+ export type EthereumAddress = Branded<Hex, "EthereumAddress">;
12
+ export type EthereumTxHash = Branded<Hex, "EthereumTxHash">;
13
+ export declare function assertEthereumAddress(hash: string): asserts hash is EthereumAddress;
14
+ export declare function assertEthereumTxHash(hash: string): asserts hash is EthereumTxHash;
@@ -0,0 +1,12 @@
1
+ export function assertEthereumAddress(hash) {
2
+ const regex = /^(0x)?[0-9a-fA-F]{40}$/;
3
+ if (!regex.test(hash)) {
4
+ throw new Error(`Invalid ethereum account ${hash}`);
5
+ }
6
+ }
7
+ export function assertEthereumTxHash(hash) {
8
+ const regex = /^(0x)?[0-9a-fA-F]{64}$/;
9
+ if (!regex.test(hash)) {
10
+ throw new Error(`Invalid ethereum tx hash ${hash}`);
11
+ }
12
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./ethereum";
2
+ export * from "./vlayer";
3
+ export * from "./webProofProvider";
@@ -0,0 +1,8 @@
1
+ import { Abi, ContractFunctionName } from "viem";
2
+ import { AbiParametersToPrimitiveTypes, ExtractAbiFunction } from "abitype";
3
+ type Without<T extends readonly unknown[], P> = T extends readonly [
4
+ infer F,
5
+ ...infer R
6
+ ] ? F extends P ? Without<R, P> : readonly [F, ...Without<R, P>] : [];
7
+ export type ContractFunctionArgsWithout<abi extends Abi, functionName extends ContractFunctionName<abi>, without> = AbiParametersToPrimitiveTypes<Without<ExtractAbiFunction<abi extends Abi ? abi : Abi, functionName>["inputs"], without>, "inputs"> extends infer args ? [args] extends [never] ? readonly unknown[] : args : readonly unknown[];
8
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import { Abi, AbiStateMutability, Address, ContractFunctionArgs, ContractFunctionName, Hex } from "viem";
2
+ type Calldata = string;
3
+ export type CallParams = {
4
+ to: Address;
5
+ data: Calldata;
6
+ };
7
+ export type CallContext = {
8
+ chain_id: number;
9
+ };
10
+ export type Proof = {
11
+ length: bigint;
12
+ seal: {
13
+ verifierSelector: Hex;
14
+ seal: readonly [Hex, Hex, Hex, Hex, Hex, Hex, Hex, Hex];
15
+ mode: number;
16
+ };
17
+ callAssumptions: {
18
+ proverContractAddress: Address;
19
+ functionSelector: Hex;
20
+ settleBlockHash: Hex;
21
+ settleBlockNumber: bigint;
22
+ };
23
+ };
24
+ export interface VCallResult {
25
+ evm_call_result: Hex;
26
+ proof: Proof;
27
+ }
28
+ export interface VCallResponse {
29
+ jsonrpc: string;
30
+ result: VCallResult;
31
+ id: number;
32
+ }
33
+ export type VlayerClient = {
34
+ prove: <T extends Abi, F extends ContractFunctionName<T>>(args: {
35
+ address: Hex;
36
+ proverAbi: T;
37
+ functionName: F;
38
+ chainId: number;
39
+ args: ContractFunctionArgs<T, AbiStateMutability, F>;
40
+ }) => Promise<{
41
+ hash: string;
42
+ }>;
43
+ waitForProvingResult: ({ hash, }: {
44
+ hash: string;
45
+ }) => Promise<[Proof, ...unknown[]]>;
46
+ };
47
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,29 @@
1
+ import { Hex, Abi, ContractFunctionName } from "viem";
2
+ import type { ContractFunctionArgsWithout } from "./viem";
3
+ import { Branded, WebProof, WebProofStep } from "../../../web-proof-commons";
4
+ export type WebProofSetupInput = {
5
+ logoUrl: string;
6
+ steps: WebProofStep[];
7
+ };
8
+ export type WebProofSetup = Branded<WebProofSetupInput & {
9
+ isWebProof: true;
10
+ }, "webProof">;
11
+ export type ProverCallCommitment<T extends Abi, F extends ContractFunctionName<T>> = {
12
+ address: Hex;
13
+ proverAbi: T;
14
+ functionName: F;
15
+ commitmentArgs: ContractFunctionArgsWithout<T, F, {
16
+ name: "webProof";
17
+ }>;
18
+ chainId: number;
19
+ };
20
+ export type GetWebProofArgs<T extends Abi, F extends ContractFunctionName<T>> = {
21
+ proverCallCommitment: ProverCallCommitment<T, F>;
22
+ } & WebProofSetupInput;
23
+ export type WebProofProvider = {
24
+ getWebProof: <T extends Abi, F extends ContractFunctionName<T>>(args: GetWebProofArgs<T, F>) => Promise<WebProof>;
25
+ };
26
+ export type WebProofProviderSetup = {
27
+ notaryUrl?: string;
28
+ wsProxyUrl?: string;
29
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { type Abi, AbiStateMutability, type Address, ContractFunctionArgs, ContractFunctionName } from "viem";
2
+ export declare function prove<T extends Abi, F extends ContractFunctionName<T>>(prover: Address, abi: T, functionName: F, args: ContractFunctionArgs<T, AbiStateMutability, F>, chainId?: number, url?: string): Promise<import("types/vlayer").VCallResponse>;
@@ -0,0 +1,15 @@
1
+ import { encodeFunctionData, } from "viem";
2
+ import { v_call } from "./v_call";
3
+ import { foundry } from "viem/chains";
4
+ export async function prove(prover, abi, functionName, args, chainId = foundry.id, url = "http://127.0.0.1:3000") {
5
+ const calldata = encodeFunctionData({
6
+ abi: abi,
7
+ functionName: functionName,
8
+ args: args,
9
+ });
10
+ const call = { to: prover, data: calldata };
11
+ const context = {
12
+ chain_id: chainId,
13
+ };
14
+ return v_call(call, context, url);
15
+ }
@@ -0,0 +1,2 @@
1
+ import { CallContext, CallParams, VCallResponse } from "types/vlayer";
2
+ export declare function v_call(call: CallParams, context: CallContext, url?: string): Promise<VCallResponse>;
@@ -0,0 +1,30 @@
1
+ function v_callBody(call, context) {
2
+ return {
3
+ method: "v_call",
4
+ params: [call, context],
5
+ id: 1,
6
+ jsonrpc: "2.0",
7
+ };
8
+ }
9
+ export async function v_call(call, context, url = "http://127.0.0.1:3000") {
10
+ const response = await fetch(url, {
11
+ method: "POST",
12
+ body: JSON.stringify(v_callBody(call, context)),
13
+ headers: { "Content-Type": "application/json" },
14
+ });
15
+ if (!response.ok) {
16
+ throw new Error(`HTTP error! status: ${response.status}`);
17
+ }
18
+ const response_json = await response.json();
19
+ //TODO we should launch some schema validation here
20
+ assertObject(response_json);
21
+ if ("error" in response_json) {
22
+ throw new Error(`Error response: ${response_json.error.message || "unknown error"}`);
23
+ }
24
+ return response_json;
25
+ }
26
+ function assertObject(x) {
27
+ if (typeof x !== "object") {
28
+ throw new Error("Expected object");
29
+ }
30
+ }
@@ -0,0 +1,2 @@
1
+ import { WebProofSetup, WebProofSetupInput } from "types/webProofProvider";
2
+ export declare const createWebProof: ({ logoUrl, steps }: WebProofSetupInput) => WebProofSetup;
@@ -0,0 +1,7 @@
1
+ export const createWebProof = ({ logoUrl, steps }) => {
2
+ return {
3
+ logoUrl,
4
+ steps,
5
+ isWebProof: true,
6
+ };
7
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./createWebProof";
2
+ export * from "./steps";
3
+ export * from "./providers";
@@ -0,0 +1,2 @@
1
+ import { type WebProofProvider, type WebProofProviderSetup } from "../../lib/types/webProofProvider";
2
+ export declare const createExtensionWebProofProvider: ({ notaryUrl, wsProxyUrl, }?: WebProofProviderSetup) => WebProofProvider;
@@ -0,0 +1,32 @@
1
+ // this id is fixed in the extension by the key in manifest.json
2
+ const EXTENSION_ID = "jbchhcgphfokabmfacnkafoeeeppjmpl";
3
+ export const createExtensionWebProofProvider = ({ notaryUrl = "https://notary.pse.dev/v0.1.0-alpha.5/", wsProxyUrl = "wss://notary.pse.dev/proxy", } = {
4
+ notaryUrl: "https://notary.pse.dev/v0.1.0-alpha.5/",
5
+ wsProxyUrl: "wss://notary.pse.dev/proxy",
6
+ }) => {
7
+ return {
8
+ getWebProof: async function (webProofSetup) {
9
+ return new Promise((resolve, reject) => {
10
+ chrome.runtime.sendMessage(EXTENSION_ID, {
11
+ action: 0 /* ExtensionAction.RequestWebProof */,
12
+ payload: {
13
+ notaryUrl,
14
+ wsProxyUrl,
15
+ logoUrl: webProofSetup.logoUrl,
16
+ steps: webProofSetup.steps,
17
+ },
18
+ });
19
+ const port = chrome.runtime.connect(EXTENSION_ID);
20
+ // TODO: validate message in runtime
21
+ port.onMessage.addListener((message) => {
22
+ if (message.type === "ProofDone" /* ExtensionMessageType.ProofDone */) {
23
+ resolve(message.proof);
24
+ }
25
+ if (message.type === "ProofError" /* ExtensionMessageType.ProofError */) {
26
+ reject(new Error(message.error));
27
+ }
28
+ });
29
+ });
30
+ },
31
+ };
32
+ };
@@ -0,0 +1 @@
1
+ export * from "./extension";
@@ -0,0 +1,2 @@
1
+ import { WebProofStepExpectUrl } from "../../../web-proof-commons";
2
+ export declare const expectUrl: (url: string, label: string) => WebProofStepExpectUrl;