@vlayer/sdk 0.1.0-nightly-20250127-5ee6ca8 → 0.1.0-nightly-20250128-0a32cfc
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 +2 -1
- package/src/api/email/dnsResolver.test.ts +19 -0
- package/src/api/email/dnsResolver.ts +87 -0
- package/src/api/email/parseEmail.test.ts +133 -0
- package/src/api/email/parseEmail.ts +55 -0
- package/src/api/email/preverify.test.ts +201 -0
- package/src/api/email/preverify.ts +70 -0
- package/src/api/email/testdata/test_email.txt +21 -0
- package/src/api/email/testdata/test_email_multiple_dkims.txt +28 -0
- package/src/api/email/testdata/test_email_subdomain.txt +21 -0
- package/src/api/email/testdata/test_email_unknown_domain.txt +21 -0
- package/src/api/lib/client.test.ts +261 -0
- package/src/api/lib/client.ts +191 -0
- package/src/api/lib/errors.ts +19 -0
- package/src/api/lib/types/ethereum.ts +45 -0
- package/src/api/lib/types/index.ts +3 -0
- package/src/api/lib/types/viem.ts +26 -0
- package/src/api/lib/types/vlayer.ts +156 -0
- package/src/api/lib/types/webProofProvider.ts +68 -0
- package/src/api/prover.ts +120 -0
- package/src/api/utils/prefixAllButNthSubstring.test.ts +24 -0
- package/src/api/utils/prefixAllButNthSubstring.ts +13 -0
- package/src/api/utils/versions.test.ts +52 -0
- package/src/api/utils/versions.ts +31 -0
- package/src/api/v_call.ts +58 -0
- package/src/api/v_getProofReceipt.ts +48 -0
- package/src/api/v_versions.ts +68 -0
- package/src/api/webProof/createWebProofRequest.ts +15 -0
- package/src/api/webProof/index.ts +3 -0
- package/src/api/webProof/providers/extension.test.ts +122 -0
- package/src/api/webProof/providers/extension.ts +197 -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 +20 -0
- package/src/api/webProof/steps/startPage.ts +12 -0
- package/src/config/createContext.ts +69 -0
- package/src/config/deploy.ts +108 -0
- package/src/config/getChainConfirmations.ts +6 -0
- package/src/config/getConfig.ts +71 -0
- package/src/config/index.ts +5 -0
- package/src/config/types.ts +26 -0
- package/src/config/writeEnvVariables.ts +28 -0
- package/src/index.ts +7 -0
- package/src/testHelpers/readFile.ts +3 -0
- package/src/web-proof-commons/index.ts +3 -0
- package/src/web-proof-commons/types/message.ts +176 -0
- package/src/web-proof-commons/types/redaction.test.ts +97 -0
- package/src/web-proof-commons/types/redaction.ts +201 -0
- package/src/web-proof-commons/utils.ts +11 -0
@@ -0,0 +1,261 @@
|
|
1
|
+
import {
|
2
|
+
describe,
|
3
|
+
expect,
|
4
|
+
it,
|
5
|
+
vi,
|
6
|
+
beforeEach,
|
7
|
+
type MockInstance,
|
8
|
+
afterEach,
|
9
|
+
} from "vitest";
|
10
|
+
|
11
|
+
import { createExtensionWebProofProvider } from "../webProof";
|
12
|
+
import { createVlayerClient } from "./client";
|
13
|
+
import { type BrandedHash, type VlayerClient } from "types/vlayer";
|
14
|
+
import { ZkProvingStatus } from "../../web-proof-commons";
|
15
|
+
import createFetchMock from "vitest-fetch-mock";
|
16
|
+
|
17
|
+
declare const global: {
|
18
|
+
chrome: object;
|
19
|
+
};
|
20
|
+
|
21
|
+
const fetchMocker = createFetchMock(vi);
|
22
|
+
|
23
|
+
beforeEach(() => {
|
24
|
+
fetchMocker.enableMocks();
|
25
|
+
global.chrome = {
|
26
|
+
runtime: {
|
27
|
+
sendMessage: vi.fn(),
|
28
|
+
connect: vi.fn().mockImplementation(() => {
|
29
|
+
return {
|
30
|
+
onMessage: {
|
31
|
+
addListener: vi.fn(),
|
32
|
+
},
|
33
|
+
postMessage: vi.fn(),
|
34
|
+
};
|
35
|
+
}),
|
36
|
+
},
|
37
|
+
};
|
38
|
+
});
|
39
|
+
|
40
|
+
afterEach(() => {
|
41
|
+
fetchMocker.disableMocks();
|
42
|
+
});
|
43
|
+
|
44
|
+
function generateRandomHash() {
|
45
|
+
let hash = "0x";
|
46
|
+
for (let i = 0; i < 40; ++i) {
|
47
|
+
hash += Math.floor(Math.random() * 16).toString(16);
|
48
|
+
}
|
49
|
+
return hash;
|
50
|
+
}
|
51
|
+
|
52
|
+
describe("Success zk-proving", () => {
|
53
|
+
let hashStr: string;
|
54
|
+
let zkProvingSpy: MockInstance<(status: ZkProvingStatus) => void>;
|
55
|
+
let vlayer: VlayerClient;
|
56
|
+
|
57
|
+
beforeEach(() => {
|
58
|
+
hashStr = generateRandomHash();
|
59
|
+
const webProofProvider = createExtensionWebProofProvider();
|
60
|
+
zkProvingSpy = vi.spyOn(webProofProvider, "notifyZkProvingStatus");
|
61
|
+
vlayer = createVlayerClient({ webProofProvider });
|
62
|
+
});
|
63
|
+
it("should send message to extension that zkproving started", async () => {
|
64
|
+
fetchMocker.mockResponseOnce(() => {
|
65
|
+
return {
|
66
|
+
body: JSON.stringify({
|
67
|
+
result: hashStr,
|
68
|
+
}),
|
69
|
+
};
|
70
|
+
});
|
71
|
+
|
72
|
+
const result = await vlayer.prove({
|
73
|
+
address: `0x${"a".repeat(40)}`,
|
74
|
+
functionName: "main",
|
75
|
+
proverAbi: [],
|
76
|
+
args: [],
|
77
|
+
chainId: 42,
|
78
|
+
});
|
79
|
+
|
80
|
+
expect(result.hash).toBe(hashStr);
|
81
|
+
expect(zkProvingSpy).toBeCalledTimes(1);
|
82
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(1, ZkProvingStatus.Proving);
|
83
|
+
});
|
84
|
+
it("should send message to extension that zkproving is done", async () => {
|
85
|
+
fetchMocker.mockResponseOnce(() => {
|
86
|
+
return {
|
87
|
+
body: JSON.stringify({
|
88
|
+
result: hashStr,
|
89
|
+
}),
|
90
|
+
};
|
91
|
+
});
|
92
|
+
|
93
|
+
await vlayer.prove({
|
94
|
+
address: `0x${"a".repeat(40)}`,
|
95
|
+
functionName: "main",
|
96
|
+
proverAbi: [],
|
97
|
+
args: [],
|
98
|
+
chainId: 42,
|
99
|
+
});
|
100
|
+
|
101
|
+
fetchMocker.mockResponseOnce(() => {
|
102
|
+
return {
|
103
|
+
body: JSON.stringify({
|
104
|
+
result: {
|
105
|
+
state: "done",
|
106
|
+
status: 1,
|
107
|
+
metrics: {},
|
108
|
+
data: {},
|
109
|
+
},
|
110
|
+
jsonrpc: "2.0",
|
111
|
+
id: 1,
|
112
|
+
}),
|
113
|
+
};
|
114
|
+
});
|
115
|
+
|
116
|
+
const hash = { hash: hashStr } as BrandedHash<[], string>;
|
117
|
+
await vlayer.waitForProvingResult({ hash });
|
118
|
+
|
119
|
+
expect(zkProvingSpy).toBeCalledTimes(2);
|
120
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(1, ZkProvingStatus.Proving);
|
121
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(2, ZkProvingStatus.Done);
|
122
|
+
});
|
123
|
+
it("should notify that zk-proving failed", async () => {
|
124
|
+
fetchMocker.mockResponseOnce(() => {
|
125
|
+
throw new Error("test");
|
126
|
+
});
|
127
|
+
|
128
|
+
const hash = { hash: hashStr } as BrandedHash<[], string>;
|
129
|
+
try {
|
130
|
+
await vlayer.waitForProvingResult({ hash });
|
131
|
+
} catch (e) {
|
132
|
+
console.log("Error waiting for proving result", e);
|
133
|
+
}
|
134
|
+
|
135
|
+
expect(zkProvingSpy).toBeCalledTimes(1);
|
136
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(1, ZkProvingStatus.Error);
|
137
|
+
});
|
138
|
+
it("should pass token if present", async () => {
|
139
|
+
const userToken = "deadbeef";
|
140
|
+
|
141
|
+
fetchMocker.mockResponseOnce((req) => {
|
142
|
+
const token = (req.headers.get("authorization") || "")
|
143
|
+
.split("Bearer ")
|
144
|
+
.at(1);
|
145
|
+
if (token !== undefined && token === userToken) {
|
146
|
+
return {
|
147
|
+
body: JSON.stringify({
|
148
|
+
result: hashStr,
|
149
|
+
}),
|
150
|
+
};
|
151
|
+
}
|
152
|
+
return {
|
153
|
+
body: JSON.stringify({
|
154
|
+
jsonrpc: "2.0",
|
155
|
+
id: 1,
|
156
|
+
error: {
|
157
|
+
code: -32603,
|
158
|
+
message:
|
159
|
+
"Gas meter error: RPC error: HTTP error: HTTP status client error (401 Unauthorized) for url (http://localhost:3000)",
|
160
|
+
},
|
161
|
+
}),
|
162
|
+
};
|
163
|
+
});
|
164
|
+
|
165
|
+
const result = await vlayer.prove({
|
166
|
+
address: `0x${"a".repeat(40)}`,
|
167
|
+
functionName: "main",
|
168
|
+
proverAbi: [],
|
169
|
+
args: [],
|
170
|
+
chainId: 42,
|
171
|
+
token: userToken,
|
172
|
+
});
|
173
|
+
expect(result.hash).toBe(hashStr);
|
174
|
+
expect(zkProvingSpy).toBeCalledTimes(1);
|
175
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(1, ZkProvingStatus.Proving);
|
176
|
+
});
|
177
|
+
});
|
178
|
+
|
179
|
+
describe("Failed zk-proving", () => {
|
180
|
+
let zkProvingSpy: MockInstance<(status: ZkProvingStatus) => void>;
|
181
|
+
let vlayer: VlayerClient;
|
182
|
+
let hashStr: string;
|
183
|
+
|
184
|
+
beforeEach(() => {
|
185
|
+
hashStr = generateRandomHash();
|
186
|
+
const webProofProvider = createExtensionWebProofProvider();
|
187
|
+
zkProvingSpy = vi.spyOn(webProofProvider, "notifyZkProvingStatus");
|
188
|
+
vlayer = createVlayerClient({ webProofProvider });
|
189
|
+
});
|
190
|
+
it("should send message to extension that zkproving started and then that failed when server error 500", async () => {
|
191
|
+
fetchMocker.mockResponseOnce((req) => {
|
192
|
+
if (req.url === "http://127.0.0.1:3000/") {
|
193
|
+
return {
|
194
|
+
status: 500,
|
195
|
+
};
|
196
|
+
}
|
197
|
+
return {};
|
198
|
+
});
|
199
|
+
|
200
|
+
try {
|
201
|
+
const hash = await vlayer.prove({
|
202
|
+
address: `0x${"a".repeat(40)}`,
|
203
|
+
functionName: "main",
|
204
|
+
proverAbi: [],
|
205
|
+
args: [],
|
206
|
+
chainId: 42,
|
207
|
+
});
|
208
|
+
await vlayer.waitForProvingResult({ hash });
|
209
|
+
} catch (e) {
|
210
|
+
console.log("Error waiting for proving result", e);
|
211
|
+
}
|
212
|
+
|
213
|
+
expect(zkProvingSpy).toBeCalledTimes(2);
|
214
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(1, ZkProvingStatus.Proving);
|
215
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(2, ZkProvingStatus.Error);
|
216
|
+
});
|
217
|
+
it("should send message to extension that zkproving started and then that failed when computation failed at any stage", async () => {
|
218
|
+
fetchMocker.mockResponseOnce(() => {
|
219
|
+
return {
|
220
|
+
body: JSON.stringify({
|
221
|
+
result: hashStr,
|
222
|
+
}),
|
223
|
+
};
|
224
|
+
});
|
225
|
+
|
226
|
+
const hash = await vlayer.prove({
|
227
|
+
address: `0x${"a".repeat(40)}`,
|
228
|
+
functionName: "main",
|
229
|
+
proverAbi: [],
|
230
|
+
args: [],
|
231
|
+
chainId: 42,
|
232
|
+
});
|
233
|
+
|
234
|
+
fetchMocker.mockResponseOnce(() => {
|
235
|
+
return {
|
236
|
+
body: JSON.stringify({
|
237
|
+
result: {
|
238
|
+
state: "preflight",
|
239
|
+
status: 0,
|
240
|
+
metrics: {},
|
241
|
+
error: "Preflight error: ...",
|
242
|
+
},
|
243
|
+
jsonrpc: "2.0",
|
244
|
+
id: 1,
|
245
|
+
}),
|
246
|
+
};
|
247
|
+
});
|
248
|
+
|
249
|
+
try {
|
250
|
+
await vlayer.waitForProvingResult({ hash });
|
251
|
+
} catch (e) {
|
252
|
+
expect((e as Error).message).toMatch(
|
253
|
+
"Preflight failed with error: Preflight error: ...",
|
254
|
+
);
|
255
|
+
}
|
256
|
+
|
257
|
+
expect(zkProvingSpy).toBeCalledTimes(2);
|
258
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(1, ZkProvingStatus.Proving);
|
259
|
+
expect(zkProvingSpy).toHaveBeenNthCalledWith(2, ZkProvingStatus.Error);
|
260
|
+
});
|
261
|
+
});
|
@@ -0,0 +1,191 @@
|
|
1
|
+
import { type VlayerClient, type BrandedHash } from "./types/vlayer";
|
2
|
+
import { type WebProofProvider } from "./types/webProofProvider";
|
3
|
+
import { prove, waitForProof } from "../prover";
|
4
|
+
import { createExtensionWebProofProvider } from "../webProof";
|
5
|
+
import {
|
6
|
+
type Abi,
|
7
|
+
type AbiStateMutability,
|
8
|
+
type ContractFunctionArgs,
|
9
|
+
type ContractFunctionName,
|
10
|
+
type ContractFunctionReturnType,
|
11
|
+
decodeFunctionResult,
|
12
|
+
} from "viem";
|
13
|
+
import {
|
14
|
+
ExtensionMessageType,
|
15
|
+
ZkProvingStatus,
|
16
|
+
type PresentationJSON,
|
17
|
+
} from "../../web-proof-commons";
|
18
|
+
import { type ContractFunctionArgsWithout } from "./types/viem";
|
19
|
+
import { type ProveArgs } from "./types/vlayer";
|
20
|
+
|
21
|
+
function dropEmptyProofFromArgs(args: unknown) {
|
22
|
+
if (Array.isArray(args)) {
|
23
|
+
return args.slice(1) as unknown[];
|
24
|
+
}
|
25
|
+
return [];
|
26
|
+
}
|
27
|
+
|
28
|
+
export const createVlayerClient = (
|
29
|
+
{
|
30
|
+
url = "http://127.0.0.1:3000",
|
31
|
+
webProofProvider = createExtensionWebProofProvider(),
|
32
|
+
}: {
|
33
|
+
url?: string;
|
34
|
+
webProofProvider?: WebProofProvider;
|
35
|
+
} = {
|
36
|
+
url: "http://127.0.0.1:3000",
|
37
|
+
webProofProvider: createExtensionWebProofProvider(),
|
38
|
+
},
|
39
|
+
): VlayerClient => {
|
40
|
+
const resultHashMap = new Map<string, [Abi, string]>();
|
41
|
+
|
42
|
+
return {
|
43
|
+
prove: async <T extends Abi, F extends ContractFunctionName<T>>({
|
44
|
+
address,
|
45
|
+
proverAbi,
|
46
|
+
functionName,
|
47
|
+
chainId,
|
48
|
+
gasLimit,
|
49
|
+
token,
|
50
|
+
args,
|
51
|
+
}: ProveArgs<T, F>) => {
|
52
|
+
webProofProvider.notifyZkProvingStatus(ZkProvingStatus.Proving);
|
53
|
+
|
54
|
+
const hash = await prove(
|
55
|
+
address,
|
56
|
+
proverAbi,
|
57
|
+
functionName,
|
58
|
+
args,
|
59
|
+
chainId,
|
60
|
+
url,
|
61
|
+
gasLimit,
|
62
|
+
token,
|
63
|
+
).catch((e) => {
|
64
|
+
webProofProvider.notifyZkProvingStatus(ZkProvingStatus.Error);
|
65
|
+
throw e;
|
66
|
+
});
|
67
|
+
|
68
|
+
resultHashMap.set(hash.hash, [proverAbi, functionName]);
|
69
|
+
return hash;
|
70
|
+
},
|
71
|
+
|
72
|
+
waitForProvingResult: async <
|
73
|
+
T extends Abi,
|
74
|
+
F extends ContractFunctionName<T>,
|
75
|
+
>({
|
76
|
+
hash,
|
77
|
+
numberOfRetries = 240,
|
78
|
+
sleepDuration = 1000,
|
79
|
+
}: {
|
80
|
+
hash: BrandedHash<T, F>;
|
81
|
+
numberOfRetries?: number;
|
82
|
+
sleepDuration?: number;
|
83
|
+
}): Promise<ContractFunctionReturnType<T, AbiStateMutability, F>> => {
|
84
|
+
try {
|
85
|
+
const { data } = await waitForProof(
|
86
|
+
hash,
|
87
|
+
url,
|
88
|
+
numberOfRetries,
|
89
|
+
sleepDuration,
|
90
|
+
);
|
91
|
+
const savedProvingData = resultHashMap.get(hash.hash);
|
92
|
+
if (!savedProvingData) {
|
93
|
+
throw new Error("No result found for hash " + hash.hash);
|
94
|
+
}
|
95
|
+
const [proverAbi, functionName] = savedProvingData;
|
96
|
+
|
97
|
+
const result = dropEmptyProofFromArgs(
|
98
|
+
decodeFunctionResult({
|
99
|
+
abi: proverAbi,
|
100
|
+
data: data.evm_call_result,
|
101
|
+
functionName,
|
102
|
+
}),
|
103
|
+
);
|
104
|
+
|
105
|
+
webProofProvider.notifyZkProvingStatus(ZkProvingStatus.Done);
|
106
|
+
|
107
|
+
return [data.proof, ...result] as ContractFunctionReturnType<
|
108
|
+
T,
|
109
|
+
AbiStateMutability,
|
110
|
+
F
|
111
|
+
>;
|
112
|
+
} catch (e) {
|
113
|
+
webProofProvider.notifyZkProvingStatus(ZkProvingStatus.Error);
|
114
|
+
throw e;
|
115
|
+
}
|
116
|
+
},
|
117
|
+
|
118
|
+
proveWeb: async function ({
|
119
|
+
address,
|
120
|
+
proverAbi,
|
121
|
+
functionName,
|
122
|
+
chainId,
|
123
|
+
gasLimit,
|
124
|
+
token,
|
125
|
+
args,
|
126
|
+
}) {
|
127
|
+
const webProofPlaceholder = args[0];
|
128
|
+
const commitmentArgs = args.slice(1) as ContractFunctionArgsWithout<
|
129
|
+
typeof proverAbi,
|
130
|
+
typeof functionName,
|
131
|
+
{ name: "webProof" }
|
132
|
+
>;
|
133
|
+
|
134
|
+
const webProofPromise: Promise<{
|
135
|
+
presentationJSON: PresentationJSON;
|
136
|
+
decodedTranscript: {
|
137
|
+
sent: string;
|
138
|
+
recv: string;
|
139
|
+
};
|
140
|
+
}> = new Promise((resolve, reject) => {
|
141
|
+
webProofProvider.addEventListeners(
|
142
|
+
ExtensionMessageType.ProofDone,
|
143
|
+
({ payload: { presentationJSON, decodedTranscript } }) => {
|
144
|
+
resolve({ presentationJSON, decodedTranscript });
|
145
|
+
},
|
146
|
+
);
|
147
|
+
|
148
|
+
webProofProvider.addEventListeners(
|
149
|
+
ExtensionMessageType.ProofError,
|
150
|
+
({ payload: { error } }) => {
|
151
|
+
reject(new Error(error));
|
152
|
+
},
|
153
|
+
);
|
154
|
+
});
|
155
|
+
|
156
|
+
webProofProvider.requestWebProof({
|
157
|
+
proverCallCommitment: {
|
158
|
+
address,
|
159
|
+
proverAbi,
|
160
|
+
functionName,
|
161
|
+
commitmentArgs,
|
162
|
+
chainId,
|
163
|
+
},
|
164
|
+
logoUrl: webProofPlaceholder.logoUrl,
|
165
|
+
steps: webProofPlaceholder.steps,
|
166
|
+
});
|
167
|
+
|
168
|
+
const webProof = await webProofPromise;
|
169
|
+
|
170
|
+
const hash = await this.prove({
|
171
|
+
address,
|
172
|
+
functionName,
|
173
|
+
chainId,
|
174
|
+
gasLimit,
|
175
|
+
proverAbi,
|
176
|
+
token,
|
177
|
+
args: [
|
178
|
+
{
|
179
|
+
webProofJson: JSON.stringify(webProof.presentationJSON),
|
180
|
+
},
|
181
|
+
...commitmentArgs,
|
182
|
+
] as ContractFunctionArgs<
|
183
|
+
typeof proverAbi,
|
184
|
+
AbiStateMutability,
|
185
|
+
typeof functionName
|
186
|
+
>,
|
187
|
+
});
|
188
|
+
return hash;
|
189
|
+
},
|
190
|
+
};
|
191
|
+
};
|
@@ -0,0 +1,19 @@
|
|
1
|
+
export class VersionError extends Error {
|
2
|
+
constructor(message: string) {
|
3
|
+
super(message);
|
4
|
+
this.name = "VersionError";
|
5
|
+
}
|
6
|
+
}
|
7
|
+
|
8
|
+
export function parseVCallResponseError({
|
9
|
+
message,
|
10
|
+
}: {
|
11
|
+
message: string | undefined;
|
12
|
+
}): Error {
|
13
|
+
if (message?.startsWith("Unsupported CallGuestID")) {
|
14
|
+
return new VersionError(`${message}
|
15
|
+
vlayer uses the daily release cycle, and SDK version must match the proving server version.
|
16
|
+
Please run "vlayer update" to update the SDK to the latest version.`);
|
17
|
+
}
|
18
|
+
return new Error(`Error response: ${message ?? "unknown error"}`);
|
19
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { type Abi, type Address, type Hex } from "viem";
|
2
|
+
import { type Branded } from "../../../web-proof-commons";
|
3
|
+
|
4
|
+
export type Bytecode = {
|
5
|
+
object: Hex;
|
6
|
+
};
|
7
|
+
|
8
|
+
export type ContractSpec = {
|
9
|
+
abi: Abi;
|
10
|
+
bytecode: Bytecode;
|
11
|
+
};
|
12
|
+
|
13
|
+
export type ContractArg =
|
14
|
+
| number
|
15
|
+
| string
|
16
|
+
| boolean
|
17
|
+
| bigint
|
18
|
+
| number[]
|
19
|
+
| string[]
|
20
|
+
| boolean[]
|
21
|
+
| bigint[]
|
22
|
+
| Address[]
|
23
|
+
| (string | bigint)[]
|
24
|
+
| (string | bigint)[][];
|
25
|
+
|
26
|
+
export type EthereumAddress = Branded<Hex, "EthereumAddress">;
|
27
|
+
export type EthereumTxHash = Branded<Hex, "EthereumTxHash">;
|
28
|
+
|
29
|
+
export function assertEthereumAddress(
|
30
|
+
hash: string,
|
31
|
+
): asserts hash is EthereumAddress {
|
32
|
+
const regex = /^(0x)?[0-9a-fA-F]{40}$/;
|
33
|
+
if (!regex.test(hash)) {
|
34
|
+
throw new Error(`Invalid ethereum account ${hash}`);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
export function assertEthereumTxHash(
|
39
|
+
hash: string,
|
40
|
+
): asserts hash is EthereumTxHash {
|
41
|
+
const regex = /^(0x)?[0-9a-fA-F]{64}$/;
|
42
|
+
if (!regex.test(hash)) {
|
43
|
+
throw new Error(`Invalid ethereum tx hash ${hash}`);
|
44
|
+
}
|
45
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { type Abi, type ContractFunctionName } from "viem";
|
2
|
+
import {
|
3
|
+
type AbiParametersToPrimitiveTypes,
|
4
|
+
type ExtractAbiFunction,
|
5
|
+
} from "abitype";
|
6
|
+
|
7
|
+
type Without<T extends readonly unknown[], P> = T extends readonly [
|
8
|
+
infer F,
|
9
|
+
...infer R,
|
10
|
+
]
|
11
|
+
? F extends P
|
12
|
+
? Without<R, P>
|
13
|
+
: readonly [F, ...Without<R, P>]
|
14
|
+
: [];
|
15
|
+
|
16
|
+
export type ContractFunctionArgsWithout<
|
17
|
+
abi extends Abi,
|
18
|
+
functionName extends ContractFunctionName<abi>,
|
19
|
+
without,
|
20
|
+
> = AbiParametersToPrimitiveTypes<
|
21
|
+
Without<
|
22
|
+
ExtractAbiFunction<abi extends Abi ? abi : Abi, functionName>["inputs"],
|
23
|
+
without
|
24
|
+
>,
|
25
|
+
"inputs"
|
26
|
+
>;
|
@@ -0,0 +1,156 @@
|
|
1
|
+
import { type Branded } from "../../../web-proof-commons/utils";
|
2
|
+
import {
|
3
|
+
type Abi,
|
4
|
+
type AbiStateMutability,
|
5
|
+
type Address,
|
6
|
+
type ContractFunctionArgs,
|
7
|
+
type ContractFunctionName,
|
8
|
+
type ContractFunctionReturnType,
|
9
|
+
type Hex,
|
10
|
+
} from "viem";
|
11
|
+
import { type WebProofRequest } from "./webProofProvider";
|
12
|
+
import { type ContractFunctionArgsWithout } from "./viem";
|
13
|
+
import { z } from "zod";
|
14
|
+
|
15
|
+
type Calldata = string;
|
16
|
+
|
17
|
+
export type CallParams = {
|
18
|
+
to: Address;
|
19
|
+
data: Calldata;
|
20
|
+
gas_limit: number;
|
21
|
+
};
|
22
|
+
|
23
|
+
export type CallContext = {
|
24
|
+
chain_id: number;
|
25
|
+
};
|
26
|
+
|
27
|
+
export type BrandedHash<T, F> = Branded<{ hash: string }, [T, F]>;
|
28
|
+
|
29
|
+
export type Proof = {
|
30
|
+
seal: {
|
31
|
+
verifierSelector: Hex;
|
32
|
+
seal: readonly [Hex, Hex, Hex, Hex, Hex, Hex, Hex, Hex];
|
33
|
+
mode: number;
|
34
|
+
};
|
35
|
+
callGuestId: Hex;
|
36
|
+
length: bigint;
|
37
|
+
callAssumptions: {
|
38
|
+
proverContractAddress: Address;
|
39
|
+
functionSelector: Hex;
|
40
|
+
settleBlockHash: Hex;
|
41
|
+
settleBlockNumber: bigint;
|
42
|
+
};
|
43
|
+
};
|
44
|
+
|
45
|
+
export type VCallResult = Hex;
|
46
|
+
|
47
|
+
export interface VCallResponse {
|
48
|
+
jsonrpc: string;
|
49
|
+
result: VCallResult;
|
50
|
+
id: number;
|
51
|
+
}
|
52
|
+
|
53
|
+
export type VGetProofReceiptParams = {
|
54
|
+
hash: Hex;
|
55
|
+
};
|
56
|
+
|
57
|
+
export enum ProofState {
|
58
|
+
Queued = "queued",
|
59
|
+
ChainProof = "chain_proof",
|
60
|
+
Preflight = "preflight",
|
61
|
+
Proving = "proving",
|
62
|
+
Done = "done",
|
63
|
+
}
|
64
|
+
|
65
|
+
export type ProofData = {
|
66
|
+
evm_call_result: Hex;
|
67
|
+
proof: Proof;
|
68
|
+
};
|
69
|
+
|
70
|
+
export type Metrics = {
|
71
|
+
gas: number;
|
72
|
+
cycles: number;
|
73
|
+
times: {
|
74
|
+
preflight: number;
|
75
|
+
proving: number;
|
76
|
+
};
|
77
|
+
};
|
78
|
+
|
79
|
+
export type ProofDataWithMetrics = {
|
80
|
+
data: ProofData;
|
81
|
+
metrics: Metrics;
|
82
|
+
};
|
83
|
+
|
84
|
+
export type ProveArgs<T extends Abi, F extends ContractFunctionName<T>> = {
|
85
|
+
address: Hex;
|
86
|
+
proverAbi: T;
|
87
|
+
functionName: F;
|
88
|
+
chainId?: number;
|
89
|
+
gasLimit?: number;
|
90
|
+
token?: string;
|
91
|
+
args: ContractFunctionArgs<T, AbiStateMutability, F>;
|
92
|
+
};
|
93
|
+
|
94
|
+
export type VlayerClient = {
|
95
|
+
prove: <T extends Abi, F extends ContractFunctionName<T>>(
|
96
|
+
args: ProveArgs<T, F>,
|
97
|
+
) => Promise<BrandedHash<T, F>>;
|
98
|
+
|
99
|
+
waitForProvingResult: <
|
100
|
+
T extends Abi,
|
101
|
+
F extends ContractFunctionName<T>,
|
102
|
+
>(args: {
|
103
|
+
hash: BrandedHash<T, F>;
|
104
|
+
numberOfRetries?: number;
|
105
|
+
sleepDuration?: number;
|
106
|
+
}) => Promise<ContractFunctionReturnType<T, AbiStateMutability, F>>;
|
107
|
+
|
108
|
+
proveWeb: <T extends Abi, F extends ContractFunctionName<T>>(args: {
|
109
|
+
address: Hex;
|
110
|
+
proverAbi: T;
|
111
|
+
functionName: F;
|
112
|
+
chainId: number;
|
113
|
+
gasLimit?: number;
|
114
|
+
token?: string;
|
115
|
+
args: [
|
116
|
+
WebProofRequest,
|
117
|
+
...ContractFunctionArgsWithout<T, F, { name: "webProof" }>,
|
118
|
+
];
|
119
|
+
}) => Promise<BrandedHash<T, F>>;
|
120
|
+
};
|
121
|
+
|
122
|
+
export const proofReceiptSchema = z.discriminatedUnion("status", [
|
123
|
+
z.object({
|
124
|
+
status: z.literal(0),
|
125
|
+
error: z.string(),
|
126
|
+
data: z.undefined(),
|
127
|
+
metrics: z.custom<Metrics>(),
|
128
|
+
state: z.enum([
|
129
|
+
ProofState.ChainProof,
|
130
|
+
ProofState.Preflight,
|
131
|
+
ProofState.Proving,
|
132
|
+
]),
|
133
|
+
}),
|
134
|
+
z.object({
|
135
|
+
status: z.literal(1),
|
136
|
+
error: z.undefined(),
|
137
|
+
state: z.enum([
|
138
|
+
ProofState.Done,
|
139
|
+
ProofState.ChainProof,
|
140
|
+
ProofState.Preflight,
|
141
|
+
ProofState.Proving,
|
142
|
+
ProofState.Queued,
|
143
|
+
]),
|
144
|
+
data: z.custom<ProofData>(),
|
145
|
+
metrics: z.custom<Metrics>(),
|
146
|
+
}),
|
147
|
+
]);
|
148
|
+
|
149
|
+
export const vGetProofReceiptSchema = z.object({
|
150
|
+
jsonrpc: z.string(),
|
151
|
+
result: proofReceiptSchema,
|
152
|
+
id: z.number(),
|
153
|
+
});
|
154
|
+
|
155
|
+
export type ProofReceipt = z.infer<typeof proofReceiptSchema>;
|
156
|
+
export type VGetProofReceiptResponse = z.infer<typeof vGetProofReceiptSchema>;
|