@waku/rln 0.1.1-5d7f77f → 0.1.1-77ba0a6
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.
- package/README.md +26 -2
- package/bundle/assets/rln_wasm_bg-a503e304.wasm +0 -0
- package/bundle/index.js +68738 -22572
- package/dist/.tsbuildinfo +1 -1
- package/dist/byte_utils.d.ts +13 -0
- package/dist/byte_utils.js +22 -0
- package/dist/byte_utils.js.map +1 -1
- package/dist/codec.d.ts +5 -3
- package/dist/codec.js +8 -4
- package/dist/codec.js.map +1 -1
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +62 -9
- package/dist/constants.js.map +1 -1
- package/dist/create.d.ts +2 -0
- package/dist/create.js +8 -0
- package/dist/create.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -10
- package/dist/index.js.map +1 -1
- package/dist/keystore/cipher.d.ts +4 -0
- package/dist/keystore/cipher.js +28 -0
- package/dist/keystore/cipher.js.map +1 -0
- package/dist/keystore/credential_validation_generated.d.ts +8 -0
- package/dist/keystore/credential_validation_generated.js +121 -0
- package/dist/keystore/credential_validation_generated.js.map +1 -0
- package/dist/keystore/index.d.ts +4 -0
- package/dist/keystore/index.js +3 -0
- package/dist/keystore/index.js.map +1 -0
- package/dist/keystore/keystore.d.ts +50 -0
- package/dist/keystore/keystore.js +202 -0
- package/dist/keystore/keystore.js.map +1 -0
- package/dist/keystore/keystore_validation_generated.d.ts +8 -0
- package/dist/keystore/keystore_validation_generated.js +75 -0
- package/dist/keystore/keystore_validation_generated.js.map +1 -0
- package/dist/keystore/schema_validator.d.ts +2 -0
- package/dist/keystore/schema_validator.js +18 -0
- package/dist/keystore/schema_validator.js.map +1 -0
- package/dist/keystore/types.d.ts +29 -0
- package/dist/keystore/types.js +2 -0
- package/dist/keystore/types.js.map +1 -0
- package/dist/message.d.ts +1 -1
- package/dist/message.js +1 -1
- package/dist/metamask.d.ts +2 -0
- package/dist/metamask.js +11 -0
- package/dist/metamask.js.map +1 -0
- package/dist/rln.d.ts +47 -0
- package/dist/rln.js +110 -12
- package/dist/rln.js.map +1 -1
- package/dist/rln_contract.d.ts +24 -14
- package/dist/rln_contract.js +73 -33
- package/dist/rln_contract.js.map +1 -1
- package/package.json +23 -8
- package/src/byte_utils.ts +24 -0
- package/src/codec.ts +10 -5
- package/src/constants.ts +63 -9
- package/src/create.ts +9 -0
- package/src/index.ts +13 -11
- package/src/message.ts +1 -1
- package/src/metamask.ts +16 -0
- package/src/rln.ts +194 -13
- package/src/rln_contract.ts +127 -52
- package/bundle/assets/rln_wasm_bg-6f96f821.wasm +0 -0
package/src/rln.ts
CHANGED
@@ -1,10 +1,28 @@
|
|
1
|
+
import { createDecoder, createEncoder } from "@waku/core";
|
1
2
|
import type { IRateLimitProof } from "@waku/interfaces";
|
2
|
-
import {
|
3
|
+
import type {
|
4
|
+
ContentTopic,
|
5
|
+
IDecodedMessage,
|
6
|
+
EncoderOptions as WakuEncoderOptions,
|
7
|
+
} from "@waku/interfaces";
|
8
|
+
import init from "@waku/zerokit-rln-wasm";
|
3
9
|
import * as zerokitRLN from "@waku/zerokit-rln-wasm";
|
10
|
+
import { ethers } from "ethers";
|
4
11
|
|
5
|
-
import { writeUIntLE } from "./byte_utils.js";
|
12
|
+
import { buildBigIntFromUint8Array, writeUIntLE } from "./byte_utils.js";
|
13
|
+
import type { RLNDecoder, RLNEncoder } from "./codec.js";
|
14
|
+
import { createRLNDecoder, createRLNEncoder } from "./codec.js";
|
15
|
+
import { SEPOLIA_CONTRACT } from "./constants.js";
|
6
16
|
import { dateToEpoch, epochIntToBytes } from "./epoch.js";
|
17
|
+
import { Keystore } from "./keystore/index.js";
|
18
|
+
import type {
|
19
|
+
DecryptedCredentials,
|
20
|
+
EncryptedCredentials,
|
21
|
+
} from "./keystore/index.js";
|
22
|
+
import { Password } from "./keystore/types.js";
|
23
|
+
import { extractMetaMaskSigner } from "./metamask.js";
|
7
24
|
import verificationKey from "./resources/verification_key.js";
|
25
|
+
import { RLNContract } from "./rln_contract.js";
|
8
26
|
import * as wc from "./witness_calculator.js";
|
9
27
|
import { WitnessCalculator } from "./witness_calculator.js";
|
10
28
|
|
@@ -27,16 +45,6 @@ function concatenate(...input: Uint8Array[]): Uint8Array {
|
|
27
45
|
return result;
|
28
46
|
}
|
29
47
|
|
30
|
-
/**
|
31
|
-
* Transforms Uint8Array into BigInt
|
32
|
-
* @param array: Uint8Array
|
33
|
-
* @returns BigInt
|
34
|
-
*/
|
35
|
-
function buildBigIntFromUint8Array(array: Uint8Array): bigint {
|
36
|
-
const dataView = new DataView(array.buffer);
|
37
|
-
return dataView.getBigUint64(0, true);
|
38
|
-
}
|
39
|
-
|
40
48
|
const stringEncoder = new TextEncoder();
|
41
49
|
|
42
50
|
const DEPTH = 20;
|
@@ -58,7 +66,7 @@ async function loadZkey(): Promise<Uint8Array> {
|
|
58
66
|
* @returns RLNInstance
|
59
67
|
*/
|
60
68
|
export async function create(): Promise<RLNInstance> {
|
61
|
-
await init();
|
69
|
+
await (init as any)?.();
|
62
70
|
zerokitRLN.init_panic_hook();
|
63
71
|
const witnessCalculator = await loadWitnessCalculator();
|
64
72
|
const zkey = await loadZkey();
|
@@ -168,12 +176,185 @@ export function sha256(input: Uint8Array): Uint8Array {
|
|
168
176
|
return zerokitRLN.hash(lenPrefixedData);
|
169
177
|
}
|
170
178
|
|
179
|
+
type StartRLNOptions = {
|
180
|
+
/**
|
181
|
+
* If not set - will extract MetaMask account and get signer from it.
|
182
|
+
*/
|
183
|
+
signer?: ethers.Signer;
|
184
|
+
/**
|
185
|
+
* If not set - will use default SEPOLIA_CONTRACT address.
|
186
|
+
*/
|
187
|
+
registryAddress?: string;
|
188
|
+
/**
|
189
|
+
* Credentials to use for generating proofs and connecting to the contract and network.
|
190
|
+
* If provided used for validating the network chainId and connecting to registry contract.
|
191
|
+
*/
|
192
|
+
credentials?: EncryptedCredentials | DecryptedCredentials;
|
193
|
+
};
|
194
|
+
|
195
|
+
type RegisterMembershipOptions =
|
196
|
+
| { signature: string }
|
197
|
+
| { identity: IdentityCredential };
|
198
|
+
|
171
199
|
export class RLNInstance {
|
200
|
+
private started = false;
|
201
|
+
private starting = false;
|
202
|
+
|
203
|
+
private _contract: undefined | RLNContract;
|
204
|
+
private _signer: undefined | ethers.Signer;
|
205
|
+
|
206
|
+
private keystore = Keystore.create();
|
207
|
+
private _credentials: undefined | DecryptedCredentials;
|
208
|
+
|
172
209
|
constructor(
|
173
210
|
private zkRLN: number,
|
174
211
|
private witnessCalculator: WitnessCalculator
|
175
212
|
) {}
|
176
213
|
|
214
|
+
public get contract(): undefined | RLNContract {
|
215
|
+
return this._contract;
|
216
|
+
}
|
217
|
+
|
218
|
+
public get signer(): undefined | ethers.Signer {
|
219
|
+
return this._signer;
|
220
|
+
}
|
221
|
+
|
222
|
+
public async start(options: StartRLNOptions = {}): Promise<void> {
|
223
|
+
if (this.started || this.starting) {
|
224
|
+
return;
|
225
|
+
}
|
226
|
+
|
227
|
+
this.starting = true;
|
228
|
+
|
229
|
+
try {
|
230
|
+
const { signer, registryAddress } = await this.determineStartOptions(
|
231
|
+
options
|
232
|
+
);
|
233
|
+
|
234
|
+
this._signer = signer!;
|
235
|
+
this._contract = await RLNContract.init(this, {
|
236
|
+
registryAddress: registryAddress!,
|
237
|
+
signer: signer!,
|
238
|
+
});
|
239
|
+
this.started = true;
|
240
|
+
} finally {
|
241
|
+
this.starting = false;
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
private async determineStartOptions(
|
246
|
+
options: StartRLNOptions
|
247
|
+
): Promise<StartRLNOptions> {
|
248
|
+
const credentials = await this.decryptCredentialsIfNeeded(
|
249
|
+
options.credentials
|
250
|
+
);
|
251
|
+
|
252
|
+
let chainId = credentials?.membership.chainId;
|
253
|
+
const registryAddress =
|
254
|
+
credentials?.membership.address ||
|
255
|
+
options.registryAddress ||
|
256
|
+
SEPOLIA_CONTRACT.address;
|
257
|
+
|
258
|
+
if (registryAddress === SEPOLIA_CONTRACT.address) {
|
259
|
+
chainId = SEPOLIA_CONTRACT.chainId;
|
260
|
+
}
|
261
|
+
|
262
|
+
const signer = options.signer || (await extractMetaMaskSigner());
|
263
|
+
const currentChainId = await signer.getChainId();
|
264
|
+
|
265
|
+
if (chainId && chainId !== currentChainId) {
|
266
|
+
throw Error(
|
267
|
+
`Failed to start RLN contract, chain ID of contract is different from current one: contract-${chainId}, current network-${currentChainId}`
|
268
|
+
);
|
269
|
+
}
|
270
|
+
|
271
|
+
return {
|
272
|
+
signer,
|
273
|
+
registryAddress,
|
274
|
+
credentials: options.credentials,
|
275
|
+
};
|
276
|
+
}
|
277
|
+
|
278
|
+
private async decryptCredentialsIfNeeded(
|
279
|
+
credentials?: EncryptedCredentials | DecryptedCredentials
|
280
|
+
): Promise<undefined | DecryptedCredentials> {
|
281
|
+
if (!credentials) {
|
282
|
+
return;
|
283
|
+
}
|
284
|
+
|
285
|
+
if ("identity" in credentials) {
|
286
|
+
this._credentials = credentials;
|
287
|
+
return credentials;
|
288
|
+
}
|
289
|
+
|
290
|
+
const keystore = Keystore.fromString(credentials.keystore);
|
291
|
+
|
292
|
+
if (!keystore) {
|
293
|
+
throw Error("Failed to start RLN: cannot read Keystore provided.");
|
294
|
+
}
|
295
|
+
|
296
|
+
this.keystore = keystore;
|
297
|
+
this._credentials = await keystore.readCredential(
|
298
|
+
credentials.id,
|
299
|
+
credentials.password
|
300
|
+
);
|
301
|
+
|
302
|
+
return this._credentials;
|
303
|
+
}
|
304
|
+
|
305
|
+
public async registerMembership(
|
306
|
+
options: RegisterMembershipOptions
|
307
|
+
): Promise<undefined | DecryptedCredentials> {
|
308
|
+
if (!this.contract) {
|
309
|
+
throw Error("RLN Contract is not initialized.");
|
310
|
+
}
|
311
|
+
|
312
|
+
let identity = "identity" in options && options.identity;
|
313
|
+
|
314
|
+
if ("signature" in options) {
|
315
|
+
identity = await this.generateSeededIdentityCredential(options.signature);
|
316
|
+
}
|
317
|
+
|
318
|
+
if (!identity) {
|
319
|
+
throw Error("Missing signature or identity to register membership.");
|
320
|
+
}
|
321
|
+
|
322
|
+
return this.contract.registerWithIdentity(identity);
|
323
|
+
}
|
324
|
+
|
325
|
+
/**
|
326
|
+
* Changes credentials in use by relying on provided Keystore earlier in rln.start
|
327
|
+
* @param id: string, hash of credentials to select from Keystore
|
328
|
+
* @param password: string or bytes to use to decrypt credentials from Keystore
|
329
|
+
*/
|
330
|
+
public async useCredentials(id: string, password: Password): Promise<void> {
|
331
|
+
this._credentials = await this.keystore?.readCredential(id, password);
|
332
|
+
}
|
333
|
+
|
334
|
+
public createEncoder(options: WakuEncoderOptions): RLNEncoder {
|
335
|
+
if (!this._credentials) {
|
336
|
+
throw Error(
|
337
|
+
"Failed to create Encoder: missing RLN credentials. Use createRLNEncoder directly."
|
338
|
+
);
|
339
|
+
}
|
340
|
+
|
341
|
+
return createRLNEncoder({
|
342
|
+
encoder: createEncoder(options),
|
343
|
+
rlnInstance: this,
|
344
|
+
index: this._credentials.membership.treeIndex,
|
345
|
+
credential: this._credentials.identity,
|
346
|
+
});
|
347
|
+
}
|
348
|
+
|
349
|
+
public createDecoder(
|
350
|
+
contentTopic: ContentTopic
|
351
|
+
): RLNDecoder<IDecodedMessage> {
|
352
|
+
return createRLNDecoder({
|
353
|
+
rlnInstance: this,
|
354
|
+
decoder: createDecoder(contentTopic),
|
355
|
+
});
|
356
|
+
}
|
357
|
+
|
177
358
|
generateIdentityCredentials(): IdentityCredential {
|
178
359
|
const memKeys = zerokitRLN.generateExtendedMembershipKey(this.zkRLN); // TODO: rename this function in zerokit rln-wasm
|
179
360
|
return IdentityCredential.fromBytes(memKeys);
|
package/src/rln_contract.ts
CHANGED
@@ -1,19 +1,30 @@
|
|
1
|
+
import { hexToBytes } from "@waku/utils/bytes";
|
1
2
|
import { ethers } from "ethers";
|
2
3
|
|
3
|
-
import {
|
4
|
-
import {
|
4
|
+
import { zeroPadLE } from "./byte_utils.js";
|
5
|
+
import { RLN_REGISTRY_ABI, RLN_STORAGE_ABI } from "./constants.js";
|
6
|
+
import type { DecryptedCredentials } from "./keystore/index.js";
|
7
|
+
import { type IdentityCredential, RLNInstance } from "./rln.js";
|
5
8
|
import { MerkleRootTracker } from "./root_tracker.js";
|
6
9
|
|
7
10
|
type Member = {
|
8
|
-
|
9
|
-
index:
|
11
|
+
idCommitment: string;
|
12
|
+
index: ethers.BigNumber;
|
10
13
|
};
|
11
14
|
|
12
|
-
type
|
13
|
-
|
14
|
-
|
15
|
+
type Signer = ethers.Signer;
|
16
|
+
|
17
|
+
type RLNContractOptions = {
|
18
|
+
signer: Signer;
|
19
|
+
registryAddress: string;
|
20
|
+
};
|
21
|
+
|
22
|
+
type RLNStorageOptions = {
|
23
|
+
storageIndex?: number;
|
15
24
|
};
|
16
25
|
|
26
|
+
type RLNContractInitOptions = RLNContractOptions & RLNStorageOptions;
|
27
|
+
|
17
28
|
type FetchMembersOptions = {
|
18
29
|
fromBlock?: number;
|
19
30
|
fetchRange?: number;
|
@@ -21,18 +32,23 @@ type FetchMembersOptions = {
|
|
21
32
|
};
|
22
33
|
|
23
34
|
export class RLNContract {
|
24
|
-
private
|
25
|
-
private membersFilter: ethers.EventFilter;
|
35
|
+
private registryContract: ethers.Contract;
|
26
36
|
private merkleRootTracker: MerkleRootTracker;
|
27
37
|
|
28
|
-
private
|
38
|
+
private deployBlock: undefined | number;
|
39
|
+
private storageIndex: undefined | number;
|
40
|
+
private storageContract: undefined | ethers.Contract;
|
41
|
+
private _membersFilter: undefined | ethers.EventFilter;
|
42
|
+
|
43
|
+
private _members: Map<number, Member> = new Map();
|
29
44
|
|
30
45
|
public static async init(
|
31
46
|
rlnInstance: RLNInstance,
|
32
|
-
options:
|
47
|
+
options: RLNContractInitOptions
|
33
48
|
): Promise<RLNContract> {
|
34
49
|
const rlnContract = new RLNContract(rlnInstance, options);
|
35
50
|
|
51
|
+
await rlnContract.initStorageContract(options.signer);
|
36
52
|
await rlnContract.fetchMembers(rlnInstance);
|
37
53
|
rlnContract.subscribeToMembers(rlnInstance);
|
38
54
|
|
@@ -41,21 +57,61 @@ export class RLNContract {
|
|
41
57
|
|
42
58
|
constructor(
|
43
59
|
rlnInstance: RLNInstance,
|
44
|
-
{
|
60
|
+
{ registryAddress, signer }: RLNContractOptions
|
45
61
|
) {
|
46
62
|
const initialRoot = rlnInstance.getMerkleRoot();
|
47
63
|
|
48
|
-
this.
|
64
|
+
this.registryContract = new ethers.Contract(
|
65
|
+
registryAddress,
|
66
|
+
RLN_REGISTRY_ABI,
|
67
|
+
signer
|
68
|
+
);
|
49
69
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
50
|
-
|
70
|
+
}
|
71
|
+
|
72
|
+
private async initStorageContract(
|
73
|
+
signer: Signer,
|
74
|
+
options: RLNStorageOptions = {}
|
75
|
+
): Promise<void> {
|
76
|
+
const storageIndex = options?.storageIndex
|
77
|
+
? options.storageIndex
|
78
|
+
: await this.registryContract.usingStorageIndex();
|
79
|
+
const storageAddress = await this.registryContract.storages(storageIndex);
|
80
|
+
|
81
|
+
if (!storageAddress || storageAddress === ethers.constants.AddressZero) {
|
82
|
+
throw Error("No RLN Storage initialized on registry contract.");
|
83
|
+
}
|
84
|
+
|
85
|
+
this.storageIndex = storageIndex;
|
86
|
+
this.storageContract = new ethers.Contract(
|
87
|
+
storageAddress,
|
88
|
+
RLN_STORAGE_ABI,
|
89
|
+
signer
|
90
|
+
);
|
91
|
+
this._membersFilter = this.storageContract.filters.MemberRegistered();
|
92
|
+
|
93
|
+
this.deployBlock = await this.storageContract.deployedBlockNumber();
|
51
94
|
}
|
52
95
|
|
53
96
|
public get contract(): ethers.Contract {
|
54
|
-
|
97
|
+
if (!this.storageContract) {
|
98
|
+
throw Error("Storage contract was not initialized");
|
99
|
+
}
|
100
|
+
return this.storageContract as ethers.Contract;
|
55
101
|
}
|
56
102
|
|
57
103
|
public get members(): Member[] {
|
58
|
-
|
104
|
+
const sortedMembers = Array.from(this._members.values()).sort(
|
105
|
+
(left, right) => left.index.toNumber() - right.index.toNumber()
|
106
|
+
);
|
107
|
+
return sortedMembers;
|
108
|
+
}
|
109
|
+
|
110
|
+
private get membersFilter(): ethers.EventFilter {
|
111
|
+
if (!this._membersFilter) {
|
112
|
+
throw Error("Members filter was not initialized.");
|
113
|
+
}
|
114
|
+
return this._membersFilter as ethers.EventFilter;
|
59
115
|
}
|
60
116
|
|
61
117
|
public async fetchMembers(
|
@@ -63,6 +119,7 @@ export class RLNContract {
|
|
63
119
|
options: FetchMembersOptions = {}
|
64
120
|
): Promise<void> {
|
65
121
|
const registeredMemberEvents = await queryFilter(this.contract, {
|
122
|
+
fromBlock: this.deployBlock,
|
66
123
|
...options,
|
67
124
|
membersFilter: this.membersFilter,
|
68
125
|
});
|
@@ -79,13 +136,13 @@ export class RLNContract {
|
|
79
136
|
}
|
80
137
|
|
81
138
|
if (evt.removed) {
|
82
|
-
const index:
|
139
|
+
const index: ethers.BigNumber = evt.args.index;
|
83
140
|
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
84
141
|
if (toRemoveVal != undefined) {
|
85
|
-
toRemoveVal.push(index);
|
142
|
+
toRemoveVal.push(index.toNumber());
|
86
143
|
toRemoveTable.set(evt.blockNumber, toRemoveVal);
|
87
144
|
} else {
|
88
|
-
toRemoveTable.set(evt.blockNumber, [index]);
|
145
|
+
toRemoveTable.set(evt.blockNumber, [index.toNumber()]);
|
89
146
|
}
|
90
147
|
} else {
|
91
148
|
let eventsPerBlock = toInsertTable.get(evt.blockNumber);
|
@@ -96,10 +153,10 @@ export class RLNContract {
|
|
96
153
|
eventsPerBlock.push(evt);
|
97
154
|
toInsertTable.set(evt.blockNumber, eventsPerBlock);
|
98
155
|
}
|
99
|
-
|
100
|
-
this.removeMembers(rlnInstance, toRemoveTable);
|
101
|
-
this.insertMembers(rlnInstance, toInsertTable);
|
102
156
|
});
|
157
|
+
|
158
|
+
this.removeMembers(rlnInstance, toRemoveTable);
|
159
|
+
this.insertMembers(rlnInstance, toInsertTable);
|
103
160
|
}
|
104
161
|
|
105
162
|
private insertMembers(
|
@@ -108,18 +165,19 @@ export class RLNContract {
|
|
108
165
|
): void {
|
109
166
|
toInsert.forEach((events: ethers.Event[], blockNumber: number) => {
|
110
167
|
events.forEach((evt) => {
|
111
|
-
|
168
|
+
const _idCommitment = evt?.args?.idCommitment;
|
169
|
+
const index: ethers.BigNumber = evt?.args?.index;
|
170
|
+
|
171
|
+
if (!_idCommitment || !index) {
|
112
172
|
return;
|
113
173
|
}
|
114
174
|
|
115
|
-
const
|
116
|
-
const index = evt.args.index;
|
117
|
-
const idCommitment = ethers.utils.zeroPad(
|
118
|
-
ethers.utils.arrayify(pubkey),
|
119
|
-
32
|
120
|
-
);
|
175
|
+
const idCommitment = zeroPadLE(hexToBytes(_idCommitment?._hex), 32);
|
121
176
|
rlnInstance.insertMember(idCommitment);
|
122
|
-
this.
|
177
|
+
this._members.set(index.toNumber(), {
|
178
|
+
index,
|
179
|
+
idCommitment: _idCommitment?._hex,
|
180
|
+
});
|
123
181
|
});
|
124
182
|
|
125
183
|
const currentRoot = rlnInstance.getMerkleRoot();
|
@@ -134,9 +192,8 @@ export class RLNContract {
|
|
134
192
|
const removeDescending = new Map([...toRemove].sort().reverse());
|
135
193
|
removeDescending.forEach((indexes: number[], blockNumber: number) => {
|
136
194
|
indexes.forEach((index) => {
|
137
|
-
|
138
|
-
|
139
|
-
this.members.splice(idx, 1);
|
195
|
+
if (this._members.has(index)) {
|
196
|
+
this._members.delete(index);
|
140
197
|
}
|
141
198
|
rlnInstance.deleteMember(index);
|
142
199
|
});
|
@@ -147,32 +204,50 @@ export class RLNContract {
|
|
147
204
|
|
148
205
|
public subscribeToMembers(rlnInstance: RLNInstance): void {
|
149
206
|
this.contract.on(this.membersFilter, (_pubkey, _index, event) =>
|
150
|
-
this.processEvents(rlnInstance, event)
|
207
|
+
this.processEvents(rlnInstance, [event])
|
151
208
|
);
|
152
209
|
}
|
153
210
|
|
154
|
-
public async
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
211
|
+
public async registerWithIdentity(
|
212
|
+
identity: IdentityCredential
|
213
|
+
): Promise<DecryptedCredentials | undefined> {
|
214
|
+
if (this.storageIndex === undefined) {
|
215
|
+
throw Error(
|
216
|
+
"Cannot register credential, no storage contract index found."
|
217
|
+
);
|
218
|
+
}
|
219
|
+
const txRegisterResponse: ethers.ContractTransaction =
|
220
|
+
await this.registryContract["register(uint16,uint256)"](
|
221
|
+
this.storageIndex,
|
222
|
+
identity.IDCommitmentBigInt,
|
223
|
+
{ gasLimit: 100000 }
|
224
|
+
);
|
225
|
+
const txRegisterReceipt = await txRegisterResponse.wait();
|
160
226
|
|
161
|
-
|
162
|
-
|
227
|
+
// assumption: register(uint16,uint256) emits one event
|
228
|
+
const memberRegistered = txRegisterReceipt?.events?.[0];
|
163
229
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
const depositValue = await this.contract.MEMBERSHIP_DEPOSIT();
|
230
|
+
if (!memberRegistered) {
|
231
|
+
return undefined;
|
232
|
+
}
|
168
233
|
|
169
|
-
const
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
const txRegisterReceipt = await txRegisterResponse.wait();
|
234
|
+
const decodedData = this.contract.interface.decodeEventLog(
|
235
|
+
"MemberRegistered",
|
236
|
+
memberRegistered.data
|
237
|
+
);
|
174
238
|
|
175
|
-
|
239
|
+
const network = await this.registryContract.provider.getNetwork();
|
240
|
+
const address = this.registryContract.address;
|
241
|
+
const membershipId = decodedData.index.toNumber();
|
242
|
+
|
243
|
+
return {
|
244
|
+
identity,
|
245
|
+
membership: {
|
246
|
+
address,
|
247
|
+
treeIndex: membershipId,
|
248
|
+
chainId: network.chainId,
|
249
|
+
},
|
250
|
+
};
|
176
251
|
}
|
177
252
|
|
178
253
|
public roots(): Uint8Array[] {
|
Binary file
|