@coordination-network/network-member-client 0.0.1

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,550 @@
1
+ import { Hex32, SerializedZkCredential, CredentialSigner, ApprovalResolver, ZkCredentialIssueParams } from '@coordination-network/credential';
2
+ export { ApprovalResolver, CredentialSigner } from '@coordination-network/credential';
3
+ import { IssuerMembershipWitness, ContractLeafReader, IssuerPublicKey } from '@coordination-network/issuer-set';
4
+ export { ContractLeafReader, IssuerMembershipWitness } from '@coordination-network/issuer-set';
5
+ import { buildAnnouncement, Hex, Address } from '@coordination-network/identity';
6
+ import { RegistryLocation, NetworkMemberProof, IdentityUpdate, RevocationUpdate } from '@coordination-network/network-member-proof';
7
+ import { Group } from '@semaphore-protocol/group';
8
+ import { ChainDomain, RegistrationRequest } from '@coordination-network/user-client';
9
+ export { ChainDomain, RegistrationRequest } from '@coordination-network/user-client';
10
+ import { Address as Address$1, PublicClient, WalletClient, Transport, Chain, Account, Hex as Hex$1, SignedAuthorization, TransactionReceipt } from 'viem';
11
+ import { Identity } from '@semaphore-protocol/identity';
12
+ import { entryPoint08Abi } from 'viem/account-abstraction';
13
+
14
+ type NetworkMemberClientErrorCode = "ISSUER_KEY_NOT_PUBLISHED" | "MEMBER_NOT_APPROVED" | "RECIPIENT_NOT_REGISTERED" | "INVALID_META_STEALTH_ADDRESS" | "INVALID_REGISTRATION_REQUEST" | "REGISTRY_UNAVAILABLE" | "GROUP_MIRROR_UNAVAILABLE" | "MEMBER_NOT_IN_GROUP" | "REGISTRATION_REJECTED" | "REVOCATION_REJECTED";
15
+ declare class NetworkMemberClientError extends Error {
16
+ readonly code: NetworkMemberClientErrorCode;
17
+ readonly cause?: unknown;
18
+ constructor(code: NetworkMemberClientErrorCode, message: string, cause?: unknown);
19
+ }
20
+ /** A named revert from IdentityRegistry or Semaphore, walked out of a viem contract-call error. */
21
+ declare class RegistryRevertError extends NetworkMemberClientError {
22
+ readonly errorName: string;
23
+ constructor(errorName: string, cause?: unknown);
24
+ }
25
+ /**
26
+ * A revert from CredentialRevocationRegistry, or from the revocation service or Semaphore behind
27
+ * it. `reason` is the decoded error name, or the raw revert data when nothing in the registry's
28
+ * ABI matches it: a caller retries `InvalidLowLeaf` against a re-synced mirror and gives up on
29
+ * `LeafAlreadyExists`, so it has to be able to tell them apart.
30
+ */
31
+ declare class RevocationRevertError extends NetworkMemberClientError {
32
+ readonly reason: string;
33
+ constructor(reason: string, cause?: unknown);
34
+ }
35
+
36
+ /** issueVC's result: the signed claim-tree credential plus a fresh Merkle path into the approved-issuer set. */
37
+ interface IssuedCredential {
38
+ credential: SerializedZkCredential;
39
+ issuerSetRoot: bigint;
40
+ issuerMembershipWitness: IssuerMembershipWitness;
41
+ }
42
+ /**
43
+ * Reads `IdentityRegistry.identity(networkId)`. Empty bytes on chain (unregistered) resolves to
44
+ * null. The method name matches the UserClient's registry-reader port so one adapter serves both.
45
+ */
46
+ interface IdentityReader {
47
+ /** The IdentityRegistry deployment this reader targets, when the reader knows one. submitRegistration checks it against `domain`. */
48
+ readonly registryAddress?: Address;
49
+ getIdentity(networkId: Hex32): Promise<Hex | null>;
50
+ }
51
+ /** `buildAnnouncement`'s return shape, derived rather than restated so it can't drift. */
52
+ type Announcement = ReturnType<typeof buildAnnouncement>;
53
+ /** Submits a built ERC-5564 announcement on chain. */
54
+ interface AnnouncementSubmitter {
55
+ announce(announcement: Announcement): Promise<Hex>;
56
+ }
57
+ /**
58
+ * deliverToStealth's result. txHash is the hash of the submitted announce transaction, not proof
59
+ * of inclusion: confirm it before treating the delivery as done.
60
+ */
61
+ interface DeliveredToStealth {
62
+ stealthAddress: Address;
63
+ announcement: Announcement;
64
+ txHash: Hex;
65
+ }
66
+ /** The approved-member group, rebuilt fresh on every call so a proof always proves against a live root. */
67
+ interface GroupMirror {
68
+ currentGroup(): Promise<Group>;
69
+ }
70
+ /** Produces the membership proof authorising one IdentityRegistry write. */
71
+ interface RegistrationProver {
72
+ /** The IdentityRegistry deployment this proof is bound to. submitRegistration checks it against `domain`. */
73
+ readonly registry: RegistryLocation;
74
+ prove(update: IdentityUpdate): Promise<NetworkMemberProof>;
75
+ }
76
+ /** Produces the membership proof authorising one CredentialRevocationRegistry write. */
77
+ interface RevocationProver {
78
+ /** The CredentialRevocationRegistry deployment this proof is bound to. */
79
+ readonly registry: RegistryLocation;
80
+ prove(update: RevocationUpdate): Promise<NetworkMemberProof>;
81
+ }
82
+ /**
83
+ * Facts about a sponsored registerIdentity call: what the disposable sender and the paymaster's
84
+ * deposit looked like before and after, so a caller can show what the paymaster actually paid.
85
+ */
86
+ interface Sponsorship {
87
+ sender: Address;
88
+ senderBalanceBefore: bigint;
89
+ senderBalanceAfter: bigint;
90
+ userOpHash: Hex;
91
+ bundleTxHash: Hex;
92
+ actualGasCost: bigint;
93
+ paymaster: Address;
94
+ paymasterDepositBefore: bigint;
95
+ paymasterDepositAfter: bigint;
96
+ }
97
+ /**
98
+ * registerIdentity's result. txHash is the hash of the write (or, when sponsored, the bundle)
99
+ * transaction, not proof of inclusion: confirm it before treating the registration as done.
100
+ */
101
+ interface RegistrationWrite {
102
+ txHash: Hex;
103
+ sponsorship?: Sponsorship;
104
+ }
105
+ /** Submits a network-member-authorised write to `IdentityRegistry`. */
106
+ interface RegistrationWriter {
107
+ /** The IdentityRegistry deployment this writer targets. submitRegistration checks it against `domain`. */
108
+ readonly registry: RegistryLocation;
109
+ /** An `AlreadyRegistered` revert must surface as `RegistryRevertError`: submitRegistration's
110
+ * lost-race handling keys on that one specifically. Any other revert may surface as any error. */
111
+ registerIdentity(networkId: Hex32, metaStealthAddress: Hex, proof: NetworkMemberProof): Promise<RegistrationWrite>;
112
+ }
113
+ /**
114
+ * revoke's result. txHash is the hash of the write (or, when sponsored, the bundle) transaction,
115
+ * not proof of inclusion: confirm it before treating the revocation as done.
116
+ */
117
+ interface RevocationWrite {
118
+ txHash: Hex;
119
+ sponsorship?: Sponsorship;
120
+ }
121
+ /** Submits a network-member-authorised write to `CredentialRevocationRegistry`. */
122
+ interface RevocationRegistryWriter {
123
+ /** The CredentialRevocationRegistry deployment this writer targets. */
124
+ readonly registry: RegistryLocation;
125
+ /** A revert must surface as `RevocationRevertError`: a caller has to tell a stale
126
+ * `lowLeafIndex`, which it retries, from an already-revoked commitment, which it does not. */
127
+ revoke(commitment: bigint, lowLeafIndex: bigint, proof: NetworkMemberProof): Promise<RevocationWrite>;
128
+ }
129
+ /**
130
+ * submitRegistration's result. txHash on `submitted` is the hash of the write transaction, not
131
+ * proof of inclusion: confirm it before treating the registration as done.
132
+ */
133
+ type SubmitRegistrationResult = {
134
+ status: "submitted";
135
+ networkId: Hex32;
136
+ metaStealthAddress: Hex;
137
+ txHash: Hex;
138
+ sponsorship?: Sponsorship;
139
+ } | {
140
+ status: "alreadyRegistered";
141
+ networkId: Hex32;
142
+ metaStealthAddress: Hex;
143
+ matchesRequest: boolean;
144
+ };
145
+
146
+ interface FetchIssuerMembershipWitnessParams {
147
+ issuerSetReader: ContractLeafReader;
148
+ issuerPublicKey: IssuerPublicKey;
149
+ }
150
+ interface IssuerMembershipWitnessResult {
151
+ root: bigint;
152
+ witness: IssuerMembershipWitness;
153
+ }
154
+ /** Rebuilds the approved-issuer set from its current on-chain leaves and proves membership against the fresh root. */
155
+ declare function fetchIssuerMembershipWitness({ issuerSetReader, issuerPublicKey }: FetchIssuerMembershipWitnessParams): Promise<IssuerMembershipWitnessResult>;
156
+
157
+ interface IssueVCPorts {
158
+ signer: CredentialSigner;
159
+ approval: ApprovalResolver;
160
+ issuerSetReader: ContractLeafReader;
161
+ }
162
+ /**
163
+ * Issues a UserApproval credential plus the issuer's fresh Merkle path into the
164
+ * approved-issuer set. The witness is fetched before any signing, so an issuer
165
+ * whose key was never published fails at issuance without spending a signature.
166
+ */
167
+ declare function issueVC(params: ZkCredentialIssueParams, { signer, approval, issuerSetReader }: IssueVCPorts): Promise<IssuedCredential>;
168
+
169
+ interface DeliverToStealthParams {
170
+ memberNetworkId: Hex32;
171
+ recipientNetworkId: Hex32;
172
+ }
173
+ interface DeliverToStealthPorts {
174
+ approval: ApprovalResolver;
175
+ identityReader: IdentityReader;
176
+ submitter: AnnouncementSubmitter;
177
+ }
178
+ /**
179
+ * Delivers value to a network member's recipient: resolves their registered identity and announces
180
+ * a fresh stealth address for it. `ERC5564Announcer.announce` is permissionless, so the member's
181
+ * approval is checked here, first, before any other port runs.
182
+ */
183
+ declare function deliverToStealth({ memberNetworkId, recipientNetworkId }: DeliverToStealthParams, { approval, identityReader, submitter }: DeliverToStealthPorts): Promise<DeliveredToStealth>;
184
+
185
+ interface SubmitRegistrationPorts {
186
+ domain: ChainDomain;
187
+ identityReader: IdentityReader;
188
+ prover: RegistrationProver;
189
+ writer: RegistrationWriter;
190
+ }
191
+ /**
192
+ * Submits a user's signed registration consent to `IdentityRegistry`, as an approved network
193
+ * member. The ports' own registry binding is checked first, then consent, both before any port
194
+ * runs, so a misconfigured member app or a forged/mistargeted request never reaches the registry.
195
+ */
196
+ declare function submitRegistration(request: RegistrationRequest, { domain, identityReader, prover, writer }: SubmitRegistrationPorts): Promise<SubmitRegistrationResult>;
197
+
198
+ /**
199
+ * Chain-backed IdentityReader over `IdentityRegistry`'s public `identity` mapping. Each read puts
200
+ * the recipient's networkId in `eth_call` calldata, visible to whoever serves the RPC.
201
+ */
202
+ declare class IdentityRegistryClient implements IdentityReader {
203
+ readonly registryAddress: Address$1;
204
+ private readonly client;
205
+ constructor(registryAddress: Address$1, client: Pick<PublicClient, "readContract">);
206
+ getIdentity(networkId: Hex$1): Promise<Hex$1 | null>;
207
+ }
208
+ /**
209
+ * Chain-backed ContractLeafReader over ApprovedIssuerSet's paging getters. Reads are pinned to
210
+ * the block observed at `getLeafCount`, so a multi-page rebuild can't mix chain states into a
211
+ * root that never existed; serve one rebuild at a time per instance.
212
+ */
213
+ declare class ApprovedIssuerSetClient implements ContractLeafReader {
214
+ private readonly setAddress;
215
+ private readonly client;
216
+ private blockNumber?;
217
+ constructor(setAddress: Address$1, client: Pick<PublicClient, "readContract" | "getBlockNumber">);
218
+ getLeafCount(): Promise<bigint>;
219
+ getLeaves(start: number, end: number): Promise<bigint[]>;
220
+ }
221
+ /** Chain-backed AnnouncementSubmitter over `ERC5564Announcer.announce`. */
222
+ declare class ERC5564AnnouncerClient implements AnnouncementSubmitter {
223
+ private readonly announcerAddress;
224
+ private readonly walletClient;
225
+ constructor(announcerAddress: Address$1, walletClient: Pick<WalletClient<Transport, Chain, Account>, "writeContract">);
226
+ announce(announcement: Announcement): Promise<Hex$1>;
227
+ }
228
+ /**
229
+ * Chain-backed GroupMirror over Semaphore's own group events. Rebuilds the approved-member group
230
+ * by replaying every MemberAdded/MembersAdded/MemberUpdated/MemberRemoved event for `groupId` in
231
+ * emission order, pinned to one `getBlockNumber` so the replay and the root check below can't
232
+ * straddle two chain states. A removal zeroes its leaf rather than deleting it, since Semaphore
233
+ * never reuses an index, so the replay must carry the zero forward into the rebuilt tree.
234
+ *
235
+ * The rebuilt root is then checked against `getMerkleTreeRoot` at that same block: a mismatch
236
+ * means the replay is wrong, not that membership is false, and this is what makes that loud
237
+ * instead of silently producing a proof nothing will accept.
238
+ */
239
+ declare class SemaphoreGroupClient implements GroupMirror {
240
+ private readonly semaphoreAddress;
241
+ private readonly groupId;
242
+ private readonly client;
243
+ private readonly fromBlock;
244
+ constructor(semaphoreAddress: Address$1, groupId: bigint, client: Pick<PublicClient, "getBlockNumber" | "getLogs" | "readContract">, { fromBlock }?: {
245
+ fromBlock?: bigint;
246
+ });
247
+ currentGroup(): Promise<Group>;
248
+ /** Replays the four membership events into a dense, index-ordered leaf array. `undefined`
249
+ * marks an index no admission log ever set, so a hole can't silently pass as leaf `0n`. */
250
+ private replayLeaves;
251
+ }
252
+ interface SemaphoreRegistrationProverParams {
253
+ /** The network member's own Semaphore identity. Its commitment must be a leaf of the mirrored group. */
254
+ identity: Identity;
255
+ groupMirror: GroupMirror;
256
+ registry: RegistryLocation;
257
+ }
258
+ /**
259
+ * Chain-backed RegistrationProver: mirrors the approved-member group fresh for every call, then
260
+ * generates the Semaphore proof authorising one IdentityRegistry write.
261
+ */
262
+ declare class SemaphoreRegistrationProver implements RegistrationProver {
263
+ private readonly identity;
264
+ private readonly groupMirror;
265
+ readonly registry: RegistryLocation;
266
+ constructor({ identity, groupMirror, registry }: SemaphoreRegistrationProverParams);
267
+ prove(update: IdentityUpdate): Promise<NetworkMemberProof>;
268
+ }
269
+ interface SemaphoreRevocationProverParams {
270
+ /** The network member's own Semaphore identity. Its commitment must be a leaf of the mirrored group. */
271
+ identity: Identity;
272
+ groupMirror: GroupMirror;
273
+ registry: RegistryLocation;
274
+ }
275
+ /**
276
+ * Chain-backed RevocationProver: mirrors the approved-member group fresh for every call, then
277
+ * generates the Semaphore proof authorising one write to the network's credential revocation
278
+ * registry. The same group as registration's, reached through the same mirror: the registry
279
+ * inherits `NetworkMemberGate`, so `SEMAPHORE()` and `NETWORK_MEMBER_GROUP_ID()` are public on it
280
+ * too and the mirror only needs a different address.
281
+ */
282
+ declare class SemaphoreRevocationProver implements RevocationProver {
283
+ private readonly identity;
284
+ private readonly groupMirror;
285
+ readonly registry: RegistryLocation;
286
+ constructor({ identity, groupMirror, registry }: SemaphoreRevocationProverParams);
287
+ prove(update: RevocationUpdate): Promise<NetworkMemberProof>;
288
+ }
289
+ /**
290
+ * Chain-backed RegistrationWriter over `IdentityRegistry.registerIdentity`. No receipt wait:
291
+ * `AlreadyRegistered` surfaces at viem's gas estimate, and a returned txHash means submitted,
292
+ * matching `RegistrationSubmitter`'s contract in `@coordination-network/user-client`.
293
+ */
294
+ declare class IdentityRegistryWriter implements RegistrationWriter {
295
+ readonly registry: RegistryLocation;
296
+ private readonly walletClient;
297
+ constructor(registry: RegistryLocation, walletClient: Pick<WalletClient<Transport, Chain, Account>, "writeContract">);
298
+ registerIdentity(networkId: Hex32, metaStealthAddress: Hex$1, proof: NetworkMemberProof): Promise<RegistrationWrite>;
299
+ }
300
+
301
+ /**
302
+ * A fully assembled ERC-4337 v0.8 user operation for a 7702-delegated, paymaster-sponsored call.
303
+ * Every gas and paymaster field is required, never left to a bundler default: `factory` is always
304
+ * the 7702 marker and `authorization` is always present, since this track has no other kind of op.
305
+ */
306
+ interface SponsoredUserOperation {
307
+ sender: Address$1;
308
+ nonce: bigint;
309
+ factory: "0x7702";
310
+ callData: Hex$1;
311
+ callGasLimit: bigint;
312
+ verificationGasLimit: bigint;
313
+ preVerificationGas: bigint;
314
+ maxFeePerGas: bigint;
315
+ maxPriorityFeePerGas: bigint;
316
+ paymaster: Address$1;
317
+ paymasterVerificationGasLimit: bigint;
318
+ paymasterPostOpGasLimit: bigint;
319
+ paymasterData: Hex$1;
320
+ authorization: SignedAuthorization;
321
+ signature: Hex$1;
322
+ }
323
+ /** One submitted user operation's outcome, parsed from the EntryPoint's own events so both submitters report the same shape. */
324
+ interface UserOperationReceipt {
325
+ transactionHash: Hex$1;
326
+ success: boolean;
327
+ actualGasCost: bigint;
328
+ actualGasUsed: bigint;
329
+ /** Raw `UserOperationRevertReason` data, present only when `success` is false. */
330
+ revertReason?: Hex$1;
331
+ }
332
+ /** Submits a signed user operation and waits for its outcome. `waitForReceipt` takes the hash `send` returns. */
333
+ interface UserOperationSubmitter {
334
+ send(userOperation: SponsoredUserOperation): Promise<Hex$1>;
335
+ waitForReceipt(userOpHash: Hex$1): Promise<UserOperationReceipt>;
336
+ }
337
+ /** Decodes `UserOperationEvent`/`UserOperationRevertReason` for one userOpHash out of a mined transaction's logs. */
338
+ declare function parseUserOperationReceipt(transactionReceipt: TransactionReceipt, entryPointAbi: typeof entryPoint08Abi, userOpHash: Hex$1): UserOperationReceipt;
339
+ /** Submits to a bundler's JSON-RPC (`eth_sendUserOperation`/`eth_getUserOperationReceipt`), for the member server. */
340
+ declare class BundlerRpcSubmitter implements UserOperationSubmitter {
341
+ private readonly entryPoint;
342
+ private readonly client;
343
+ constructor(url: string, entryPoint: Address$1);
344
+ send(userOperation: SponsoredUserOperation): Promise<Hex$1>;
345
+ waitForReceipt(userOpHash: Hex$1): Promise<UserOperationReceipt>;
346
+ }
347
+ type EntryPointChainClient = Pick<WalletClient<Transport, Chain, Account>, "account" | "chain" | "sendTransaction"> & Pick<PublicClient, "waitForTransactionReceipt">;
348
+ /**
349
+ * Submits straight to the EntryPoint's `handleOps`, for the stack bundler and the integration
350
+ * test: no mempool, one operation per call, the beneficiary is the submitting account itself.
351
+ */
352
+ declare class EntryPointSubmitter implements UserOperationSubmitter {
353
+ private readonly client;
354
+ private readonly entryPoint;
355
+ private readonly transactionHashes;
356
+ constructor(client: EntryPointChainClient, entryPoint: Address$1);
357
+ send(userOperation: SponsoredUserOperation): Promise<Hex$1>;
358
+ waitForReceipt(userOpHash: Hex$1): Promise<UserOperationReceipt>;
359
+ }
360
+
361
+ interface SponsoredMemberKeys {
362
+ /** The member's own long-term meta-stealth address; each call derives a fresh, disposable sender from it. */
363
+ metaStealthAddress: Hex$1;
364
+ spendingPrivateKey: Hex$1;
365
+ viewingPrivateKey: Hex$1;
366
+ }
367
+ interface SponsoredRelayParams {
368
+ chainId: number;
369
+ entryPoint: Address$1;
370
+ paymaster: Address$1;
371
+ accountImplementation: Address$1;
372
+ memberKeys: SponsoredMemberKeys;
373
+ /** The member's own Semaphore identity; must be a leaf of `paymasterGroup`. */
374
+ paymasterIdentity: Identity;
375
+ /** The paymaster's own mirrored Semaphore group (its admitted members, not the network's). */
376
+ paymasterGroup: GroupMirror;
377
+ submitter: UserOperationSubmitter;
378
+ publicClient: Pick<PublicClient, "getBalance" | "getTransactionCount" | "readContract">;
379
+ }
380
+ /** One relayed call's outcome: whatever the EntryPoint reported, plus what the sponsorship cost. */
381
+ interface RelayedCall {
382
+ receipt: UserOperationReceipt;
383
+ sponsorship: Sponsorship;
384
+ }
385
+ /** The call to relay. `value` defaults to zero, which is every call this track makes today. */
386
+ interface RelayCall {
387
+ target: Address$1;
388
+ value?: bigint;
389
+ data: Hex$1;
390
+ }
391
+ /**
392
+ * Relays one call through a fresh, disposable stealth sender delegated to Simple7702Account and
393
+ * sponsored by SemaphorePaymaster, so the member pays nothing and no sender links two of the
394
+ * member's relayed calls to each other.
395
+ *
396
+ * A reverted operation comes back as a receipt, not an error: which reverts are worth retrying and
397
+ * which are final depends on the contract being called, so the caller owns that reading.
398
+ */
399
+ declare class SponsoredRelay {
400
+ private readonly chainId;
401
+ private readonly entryPoint;
402
+ private readonly paymaster;
403
+ private readonly accountImplementation;
404
+ private readonly memberKeys;
405
+ private readonly paymasterIdentity;
406
+ private readonly paymasterGroup;
407
+ private readonly submitter;
408
+ private readonly publicClient;
409
+ constructor(params: SponsoredRelayParams);
410
+ relay({ target, value, data }: RelayCall): Promise<RelayedCall>;
411
+ /**
412
+ * A fresh, disposable stealth address derived from the member's own meta-address: used once
413
+ * to sign and pay (nothing, since it's sponsored) for this call, then dropped. No announcement
414
+ * is made, so it can't link two of the member's relayed calls to each other.
415
+ */
416
+ private deriveSender;
417
+ private readPaymasterDeposit;
418
+ /** The paymaster's own proof: the member's Semaphore identity against its mirrored group, message and scope both the disposable sender (`SemaphorePaymaster`'s own binding). */
419
+ private buildPaymasterProof;
420
+ }
421
+
422
+ interface SponsoredIdentityRegistryWriterParams extends SponsoredRelayParams {
423
+ registry: RegistryLocation;
424
+ }
425
+ /**
426
+ * Sponsored RegistrationWriter: relays a `registerIdentity` call through {@link SponsoredRelay},
427
+ * so the member pays nothing and no sender links two of the member's relayed registrations to
428
+ * each other.
429
+ */
430
+ declare class SponsoredIdentityRegistryWriter implements RegistrationWriter {
431
+ readonly registry: RegistryLocation;
432
+ private readonly relay;
433
+ constructor({ registry, ...relayParams }: SponsoredIdentityRegistryWriterParams);
434
+ registerIdentity(networkId: Hex32, metaStealthAddress: Hex$1, proof: NetworkMemberProof): Promise<RegistrationWrite>;
435
+ }
436
+
437
+ /**
438
+ * The `CredentialRevocationRegistry` fragments a writer needs. The errors matter as much as the
439
+ * function: `InvalidLowLeaf` is the one a caller recomputes an index and retries on, and
440
+ * `LeafAlreadyExists` the one it stops on, so both writers must decode the same names.
441
+ */
442
+ declare const CREDENTIAL_REVOCATION_REGISTRY_ABI: readonly [{
443
+ readonly type: "function";
444
+ readonly name: "revoke";
445
+ readonly stateMutability: "nonpayable";
446
+ readonly inputs: readonly [{
447
+ readonly name: "revocationCommitment";
448
+ readonly type: "uint256";
449
+ }, {
450
+ readonly name: "lowLeafIndex";
451
+ readonly type: "uint256";
452
+ }, {
453
+ readonly name: "proof";
454
+ readonly type: "tuple";
455
+ readonly components: readonly [{
456
+ readonly name: "merkleTreeDepth";
457
+ readonly type: "uint256";
458
+ }, {
459
+ readonly name: "merkleTreeRoot";
460
+ readonly type: "uint256";
461
+ }, {
462
+ readonly name: "nullifier";
463
+ readonly type: "uint256";
464
+ }, {
465
+ readonly name: "scope";
466
+ readonly type: "uint256";
467
+ }, {
468
+ readonly name: "points";
469
+ readonly type: "uint256[8]";
470
+ }];
471
+ }];
472
+ readonly outputs: readonly [];
473
+ }, {
474
+ readonly type: "error";
475
+ readonly name: "InvalidLowLeaf";
476
+ readonly inputs: readonly [];
477
+ }, {
478
+ readonly type: "error";
479
+ readonly name: "LeafAlreadyExists";
480
+ readonly inputs: readonly [];
481
+ }, {
482
+ readonly type: "error";
483
+ readonly name: "LeafCannotBeZero";
484
+ readonly inputs: readonly [];
485
+ }, {
486
+ readonly type: "error";
487
+ readonly name: "LeafGreaterThanSnarkScalarField";
488
+ readonly inputs: readonly [];
489
+ }, {
490
+ readonly type: "error";
491
+ readonly name: "RegistryDoesNotExist";
492
+ readonly inputs: readonly [];
493
+ }, {
494
+ readonly type: "error";
495
+ readonly name: "CallerIsNotTheRegistryAdmin";
496
+ readonly inputs: readonly [];
497
+ }, {
498
+ readonly type: "error";
499
+ readonly name: "Semaphore__GroupHasNoMembers";
500
+ readonly inputs: readonly [];
501
+ }, {
502
+ readonly type: "error";
503
+ readonly name: "Semaphore__MerkleTreeDepthIsNotSupported";
504
+ readonly inputs: readonly [];
505
+ }, {
506
+ readonly type: "error";
507
+ readonly name: "Semaphore__MerkleTreeRootIsExpired";
508
+ readonly inputs: readonly [];
509
+ }, {
510
+ readonly type: "error";
511
+ readonly name: "Semaphore__MerkleTreeRootIsNotPartOfTheGroup";
512
+ readonly inputs: readonly [];
513
+ }, {
514
+ readonly type: "error";
515
+ readonly name: "Semaphore__YouAreUsingTheSameNullifierTwice";
516
+ readonly inputs: readonly [];
517
+ }, {
518
+ readonly type: "error";
519
+ readonly name: "Semaphore__InvalidProof";
520
+ readonly inputs: readonly [];
521
+ }];
522
+ /**
523
+ * Sponsored RevocationRegistryWriter: relays a `revoke` call through {@link SponsoredRelay}, so
524
+ * the write costs the member nothing and its sender names no member. That matters more here than for
525
+ * registration: one tree holds the whole network's revocations, and an EOA paying for the write
526
+ * would say which member revoked which credential.
527
+ */
528
+ declare class SponsoredRevocationWriter implements RevocationRegistryWriter {
529
+ readonly registry: RegistryLocation;
530
+ private readonly relay;
531
+ constructor(registry: RegistryLocation, relay: SponsoredRelay);
532
+ revoke(commitment: bigint, lowLeafIndex: bigint, proof: NetworkMemberProof): Promise<RevocationWrite>;
533
+ }
534
+ /**
535
+ * Chain-backed RevocationRegistryWriter over `CredentialRevocationRegistry.revoke`, for a member
536
+ * server running without an account-abstraction stack. The submitting EOA is on chain, so it says
537
+ * which member revoked; the sponsored writer above is what keeps that unattributable.
538
+ *
539
+ * No receipt wait: a reverting write surfaces at viem's gas estimate, and a returned txHash means
540
+ * submitted, matching `IdentityRegistryWriter`.
541
+ */
542
+ declare class DirectRevocationWriter implements RevocationRegistryWriter {
543
+ readonly registry: RegistryLocation;
544
+ private readonly walletClient;
545
+ constructor(registry: RegistryLocation, walletClient: Pick<WalletClient<Transport, Chain, Account>, "writeContract">);
546
+ revoke(commitment: bigint, lowLeafIndex: bigint, proof: NetworkMemberProof): Promise<RevocationWrite>;
547
+ }
548
+
549
+ export { ApprovedIssuerSetClient, BundlerRpcSubmitter, CREDENTIAL_REVOCATION_REGISTRY_ABI, DirectRevocationWriter, ERC5564AnnouncerClient, EntryPointSubmitter, IdentityRegistryClient, IdentityRegistryWriter, NetworkMemberClientError, RegistryRevertError, RevocationRevertError, SemaphoreGroupClient, SemaphoreRegistrationProver, SemaphoreRevocationProver, SponsoredIdentityRegistryWriter, SponsoredRelay, SponsoredRevocationWriter, deliverToStealth, fetchIssuerMembershipWitness, issueVC, parseUserOperationReceipt, submitRegistration };
550
+ export type { Announcement, AnnouncementSubmitter, DeliverToStealthParams, DeliverToStealthPorts, DeliveredToStealth, FetchIssuerMembershipWitnessParams, GroupMirror, IdentityReader, IssueVCPorts, IssuedCredential, IssuerMembershipWitnessResult, NetworkMemberClientErrorCode, RegistrationProver, RegistrationWrite, RegistrationWriter, RelayCall, RelayedCall, RevocationProver, RevocationRegistryWriter, RevocationWrite, SemaphoreRegistrationProverParams, SemaphoreRevocationProverParams, SponsoredIdentityRegistryWriterParams, SponsoredMemberKeys, SponsoredRelayParams, SponsoredUserOperation, Sponsorship, SubmitRegistrationPorts, SubmitRegistrationResult, UserOperationReceipt, UserOperationSubmitter };