@waku/rln 0.1.1-5b9414a → 0.1.1-60a5070

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.
@@ -5,17 +5,23 @@ import { IdentityCredential, RLNInstance } from "./rln.js";
5
5
  import { MerkleRootTracker } from "./root_tracker.js";
6
6
 
7
7
  type Member = {
8
- pubkey: string;
9
- index: number;
8
+ idCommitment: string;
9
+ index: ethers.BigNumber;
10
10
  };
11
11
 
12
12
  type Provider = ethers.Signer | ethers.providers.Provider;
13
13
 
14
- type ContractOptions = {
15
- address: string;
14
+ type RLNContractOptions = {
16
15
  provider: Provider;
16
+ registryAddress: string;
17
17
  };
18
18
 
19
+ type RLNStorageOptions = {
20
+ storageIndex?: number;
21
+ };
22
+
23
+ type RLNContractInitOptions = RLNContractOptions & RLNStorageOptions;
24
+
19
25
  type FetchMembersOptions = {
20
26
  fromBlock?: number;
21
27
  fetchRange?: number;
@@ -31,11 +37,11 @@ export class RLNContract {
31
37
  private storageContract: undefined | ethers.Contract;
32
38
  private _membersFilter: undefined | ethers.EventFilter;
33
39
 
34
- private _members: Member[] = [];
40
+ private _members: Map<number, Member> = new Map();
35
41
 
36
42
  public static async init(
37
43
  rlnInstance: RLNInstance,
38
- options: ContractOptions
44
+ options: RLNContractInitOptions
39
45
  ): Promise<RLNContract> {
40
46
  const rlnContract = new RLNContract(rlnInstance, options);
41
47
 
@@ -48,25 +54,34 @@ export class RLNContract {
48
54
 
49
55
  constructor(
50
56
  rlnInstance: RLNInstance,
51
- { address, provider }: ContractOptions
57
+ { registryAddress, provider }: RLNContractOptions
52
58
  ) {
53
59
  const initialRoot = rlnInstance.getMerkleRoot();
54
60
 
55
61
  this.registryContract = new ethers.Contract(
56
- address,
62
+ registryAddress,
57
63
  RLN_REGISTRY_ABI,
58
64
  provider
59
65
  );
60
66
  this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
61
67
  }
62
68
 
63
- private async initStorageContract(provider: Provider): Promise<void> {
64
- const index = await this.registryContract.usingStorageIndex();
65
- const address = await this.registryContract.storages(index);
69
+ private async initStorageContract(
70
+ provider: Provider,
71
+ options: RLNStorageOptions = {}
72
+ ): Promise<void> {
73
+ const storageIndex = options?.storageIndex
74
+ ? options.storageIndex
75
+ : await this.registryContract.usingStorageIndex();
76
+ const storageAddress = await this.registryContract.storages(storageIndex);
77
+
78
+ if (!storageAddress || storageAddress === ethers.constants.AddressZero) {
79
+ throw Error("No RLN Storage initialized on registry contract.");
80
+ }
66
81
 
67
- this.storageIndex = index;
82
+ this.storageIndex = storageIndex;
68
83
  this.storageContract = new ethers.Contract(
69
- address,
84
+ storageAddress,
70
85
  RLN_STORAGE_ABI,
71
86
  provider
72
87
  );
@@ -77,13 +92,16 @@ export class RLNContract {
77
92
 
78
93
  public get contract(): ethers.Contract {
79
94
  if (!this.storageContract) {
80
- throw Error("Storage contract was not initialized.");
95
+ throw Error("Storage contract was not initialized");
81
96
  }
82
97
  return this.storageContract as ethers.Contract;
83
98
  }
84
99
 
85
100
  public get members(): Member[] {
86
- return this._members;
101
+ const sortedMembers = Array.from(this._members.values()).sort(
102
+ (left, right) => left.index.toNumber() - right.index.toNumber()
103
+ );
104
+ return sortedMembers;
87
105
  }
88
106
 
89
107
  private get membersFilter(): ethers.EventFilter {
@@ -115,13 +133,13 @@ export class RLNContract {
115
133
  }
116
134
 
117
135
  if (evt.removed) {
118
- const index: number = evt.args.index;
136
+ const index: ethers.BigNumber = evt.args.index;
119
137
  const toRemoveVal = toRemoveTable.get(evt.blockNumber);
120
138
  if (toRemoveVal != undefined) {
121
- toRemoveVal.push(index);
139
+ toRemoveVal.push(index.toNumber());
122
140
  toRemoveTable.set(evt.blockNumber, toRemoveVal);
123
141
  } else {
124
- toRemoveTable.set(evt.blockNumber, [index]);
142
+ toRemoveTable.set(evt.blockNumber, [index.toNumber()]);
125
143
  }
126
144
  } else {
127
145
  let eventsPerBlock = toInsertTable.get(evt.blockNumber);
@@ -132,10 +150,10 @@ export class RLNContract {
132
150
  eventsPerBlock.push(evt);
133
151
  toInsertTable.set(evt.blockNumber, eventsPerBlock);
134
152
  }
135
-
136
- this.removeMembers(rlnInstance, toRemoveTable);
137
- this.insertMembers(rlnInstance, toInsertTable);
138
153
  });
154
+
155
+ this.removeMembers(rlnInstance, toRemoveTable);
156
+ this.insertMembers(rlnInstance, toInsertTable);
139
157
  }
140
158
 
141
159
  private insertMembers(
@@ -144,18 +162,23 @@ export class RLNContract {
144
162
  ): void {
145
163
  toInsert.forEach((events: ethers.Event[], blockNumber: number) => {
146
164
  events.forEach((evt) => {
147
- if (!evt.args) {
165
+ const _idCommitment = evt?.args?.idCommitment;
166
+ const index: ethers.BigNumber = evt?.args?.index;
167
+
168
+ if (!_idCommitment || !index) {
148
169
  return;
149
170
  }
150
171
 
151
- const pubkey = evt.args.pubkey;
152
- const index = evt.args.index;
153
172
  const idCommitment = ethers.utils.zeroPad(
154
- ethers.utils.arrayify(pubkey),
173
+ ethers.utils.arrayify(_idCommitment),
155
174
  32
156
175
  );
157
176
  rlnInstance.insertMember(idCommitment);
158
- this.members.push({ index, pubkey });
177
+ this._members.set(index.toNumber(), {
178
+ index,
179
+ idCommitment:
180
+ _idCommitment?._hex || ethers.utils.hexlify(idCommitment),
181
+ });
159
182
  });
160
183
 
161
184
  const currentRoot = rlnInstance.getMerkleRoot();
@@ -170,9 +193,8 @@ export class RLNContract {
170
193
  const removeDescending = new Map([...toRemove].sort().reverse());
171
194
  removeDescending.forEach((indexes: number[], blockNumber: number) => {
172
195
  indexes.forEach((index) => {
173
- const idx = this.members.findIndex((m) => m.index === index);
174
- if (idx > -1) {
175
- this.members.splice(idx, 1);
196
+ if (this._members.has(index)) {
197
+ this._members.delete(index);
176
198
  }
177
199
  rlnInstance.deleteMember(index);
178
200
  });
@@ -183,14 +205,14 @@ export class RLNContract {
183
205
 
184
206
  public subscribeToMembers(rlnInstance: RLNInstance): void {
185
207
  this.contract.on(this.membersFilter, (_pubkey, _index, event) =>
186
- this.processEvents(rlnInstance, event)
208
+ this.processEvents(rlnInstance, [event])
187
209
  );
188
210
  }
189
211
 
190
212
  public async registerWithSignature(
191
213
  rlnInstance: RLNInstance,
192
214
  signature: string
193
- ): Promise<ethers.Event | undefined> {
215
+ ): Promise<Member | undefined> {
194
216
  const identityCredential =
195
217
  await rlnInstance.generateSeededIdentityCredential(signature);
196
218
 
@@ -199,23 +221,36 @@ export class RLNContract {
199
221
 
200
222
  public async registerWithKey(
201
223
  credential: IdentityCredential
202
- ): Promise<ethers.Event | undefined> {
203
- if (!this.storageIndex) {
224
+ ): Promise<Member | undefined> {
225
+ if (this.storageIndex === undefined) {
204
226
  throw Error(
205
227
  "Cannot register credential, no storage contract index found."
206
228
  );
207
229
  }
208
230
  const txRegisterResponse: ethers.ContractTransaction =
209
- await this.registryContract.register(
231
+ await this.registryContract["register(uint16,uint256)"](
210
232
  this.storageIndex,
211
233
  credential.IDCommitmentBigInt,
212
- {
213
- gasLimit: 100000,
214
- }
234
+ { gasLimit: 100000 }
215
235
  );
216
236
  const txRegisterReceipt = await txRegisterResponse.wait();
217
237
 
218
- return txRegisterReceipt?.events?.[0];
238
+ // assumption: register(uint16,uint256) emits one event
239
+ const memberRegistered = txRegisterReceipt?.events?.[0];
240
+
241
+ if (!memberRegistered) {
242
+ return undefined;
243
+ }
244
+
245
+ const decodedData = this.contract.interface.decodeEventLog(
246
+ "MemberRegistered",
247
+ memberRegistered.data
248
+ );
249
+
250
+ return {
251
+ idCommitment: decodedData.idCommitment,
252
+ index: decodedData.index,
253
+ };
219
254
  }
220
255
 
221
256
  public roots(): Uint8Array[] {