@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 +6 -4
- package/src/api/email/dnsResolver.ts +4 -11
- package/src/api/email/parseEmail.test.ts +44 -16
- package/src/api/email/parseEmail.ts +25 -21
- package/src/api/email/preverify.test.ts +1 -1
- package/src/api/helpers.ts +2 -6
- package/src/api/lib/client.ts +6 -5
- package/src/api/lib/types/index.ts +3 -0
- package/src/api/lib/types/viem.ts +28 -0
- package/src/api/lib/types/vlayer.ts +25 -3
- package/src/api/lib/types/webProof.ts +11 -6
- package/src/api/lib/types/webProofProvider.ts +93 -0
- package/src/api/prover.ts +5 -24
- package/src/api/webProof/createWebProof.ts +9 -0
- package/src/api/webProof/index.ts +3 -0
- package/src/api/webProof/providers/extension.ts +73 -0
- package/src/api/webProof/providers/index.ts +1 -0
- package/src/api/webProof/steps/expectUrl.ts +12 -0
- package/src/api/webProof/steps/index.ts +11 -0
- package/src/api/webProof/steps/notarize.ts +17 -0
- package/src/api/webProof/steps/startPage.ts +12 -0
- package/src/index.ts +3 -0
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-
|
|
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
|
-
"
|
|
23
|
-
"
|
|
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
|
|
1
|
+
import DnsResolver from "dns-over-http-resolver";
|
|
2
2
|
|
|
3
3
|
export async function resolveDkimDns(domain: string, selector: string) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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.
|
|
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.
|
|
42
|
-
|
|
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].
|
|
46
|
-
expect(dkim[1].
|
|
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 {
|
|
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
|
|
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:
|
|
20
|
-
const dkimHeader = mail.headers.
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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:
|
|
29
|
-
|
|
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 (!
|
|
38
|
+
if (!params.d) {
|
|
34
39
|
throw new DkimParsingError("DKIM header missing domain");
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
if (!
|
|
42
|
+
if (!params.s) {
|
|
38
43
|
throw new DkimParsingError("DKIM header missing selector");
|
|
39
44
|
}
|
|
40
|
-
|
|
41
45
|
return {
|
|
42
|
-
domain:
|
|
43
|
-
selector:
|
|
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 () => {
|
package/src/api/helpers.ts
CHANGED
|
@@ -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
|
|
24
|
+
export const chainIds = [testChainId1];
|
|
29
25
|
|
|
30
26
|
export function client(
|
|
31
27
|
chainId: number = testChainId1,
|
package/src/api/lib/client.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { VlayerClient } from "types/vlayer";
|
|
2
|
-
import { WebProofProvider } from "types/
|
|
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
|
-
|
|
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
|
};
|
|
@@ -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 {
|
|
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
|
-
|
|
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:
|
|
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
|
|
3
|
-
//
|
|
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
|
-
|
|
105
|
-
|
|
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
|
|
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
|
-
|
|
70
|
-
proof.dynamicParamsOffsets[0] = BigInt(32);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
53
|
+
return { proof, returnValue };
|
|
73
54
|
}
|
|
@@ -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,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";
|