@vlayer/sdk 0.1.0-nightly-20241127-882e178 → 0.1.0-nightly-20241128-59dd64d

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.
@@ -1,6 +1,6 @@
1
1
  import { Hex, Abi, ContractFunctionName } from "viem";
2
2
  import type { ContractFunctionArgsWithout } from "./viem.js";
3
- import { Branded, ExtensionMessageType, ExtensionMessage, WebProof, WebProofStep, ZkProvingStatus } from "../../../web-proof-commons/index.js";
3
+ import { Branded, ExtensionMessageType, ExtensionMessage, type PresentationJSON, WebProofStep, ZkProvingStatus } from "../../../web-proof-commons/index.js";
4
4
  export type WebProofRequestInput = {
5
5
  logoUrl: string;
6
6
  steps: WebProofStep[];
@@ -22,7 +22,7 @@ export type GetWebProofArgs<T extends Abi, F extends ContractFunctionName<T>> =
22
22
  proverCallCommitment: ProverCallCommitment<T, F>;
23
23
  } & WebProofRequestInput;
24
24
  export type WebProofProvider = {
25
- getWebProof: <T extends Abi, F extends ContractFunctionName<T>>(args: GetWebProofArgs<T, F>) => Promise<WebProof>;
25
+ getWebProof: <T extends Abi, F extends ContractFunctionName<T>>(args: GetWebProofArgs<T, F>) => Promise<PresentationJSON>;
26
26
  requestWebProof: <T extends Abi, F extends ContractFunctionName<T>>(args: GetWebProofArgs<T, F>) => void;
27
27
  notifyZkProvingStatus: (status: ZkProvingStatus) => void;
28
28
  addEventListeners: <T extends ExtensionMessageType>(messageType: T, listener: (args: Extract<ExtensionMessage, {
@@ -1,2 +1,5 @@
1
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, gasLimit?: number, url?: string): Promise<import("./lib/types/vlayer.js").VCallResponse>;
2
+ export interface ProveOptions {
3
+ preverifyVersions?: boolean;
4
+ }
5
+ export declare function prove<T extends Abi, F extends ContractFunctionName<T>>(prover: Address, abi: T, functionName: F, args: ContractFunctionArgs<T, AbiStateMutability, F>, chainId?: number, gasLimit?: number, url?: string, options?: ProveOptions): Promise<import("./lib/types/vlayer.js").VCallResponse>;
@@ -1,7 +1,17 @@
1
1
  import { encodeFunctionData, } from "viem";
2
2
  import { v_call } from "./v_call.js";
3
3
  import { foundry } from "viem/chains";
4
- export async function prove(prover, abi, functionName, args, chainId = foundry.id, gasLimit = 1_000_000, url = "http://127.0.0.1:3000") {
4
+ import { v_versions } from "./v_versions.js";
5
+ import { checkVersionCompatibility } from "./utils/versions.js";
6
+ import { version as sdkVersion } from "../../package.json";
7
+ async function preverifyVersions(url, shouldPreverify) {
8
+ if (shouldPreverify) {
9
+ const proverVersions = await v_versions(url);
10
+ checkVersionCompatibility(proverVersions.result.api_version, sdkVersion);
11
+ }
12
+ }
13
+ export async function prove(prover, abi, functionName, args, chainId = foundry.id, gasLimit = 1_000_000, url = "http://127.0.0.1:3000", options = { preverifyVersions: false }) {
14
+ await preverifyVersions(url, !!options.preverifyVersions);
5
15
  const calldata = encodeFunctionData({
6
16
  abi: abi,
7
17
  functionName: functionName,
@@ -0,0 +1 @@
1
+ export declare function checkVersionCompatibility(proverSemver: string, sdkSemver: string): void;
@@ -0,0 +1,19 @@
1
+ import { parse } from "semver";
2
+ import { VersionError } from "../lib/errors.js";
3
+ function safeParseSemver(semverString) {
4
+ const parsed = parse(semverString);
5
+ if (parsed === null) {
6
+ throw new VersionError(`Invalid semver string: ${semverString}`);
7
+ }
8
+ return parsed;
9
+ }
10
+ export function checkVersionCompatibility(proverSemver, sdkSemver) {
11
+ const { major: proverMajor, minor: proverMinor } = safeParseSemver(proverSemver);
12
+ const { major: sdkMajor, minor: sdkMinor } = safeParseSemver(sdkSemver);
13
+ if (proverMajor !== sdkMajor) {
14
+ throw new VersionError(`SDK version ${sdkSemver} is incompatible with prover version ${proverSemver}`);
15
+ }
16
+ if (proverMajor === 0 && proverMinor !== sdkMinor) {
17
+ throw new VersionError(`SDK version ${sdkSemver} is incompatible with prover version ${proverSemver}`);
18
+ }
19
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { checkVersionCompatibility } from "./versions.js";
3
+ describe("versions compatibility", () => {
4
+ test("throws if major version mismatches", () => {
5
+ expect(() => {
6
+ checkVersionCompatibility("1.2.3", "2.1.3");
7
+ }).toThrowError("SDK version 2.1.3 is incompatible with prover version 1.2.3");
8
+ });
9
+ test("throws if major version mismatches with metadata after dash", () => {
10
+ expect(() => {
11
+ checkVersionCompatibility("1.2.3-dev-123456-deadbeef", "2.1.3");
12
+ }).toThrowError("SDK version 2.1.3 is incompatible with prover version 1.2.3-dev-123456-deadbeef");
13
+ });
14
+ test("throws if major version is 0 and minor version mismatches", () => {
15
+ expect(() => {
16
+ checkVersionCompatibility("0.2.3", "0.1.3");
17
+ }).toThrowError("SDK version 0.1.3 is incompatible with prover version 0.2.3");
18
+ });
19
+ test("does not throw if major and minor versions match", () => {
20
+ expect(() => {
21
+ checkVersionCompatibility("1.2.3", "1.2.13");
22
+ }).not.toThrow();
23
+ });
24
+ test("does not throw if major version is >0 and minor mismatches", () => {
25
+ expect(() => {
26
+ checkVersionCompatibility("1.2.3", "1.5.8");
27
+ }).not.toThrow();
28
+ });
29
+ test("does not throw if major version is 0 and minor matches", () => {
30
+ expect(() => {
31
+ checkVersionCompatibility("0.2.3", "0.2.7");
32
+ }).not.toThrow();
33
+ });
34
+ test("works for semvers with metadata after dash", () => {
35
+ expect(() => {
36
+ checkVersionCompatibility("0.2.3-dev-123456-deadbeef", "0.2.7");
37
+ }).not.toThrow();
38
+ });
39
+ });
@@ -0,0 +1,12 @@
1
+ interface VVersionsResponseResult {
2
+ call_guest_id: string;
3
+ chain_guest_id: string;
4
+ api_version: string;
5
+ }
6
+ export interface VVersionsResponse {
7
+ jsonrpc: string;
8
+ result: VVersionsResponseResult;
9
+ id: number;
10
+ }
11
+ export declare function v_versions(url?: string): Promise<VVersionsResponse>;
12
+ export {};
@@ -0,0 +1,36 @@
1
+ const v_versionsBody = {
2
+ method: "v_versions",
3
+ params: [],
4
+ id: 1,
5
+ jsonrpc: "2.0",
6
+ };
7
+ export async function v_versions(url = "http://127.0.0.1:3000") {
8
+ const response = await fetch(url, {
9
+ method: "POST",
10
+ body: JSON.stringify(v_versionsBody),
11
+ headers: { "Content-Type": "application/json" },
12
+ });
13
+ console.log("response", response);
14
+ if (!response.ok) {
15
+ throw new Error(`HTTP error! status: ${response.status}`);
16
+ }
17
+ const response_json = await response.json();
18
+ assertResponseObject(response_json);
19
+ return response_json;
20
+ }
21
+ function isFieldAString(x, field) {
22
+ return (field in x && typeof x[field] === "string");
23
+ }
24
+ function assertResponseObject(x) {
25
+ if (!x || typeof x !== "object") {
26
+ throw new Error("Expected object");
27
+ }
28
+ if (!("result" in x) || !x.result || typeof x.result !== "object") {
29
+ throw new Error(`Unexpected \`v_versions\` response: ${JSON.stringify(x, null, 2)}`);
30
+ }
31
+ if (!isFieldAString(x.result, "call_guest_id") ||
32
+ !isFieldAString(x.result, "chain_guest_id") ||
33
+ !isFieldAString(x.result, "api_version")) {
34
+ throw new Error(`Unexpected \`v_versions\` response: ${JSON.stringify(x, null, 2)}`);
35
+ }
36
+ }
@@ -1,2 +1,3 @@
1
- import { type WebProofProvider, type WebProofProviderSetup } from "../../lib/types/webProofProvider.js";
1
+ import { type WebProofProvider, type WebProofProviderSetup, type WebProofRequestInput } from "../../lib/types/webProofProvider.js";
2
+ export declare const validateWebProofRequest: (webProofRequest: WebProofRequestInput) => void;
2
3
  export declare const createExtensionWebProofProvider: ({ notaryUrl, wsProxyUrl, }?: WebProofProviderSetup) => WebProofProvider;
@@ -1,4 +1,4 @@
1
- import { ExtensionMessageType, } from "../../../web-proof-commons/index.js";
1
+ import { EXTENSION_STEP, ExtensionMessageType, assertUrl, assertUrlPattern, } from "../../../web-proof-commons/index.js";
2
2
  const EXTENSION_ID = "jbchhcgphfokabmfacnkafoeeeppjmpl";
3
3
  class ExtensionWebProofProvider {
4
4
  notaryUrl;
@@ -54,6 +54,7 @@ class ExtensionWebProofProvider {
54
54
  this.listeners[messageType].push(listener);
55
55
  }
56
56
  requestWebProof(webProofRequest) {
57
+ validateWebProofRequest(webProofRequest);
57
58
  this.connectToExtension().postMessage({
58
59
  action: "RequestWebProof" /* ExtensionAction.RequestWebProof */,
59
60
  payload: {
@@ -86,6 +87,19 @@ class ExtensionWebProofProvider {
86
87
  });
87
88
  }
88
89
  }
89
- export const createExtensionWebProofProvider = ({ notaryUrl = "https://notary.pse.dev/v0.1.0-alpha.5/", wsProxyUrl = "wss://notary.pse.dev/proxy", } = {}) => {
90
+ const validateSteps = (steps) => {
91
+ steps.forEach(({ step, url }) => {
92
+ if (step === EXTENSION_STEP.startPage) {
93
+ assertUrl(url);
94
+ }
95
+ else {
96
+ assertUrlPattern(url);
97
+ }
98
+ });
99
+ };
100
+ export const validateWebProofRequest = (webProofRequest) => {
101
+ validateSteps(webProofRequest.steps);
102
+ };
103
+ export const createExtensionWebProofProvider = ({ notaryUrl = "https://notary.pse.dev/v0.1.0-alpha.7", wsProxyUrl = "wss://notary.pse.dev/proxy", } = {}) => {
90
104
  return new ExtensionWebProofProvider(notaryUrl, wsProxyUrl);
91
105
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,65 @@
1
+ import { createExtensionWebProofProvider } from "./extension.js";
2
+ import { describe, it, expect } from "vitest";
3
+ import { expectUrl, startPage, notarize } from "../steps/index.js";
4
+ import { StepValidationError } from "../../../web-proof-commons/index.js";
5
+ const defaults = {
6
+ logoUrl: "https://example.com/logo.png",
7
+ proverCallCommitment: {
8
+ address: "0x",
9
+ proverAbi: [],
10
+ chainId: 1,
11
+ functionName: "test",
12
+ commitmentArgs: null,
13
+ },
14
+ };
15
+ const invalidUrl = "http:/example.com";
16
+ const invalidUrlPattern = "http://+.test";
17
+ const validUrl = "https://example.com";
18
+ const validUrlPattern = "https://example.com/test";
19
+ const label = "test";
20
+ describe("ExtensionWebProofProvider", () => {
21
+ it("should properly validate startPage step", () => {
22
+ const provider = createExtensionWebProofProvider();
23
+ expect(() => provider.requestWebProof({
24
+ ...defaults,
25
+ steps: [startPage(invalidUrl, label)],
26
+ })).toThrow(StepValidationError);
27
+ });
28
+ it("should properly validate expectUrl step", () => {
29
+ const provider = createExtensionWebProofProvider();
30
+ expect(() => provider.requestWebProof({
31
+ ...defaults,
32
+ steps: [expectUrl(invalidUrlPattern, label)],
33
+ })).toThrow(StepValidationError);
34
+ });
35
+ it("should properly validate notarize step", () => {
36
+ const provider = createExtensionWebProofProvider();
37
+ expect(() => provider.requestWebProof({
38
+ ...defaults,
39
+ steps: [notarize(invalidUrlPattern, "GET", label)],
40
+ })).toThrow(StepValidationError);
41
+ });
42
+ it("successfully validates all steps", () => {
43
+ const provider = createExtensionWebProofProvider();
44
+ expect(() => provider.requestWebProof({
45
+ ...defaults,
46
+ steps: [
47
+ startPage(validUrl, label),
48
+ expectUrl(validUrlPattern, label),
49
+ notarize(validUrlPattern, "GET", label),
50
+ ],
51
+ })).not.toThrow(StepValidationError);
52
+ });
53
+ it("should properly work backward compatible way with only urls used", () => {
54
+ const provider = createExtensionWebProofProvider();
55
+ expect(() => provider.requestWebProof({
56
+ ...defaults,
57
+ steps: [
58
+ startPage(validUrl, label),
59
+ expectUrl(validUrl, label),
60
+ expectUrl(validUrl, label),
61
+ notarize(validUrl, "GET", label),
62
+ ],
63
+ })).not.toThrow(StepValidationError);
64
+ });
65
+ });
package/dist/index.d.ts CHANGED
@@ -2,6 +2,5 @@ export * as testHelpers from "./api/helpers.js";
2
2
  export { preverifyEmail } from "./api/email/preverify.js";
3
3
  export { createVlayerClient } from "./api/lib/client.js";
4
4
  export * from "./api/lib/types/index.js";
5
- export * from "./web-proof-commons/types/webProof.js";
6
5
  export * from "./web-proof-commons/utils.js";
7
6
  export * from "./web-proof-commons/types/message.js";
package/dist/index.js CHANGED
@@ -2,6 +2,5 @@ export * as testHelpers from "./api/helpers.js";
2
2
  export { preverifyEmail } from "./api/email/preverify.js";
3
3
  export { createVlayerClient } from "./api/lib/client.js";
4
4
  export * from "./api/lib/types/index.js";
5
- export * from "./web-proof-commons/types/webProof.js";
6
5
  export * from "./web-proof-commons/utils.js";
7
6
  export * from "./web-proof-commons/types/message.js";
@@ -1,3 +1,2 @@
1
1
  export * from "./types/message.js";
2
- export * from "./types/webProof.js";
3
2
  export * from "./utils.js";
@@ -1,3 +1,2 @@
1
1
  export * from "./types/message.js";
2
- export * from "./types/webProof.js";
3
2
  export * from "./utils.js";
@@ -1,5 +1,5 @@
1
1
  import type { Branded } from "../utils.js";
2
- import type { WebProof } from "./webProof.js";
2
+ import type { PresentationJSON as TLSNPresentationJSON } from "tlsn-js/src/types";
3
3
  export declare const EXTENSION_STEP: {
4
4
  readonly expectUrl: "expectUrl";
5
5
  readonly startPage: "startPage";
@@ -32,10 +32,11 @@ export declare enum ExtensionMessageType {
32
32
  TabOpened = "TabOpened",
33
33
  ProofProcessing = "ProofProcessing"
34
34
  }
35
+ export type PresentationJSON = TLSNPresentationJSON;
35
36
  export type ExtensionMessage = {
36
37
  type: ExtensionMessageType.ProofDone;
37
38
  payload: {
38
- proof: WebProof;
39
+ proof: PresentationJSON;
39
40
  };
40
41
  } | {
41
42
  type: ExtensionMessageType.ProofError;
@@ -62,19 +63,34 @@ export type WebProverSessionConfig = {
62
63
  steps: WebProofStep[];
63
64
  };
64
65
  export type WebProofStep = WebProofStepNotarize | WebProofStepExpectUrl | WebProofStepStartPage;
66
+ export type UrlPattern = Branded<string, "UrlPattern">;
67
+ export type Url = Branded<UrlPattern, "Url">;
65
68
  export type WebProofStepNotarize = Branded<{
66
- url: string;
69
+ url: UrlPattern;
67
70
  method: string;
68
71
  label: string;
69
72
  step: typeof EXTENSION_STEP.notarize;
70
73
  }, "notarize">;
71
- export type WebProofStepExpectUrl = Branded<{
72
- url: string;
73
- label: string;
74
- step: typeof EXTENSION_STEP.expectUrl;
75
- }, "expectUrl">;
76
74
  export type WebProofStepStartPage = Branded<{
77
- url: string;
75
+ url: Url;
78
76
  label: string;
79
77
  step: typeof EXTENSION_STEP.startPage;
80
78
  }, "startPage">;
79
+ export type WebProofStepExpectUrl = Branded<{
80
+ url: UrlPattern;
81
+ label: string;
82
+ step: typeof EXTENSION_STEP.expectUrl;
83
+ }, "expectUrl">;
84
+ export declare enum StepValidationErrors {
85
+ InvalidUrl = "InvalidUrl",
86
+ InvalidUrlPattern = "InvalidUrlPattern"
87
+ }
88
+ export declare enum StepValidationErrorMessage {
89
+ InvalidUrl = "Wrong url",
90
+ InvalidUrlPattern = "Wrong url pattern"
91
+ }
92
+ export declare class StepValidationError extends Error {
93
+ constructor(message: string, name: StepValidationErrors);
94
+ }
95
+ export declare function assertUrl(url: string): asserts url is Url;
96
+ export declare function assertUrlPattern(urlPattern: string): asserts urlPattern is UrlPattern;
@@ -1,3 +1,5 @@
1
+ import { URLPattern } from "urlpattern-polyfill";
2
+ import urlRegex from "url-regex";
1
3
  export const EXTENSION_STEP = {
2
4
  expectUrl: "expectUrl",
3
5
  startPage: "startPage",
@@ -18,3 +20,33 @@ export var ExtensionMessageType;
18
20
  ExtensionMessageType["TabOpened"] = "TabOpened";
19
21
  ExtensionMessageType["ProofProcessing"] = "ProofProcessing";
20
22
  })(ExtensionMessageType || (ExtensionMessageType = {}));
23
+ export var StepValidationErrors;
24
+ (function (StepValidationErrors) {
25
+ StepValidationErrors["InvalidUrl"] = "InvalidUrl";
26
+ StepValidationErrors["InvalidUrlPattern"] = "InvalidUrlPattern";
27
+ })(StepValidationErrors || (StepValidationErrors = {}));
28
+ export var StepValidationErrorMessage;
29
+ (function (StepValidationErrorMessage) {
30
+ StepValidationErrorMessage["InvalidUrl"] = "Wrong url";
31
+ StepValidationErrorMessage["InvalidUrlPattern"] = "Wrong url pattern";
32
+ })(StepValidationErrorMessage || (StepValidationErrorMessage = {}));
33
+ export class StepValidationError extends Error {
34
+ constructor(message, name) {
35
+ super(message);
36
+ this.name = name;
37
+ }
38
+ }
39
+ export function assertUrl(url) {
40
+ const isUrl = urlRegex({ strict: true }).test(url);
41
+ if (!isUrl) {
42
+ throw new StepValidationError(`${StepValidationErrorMessage.InvalidUrl}: ${url}`, StepValidationErrors.InvalidUrl);
43
+ }
44
+ }
45
+ export function assertUrlPattern(urlPattern) {
46
+ try {
47
+ new URLPattern(urlPattern);
48
+ }
49
+ catch {
50
+ throw new StepValidationError(`${StepValidationErrorMessage.InvalidUrlPattern}: ${urlPattern} `, StepValidationErrors.InvalidUrlPattern);
51
+ }
52
+ }
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "types": "./dist/config/index.d.ts"
16
16
  }
17
17
  },
18
- "version": "0.1.0-nightly-20241127-882e178",
18
+ "version": "0.1.0-nightly-20241128-59dd64d",
19
19
  "scripts": {
20
20
  "build": "bun tsc && bun tsc-alias",
21
21
  "test:unit": "vitest --run",
@@ -25,6 +25,7 @@
25
25
  "devDependencies": {
26
26
  "@changesets/cli": "^2.27.7",
27
27
  "@types/bun": "latest",
28
+ "@types/semver": "^7.5.8",
28
29
  "abitype": "^1.0.6",
29
30
  "vitest": "^2.1.1",
30
31
  "vitest-fetch-mock": "^0.4.1"
@@ -37,7 +38,9 @@
37
38
  "dns-over-http-resolver": "^3.0.3",
38
39
  "dotenv-flow": "^4.1.0",
39
40
  "postal-mime": "^2.3.2",
41
+ "semver": "^7.6.3",
40
42
  "tsc-alias": "^1.8.10",
43
+ "url-regex": "^5.0.0",
41
44
  "viem": "2.21.0",
42
45
  "vite-tsconfig-paths": "^5.0.1"
43
46
  },
@@ -1,86 +0,0 @@
1
- export interface WebProof {
2
- session: Session;
3
- substrings: Substrings;
4
- notaryUrl: string;
5
- }
6
- export interface Session {
7
- header: Header;
8
- signature: Signature;
9
- session_info: SessionInfo;
10
- }
11
- export interface SessionInfo {
12
- server_name: ServerName;
13
- handshake_decommitment: HandshakeDecommitment;
14
- }
15
- export interface HandshakeDecommitment {
16
- nonce: number[];
17
- data: Data;
18
- }
19
- export interface Data {
20
- server_cert_details: ServerCERTDetails;
21
- server_kx_details: ServerKxDetails;
22
- client_random: number[];
23
- server_random: number[];
24
- }
25
- export interface ServerCERTDetails {
26
- cert_chain: Array<number[]>;
27
- ocsp_response: number[];
28
- scts: null;
29
- }
30
- export interface ServerKxDetails {
31
- kx_params: number[];
32
- kx_sig: KxSig;
33
- }
34
- export interface KxSig {
35
- scheme: string;
36
- sig: number[];
37
- }
38
- export interface Header {
39
- encoder_seed: number[];
40
- merkle_root: number[];
41
- sent_len: number;
42
- recv_len: number;
43
- handshake_summary: HandshakeSummary;
44
- }
45
- export interface HandshakeSummary {
46
- time: number;
47
- server_public_key: ServerPublicKey;
48
- handshake_commitment: number[];
49
- }
50
- export interface ServerPublicKey {
51
- group: string;
52
- key: number[];
53
- }
54
- export interface ServerName {
55
- Dns: string;
56
- }
57
- export interface Signature {
58
- P256: string;
59
- }
60
- export interface Substrings {
61
- openings: {
62
- [key: string]: Opening[];
63
- };
64
- inclusion_proof: InclusionProof;
65
- }
66
- export interface InclusionProof {
67
- proof: unknown[];
68
- total_leaves: number;
69
- }
70
- export interface Opening {
71
- kind?: string;
72
- ranges?: Range[];
73
- direction?: string;
74
- Blake3?: Blake3;
75
- }
76
- export interface Blake3 {
77
- data: number[];
78
- nonce: number[];
79
- }
80
- export interface Range {
81
- start: number;
82
- end: number;
83
- }
84
- export declare const assertWebProof: (candidate: {
85
- notaryUrl?: string;
86
- }) => asserts candidate is WebProof;
@@ -1,10 +0,0 @@
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
- export const assertWebProof = function (candidate) {
5
- //for now only thing we check is notary url
6
- //TODO: implement later once we known the conteact with tlsn-js
7
- if (!candidate.notaryUrl) {
8
- throw new Error("Missing required parameter");
9
- }
10
- };