@waku/rln 0.0.2-8a6571f.0 → 0.0.2-a3e7f15.0

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.
@@ -30,7 +30,7 @@ interface RLNContractInitOptions extends RLNContractOptions {
30
30
 
31
31
  export interface MembershipRegisteredEvent {
32
32
  idCommitment: string;
33
- rateLimit: number;
33
+ membershipRateLimit: ethers.BigNumber;
34
34
  index: ethers.BigNumber;
35
35
  }
36
36
 
@@ -65,7 +65,8 @@ export class RLNContract {
65
65
 
66
66
  private _members: Map<number, Member> = new Map();
67
67
  private _membersFilter: ethers.EventFilter;
68
- private _membersRemovedFilter: ethers.EventFilter;
68
+ private _membershipErasedFilter: ethers.EventFilter;
69
+ private _membersExpiredFilter: ethers.EventFilter;
69
70
 
70
71
  /**
71
72
  * Asynchronous initializer for RLNContract.
@@ -111,9 +112,10 @@ export class RLNContract {
111
112
  this.contract = contract || new ethers.Contract(address, RLN_ABI, signer);
112
113
  this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
113
114
 
114
- // Initialize event filters for MembershipRegistered and MembershipErased
115
+ // Initialize event filters
115
116
  this._membersFilter = this.contract.filters.MembershipRegistered();
116
- this._membersRemovedFilter = this.contract.filters.MembershipErased();
117
+ this._membershipErasedFilter = this.contract.filters.MembershipErased();
118
+ this._membersExpiredFilter = this.contract.filters.MembershipExpired();
117
119
  }
118
120
 
119
121
  /**
@@ -182,7 +184,7 @@ export class RLNContract {
182
184
  this.contract.maxTotalRateLimit(),
183
185
  this.contract.currentTotalRateLimit()
184
186
  ]);
185
- return maxTotal.sub(currentTotal).toNumber();
187
+ return Number(maxTotal) - Number(currentTotal);
186
188
  }
187
189
 
188
190
  /**
@@ -207,11 +209,18 @@ export class RLNContract {
207
209
  return this._membersFilter;
208
210
  }
209
211
 
210
- private get membersRemovedFilter(): ethers.EventFilter {
211
- if (!this._membersRemovedFilter) {
212
- throw Error("MembersErased filter was not initialized.");
212
+ private get membershipErasedFilter(): ethers.EventFilter {
213
+ if (!this._membershipErasedFilter) {
214
+ throw Error("MembershipErased filter was not initialized.");
215
+ }
216
+ return this._membershipErasedFilter;
217
+ }
218
+
219
+ private get membersExpiredFilter(): ethers.EventFilter {
220
+ if (!this._membersExpiredFilter) {
221
+ throw Error("MembersExpired filter was not initialized.");
213
222
  }
214
- return this._membersRemovedFilter;
223
+ return this._membersExpiredFilter;
215
224
  }
216
225
 
217
226
  public async fetchMembers(
@@ -226,10 +235,19 @@ export class RLNContract {
226
235
  const removedMemberEvents = await queryFilter(this.contract, {
227
236
  fromBlock: this.deployBlock,
228
237
  ...options,
229
- membersFilter: this.membersRemovedFilter
238
+ membersFilter: this.membershipErasedFilter
239
+ });
240
+ const expiredMemberEvents = await queryFilter(this.contract, {
241
+ fromBlock: this.deployBlock,
242
+ ...options,
243
+ membersFilter: this.membersExpiredFilter
230
244
  });
231
245
 
232
- const events = [...registeredMemberEvents, ...removedMemberEvents];
246
+ const events = [
247
+ ...registeredMemberEvents,
248
+ ...removedMemberEvents,
249
+ ...expiredMemberEvents
250
+ ];
233
251
  this.processEvents(rlnInstance, events);
234
252
  }
235
253
 
@@ -242,8 +260,20 @@ export class RLNContract {
242
260
  return;
243
261
  }
244
262
 
245
- if (evt.event === "MembershipErased") {
246
- const index = evt.args.index as ethers.BigNumber;
263
+ if (
264
+ evt.event === "MembershipErased" ||
265
+ evt.event === "MembershipExpired"
266
+ ) {
267
+ let index = evt.args.index;
268
+
269
+ if (!index) {
270
+ return;
271
+ }
272
+
273
+ if (typeof index === "number" || typeof index === "string") {
274
+ index = ethers.BigNumber.from(index);
275
+ }
276
+
247
277
  const toRemoveVal = toRemoveTable.get(evt.blockNumber);
248
278
  if (toRemoveVal != undefined) {
249
279
  toRemoveVal.push(index.toNumber());
@@ -275,15 +305,21 @@ export class RLNContract {
275
305
  if (!evt.args) return;
276
306
 
277
307
  const _idCommitment = evt.args.idCommitment as string;
278
- const index = evt.args.index as ethers.BigNumber;
308
+ let index = evt.args.index;
279
309
 
280
310
  if (!_idCommitment || !index) {
281
311
  return;
282
312
  }
283
313
 
314
+ if (typeof index === "number" || typeof index === "string") {
315
+ index = ethers.BigNumber.from(index);
316
+ }
317
+
284
318
  const idCommitment = zeroPadLE(hexToBytes(_idCommitment), 32);
285
319
  rlnInstance.zerokit.insertMember(idCommitment);
286
- this._members.set(index.toNumber(), {
320
+
321
+ const numericIndex = index.toNumber();
322
+ this._members.set(numericIndex, {
287
323
  index,
288
324
  idCommitment: _idCommitment
289
325
  });
@@ -316,7 +352,19 @@ export class RLNContract {
316
352
  this.membersFilter,
317
353
  (
318
354
  _idCommitment: string,
319
- _rateLimit: number,
355
+ _membershipRateLimit: ethers.BigNumber,
356
+ _index: ethers.BigNumber,
357
+ event: ethers.Event
358
+ ) => {
359
+ this.processEvents(rlnInstance, [event]);
360
+ }
361
+ );
362
+
363
+ this.contract.on(
364
+ this.membershipErasedFilter,
365
+ (
366
+ _idCommitment: string,
367
+ _membershipRateLimit: ethers.BigNumber,
320
368
  _index: ethers.BigNumber,
321
369
  event: ethers.Event
322
370
  ) => {
@@ -325,10 +373,10 @@ export class RLNContract {
325
373
  );
326
374
 
327
375
  this.contract.on(
328
- this.membersRemovedFilter,
376
+ this.membersExpiredFilter,
329
377
  (
330
378
  _idCommitment: string,
331
- _rateLimit: number,
379
+ _membershipRateLimit: ethers.BigNumber,
332
380
  _index: ethers.BigNumber,
333
381
  event: ethers.Event
334
382
  ) => {
@@ -345,15 +393,45 @@ export class RLNContract {
345
393
  `Registering identity with rate limit: ${this.rateLimit} messages/epoch`
346
394
  );
347
395
 
396
+ // Check if the ID commitment is already registered
397
+ const existingIndex = await this.getMemberIndex(
398
+ identity.IDCommitmentBigInt.toString()
399
+ );
400
+ if (existingIndex) {
401
+ throw new Error(
402
+ `ID commitment is already registered with index ${existingIndex}`
403
+ );
404
+ }
405
+
406
+ // Check if there's enough remaining rate limit
407
+ const remainingRateLimit = await this.getRemainingTotalRateLimit();
408
+ if (remainingRateLimit < this.rateLimit) {
409
+ throw new Error(
410
+ `Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`
411
+ );
412
+ }
413
+
414
+ const estimatedGas = await this.contract.estimateGas.register(
415
+ identity.IDCommitmentBigInt,
416
+ this.rateLimit,
417
+ []
418
+ );
419
+ const gasLimit = estimatedGas.add(10000);
420
+
348
421
  const txRegisterResponse: ethers.ContractTransaction =
349
422
  await this.contract.register(
350
423
  identity.IDCommitmentBigInt,
351
424
  this.rateLimit,
352
425
  [],
353
- { gasLimit: 300000 }
426
+ { gasLimit }
354
427
  );
428
+
355
429
  const txRegisterReceipt = await txRegisterResponse.wait();
356
430
 
431
+ if (txRegisterReceipt.status === 0) {
432
+ throw new Error("Transaction failed on-chain");
433
+ }
434
+
357
435
  const memberRegistered = txRegisterReceipt.events?.find(
358
436
  (event) => event.event === "MembershipRegistered"
359
437
  );
@@ -367,18 +445,18 @@ export class RLNContract {
367
445
 
368
446
  const decodedData: MembershipRegisteredEvent = {
369
447
  idCommitment: memberRegistered.args.idCommitment,
370
- rateLimit: memberRegistered.args.rateLimit,
448
+ membershipRateLimit: memberRegistered.args.membershipRateLimit,
371
449
  index: memberRegistered.args.index
372
450
  };
373
451
 
374
452
  log.info(
375
453
  `Successfully registered membership with index ${decodedData.index} ` +
376
- `and rate limit ${decodedData.rateLimit}`
454
+ `and rate limit ${decodedData.membershipRateLimit}`
377
455
  );
378
456
 
379
457
  const network = await this.contract.provider.getNetwork();
380
458
  const address = this.contract.address;
381
- const membershipId = decodedData.index.toNumber();
459
+ const membershipId = Number(decodedData.index);
382
460
 
383
461
  return {
384
462
  identity,
@@ -389,8 +467,32 @@ export class RLNContract {
389
467
  }
390
468
  };
391
469
  } catch (error) {
392
- log.error(`Error in registerWithIdentity: ${(error as Error).message}`);
393
- return undefined;
470
+ if (error instanceof Error) {
471
+ const errorMessage = error.message;
472
+ log.error("registerWithIdentity - error message:", errorMessage);
473
+ log.error("registerWithIdentity - error stack:", error.stack);
474
+
475
+ // Try to extract more specific error information
476
+ if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
477
+ throw new Error(
478
+ "Registration failed: Cannot exceed maximum total rate limit"
479
+ );
480
+ } else if (errorMessage.includes("InvalidIdCommitment")) {
481
+ throw new Error("Registration failed: Invalid ID commitment");
482
+ } else if (errorMessage.includes("InvalidMembershipRateLimit")) {
483
+ throw new Error("Registration failed: Invalid membership rate limit");
484
+ } else if (errorMessage.includes("execution reverted")) {
485
+ throw new Error(
486
+ "Contract execution reverted. Check contract requirements."
487
+ );
488
+ } else {
489
+ throw new Error(`Error in registerWithIdentity: ${errorMessage}`);
490
+ }
491
+ } else {
492
+ throw new Error("Unknown error in registerWithIdentity", {
493
+ cause: error
494
+ });
495
+ }
394
496
  }
395
497
  }
396
498
 
@@ -468,18 +570,18 @@ export class RLNContract {
468
570
 
469
571
  const decodedData: MembershipRegisteredEvent = {
470
572
  idCommitment: memberRegistered.args.idCommitment,
471
- rateLimit: memberRegistered.args.rateLimit,
573
+ membershipRateLimit: memberRegistered.args.membershipRateLimit,
472
574
  index: memberRegistered.args.index
473
575
  };
474
576
 
475
577
  log.info(
476
578
  `Successfully registered membership with permit. Index: ${decodedData.index}, ` +
477
- `Rate limit: ${decodedData.rateLimit}, Erased ${idCommitmentsToErase.length} commitments`
579
+ `Rate limit: ${decodedData.membershipRateLimit}, Erased ${idCommitmentsToErase.length} commitments`
478
580
  );
479
581
 
480
582
  const network = await this.contract.provider.getNetwork();
481
583
  const address = this.contract.address;
482
- const membershipId = decodedData.index.toNumber();
584
+ const membershipId = Number(decodedData.index);
483
585
 
484
586
  return {
485
587
  identity,
package/src/index.ts CHANGED
@@ -23,3 +23,14 @@ export {
23
23
  extractMetaMaskSigner,
24
24
  RLN_ABI
25
25
  };
26
+
27
+ export type {
28
+ DecryptedCredentials,
29
+ EncryptedCredentials,
30
+ Keccak256Hash,
31
+ KeystoreEntity,
32
+ MembershipHash,
33
+ MembershipInfo,
34
+ Password,
35
+ Sha256Hash
36
+ } from "./keystore/types.js";
package/src/rln.ts CHANGED
@@ -151,8 +151,6 @@ export class RLNInstance {
151
151
  }
152
152
 
153
153
  public async start(options: StartRLNOptions = {}): Promise<void> {
154
- // eslint-disable-next-line no-console
155
- console.log("starting", options);
156
154
  if (this.started || this.starting) {
157
155
  return;
158
156
  }
@@ -198,13 +196,6 @@ export class RLNInstance {
198
196
  chainId = SEPOLIA_CONTRACT.chainId;
199
197
  }
200
198
 
201
- // eslint-disable-next-line no-console
202
- console.log({
203
- chainId,
204
- address,
205
- SEPOLIA_CONTRACT
206
- });
207
-
208
199
  const signer = options.signer || (await extractMetaMaskSigner());
209
200
  const currentChainId = await signer.getChainId();
210
201