@waku/rln 0.1.5-cad3e7a.0 → 0.1.5-db38a7e.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.
Files changed (78) hide show
  1. package/bundle/_virtual/utils.js +2 -2
  2. package/bundle/_virtual/utils2.js +2 -2
  3. package/bundle/index.js +2 -2
  4. package/bundle/packages/rln/dist/contract/constants.js +2 -5
  5. package/bundle/packages/rln/dist/contract/{rln_light_contract.js → rln_base_contract.js} +190 -181
  6. package/bundle/packages/rln/dist/contract/rln_contract.js +9 -419
  7. package/bundle/packages/rln/dist/contract/types.js +9 -0
  8. package/bundle/packages/rln/dist/create.js +1 -1
  9. package/bundle/packages/rln/dist/{rln_light.js → credentials_manager.js} +114 -48
  10. package/bundle/packages/rln/dist/identity.js +0 -9
  11. package/bundle/packages/rln/dist/keystore/keystore.js +31 -17
  12. package/bundle/packages/rln/dist/rln.js +57 -167
  13. package/bundle/packages/rln/dist/zerokit.js +5 -5
  14. package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
  15. package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
  16. package/bundle/packages/rln/node_modules/@noble/hashes/_sha2.js +1 -1
  17. package/bundle/packages/rln/node_modules/@noble/hashes/hmac.js +1 -1
  18. package/bundle/packages/rln/node_modules/@noble/hashes/pbkdf2.js +1 -1
  19. package/bundle/packages/rln/node_modules/@noble/hashes/scrypt.js +1 -1
  20. package/bundle/packages/rln/node_modules/@noble/hashes/sha256.js +1 -1
  21. package/bundle/packages/rln/node_modules/@noble/hashes/sha512.js +1 -1
  22. package/bundle/packages/rln/node_modules/@noble/hashes/utils.js +1 -1
  23. package/dist/.tsbuildinfo +1 -1
  24. package/dist/contract/constants.d.ts +1 -1
  25. package/dist/contract/constants.js +1 -1
  26. package/dist/contract/constants.js.map +1 -1
  27. package/dist/contract/{rln_light_contract.d.ts → rln_base_contract.d.ts} +24 -58
  28. package/dist/contract/{rln_light_contract.js → rln_base_contract.js} +190 -181
  29. package/dist/contract/rln_base_contract.js.map +1 -0
  30. package/dist/contract/rln_contract.d.ts +5 -122
  31. package/dist/contract/rln_contract.js +8 -417
  32. package/dist/contract/rln_contract.js.map +1 -1
  33. package/dist/contract/types.d.ts +45 -0
  34. package/dist/contract/types.js +8 -0
  35. package/dist/contract/types.js.map +1 -0
  36. package/dist/create.js +1 -1
  37. package/dist/create.js.map +1 -1
  38. package/dist/credentials_manager.d.ts +44 -0
  39. package/dist/credentials_manager.js +197 -0
  40. package/dist/credentials_manager.js.map +1 -0
  41. package/dist/identity.d.ts +0 -1
  42. package/dist/identity.js +0 -9
  43. package/dist/identity.js.map +1 -1
  44. package/dist/index.d.ts +3 -3
  45. package/dist/index.js +3 -3
  46. package/dist/index.js.map +1 -1
  47. package/dist/keystore/keystore.d.ts +1 -0
  48. package/dist/keystore/keystore.js +31 -17
  49. package/dist/keystore/keystore.js.map +1 -1
  50. package/dist/keystore/types.d.ts +1 -1
  51. package/dist/rln.d.ts +9 -52
  52. package/dist/rln.js +55 -164
  53. package/dist/rln.js.map +1 -1
  54. package/dist/types.d.ts +27 -0
  55. package/dist/types.js +2 -0
  56. package/dist/types.js.map +1 -0
  57. package/dist/zerokit.d.ts +3 -3
  58. package/dist/zerokit.js +5 -5
  59. package/dist/zerokit.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/contract/constants.ts +1 -1
  62. package/src/contract/{rln_light_contract.ts → rln_base_contract.ts} +306 -315
  63. package/src/contract/rln_contract.ts +9 -663
  64. package/src/contract/types.ts +53 -0
  65. package/src/create.ts +1 -1
  66. package/src/credentials_manager.ts +282 -0
  67. package/src/identity.ts +0 -10
  68. package/src/index.ts +4 -4
  69. package/src/keystore/keystore.ts +53 -29
  70. package/src/keystore/types.ts +1 -1
  71. package/src/rln.ts +68 -259
  72. package/src/types.ts +31 -0
  73. package/src/zerokit.ts +3 -3
  74. package/dist/contract/rln_light_contract.js.map +0 -1
  75. package/dist/rln_light.d.ts +0 -64
  76. package/dist/rln_light.js +0 -144
  77. package/dist/rln_light.js.map +0 -1
  78. package/src/rln_light.ts +0 -235
@@ -1,3 +1,3 @@
1
- var utils = {};
1
+ var utils = {exports: {}};
2
2
 
3
- export { utils as __exports };
3
+ export { utils as __module };
@@ -1,3 +1,3 @@
1
- var utils = {exports: {}};
1
+ var utils = {};
2
2
 
3
- export { utils as __module };
3
+ export { utils as __exports };
package/bundle/index.js CHANGED
@@ -2,13 +2,13 @@ export { RLNDecoder, RLNEncoder } from './packages/rln/dist/codec.js';
2
2
  export { RLN_ABI } from './packages/rln/dist/contract/abi.js';
3
3
  export { RLNContract } from './packages/rln/dist/contract/rln_contract.js';
4
4
  export { LINEA_CONTRACT } from './packages/rln/dist/contract/constants.js';
5
- export { RLNLightContract } from './packages/rln/dist/contract/rln_light_contract.js';
5
+ export { RLNBaseContract } from './packages/rln/dist/contract/rln_base_contract.js';
6
6
  export { createRLN } from './packages/rln/dist/create.js';
7
+ export { RLNCredentialsManager } from './packages/rln/dist/credentials_manager.js';
7
8
  export { IdentityCredential } from './packages/rln/dist/identity.js';
8
9
  export { Keystore } from './packages/rln/dist/keystore/keystore.js';
9
10
  export { Proof } from './packages/rln/dist/proof.js';
10
11
  export { RLNInstance } from './packages/rln/dist/rln.js';
11
- export { RLNLightInstance } from './packages/rln/dist/rln_light.js';
12
12
  export { MerkleRootTracker } from './packages/rln/dist/root_tracker.js';
13
13
  export { extractMetaMaskSigner } from './packages/rln/dist/utils/metamask.js';
14
14
  import './packages/rln/dist/utils/epoch.js';
@@ -1,7 +1,7 @@
1
1
  import { RLN_ABI } from './abi.js';
2
2
 
3
3
  const LINEA_CONTRACT = {
4
- chainId: "59141",
4
+ chainId: 59141,
5
5
  address: "0xb9cd878c90e49f797b4431fbf4fb333108cb90e6",
6
6
  abi: RLN_ABI
7
7
  };
@@ -17,10 +17,7 @@ const RATE_LIMIT_TIERS = {
17
17
  // Global rate limit parameters
18
18
  const RATE_LIMIT_PARAMS = {
19
19
  MIN_RATE: RATE_LIMIT_TIERS.LOW,
20
- MAX_RATE: RATE_LIMIT_TIERS.HIGH,
21
- MAX_TOTAL_RATE: 160_000, // Maximum total rate limit across all memberships
22
- EPOCH_LENGTH: 600 // Epoch length in seconds (10 minutes)
23
- };
20
+ MAX_RATE: RATE_LIMIT_TIERS.HIGH};
24
21
  const DEFAULT_RATE_LIMIT = RATE_LIMIT_PARAMS.MAX_RATE;
25
22
 
26
23
  export { DEFAULT_RATE_LIMIT, LINEA_CONTRACT, RATE_LIMIT_PARAMS, RATE_LIMIT_TIERS };
@@ -15,18 +15,13 @@ import '../../../../node_modules/multiformats/dist/src/codecs/json.js';
15
15
  import { Logger } from '../../../utils/dist/logger/index.js';
16
16
  import { RLN_ABI } from './abi.js';
17
17
  import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from './constants.js';
18
+ import { MembershipState } from './types.js';
18
19
  import { Contract } from '../../../../node_modules/@ethersproject/contracts/lib.esm/index.js';
19
20
  import { BigNumber } from '../../../../node_modules/@ethersproject/bignumber/lib.esm/bignumber.js';
20
21
 
21
- const log = new Logger("waku:rln:contract");
22
- var MembershipState;
23
- (function (MembershipState) {
24
- MembershipState["Active"] = "Active";
25
- MembershipState["GracePeriod"] = "GracePeriod";
26
- MembershipState["Expired"] = "Expired";
27
- MembershipState["ErasedAwaitsWithdrawal"] = "ErasedAwaitsWithdrawal";
28
- })(MembershipState || (MembershipState = {}));
29
- class RLNLightContract {
22
+ /* eslint-disable no-console */
23
+ const log = new Logger("waku:rln:contract:base");
24
+ class RLNBaseContract {
30
25
  contract;
31
26
  deployBlock;
32
27
  rateLimit;
@@ -35,28 +30,38 @@ class RLNLightContract {
35
30
  _membershipErasedFilter;
36
31
  _membersExpiredFilter;
37
32
  /**
38
- * Asynchronous initializer for RLNContract.
33
+ * Constructor for RLNBaseContract.
39
34
  * Allows injecting a mocked contract for testing purposes.
40
35
  */
41
- static async init(options) {
42
- const rlnContract = new RLNLightContract(options);
43
- await rlnContract.fetchMembers();
44
- rlnContract.subscribeToMembers();
45
- return rlnContract;
46
- }
47
36
  constructor(options) {
48
37
  const { address, signer, rateLimit = DEFAULT_RATE_LIMIT, contract } = options;
49
- if (rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
50
- rateLimit > RATE_LIMIT_PARAMS.MAX_RATE) {
51
- throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE} messages per epoch`);
52
- }
53
- this.rateLimit = rateLimit;
54
- // Use the injected contract if provided; otherwise, instantiate a new one.
38
+ log.info("Initializing RLNBaseContract", { address, rateLimit });
55
39
  this.contract = contract || new Contract(address, RLN_ABI, signer);
56
- // Initialize event filters
57
- this._membersFilter = this.contract.filters.MembershipRegistered();
58
- this._membershipErasedFilter = this.contract.filters.MembershipErased();
59
- this._membersExpiredFilter = this.contract.filters.MembershipExpired();
40
+ this.rateLimit = rateLimit;
41
+ try {
42
+ log.info("Setting up event filters");
43
+ // Initialize event filters
44
+ this._membersFilter = this.contract.filters.MembershipRegistered();
45
+ this._membershipErasedFilter = this.contract.filters.MembershipErased();
46
+ this._membersExpiredFilter = this.contract.filters.MembershipExpired();
47
+ log.info("Event filters initialized successfully");
48
+ }
49
+ catch (error) {
50
+ log.error("Failed to initialize event filters", { error });
51
+ throw new Error("Failed to initialize event filters: " + error.message);
52
+ }
53
+ // Initialize members and subscriptions
54
+ this.fetchMembers()
55
+ .then(() => {
56
+ this.subscribeToMembers();
57
+ })
58
+ .catch((error) => {
59
+ log.error("Failed to initialize members", { error });
60
+ });
61
+ // Validate rate limit asynchronously
62
+ this.validateRateLimit(rateLimit).catch((error) => {
63
+ log.error("Failed to validate initial rate limit", { error });
64
+ });
60
65
  }
61
66
  /**
62
67
  * Gets the current rate limit for this contract instance
@@ -98,7 +103,7 @@ class RLNLightContract {
98
103
  */
99
104
  async getMaxTotalRateLimit() {
100
105
  const maxTotalRate = await this.contract.maxTotalRateLimit();
101
- return BigNumber.from(maxTotalRate).toNumber();
106
+ return maxTotalRate.toNumber();
102
107
  }
103
108
  /**
104
109
  * Gets the current total rate limit usage across all memberships
@@ -106,7 +111,7 @@ class RLNLightContract {
106
111
  */
107
112
  async getCurrentTotalRateLimit() {
108
113
  const currentTotal = await this.contract.currentTotalRateLimit();
109
- return BigNumber.from(currentTotal).toNumber();
114
+ return currentTotal.toNumber();
110
115
  }
111
116
  /**
112
117
  * Gets the remaining available total rate limit that can be allocated
@@ -117,51 +122,32 @@ class RLNLightContract {
117
122
  this.contract.maxTotalRateLimit(),
118
123
  this.contract.currentTotalRateLimit()
119
124
  ]);
120
- return BigNumber.from(maxTotal)
121
- .sub(BigNumber.from(currentTotal))
122
- .toNumber();
125
+ return Number(maxTotal) - Number(currentTotal);
123
126
  }
124
127
  /**
125
128
  * Updates the rate limit for future registrations
126
129
  * @param newRateLimit The new rate limit to use
127
130
  */
128
131
  async setRateLimit(newRateLimit) {
132
+ await this.validateRateLimit(newRateLimit);
129
133
  this.rateLimit = newRateLimit;
130
134
  }
131
135
  get members() {
132
136
  const sortedMembers = Array.from(this._members.values()).sort((left, right) => left.index.toNumber() - right.index.toNumber());
133
137
  return sortedMembers;
134
138
  }
135
- get membersFilter() {
136
- if (!this._membersFilter) {
137
- throw Error("Members filter was not initialized.");
138
- }
139
- return this._membersFilter;
140
- }
141
- get membershipErasedFilter() {
142
- if (!this._membershipErasedFilter) {
143
- throw Error("MembershipErased filter was not initialized.");
144
- }
145
- return this._membershipErasedFilter;
146
- }
147
- get membersExpiredFilter() {
148
- if (!this._membersExpiredFilter) {
149
- throw Error("MembersExpired filter was not initialized.");
150
- }
151
- return this._membersExpiredFilter;
152
- }
153
139
  async fetchMembers(options = {}) {
154
- const registeredMemberEvents = await queryFilter(this.contract, {
140
+ const registeredMemberEvents = await RLNBaseContract.queryFilter(this.contract, {
155
141
  fromBlock: this.deployBlock,
156
142
  ...options,
157
143
  membersFilter: this.membersFilter
158
144
  });
159
- const removedMemberEvents = await queryFilter(this.contract, {
145
+ const removedMemberEvents = await RLNBaseContract.queryFilter(this.contract, {
160
146
  fromBlock: this.deployBlock,
161
147
  ...options,
162
148
  membersFilter: this.membershipErasedFilter
163
149
  });
164
- const expiredMemberEvents = await queryFilter(this.contract, {
150
+ const expiredMemberEvents = await RLNBaseContract.queryFilter(this.contract, {
165
151
  fromBlock: this.deployBlock,
166
152
  ...options,
167
153
  membersFilter: this.membersExpiredFilter
@@ -173,6 +159,29 @@ class RLNLightContract {
173
159
  ];
174
160
  this.processEvents(events);
175
161
  }
162
+ static async queryFilter(contract, options) {
163
+ const FETCH_CHUNK = 5;
164
+ const BLOCK_RANGE = 3000;
165
+ const { fromBlock, membersFilter, fetchRange = BLOCK_RANGE, fetchChunks = FETCH_CHUNK } = options;
166
+ if (fromBlock === undefined) {
167
+ return contract.queryFilter(membersFilter);
168
+ }
169
+ if (!contract.provider) {
170
+ throw Error("No provider found on the contract.");
171
+ }
172
+ const toBlock = await contract.provider.getBlockNumber();
173
+ if (toBlock - fromBlock < fetchRange) {
174
+ return contract.queryFilter(membersFilter, fromBlock, toBlock);
175
+ }
176
+ const events = [];
177
+ const chunks = RLNBaseContract.splitToChunks(fromBlock, toBlock, fetchRange);
178
+ for (const portion of RLNBaseContract.takeN(chunks, fetchChunks)) {
179
+ const promises = portion.map(([left, right]) => RLNBaseContract.ignoreErrors(contract.queryFilter(membersFilter, left, right), []));
180
+ const fetchedEvents = await Promise.all(promises);
181
+ events.push(fetchedEvents.flatMap((v) => v));
182
+ }
183
+ return events.flatMap((v) => v);
184
+ }
176
185
  processEvents(events) {
177
186
  const toRemoveTable = new Map();
178
187
  const toInsertTable = new Map();
@@ -208,6 +217,38 @@ class RLNLightContract {
208
217
  }
209
218
  });
210
219
  }
220
+ static splitToChunks(from, to, step) {
221
+ const chunks = [];
222
+ let left = from;
223
+ while (left < to) {
224
+ const right = left + step < to ? left + step : to;
225
+ chunks.push([left, right]);
226
+ left = right;
227
+ }
228
+ return chunks;
229
+ }
230
+ static *takeN(array, size) {
231
+ let start = 0;
232
+ while (start < array.length) {
233
+ const portion = array.slice(start, start + size);
234
+ yield portion;
235
+ start += size;
236
+ }
237
+ }
238
+ static async ignoreErrors(promise, defaultValue) {
239
+ try {
240
+ return await promise;
241
+ }
242
+ catch (err) {
243
+ if (err instanceof Error) {
244
+ log.info(`Ignoring an error during query: ${err.message}`);
245
+ }
246
+ else {
247
+ log.info(`Ignoring an unknown error during query`);
248
+ }
249
+ return defaultValue;
250
+ }
251
+ }
211
252
  subscribeToMembers() {
212
253
  this.contract.on(this.membersFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
213
254
  this.processEvents([event]);
@@ -219,6 +260,72 @@ class RLNLightContract {
219
260
  this.processEvents([event]);
220
261
  });
221
262
  }
263
+ async getMembershipInfo(idCommitmentBigInt) {
264
+ try {
265
+ console.log("idCommitmentBigInt", idCommitmentBigInt);
266
+ const membershipData = await this.contract.memberships(idCommitmentBigInt);
267
+ const currentBlock = await this.contract.provider.getBlockNumber();
268
+ console.log("membershipData", membershipData);
269
+ const [depositAmount, activeDuration, gracePeriodStartTimestamp, gracePeriodDuration, rateLimit, index, holder, token] = membershipData;
270
+ const gracePeriodEnd = gracePeriodStartTimestamp.add(gracePeriodDuration);
271
+ console.log("gracePeriodEnd", gracePeriodEnd);
272
+ let state;
273
+ if (currentBlock < gracePeriodStartTimestamp.toNumber()) {
274
+ state = MembershipState.Active;
275
+ }
276
+ else if (currentBlock < gracePeriodEnd.toNumber()) {
277
+ state = MembershipState.GracePeriod;
278
+ }
279
+ else {
280
+ state = MembershipState.Expired;
281
+ }
282
+ console.log("state", state);
283
+ console.log("index", index);
284
+ console.log("idCommitment", idCommitmentBigInt.toString());
285
+ console.log("rateLimit", rateLimit);
286
+ console.log("gracePeriodStartTimestamp", gracePeriodStartTimestamp);
287
+ console.log("gracePeriodEnd", gracePeriodEnd);
288
+ return {
289
+ index,
290
+ idCommitment: idCommitmentBigInt.toString(),
291
+ rateLimit: Number(rateLimit),
292
+ startBlock: gracePeriodStartTimestamp.toNumber(),
293
+ endBlock: gracePeriodEnd.toNumber(),
294
+ state,
295
+ depositAmount,
296
+ activeDuration,
297
+ gracePeriodDuration,
298
+ holder,
299
+ token
300
+ };
301
+ }
302
+ catch (error) {
303
+ console.error("Error in getMembershipInfo:", error);
304
+ return undefined;
305
+ }
306
+ }
307
+ async extendMembership(idCommitment) {
308
+ return this.contract.extendMemberships([idCommitment]);
309
+ }
310
+ async eraseMembership(idCommitment, eraseFromMembershipSet = true) {
311
+ return this.contract.eraseMemberships([idCommitment], eraseFromMembershipSet);
312
+ }
313
+ async registerMembership(idCommitment, rateLimit = DEFAULT_RATE_LIMIT) {
314
+ if (rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
315
+ rateLimit > RATE_LIMIT_PARAMS.MAX_RATE) {
316
+ throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`);
317
+ }
318
+ return this.contract.register(idCommitment, rateLimit, []);
319
+ }
320
+ async withdraw(token) {
321
+ try {
322
+ const tx = await this.contract.withdraw(token);
323
+ await tx.wait();
324
+ }
325
+ catch (error) {
326
+ log.error(`Error in withdraw: ${error.message}`);
327
+ }
328
+ }
222
329
  async registerWithIdentity(identity) {
223
330
  try {
224
331
  log.info(`Registering identity with rate limit: ${this.rateLimit} messages/epoch`);
@@ -253,12 +360,12 @@ class RLNLightContract {
253
360
  `and rate limit ${decodedData.membershipRateLimit}`);
254
361
  const network = await this.contract.provider.getNetwork();
255
362
  const address = this.contract.address;
256
- const membershipId = decodedData.index.toString();
363
+ const membershipId = Number(decodedData.index);
257
364
  return {
258
365
  identity,
259
366
  membership: {
260
367
  address,
261
- treeIndex: `0x${membershipId}`,
368
+ treeIndex: membershipId,
262
369
  chainId: network.chainId.toString(),
263
370
  rateLimit: decodedData.membershipRateLimit.toNumber()
264
371
  }
@@ -293,29 +400,6 @@ class RLNLightContract {
293
400
  }
294
401
  }
295
402
  }
296
- /**
297
- * Helper method to get remaining messages in current epoch
298
- * @param membershipId The ID of the membership to check
299
- * @returns number of remaining messages allowed in current epoch
300
- */
301
- async getRemainingMessages(membershipId) {
302
- try {
303
- const [startTime, , rateLimit] = await this.contract.getMembershipInfo(membershipId);
304
- // Calculate current epoch
305
- const currentTime = Math.floor(Date.now() / 1000);
306
- const epochsPassed = Math.floor((currentTime - startTime) / RATE_LIMIT_PARAMS.EPOCH_LENGTH);
307
- const currentEpochStart = startTime + epochsPassed * RATE_LIMIT_PARAMS.EPOCH_LENGTH;
308
- // Get message count in current epoch using contract's function
309
- const messageCount = await this.contract.getMessageCount(membershipId, currentEpochStart);
310
- return Math.max(0, BigNumber.from(rateLimit)
311
- .sub(BigNumber.from(messageCount))
312
- .toNumber());
313
- }
314
- catch (error) {
315
- log.error(`Error getting remaining messages: ${error.message}`);
316
- return 0; // Fail safe: assume no messages remaining on error
317
- }
318
- }
319
403
  async registerWithPermitAndErase(identity, permit, idCommitmentsToErase) {
320
404
  try {
321
405
  log.info(`Registering identity with permit and rate limit: ${this.rateLimit} messages/epoch`);
@@ -335,12 +419,12 @@ class RLNLightContract {
335
419
  `Rate limit: ${decodedData.membershipRateLimit}, Erased ${idCommitmentsToErase.length} commitments`);
336
420
  const network = await this.contract.provider.getNetwork();
337
421
  const address = this.contract.address;
338
- const membershipId = decodedData.index.toString();
422
+ const membershipId = Number(decodedData.index);
339
423
  return {
340
424
  identity,
341
425
  membership: {
342
426
  address,
343
- treeIndex: `0x${membershipId}`,
427
+ treeIndex: membershipId,
344
428
  chainId: network.chainId.toString(),
345
429
  rateLimit: decodedData.membershipRateLimit.toNumber()
346
430
  }
@@ -351,57 +435,38 @@ class RLNLightContract {
351
435
  return undefined;
352
436
  }
353
437
  }
354
- async withdraw(token, holder) {
355
- try {
356
- const tx = await this.contract.withdraw(token, { from: holder });
357
- await tx.wait();
358
- }
359
- catch (error) {
360
- log.error(`Error in withdraw: ${error.message}`);
438
+ /**
439
+ * Validates that the rate limit is within the allowed range
440
+ * @throws Error if the rate limit is outside the allowed range
441
+ */
442
+ async validateRateLimit(rateLimit) {
443
+ const [minRate, maxRate] = await Promise.all([
444
+ this.contract.minMembershipRateLimit(),
445
+ this.contract.maxMembershipRateLimit()
446
+ ]);
447
+ const minRateNum = BigNumber.from(minRate).toNumber();
448
+ const maxRateNum = BigNumber.from(maxRate).toNumber();
449
+ if (rateLimit < minRateNum || rateLimit > maxRateNum) {
450
+ throw new Error(`Rate limit must be between ${minRateNum} and ${maxRateNum} messages per epoch`);
361
451
  }
362
452
  }
363
- async getMembershipInfo(idCommitment) {
364
- try {
365
- const [startBlock, endBlock, rateLimit] = await this.contract.getMembershipInfo(idCommitment);
366
- const currentBlock = await this.contract.provider.getBlockNumber();
367
- let state;
368
- if (currentBlock < startBlock) {
369
- state = MembershipState.Active;
370
- }
371
- else if (currentBlock < endBlock) {
372
- state = MembershipState.GracePeriod;
373
- }
374
- else {
375
- state = MembershipState.Expired;
376
- }
377
- const index = await this.getMemberIndex(idCommitment);
378
- if (!index)
379
- return undefined;
380
- return {
381
- index,
382
- idCommitment,
383
- rateLimit: rateLimit.toNumber(),
384
- startBlock: startBlock.toNumber(),
385
- endBlock: endBlock.toNumber(),
386
- state
387
- };
388
- }
389
- catch (error) {
390
- return undefined;
453
+ get membersFilter() {
454
+ if (!this._membersFilter) {
455
+ throw Error("Members filter was not initialized.");
391
456
  }
457
+ return this._membersFilter;
392
458
  }
393
- async extendMembership(idCommitment) {
394
- return this.contract.extendMemberships([idCommitment]);
395
- }
396
- async eraseMembership(idCommitment, eraseFromMembershipSet = true) {
397
- return this.contract.eraseMemberships([idCommitment], eraseFromMembershipSet);
459
+ get membershipErasedFilter() {
460
+ if (!this._membershipErasedFilter) {
461
+ throw Error("MembershipErased filter was not initialized.");
462
+ }
463
+ return this._membershipErasedFilter;
398
464
  }
399
- async registerMembership(idCommitment, rateLimit = DEFAULT_RATE_LIMIT) {
400
- if (rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
401
- rateLimit > RATE_LIMIT_PARAMS.MAX_RATE) {
402
- throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`);
465
+ get membersExpiredFilter() {
466
+ if (!this._membersExpiredFilter) {
467
+ throw Error("MembersExpired filter was not initialized.");
403
468
  }
404
- return this.contract.register(idCommitment, rateLimit, []);
469
+ return this._membersExpiredFilter;
405
470
  }
406
471
  async getMemberIndex(idCommitment) {
407
472
  try {
@@ -417,61 +482,5 @@ class RLNLightContract {
417
482
  }
418
483
  }
419
484
  }
420
- // These values should be tested on other networks
421
- const FETCH_CHUNK = 5;
422
- const BLOCK_RANGE = 3000;
423
- async function queryFilter(contract, options) {
424
- const { fromBlock, membersFilter, fetchRange = BLOCK_RANGE, fetchChunks = FETCH_CHUNK } = options;
425
- if (fromBlock === undefined) {
426
- return contract.queryFilter(membersFilter);
427
- }
428
- if (!contract.provider) {
429
- throw Error("No provider found on the contract.");
430
- }
431
- const toBlock = await contract.provider.getBlockNumber();
432
- if (toBlock - fromBlock < fetchRange) {
433
- return contract.queryFilter(membersFilter, fromBlock, toBlock);
434
- }
435
- const events = [];
436
- const chunks = splitToChunks(fromBlock, toBlock, fetchRange);
437
- for (const portion of takeN(chunks, fetchChunks)) {
438
- const promises = portion.map(([left, right]) => ignoreErrors(contract.queryFilter(membersFilter, left, right), []));
439
- const fetchedEvents = await Promise.all(promises);
440
- events.push(fetchedEvents.flatMap((v) => v));
441
- }
442
- return events.flatMap((v) => v);
443
- }
444
- function splitToChunks(from, to, step) {
445
- const chunks = [];
446
- let left = from;
447
- while (left < to) {
448
- const right = left + step < to ? left + step : to;
449
- chunks.push([left, right]);
450
- left = right;
451
- }
452
- return chunks;
453
- }
454
- function* takeN(array, size) {
455
- let start = 0;
456
- while (start < array.length) {
457
- const portion = array.slice(start, start + size);
458
- yield portion;
459
- start += size;
460
- }
461
- }
462
- async function ignoreErrors(promise, defaultValue) {
463
- try {
464
- return await promise;
465
- }
466
- catch (err) {
467
- if (err instanceof Error) {
468
- log.info(`Ignoring an error during query: ${err.message}`);
469
- }
470
- else {
471
- log.info(`Ignoring an unknown error during query`);
472
- }
473
- return defaultValue;
474
- }
475
- }
476
485
 
477
- export { MembershipState, RLNLightContract };
486
+ export { RLNBaseContract };