1
1
import { Logger } from "@waku/utils" ;
2
- import { Contract , ethers } from "ethers" ;
2
+ import { ethers } from "ethers" ;
3
3
4
4
import { IdentityCredential } from "../identity.js" ;
5
5
import { DecryptedCredentials } from "../keystore/types.js" ;
@@ -22,17 +22,18 @@ export class RLNBaseContract {
22
22
public contract : ethers . Contract ;
23
23
private deployBlock : undefined | number ;
24
24
private rateLimit : number ;
25
+ private minRateLimit ?: number ;
26
+ private maxRateLimit ?: number ;
25
27
26
28
protected _members : Map < number , Member > = new Map ( ) ;
27
29
private _membersFilter : ethers . EventFilter ;
28
30
private _membershipErasedFilter : ethers . EventFilter ;
29
31
private _membersExpiredFilter : ethers . EventFilter ;
30
32
31
33
/**
32
- * Constructor for RLNBaseContract.
33
- * Allows injecting a mocked contract for testing purposes.
34
+ * Private constructor for RLNBaseContract. Use static create() instead.
34
35
*/
35
- public constructor ( options : RLNContractInitOptions ) {
36
+ private constructor ( options : RLNContractInitOptions ) {
36
37
const {
37
38
address,
38
39
signer,
@@ -67,11 +68,24 @@ export class RLNBaseContract {
67
68
. catch ( ( error ) => {
68
69
log . error ( "Failed to initialize members" , { error } ) ;
69
70
} ) ;
71
+ }
70
72
71
- // Validate rate limit asynchronously
72
- this . validateRateLimit ( rateLimit ) . catch ( ( error ) => {
73
- log . error ( "Failed to validate initial rate limit" , { error } ) ;
74
- } ) ;
73
+ /**
74
+ * Static async factory to create and initialize RLNBaseContract
75
+ */
76
+ public static async create (
77
+ options : RLNContractInitOptions
78
+ ) : Promise < RLNBaseContract > {
79
+ const instance = new RLNBaseContract ( options ) ;
80
+ const [ min , max ] = await Promise . all ( [
81
+ instance . contract . minMembershipRateLimit ( ) ,
82
+ instance . contract . maxMembershipRateLimit ( )
83
+ ] ) ;
84
+ instance . minRateLimit = ethers . BigNumber . from ( min ) . toNumber ( ) ;
85
+ instance . maxRateLimit = ethers . BigNumber . from ( max ) . toNumber ( ) ;
86
+
87
+ instance . validateRateLimit ( instance . rateLimit ) ;
88
+ return instance ;
75
89
}
76
90
77
91
/**
@@ -96,21 +110,21 @@ export class RLNBaseContract {
96
110
}
97
111
98
112
/**
99
- * Gets the minimum allowed rate limit from the contract
100
- * @returns Promise<number> The minimum rate limit in messages per epoch
113
+ * Gets the minimum allowed rate limit (cached)
101
114
*/
102
- public async getMinRateLimit ( ) : Promise < number > {
103
- const minRate = await this . contract . minMembershipRateLimit ( ) ;
104
- return ethers . BigNumber . from ( minRate ) . toNumber ( ) ;
115
+ public getMinRateLimit ( ) : number {
116
+ if ( this . minRateLimit === undefined )
117
+ throw new Error ( "minRateLimit not initialized" ) ;
118
+ return this . minRateLimit ;
105
119
}
106
120
107
121
/**
108
- * Gets the maximum allowed rate limit from the contract
109
- * @returns Promise<number> The maximum rate limit in messages per epoch
122
+ * Gets the maximum allowed rate limit (cached)
110
123
*/
111
- public async getMaxRateLimit ( ) : Promise < number > {
112
- const maxRate = await this . contract . maxMembershipRateLimit ( ) ;
113
- return ethers . BigNumber . from ( maxRate ) . toNumber ( ) ;
124
+ public getMaxRateLimit ( ) : number {
125
+ if ( this . maxRateLimit === undefined )
126
+ throw new Error ( "maxRateLimit not initialized" ) ;
127
+ return this . maxRateLimit ;
114
128
}
115
129
116
130
/**
@@ -147,8 +161,8 @@ export class RLNBaseContract {
147
161
* Updates the rate limit for future registrations
148
162
* @param newRateLimit The new rate limit to use
149
163
*/
150
- public async setRateLimit ( newRateLimit : number ) : Promise < void > {
151
- await this . validateRateLimit ( newRateLimit ) ;
164
+ public setRateLimit ( newRateLimit : number ) : void {
165
+ this . validateRateLimit ( newRateLimit ) ;
152
166
this . rateLimit = newRateLimit ;
153
167
}
154
168
@@ -662,21 +676,16 @@ export class RLNBaseContract {
662
676
}
663
677
664
678
/**
665
- * Validates that the rate limit is within the allowed range
679
+ * Validates that the rate limit is within the allowed range (sync)
666
680
* @throws Error if the rate limit is outside the allowed range
667
681
*/
668
- private async validateRateLimit ( rateLimit : number ) : Promise < void > {
669
- const [ minRate , maxRate ] = await Promise . all ( [
670
- this . contract . minMembershipRateLimit ( ) ,
671
- this . contract . maxMembershipRateLimit ( )
672
- ] ) ;
673
-
674
- const minRateNum = ethers . BigNumber . from ( minRate ) . toNumber ( ) ;
675
- const maxRateNum = ethers . BigNumber . from ( maxRate ) . toNumber ( ) ;
676
-
677
- if ( rateLimit < minRateNum || rateLimit > maxRateNum ) {
682
+ private validateRateLimit ( rateLimit : number ) : void {
683
+ if ( this . minRateLimit === undefined || this . maxRateLimit === undefined ) {
684
+ throw new Error ( "Rate limits not initialized" ) ;
685
+ }
686
+ if ( rateLimit < this . minRateLimit || rateLimit > this . maxRateLimit ) {
678
687
throw new Error (
679
- `Rate limit must be between ${ minRateNum } and ${ maxRateNum } messages per epoch`
688
+ `Rate limit must be between ${ this . minRateLimit } and ${ this . maxRateLimit } messages per epoch`
680
689
) ;
681
690
}
682
691
}
0 commit comments