@provex/extension-react 1.0.16 → 1.2.3

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.
@@ -0,0 +1,298 @@
1
+ import { Hex } from 'viem';
2
+ import { IntentStruct } from '@provex/utils/intent';
3
+ import { TokenInfo } from '@provex/utils/tokens';
4
+ import { ActionType, PlatformKey, ProviderKey } from '@provex/utils/payment';
5
+
6
+ /**
7
+ * @fileoverview React hook and utilities for PeerAuth browser extension integration.
8
+ *
9
+ * The PeerAuth extension (formerly ZK-TLS) provides secure proof generation
10
+ * for off-chain payment verification. This module provides:
11
+ *
12
+ * 1. Type definitions for extension API (window.peer)
13
+ * 2. useZKTLS hook for React components
14
+ * 3. Utility functions for transaction matching and proof encoding
15
+ *
16
+ * @remarks
17
+ * The extension exposes `window.peer` (or deprecated `window.zktls`) for:
18
+ * - Requesting connection (OAuth-like flow)
19
+ * - Authenticating with payment providers
20
+ * - Generating notarized proofs
21
+ * - Fetching transaction metadata
22
+ *
23
+ * @see {@link ZKTLSContext} for the React context provider
24
+ */
25
+
26
+ declare global {
27
+ interface ZKTLS {
28
+ requestConnection(): Promise<boolean>;
29
+ checkConnectionStatus(): Promise<Status>;
30
+ getVersion(): Promise<string>;
31
+ authenticate(inputs: AuthenticationInputs): Promise<void>;
32
+ generateProof(inputs: GenerateProofInputs): Promise<GenerateProofResponse>;
33
+ fetchProofById(proofId: string): Promise<ProofResponse>;
34
+ fetchProofs(): Promise<FetchProofsResponse>;
35
+ openSidebar(route: string): Promise<void>;
36
+ onMetadataMessage(fn: (data: MetadataMessageResponse) => void): () => void;
37
+ }
38
+ interface Window {
39
+ /** @deprecated Use window.peer instead */
40
+ zktls: ZKTLS | undefined;
41
+ /** PeerAuth extension API (replaces window.zktls) */
42
+ peer: ZKTLS | undefined;
43
+ }
44
+ }
45
+ /** the status of the PeerAuth extension */
46
+ type Status = 'connected' | 'disconnected' | 'pending';
47
+ /** the individual metadata message sent by the PeerAuth extension */
48
+ interface MetadataMessage {
49
+ amount: number;
50
+ /** Currency code (e.g., 'USD', 'EUR') */
51
+ currency?: string;
52
+ /**
53
+ * Date of the transaction.
54
+ * Can be a string in YYYYMMDD format, a number (YYYYMMDD or timestamp), or Date object.
55
+ * The actual type depends on the extension implementation.
56
+ */
57
+ date: string | number | Date;
58
+ hidden: boolean;
59
+ originalIndex: number;
60
+ paymentId: number;
61
+ recipient: string;
62
+ }
63
+ /** the response from the PeerAuth extension when a metadata message is received */
64
+ interface MetadataMessageResponse {
65
+ expiresAt: number;
66
+ platform: ProviderKey;
67
+ requestId: string;
68
+ metadata: MetadataMessage[];
69
+ }
70
+ /** the response from the PeerAuth extension when fetching proofs */
71
+ interface FetchProofsResponse {
72
+ notaryRequests: NotaryRequest[];
73
+ }
74
+ /** the inputs for the generateProof function */
75
+ type GenerateProofInputsAbstracted = {
76
+ platform: PlatformKey;
77
+ provider: ProviderKey;
78
+ intentHash: Hex;
79
+ originalIndex: number;
80
+ };
81
+ /** the inputs for the generateProof function */
82
+ type GenerateProofInputs = {
83
+ platform: ProviderKey;
84
+ originalIndex: number;
85
+ proofIndex?: number;
86
+ intentHash: string;
87
+ };
88
+ /**
89
+ * inputs for the generate proof function that requires the intent hash
90
+ * as hex to ensure it can be converted to a bigint string accurately
91
+ */
92
+ type HexIntentGenerateProofInputs = Exclude<GenerateProofInputs, 'intentHash'> & {
93
+ intentHash: Hex;
94
+ };
95
+ /** the response from the PeerAuth extension when generating a proof */
96
+ type GenerateProofResponse = {
97
+ proofId: string;
98
+ platform: ProviderKey;
99
+ };
100
+ /** the inputs for the authenticate function */
101
+ type AuthenticationInputs = {
102
+ actionType: ActionType;
103
+ platform: PlatformKey;
104
+ };
105
+ /** the response from the PeerAuth extension when fetching a proof */
106
+ interface Proof {
107
+ claimInfo: ClaimInfo;
108
+ signedClaim: SignedClaim;
109
+ isAppclipProof: boolean;
110
+ status: string;
111
+ }
112
+ /** the response from the PeerAuth extension when fetching a proof */
113
+ interface NotarizedProof {
114
+ claim: {
115
+ context: string;
116
+ epoch: number;
117
+ identifier: Hex;
118
+ owner: Hex;
119
+ parameters: string;
120
+ provider: string;
121
+ timestampS: number;
122
+ };
123
+ signatures: {
124
+ attestorAddress: Hex;
125
+ claimSignature: Record<number, number>;
126
+ resultSignature: Record<number, number>;
127
+ };
128
+ }
129
+ /** the claim info for a proof */
130
+ interface ClaimInfo {
131
+ provider: string;
132
+ parameters: string;
133
+ context: string;
134
+ }
135
+ /** the complete claim data for a proof */
136
+ interface CompleteClaimData {
137
+ identifier: Hex;
138
+ owner: Hex;
139
+ timestampS: number;
140
+ epoch: number;
141
+ }
142
+ /** the signed claim for a proof */
143
+ interface SignedClaim {
144
+ claim: CompleteClaimData;
145
+ signatures: Hex[];
146
+ }
147
+ /** the reclaim proof for a proof */
148
+ type ReclaimProof = {
149
+ claimInfo: ClaimInfo;
150
+ signedClaim: SignedClaim;
151
+ isAppclipProof: boolean;
152
+ };
153
+ /** the notary request for a proof */
154
+ interface NotaryRequest {
155
+ metadata: (string | number)[];
156
+ actionType: ActionType;
157
+ id: string;
158
+ status: string;
159
+ timestamp: number;
160
+ proof: NotarizedProof;
161
+ }
162
+ /** the response from the PeerAuth extension when fetching a proof */
163
+ interface ProofResponse {
164
+ notaryRequest: NotaryRequest;
165
+ }
166
+ declare const extensionUrl = "https://chromewebstore.google.com/detail/ijpgccednehjpeclfcllnjjcmiohdjih";
167
+ /** convert a byte array to a hex string */
168
+ declare const byteArrayToHexString: (byteArray: number[]) => Hex;
169
+ /** parse a proof object from the PeerAuth extension */
170
+ declare const parseExtensionProof: (proofObject: NotarizedProof) => ReclaimProof;
171
+ /** the abi encoding for a proof */
172
+ declare const PROOF_ENCODING: {
173
+ readonly type: "tuple";
174
+ readonly components: readonly [{
175
+ readonly type: "tuple";
176
+ readonly components: readonly [{
177
+ readonly type: "string";
178
+ readonly name: "provider";
179
+ }, {
180
+ readonly type: "string";
181
+ readonly name: "parameters";
182
+ }, {
183
+ readonly type: "string";
184
+ readonly name: "context";
185
+ }];
186
+ readonly name: "claimInfo";
187
+ }, {
188
+ readonly type: "tuple";
189
+ readonly components: readonly [{
190
+ readonly type: "tuple";
191
+ readonly components: readonly [{
192
+ readonly type: "bytes32";
193
+ readonly name: "identifier";
194
+ }, {
195
+ readonly type: "address";
196
+ readonly name: "owner";
197
+ }, {
198
+ readonly type: "uint32";
199
+ readonly name: "timestampS";
200
+ }, {
201
+ readonly type: "uint32";
202
+ readonly name: "epoch";
203
+ }];
204
+ readonly name: "claim";
205
+ }, {
206
+ readonly type: "bytes[]";
207
+ readonly name: "signatures";
208
+ }];
209
+ readonly name: "signedClaim";
210
+ }, {
211
+ readonly type: "bool";
212
+ readonly name: "isAppclipProof";
213
+ }];
214
+ };
215
+ /** encode a single proof as a bytes array */
216
+ declare function encodeProofAsBytes(proof: ReclaimProof): Hex;
217
+ /** encode two proofs to be passed to the underlying sub-provider */
218
+ declare const encodeTwoProofs: (proof1: ReclaimProof, proof2: ReclaimProof) => `0x${string}`;
219
+ /** a high level function to encode a proof for a given provider and sub-provider */
220
+ declare const encodeProof: ({ extensionProofs, subProvider, provider }: {
221
+ extensionProofs: NotarizedProof[];
222
+ subProvider: PlatformKey | null;
223
+ provider: ProviderKey;
224
+ }) => `0x${string}`;
225
+ /**
226
+ * wrap a proof with a payment method and proof
227
+ * this allows us to use a single verifier as an entry point for multiple underlying sub-providers
228
+ */
229
+ declare const encodeProofWithPaymentMethod: ({ proof, paymentMethod }: {
230
+ proof: Hex;
231
+ paymentMethod: number;
232
+ }) => Hex;
233
+ /** the progress of a proof series */
234
+ declare enum SeriesProgress {
235
+ Generating = 0,
236
+ Polling = 1,
237
+ Complete = 2
238
+ }
239
+ type ProgressInfo = {
240
+ progress: SeriesProgress;
241
+ total: number;
242
+ step: number | null;
243
+ id: string | null;
244
+ };
245
+ /** the mutations for the generate proof series function */
246
+ type GenerateProofSeriesMutations = {
247
+ progress?: ({ progress, step, id }: ProgressInfo) => void;
248
+ setOwnerName?: (name: string) => void;
249
+ };
250
+ /** React hook to interact with the PeerAuth extension */
251
+ declare const useZKTLS: () => {
252
+ /** check if the PeerAuth extension is initialized */
253
+ isInitialized: boolean;
254
+ /** request a connection to the PeerAuth extension */
255
+ requestConnection: () => Promise<boolean>;
256
+ /**
257
+ * check the connection status of the PeerAuth extension
258
+ * @returns the connection status
259
+ */
260
+ checkConnectionStatus: () => Promise<Status>;
261
+ /** get the version of the PeerAuth extension */
262
+ getVersion: () => Promise<string | undefined>;
263
+ /** authenticate with the PeerAuth extension */
264
+ authenticate: (inputs: AuthenticationInputs) => Promise<MetadataMessageResponse>;
265
+ /** generate a proof */
266
+ generateProof: (inputs: HexIntentGenerateProofInputs) => Promise<GenerateProofResponse>;
267
+ /** wait for a proof to be generated */
268
+ waitForProof: (proofId: string, onCurrent?: (notaryRequest: NotaryRequest | null) => void) => Promise<NotaryRequest>;
269
+ /** generate a proof series */
270
+ generateProofSeries: (inputs: GenerateProofInputsAbstracted, { progress: progressCallback }?: GenerateProofSeriesMutations) => Promise<NotaryRequest[]>;
271
+ /** subscribe to metadata messages */
272
+ onMetadataMessage: (fn: (data: any) => void) => () => void;
273
+ /** fetch a proof by its id */
274
+ fetchProofById: (proofId: string) => Promise<NotaryRequest | null>;
275
+ /** fetch generated proofs */
276
+ fetchGeneratedProofs: (genProofResponses: GenerateProofResponse[]) => Promise<(NotaryRequest | null)[]>;
277
+ /** fetch all proofs */
278
+ fetchProofs: () => Promise<FetchProofsResponse>;
279
+ /** open the PeerAuth sidebar */
280
+ openSidebar: (route: string) => Promise<void>;
281
+ };
282
+ /**
283
+ * Find the metadata message that matches the intent by amount.
284
+ * Returns the first (most recent) transaction in the metadata array that matches the expected amount.
285
+ *
286
+ * Simplified matching: just find transactions with the correct amount.
287
+ * The user can manually select if multiple matches exist.
288
+ */
289
+ declare const findMetadataMessage: ({ metadata, intent, token, centIsInt }: {
290
+ metadata: MetadataMessage[];
291
+ intent: IntentStruct;
292
+ token: TokenInfo;
293
+ /** @deprecated No longer used - kept for API compatibility */
294
+ recipient?: string;
295
+ centIsInt?: boolean;
296
+ }) => MetadataMessage | null;
297
+
298
+ export { type AuthenticationInputs, type ClaimInfo, type CompleteClaimData, type FetchProofsResponse, type GenerateProofInputs, type GenerateProofInputsAbstracted, type GenerateProofResponse, type GenerateProofSeriesMutations, type HexIntentGenerateProofInputs, type MetadataMessage, type MetadataMessageResponse, type NotarizedProof, type NotaryRequest, PROOF_ENCODING, type ProgressInfo, type Proof, type ProofResponse, type ReclaimProof, SeriesProgress, type SignedClaim, type Status, byteArrayToHexString, encodeProof, encodeProofAsBytes, encodeProofWithPaymentMethod, encodeTwoProofs, extensionUrl, findMetadataMessage, parseExtensionProof, useZKTLS };
@@ -0,0 +1,298 @@
1
+ import { Hex } from 'viem';
2
+ import { IntentStruct } from '@provex/utils/intent';
3
+ import { TokenInfo } from '@provex/utils/tokens';
4
+ import { ActionType, PlatformKey, ProviderKey } from '@provex/utils/payment';
5
+
6
+ /**
7
+ * @fileoverview React hook and utilities for PeerAuth browser extension integration.
8
+ *
9
+ * The PeerAuth extension (formerly ZK-TLS) provides secure proof generation
10
+ * for off-chain payment verification. This module provides:
11
+ *
12
+ * 1. Type definitions for extension API (window.peer)
13
+ * 2. useZKTLS hook for React components
14
+ * 3. Utility functions for transaction matching and proof encoding
15
+ *
16
+ * @remarks
17
+ * The extension exposes `window.peer` (or deprecated `window.zktls`) for:
18
+ * - Requesting connection (OAuth-like flow)
19
+ * - Authenticating with payment providers
20
+ * - Generating notarized proofs
21
+ * - Fetching transaction metadata
22
+ *
23
+ * @see {@link ZKTLSContext} for the React context provider
24
+ */
25
+
26
+ declare global {
27
+ interface ZKTLS {
28
+ requestConnection(): Promise<boolean>;
29
+ checkConnectionStatus(): Promise<Status>;
30
+ getVersion(): Promise<string>;
31
+ authenticate(inputs: AuthenticationInputs): Promise<void>;
32
+ generateProof(inputs: GenerateProofInputs): Promise<GenerateProofResponse>;
33
+ fetchProofById(proofId: string): Promise<ProofResponse>;
34
+ fetchProofs(): Promise<FetchProofsResponse>;
35
+ openSidebar(route: string): Promise<void>;
36
+ onMetadataMessage(fn: (data: MetadataMessageResponse) => void): () => void;
37
+ }
38
+ interface Window {
39
+ /** @deprecated Use window.peer instead */
40
+ zktls: ZKTLS | undefined;
41
+ /** PeerAuth extension API (replaces window.zktls) */
42
+ peer: ZKTLS | undefined;
43
+ }
44
+ }
45
+ /** the status of the PeerAuth extension */
46
+ type Status = 'connected' | 'disconnected' | 'pending';
47
+ /** the individual metadata message sent by the PeerAuth extension */
48
+ interface MetadataMessage {
49
+ amount: number;
50
+ /** Currency code (e.g., 'USD', 'EUR') */
51
+ currency?: string;
52
+ /**
53
+ * Date of the transaction.
54
+ * Can be a string in YYYYMMDD format, a number (YYYYMMDD or timestamp), or Date object.
55
+ * The actual type depends on the extension implementation.
56
+ */
57
+ date: string | number | Date;
58
+ hidden: boolean;
59
+ originalIndex: number;
60
+ paymentId: number;
61
+ recipient: string;
62
+ }
63
+ /** the response from the PeerAuth extension when a metadata message is received */
64
+ interface MetadataMessageResponse {
65
+ expiresAt: number;
66
+ platform: ProviderKey;
67
+ requestId: string;
68
+ metadata: MetadataMessage[];
69
+ }
70
+ /** the response from the PeerAuth extension when fetching proofs */
71
+ interface FetchProofsResponse {
72
+ notaryRequests: NotaryRequest[];
73
+ }
74
+ /** the inputs for the generateProof function */
75
+ type GenerateProofInputsAbstracted = {
76
+ platform: PlatformKey;
77
+ provider: ProviderKey;
78
+ intentHash: Hex;
79
+ originalIndex: number;
80
+ };
81
+ /** the inputs for the generateProof function */
82
+ type GenerateProofInputs = {
83
+ platform: ProviderKey;
84
+ originalIndex: number;
85
+ proofIndex?: number;
86
+ intentHash: string;
87
+ };
88
+ /**
89
+ * inputs for the generate proof function that requires the intent hash
90
+ * as hex to ensure it can be converted to a bigint string accurately
91
+ */
92
+ type HexIntentGenerateProofInputs = Exclude<GenerateProofInputs, 'intentHash'> & {
93
+ intentHash: Hex;
94
+ };
95
+ /** the response from the PeerAuth extension when generating a proof */
96
+ type GenerateProofResponse = {
97
+ proofId: string;
98
+ platform: ProviderKey;
99
+ };
100
+ /** the inputs for the authenticate function */
101
+ type AuthenticationInputs = {
102
+ actionType: ActionType;
103
+ platform: PlatformKey;
104
+ };
105
+ /** the response from the PeerAuth extension when fetching a proof */
106
+ interface Proof {
107
+ claimInfo: ClaimInfo;
108
+ signedClaim: SignedClaim;
109
+ isAppclipProof: boolean;
110
+ status: string;
111
+ }
112
+ /** the response from the PeerAuth extension when fetching a proof */
113
+ interface NotarizedProof {
114
+ claim: {
115
+ context: string;
116
+ epoch: number;
117
+ identifier: Hex;
118
+ owner: Hex;
119
+ parameters: string;
120
+ provider: string;
121
+ timestampS: number;
122
+ };
123
+ signatures: {
124
+ attestorAddress: Hex;
125
+ claimSignature: Record<number, number>;
126
+ resultSignature: Record<number, number>;
127
+ };
128
+ }
129
+ /** the claim info for a proof */
130
+ interface ClaimInfo {
131
+ provider: string;
132
+ parameters: string;
133
+ context: string;
134
+ }
135
+ /** the complete claim data for a proof */
136
+ interface CompleteClaimData {
137
+ identifier: Hex;
138
+ owner: Hex;
139
+ timestampS: number;
140
+ epoch: number;
141
+ }
142
+ /** the signed claim for a proof */
143
+ interface SignedClaim {
144
+ claim: CompleteClaimData;
145
+ signatures: Hex[];
146
+ }
147
+ /** the reclaim proof for a proof */
148
+ type ReclaimProof = {
149
+ claimInfo: ClaimInfo;
150
+ signedClaim: SignedClaim;
151
+ isAppclipProof: boolean;
152
+ };
153
+ /** the notary request for a proof */
154
+ interface NotaryRequest {
155
+ metadata: (string | number)[];
156
+ actionType: ActionType;
157
+ id: string;
158
+ status: string;
159
+ timestamp: number;
160
+ proof: NotarizedProof;
161
+ }
162
+ /** the response from the PeerAuth extension when fetching a proof */
163
+ interface ProofResponse {
164
+ notaryRequest: NotaryRequest;
165
+ }
166
+ declare const extensionUrl = "https://chromewebstore.google.com/detail/ijpgccednehjpeclfcllnjjcmiohdjih";
167
+ /** convert a byte array to a hex string */
168
+ declare const byteArrayToHexString: (byteArray: number[]) => Hex;
169
+ /** parse a proof object from the PeerAuth extension */
170
+ declare const parseExtensionProof: (proofObject: NotarizedProof) => ReclaimProof;
171
+ /** the abi encoding for a proof */
172
+ declare const PROOF_ENCODING: {
173
+ readonly type: "tuple";
174
+ readonly components: readonly [{
175
+ readonly type: "tuple";
176
+ readonly components: readonly [{
177
+ readonly type: "string";
178
+ readonly name: "provider";
179
+ }, {
180
+ readonly type: "string";
181
+ readonly name: "parameters";
182
+ }, {
183
+ readonly type: "string";
184
+ readonly name: "context";
185
+ }];
186
+ readonly name: "claimInfo";
187
+ }, {
188
+ readonly type: "tuple";
189
+ readonly components: readonly [{
190
+ readonly type: "tuple";
191
+ readonly components: readonly [{
192
+ readonly type: "bytes32";
193
+ readonly name: "identifier";
194
+ }, {
195
+ readonly type: "address";
196
+ readonly name: "owner";
197
+ }, {
198
+ readonly type: "uint32";
199
+ readonly name: "timestampS";
200
+ }, {
201
+ readonly type: "uint32";
202
+ readonly name: "epoch";
203
+ }];
204
+ readonly name: "claim";
205
+ }, {
206
+ readonly type: "bytes[]";
207
+ readonly name: "signatures";
208
+ }];
209
+ readonly name: "signedClaim";
210
+ }, {
211
+ readonly type: "bool";
212
+ readonly name: "isAppclipProof";
213
+ }];
214
+ };
215
+ /** encode a single proof as a bytes array */
216
+ declare function encodeProofAsBytes(proof: ReclaimProof): Hex;
217
+ /** encode two proofs to be passed to the underlying sub-provider */
218
+ declare const encodeTwoProofs: (proof1: ReclaimProof, proof2: ReclaimProof) => `0x${string}`;
219
+ /** a high level function to encode a proof for a given provider and sub-provider */
220
+ declare const encodeProof: ({ extensionProofs, subProvider, provider }: {
221
+ extensionProofs: NotarizedProof[];
222
+ subProvider: PlatformKey | null;
223
+ provider: ProviderKey;
224
+ }) => `0x${string}`;
225
+ /**
226
+ * wrap a proof with a payment method and proof
227
+ * this allows us to use a single verifier as an entry point for multiple underlying sub-providers
228
+ */
229
+ declare const encodeProofWithPaymentMethod: ({ proof, paymentMethod }: {
230
+ proof: Hex;
231
+ paymentMethod: number;
232
+ }) => Hex;
233
+ /** the progress of a proof series */
234
+ declare enum SeriesProgress {
235
+ Generating = 0,
236
+ Polling = 1,
237
+ Complete = 2
238
+ }
239
+ type ProgressInfo = {
240
+ progress: SeriesProgress;
241
+ total: number;
242
+ step: number | null;
243
+ id: string | null;
244
+ };
245
+ /** the mutations for the generate proof series function */
246
+ type GenerateProofSeriesMutations = {
247
+ progress?: ({ progress, step, id }: ProgressInfo) => void;
248
+ setOwnerName?: (name: string) => void;
249
+ };
250
+ /** React hook to interact with the PeerAuth extension */
251
+ declare const useZKTLS: () => {
252
+ /** check if the PeerAuth extension is initialized */
253
+ isInitialized: boolean;
254
+ /** request a connection to the PeerAuth extension */
255
+ requestConnection: () => Promise<boolean>;
256
+ /**
257
+ * check the connection status of the PeerAuth extension
258
+ * @returns the connection status
259
+ */
260
+ checkConnectionStatus: () => Promise<Status>;
261
+ /** get the version of the PeerAuth extension */
262
+ getVersion: () => Promise<string | undefined>;
263
+ /** authenticate with the PeerAuth extension */
264
+ authenticate: (inputs: AuthenticationInputs) => Promise<MetadataMessageResponse>;
265
+ /** generate a proof */
266
+ generateProof: (inputs: HexIntentGenerateProofInputs) => Promise<GenerateProofResponse>;
267
+ /** wait for a proof to be generated */
268
+ waitForProof: (proofId: string, onCurrent?: (notaryRequest: NotaryRequest | null) => void) => Promise<NotaryRequest>;
269
+ /** generate a proof series */
270
+ generateProofSeries: (inputs: GenerateProofInputsAbstracted, { progress: progressCallback }?: GenerateProofSeriesMutations) => Promise<NotaryRequest[]>;
271
+ /** subscribe to metadata messages */
272
+ onMetadataMessage: (fn: (data: any) => void) => () => void;
273
+ /** fetch a proof by its id */
274
+ fetchProofById: (proofId: string) => Promise<NotaryRequest | null>;
275
+ /** fetch generated proofs */
276
+ fetchGeneratedProofs: (genProofResponses: GenerateProofResponse[]) => Promise<(NotaryRequest | null)[]>;
277
+ /** fetch all proofs */
278
+ fetchProofs: () => Promise<FetchProofsResponse>;
279
+ /** open the PeerAuth sidebar */
280
+ openSidebar: (route: string) => Promise<void>;
281
+ };
282
+ /**
283
+ * Find the metadata message that matches the intent by amount.
284
+ * Returns the first (most recent) transaction in the metadata array that matches the expected amount.
285
+ *
286
+ * Simplified matching: just find transactions with the correct amount.
287
+ * The user can manually select if multiple matches exist.
288
+ */
289
+ declare const findMetadataMessage: ({ metadata, intent, token, centIsInt }: {
290
+ metadata: MetadataMessage[];
291
+ intent: IntentStruct;
292
+ token: TokenInfo;
293
+ /** @deprecated No longer used - kept for API compatibility */
294
+ recipient?: string;
295
+ centIsInt?: boolean;
296
+ }) => MetadataMessage | null;
297
+
298
+ export { type AuthenticationInputs, type ClaimInfo, type CompleteClaimData, type FetchProofsResponse, type GenerateProofInputs, type GenerateProofInputsAbstracted, type GenerateProofResponse, type GenerateProofSeriesMutations, type HexIntentGenerateProofInputs, type MetadataMessage, type MetadataMessageResponse, type NotarizedProof, type NotaryRequest, PROOF_ENCODING, type ProgressInfo, type Proof, type ProofResponse, type ReclaimProof, SeriesProgress, type SignedClaim, type Status, byteArrayToHexString, encodeProof, encodeProofAsBytes, encodeProofWithPaymentMethod, encodeTwoProofs, extensionUrl, findMetadataMessage, parseExtensionProof, useZKTLS };
@@ -0,0 +1,3 @@
1
+ export { PROOF_ENCODING, SeriesProgress, byteArrayToHexString, encodeProof, encodeProofAsBytes, encodeProofWithPaymentMethod, encodeTwoProofs, extensionUrl, findMetadataMessage, parseExtensionProof, useZKTLS } from './chunk-DVOEKDW7.js';
2
+ //# sourceMappingURL=useZKTLS.js.map
3
+ //# sourceMappingURL=useZKTLS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"useZKTLS.js"}
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var viem = require('viem');
5
+ require('@provex/utils/time');
6
+ require('@provex/utils/payment');
7
+ require('@provex/utils/conversionRates');
8
+ require('react/jsx-runtime');
9
+
10
+ // src/ZKTLSContext.tsx
11
+ viem.parseAbiParameter("((string provider, string parameters, string context) claimInfo, ((bytes32 identifier, address owner, uint32 timestampS, uint32 epoch) claim, bytes[] signatures) signedClaim, bool isAppclipProof)");
12
+ var ZKTLSContext = react.createContext(void 0);
13
+ function useZKTLSContext() {
14
+ const context = react.useContext(ZKTLSContext);
15
+ if (context === void 0) {
16
+ throw new Error("useZKTLSContext must be used within a ZKTLSProvider");
17
+ }
18
+ return context;
19
+ }
20
+
21
+ exports.useZKTLSContext = useZKTLSContext;
22
+ //# sourceMappingURL=useZKTLSContext.cjs.map
23
+ //# sourceMappingURL=useZKTLSContext.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useZKTLS.ts","../src/ZKTLSContext.tsx"],"names":["parseAbiParameter","createContext","useContext"],"mappings":";;;;;;;;;;AAuN8BA,uBAAkB,qMAAqM;ACtM9O,IAAM,YAAA,GAAeC,oBAA4C,MAAS,CAAA;AAY1E,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,OAAA,GAAUC,iBAAW,YAAY,CAAA;AACvC,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,EACvE;AACA,EAAA,OAAO,OAAA;AACT","file":"useZKTLSContext.cjs","sourcesContent":["/**\n * @fileoverview React hook and utilities for PeerAuth browser extension integration.\n *\n * The PeerAuth extension (formerly ZK-TLS) provides secure proof generation\n * for off-chain payment verification. This module provides:\n *\n * 1. Type definitions for extension API (window.peer)\n * 2. useZKTLS hook for React components\n * 3. Utility functions for transaction matching and proof encoding\n *\n * @remarks\n * The extension exposes `window.peer` (or deprecated `window.zktls`) for:\n * - Requesting connection (OAuth-like flow)\n * - Authenticating with payment providers\n * - Generating notarized proofs\n * - Fetching transaction metadata\n *\n * @see {@link ZKTLSContext} for the React context provider\n */\n\nimport { useEffect, useMemo, useState } from \"react\"\nimport { encodeAbiParameters, encodePacked, parseAbiParameter, parseUnits, type Hex } from \"viem\"\nimport { sleep } from \"@provex/utils/time\"\nimport type { IntentStruct } from \"@provex/utils/intent\"\nimport type { TokenInfo } from \"@provex/utils/tokens\"\nimport { extensionPlatforms, providers, subProviderConfigs, type ActionType, type PlatformKey, type ProviderKey, type SubProviderKey } from \"@provex/utils/payment\"\nimport { convertTokenInputToCurrency } from \"@provex/utils/conversionRates\"\n\ndeclare global {\n interface ZKTLS {\n requestConnection(): Promise<boolean>\n checkConnectionStatus(): Promise<Status>\n getVersion(): Promise<string>\n authenticate(inputs: AuthenticationInputs): Promise<void>\n generateProof(inputs: GenerateProofInputs): Promise<GenerateProofResponse>\n fetchProofById(proofId: string): Promise<ProofResponse>\n fetchProofs(): Promise<FetchProofsResponse>\n openSidebar(route: string): Promise<void>\n onMetadataMessage(fn: (data: MetadataMessageResponse) => void): () => void\n }\n interface Window {\n /** @deprecated Use window.peer instead */\n zktls: ZKTLS | undefined\n /** PeerAuth extension API (replaces window.zktls) */\n peer: ZKTLS | undefined\n }\n}\n\n/** the status of the PeerAuth extension */\nexport type Status = 'connected' | 'disconnected' | 'pending'\n\n/** the individual metadata message sent by the PeerAuth extension */\nexport interface MetadataMessage {\n amount: number\n /** Currency code (e.g., 'USD', 'EUR') */\n currency?: string\n /**\n * Date of the transaction.\n * Can be a string in YYYYMMDD format, a number (YYYYMMDD or timestamp), or Date object.\n * The actual type depends on the extension implementation.\n */\n date: string | number | Date\n hidden: boolean\n originalIndex: number\n paymentId: number\n recipient: string\n}\n\n/** the response from the PeerAuth extension when a metadata message is received */\nexport interface MetadataMessageResponse {\n expiresAt: number\n platform: ProviderKey\n requestId: string\n metadata: MetadataMessage[]\n}\n\n/** the response from the PeerAuth extension when fetching proofs */\nexport interface FetchProofsResponse {\n notaryRequests: NotaryRequest[]\n}\n\n/** the inputs for the generateProof function */\nexport type GenerateProofInputsAbstracted = {\n platform: PlatformKey\n provider: ProviderKey\n intentHash: Hex\n originalIndex: number\n}\n\n/** the inputs for the generateProof function */\nexport type GenerateProofInputs = {\n platform: ProviderKey\n originalIndex: number\n proofIndex?: number\n intentHash: string\n}\n\n/**\n * inputs for the generate proof function that requires the intent hash\n * as hex to ensure it can be converted to a bigint string accurately\n */\nexport type HexIntentGenerateProofInputs = Exclude<GenerateProofInputs, 'intentHash'> & { intentHash: Hex }\n\n/** the response from the PeerAuth extension when generating a proof */\nexport type GenerateProofResponse = {\n proofId: string\n platform: ProviderKey\n}\n\n/** the inputs for the authenticate function */\nexport type AuthenticationInputs = {\n actionType: ActionType\n platform: PlatformKey\n}\n\n/** the response from the PeerAuth extension when fetching a proof */\nexport interface Proof {\n claimInfo: ClaimInfo\n signedClaim: SignedClaim\n isAppclipProof: boolean\n status: string\n}\n\n/** the response from the PeerAuth extension when fetching a proof */\nexport interface NotarizedProof {\n claim: {\n context: string\n epoch: number\n identifier: Hex\n owner: Hex\n parameters: string\n provider: string\n timestampS: number\n },\n signatures: {\n attestorAddress: Hex\n claimSignature: Record<number, number>\n resultSignature: Record<number, number>\n },\n}\n\n/** the claim info for a proof */\nexport interface ClaimInfo {\n provider: string\n parameters: string\n context: string\n}\n\n/** the complete claim data for a proof */\nexport interface CompleteClaimData {\n identifier: Hex\n owner: Hex\n timestampS: number\n epoch: number\n}\n\n/** the signed claim for a proof */\nexport interface SignedClaim {\n claim: CompleteClaimData\n signatures: Hex[]\n}\n\n/** the reclaim proof for a proof */\nexport type ReclaimProof = {\n claimInfo: ClaimInfo\n signedClaim: SignedClaim\n isAppclipProof: boolean\n}\n\n/** the notary request for a proof */\nexport interface NotaryRequest {\n metadata: (string | number)[]\n actionType: ActionType\n id: string\n status: string\n timestamp: number\n proof: NotarizedProof\n}\n\n/** the response from the PeerAuth extension when fetching a proof */\nexport interface ProofResponse {\n notaryRequest: NotaryRequest\n}\n\nexport const extensionUrl = 'https://chromewebstore.google.com/detail/ijpgccednehjpeclfcllnjjcmiohdjih'\n\n/** convert a byte array to a hex string */\nexport const byteArrayToHexString = (byteArray: number[]): Hex => {\n return `0x${byteArray\n .map(byte => byte.toString(16).padStart(2, '0'))\n .join('')}`\n}\n\n/** parse a proof object from the PeerAuth extension */\nexport const parseExtensionProof = (proofObject: NotarizedProof) => {\n return {\n claimInfo: {\n provider: proofObject.claim.provider,\n parameters: proofObject.claim.parameters,\n context: proofObject.claim.context\n },\n signedClaim: {\n claim: {\n identifier: proofObject.claim.identifier as Hex,\n owner: proofObject.claim.owner as Hex,\n timestampS: proofObject.claim.timestampS,\n epoch: proofObject.claim.epoch\n },\n signatures: [byteArrayToHexString(Object.values(proofObject.signatures.claimSignature))]\n },\n isAppclipProof: false\n } as ReclaimProof\n}\n\n/** the abi encoding for a proof */\nexport const PROOF_ENCODING = parseAbiParameter(\"((string provider, string parameters, string context) claimInfo, ((bytes32 identifier, address owner, uint32 timestampS, uint32 epoch) claim, bytes[] signatures) signedClaim, bool isAppclipProof)\")\n\n/** encode a single proof as a bytes array */\nexport function encodeProofAsBytes(proof: ReclaimProof): Hex {\n return encodeAbiParameters([PROOF_ENCODING], [proof])\n}\n\n/** encode two proofs to be passed to the underlying sub-provider */\nexport const encodeTwoProofs = (proof1: ReclaimProof, proof2: ReclaimProof) => {\n return encodeAbiParameters([PROOF_ENCODING, PROOF_ENCODING], [proof1, proof2])\n}\n\n/** a high level function to encode a proof for a given provider and sub-provider */\nexport const encodeProof = ({ extensionProofs, subProvider, provider }: {\n extensionProofs: NotarizedProof[],\n subProvider: PlatformKey | null,\n provider: ProviderKey\n}) => {\n const reclaimProofs = extensionProofs.map((p) => parseExtensionProof(p))\n if (provider === 'zelle') {\n // move this to check the blockchain for the payment method\n const paymentMethod = subProviderConfigs![provider]![subProvider as SubProviderKey]!.paymentMethod\n const twoEncoded = reclaimProofs.length === 2\n ? encodeTwoProofs(reclaimProofs[0]!, reclaimProofs[1]!)\n : encodeProofAsBytes(reclaimProofs[0]!)\n // select between various possible sub-providers\n const withPaymentMethod = encodeProofWithPaymentMethod({\n paymentMethod,\n proof: twoEncoded,\n })\n return withPaymentMethod\n }\n const [reclaimProof] = reclaimProofs\n return encodeProofAsBytes(reclaimProof!)\n}\n\n/**\n * wrap a proof with a payment method and proof\n * this allows us to use a single verifier as an entry point for multiple underlying sub-providers\n */\nexport const encodeProofWithPaymentMethod = ({\n proof,\n paymentMethod\n}: {\n proof: Hex,\n paymentMethod: number\n}): Hex => {\n return encodePacked(['uint8', 'bytes'], [paymentMethod, proof])\n}\n\n/** the progress of a proof series */\nexport enum SeriesProgress {\n Generating,\n Polling,\n Complete,\n}\n\nexport type ProgressInfo = {\n progress: SeriesProgress\n total: number\n step: number | null\n id: string | null\n}\n\n/** the mutations for the generate proof series function */\nexport type GenerateProofSeriesMutations = {\n progress?: ({ progress, step, id }: ProgressInfo) => void\n setOwnerName?: (name: string) => void\n}\n\n/** React hook to interact with the PeerAuth extension */\nexport const useZKTLS = () => {\n const [isInitialized, setIsInitialized] = useState(false)\n useEffect(() => {\n const setup = () => {\n setIsInitialized(true)\n }\n const eventName = 'peer#initialized'\n if (typeof window.peer !== 'undefined') {\n // api is available\n setup()\n } else {\n window.addEventListener(eventName, setup)\n return () => {\n window.removeEventListener(eventName, setup)\n }\n }\n }, [])\n return useMemo(() => {\n /** fetch a proof by its id */\n const fetchProofById = async (proofId: string): Promise<NotaryRequest | null> => {\n const proof = await window.peer!.fetchProofById(proofId)\n if (proof && proof.notaryRequest) return proof.notaryRequest\n const proofs = await window.peer!.fetchProofs()\n const proofFromList = proofs.notaryRequests.find((p) => p.id === proofId)\n if (proofFromList) return proofFromList\n return null\n }\n /** wait for a proof to be generated */\n const waitForProof = async (proofId: string, onCurrent?: (notaryRequest: NotaryRequest | null) => void) => {\n let notaryRequest: NotaryRequest | null = null\n do {\n notaryRequest = await fetchProofById(proofId)\n onCurrent?.(notaryRequest)\n await sleep(1_000)\n } while (!notaryRequest || !notaryRequest.status || notaryRequest.status === 'pending')\n if (notaryRequest.status === 'failed' || notaryRequest.status === 'expired' || notaryRequest.status === 'cancelled' || notaryRequest.status === 'error') {\n throw new Error(`Proof generation failed: ${notaryRequest.status}`)\n }\n return notaryRequest\n }\n /** generate a proof */\n const generateProof = async (inputs: HexIntentGenerateProofInputs): Promise<GenerateProofResponse> => {\n return await window.peer!.generateProof({\n proofIndex: 0,\n ...inputs,\n intentHash: BigInt(inputs.intentHash).toString(),\n })\n }\n return {\n /** check if the PeerAuth extension is initialized */\n isInitialized,\n /** request a connection to the PeerAuth extension */\n requestConnection: async () => {\n if (!window.peer) return false\n return window.peer!.requestConnection()\n },\n /**\n * check the connection status of the PeerAuth extension\n * @returns the connection status\n */\n checkConnectionStatus: async () => {\n return await window.peer!.checkConnectionStatus()\n },\n /** get the version of the PeerAuth extension */\n getVersion: async () => {\n return await window.peer?.getVersion()\n },\n /** authenticate with the PeerAuth extension */\n authenticate: async (inputs: AuthenticationInputs) => {\n // Create promise first to avoid race condition where message arrives before resolver is assigned\n let resolve: (value: MetadataMessageResponse) => void\n const promise = new Promise<MetadataMessageResponse>((resolver) => {\n resolve = resolver\n })\n\n // Now set up the listener - resolve is guaranteed to be the real resolver\n const unsub = window.peer!.onMetadataMessage((data) => {\n if (`transfer_${data.platform}` === inputs.actionType) {\n resolve(data)\n }\n })\n\n await window.peer!.authenticate(inputs)\n\n return await promise.then((data) => {\n unsub()\n return data\n })\n },\n /** generate a proof */\n generateProof,\n /** wait for a proof to be generated */\n waitForProof,\n /** generate a proof series */\n generateProofSeries: async (\n inputs: GenerateProofInputsAbstracted,\n { progress: progressCallback }: GenerateProofSeriesMutations = {},\n ): Promise<NotaryRequest[]> => {\n const { platform, provider, intentHash, originalIndex } = inputs\n const args = {\n platform: provider,\n originalIndex,\n intentHash,\n } as const\n // Chase requires 2 proofs (account verification + transaction)\n // Platform is the bank name (e.g., 'chase') from extensionPlatform config\n const isChase = platform === extensionPlatforms.CHASE\n const isZelle = provider === providers.ZELLE\n const expectedTotal = isZelle && isChase ? 2 : 1\n progressCallback?.({ progress: SeriesProgress.Generating, step: 0, id: null, total: expectedTotal })\n const genProofA = await generateProof({ ...args, proofIndex: 0 })\n progressCallback?.({ progress: SeriesProgress.Polling, step: 0, id: genProofA.proofId, total: expectedTotal })\n const proofA = await waitForProof(genProofA.proofId)\n if (!isChase || !isZelle) {\n progressCallback?.({ progress: SeriesProgress.Complete, step: null, id: null, total: expectedTotal })\n return [proofA]\n }\n progressCallback?.({ progress: SeriesProgress.Generating, step: 1, id: null, total: expectedTotal })\n const genProofB = await generateProof({ ...args, proofIndex: 1 })\n progressCallback?.({ progress: SeriesProgress.Polling, step: 1, id: genProofB.proofId, total: expectedTotal })\n const proofB = await waitForProof(genProofB.proofId)\n progressCallback?.({ progress: SeriesProgress.Complete, step: null, id: null, total: expectedTotal })\n return [proofA, proofB]\n },\n /** subscribe to metadata messages */\n onMetadataMessage: (fn: (data: any) => void) => {\n return window.peer!.onMetadataMessage(fn)\n },\n /** fetch a proof by its id */\n fetchProofById,\n /** fetch generated proofs */\n fetchGeneratedProofs: async (genProofResponses: GenerateProofResponse[]) => {\n return await Promise.all(genProofResponses.map((r) => fetchProofById(r.proofId)))\n },\n /** fetch all proofs */\n fetchProofs: async () => {\n return await window.peer!.fetchProofs()\n },\n /** open the PeerAuth sidebar */\n openSidebar: async (route: string) => {\n return await window.peer!.openSidebar(route)\n },\n }\n }, [isInitialized])\n}\n\n/**\n * Find the metadata message that matches the intent by amount.\n * Returns the first (most recent) transaction in the metadata array that matches the expected amount.\n *\n * Simplified matching: just find transactions with the correct amount.\n * The user can manually select if multiple matches exist.\n */\nexport const findMetadataMessage = ({ metadata, intent, token, centIsInt = false }: {\n metadata: MetadataMessage[],\n intent: IntentStruct,\n token: TokenInfo,\n /** @deprecated No longer used - kept for API compatibility */\n recipient?: string,\n centIsInt?: boolean,\n}): MetadataMessage | null => {\n const currencyAmount = convertTokenInputToCurrency({\n token,\n amountOutInt: intent.amount,\n rate: intent.conversionRate,\n })\n /**\n * Normalize an amount from the extension into a bigint in token base units.\n *\n * The extension sends amounts in different formats per provider:\n * - Venmo: `\"- $1.00\"` (formatted dollar string)\n * - Others: `100` (integer cents) or `1.00` (decimal dollars)\n *\n * We detect the format by checking for currency symbols or decimal points\n * in the raw value. If present, the value is already in dollars and we\n * skip the centIsInt division.\n */\n const normalizeAmount = (amount: number | string): bigint => {\n const raw = String(amount)\n const isFormattedDollars = /[^0-9\\-]/.test(raw) && raw.includes('.')\n const cleaned = raw.replace(/[^0-9.]/g, '')\n let value = parseUnits(cleaned, token.decimals)\n if (centIsInt && !isFormattedDollars) {\n value = value / 100n\n }\n return value\n }\n\n // Skip auto-match when manual selection is forced (dev/testing)\n if (typeof window !== 'undefined' && (window as unknown as Record<string, unknown>).__FORCE_MANUAL_TX_SELECT__) {\n return null\n }\n\n // Find the first transaction that matches the amount (first in array = most recent)\n // Note: We ignore the hidden flag - matching is purely by amount\n const match = metadata.find((m) => {\n const converted = normalizeAmount(m.amount)\n return converted === currencyAmount || converted === (currencyAmount * -1n)\n })\n\n if (!match) {\n return null\n }\n\n return match\n}\n","/**\n * @fileoverview React context for PeerAuth extension state.\n *\n * Provides global access to the useZKTLS hook state throughout the\n * component tree, avoiding prop drilling for extension status.\n *\n * @see {@link useZKTLS} for the underlying hook\n */\n\nimport { createContext, useContext, type ReactNode } from 'react'\nimport { useZKTLS } from './useZKTLS'\n\n/**\n * Context type derived from useZKTLS hook return value.\n */\ntype ZKTLSContextType = ReturnType<typeof useZKTLS>\n\nexport const ZKTLSContext = createContext<ZKTLSContextType | undefined>(undefined)\n\ninterface ZKTLSProviderProps {\n children: ReactNode\n}\n\n/**\n * Hook to consume the ZKTLS context.\n * Must be used within a ZKTLSProvider.\n *\n * @throws Error if used outside of ZKTLSProvider\n */\nexport function useZKTLSContext() {\n const context = useContext(ZKTLSContext)\n if (context === undefined) {\n throw new Error('useZKTLSContext must be used within a ZKTLSProvider')\n }\n return context\n}\n\nexport function ZKTLSProvider({ children }: ZKTLSProviderProps) {\n const zktlsHook = useZKTLS()\n\n return (\n <ZKTLSContext.Provider value={zktlsHook}>\n {children}\n </ZKTLSContext.Provider>\n )\n}\n"]}
@@ -0,0 +1,8 @@
1
+ export { useZKTLSContext } from './ZKTLSContext.cjs';
2
+ import './useZKTLS.cjs';
3
+ import 'viem';
4
+ import '@provex/utils/intent';
5
+ import '@provex/utils/tokens';
6
+ import '@provex/utils/payment';
7
+ import 'react/jsx-runtime';
8
+ import 'react';