@waku/rln 0.1.5-053bb95.0 → 0.1.5-164df63.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.
- package/bundle/_virtual/utils.js +2 -2
- package/bundle/_virtual/utils2.js +2 -2
- package/bundle/index.js +2 -1
- package/bundle/packages/rln/dist/contract/constants.js +6 -2
- package/bundle/packages/rln/dist/contract/rln_base_contract.js +282 -146
- package/bundle/packages/rln/dist/contract/rln_contract.js +74 -89
- package/bundle/packages/rln/dist/credentials_manager.js +1 -1
- package/bundle/packages/rln/dist/identity.js +0 -8
- package/bundle/packages/rln/dist/keystore/keystore.js +28 -15
- package/bundle/packages/rln/dist/utils/bytes.js +8 -2
- package/bundle/packages/rln/dist/utils/metamask.js +2 -2
- package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
- package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
- package/bundle/packages/rln/node_modules/@noble/hashes/_sha2.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/hmac.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/pbkdf2.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/scrypt.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/sha256.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/sha512.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/utils.js +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/constants.d.ts +1 -1
- package/dist/contract/constants.js +1 -1
- package/dist/contract/constants.js.map +1 -1
- package/dist/contract/index.d.ts +1 -0
- package/dist/contract/index.js +1 -0
- package/dist/contract/index.js.map +1 -1
- package/dist/contract/rln_base_contract.d.ts +27 -25
- package/dist/contract/rln_base_contract.js +280 -144
- package/dist/contract/rln_base_contract.js.map +1 -1
- package/dist/contract/rln_contract.d.ts +4 -24
- package/dist/contract/rln_contract.js +74 -89
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/contract/types.d.ts +5 -0
- package/dist/contract/types.js.map +1 -1
- package/dist/credentials_manager.js +1 -1
- package/dist/credentials_manager.js.map +1 -1
- package/dist/identity.d.ts +0 -1
- package/dist/identity.js +0 -8
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/keystore/keystore.d.ts +1 -0
- package/dist/keystore/keystore.js +28 -15
- package/dist/keystore/keystore.js.map +1 -1
- package/dist/keystore/types.d.ts +2 -2
- package/dist/utils/bytes.js +8 -2
- package/dist/utils/bytes.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/constants.ts +1 -1
- package/src/contract/index.ts +1 -0
- package/src/contract/rln_base_contract.ts +428 -216
- package/src/contract/rln_contract.ts +95 -120
- package/src/contract/types.ts +5 -0
- package/src/credentials_manager.ts +1 -1
- package/src/identity.ts +0 -9
- package/src/index.ts +3 -1
- package/src/keystore/keystore.ts +54 -29
- package/src/keystore/types.ts +2 -2
- package/src/utils/bytes.ts +10 -2
- package/bundle/_virtual/__node-resolve_empty.js +0 -6
- package/bundle/_virtual/_node-resolve_empty.js +0 -3
- package/bundle/_virtual/bn.js +0 -3
- package/bundle/_virtual/common.js +0 -3
- package/bundle/_virtual/common2.js +0 -3
- package/bundle/_virtual/hash.js +0 -3
- package/bundle/_virtual/inherits_browser.js +0 -3
- package/bundle/_virtual/ripemd.js +0 -3
- package/bundle/_virtual/sha.js +0 -3
- package/bundle/_virtual/sha3.js +0 -3
- package/bundle/_virtual/utils3.js +0 -3
- package/bundle/node_modules/@ethersproject/abi/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/abi/lib.esm/abi-coder.js +0 -96
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/abstract-coder.js +0 -148
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/address.js +0 -26
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/anonymous.js +0 -20
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/array.js +0 -210
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/boolean.js +0 -18
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/bytes.js +0 -30
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/fixed-bytes.js +0 -26
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/null.js +0 -22
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/number.js +0 -43
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/string.js +0 -19
- package/bundle/node_modules/@ethersproject/abi/lib.esm/coders/tuple.js +0 -58
- package/bundle/node_modules/@ethersproject/abi/lib.esm/fragments.js +0 -854
- package/bundle/node_modules/@ethersproject/abi/lib.esm/interface.js +0 -609
- package/bundle/node_modules/@ethersproject/abstract-provider/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/abstract-provider/lib.esm/index.js +0 -66
- package/bundle/node_modules/@ethersproject/abstract-signer/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/abstract-signer/lib.esm/index.js +0 -302
- package/bundle/node_modules/@ethersproject/address/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/address/lib.esm/index.js +0 -110
- package/bundle/node_modules/@ethersproject/base64/lib.esm/base64.js +0 -20
- package/bundle/node_modules/@ethersproject/basex/lib.esm/index.js +0 -120
- package/bundle/node_modules/@ethersproject/bignumber/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/bignumber/lib.esm/bignumber.js +0 -287
- package/bundle/node_modules/@ethersproject/bytes/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/bytes/lib.esm/index.js +0 -402
- package/bundle/node_modules/@ethersproject/constants/lib.esm/addresses.js +0 -3
- package/bundle/node_modules/@ethersproject/constants/lib.esm/bignumbers.js +0 -8
- package/bundle/node_modules/@ethersproject/constants/lib.esm/hashes.js +0 -3
- package/bundle/node_modules/@ethersproject/contracts/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/contracts/lib.esm/index.js +0 -893
- package/bundle/node_modules/@ethersproject/hash/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/hash/lib.esm/ens-normalize/decoder.js +0 -256
- package/bundle/node_modules/@ethersproject/hash/lib.esm/ens-normalize/include.js +0 -36
- package/bundle/node_modules/@ethersproject/hash/lib.esm/ens-normalize/lib.js +0 -135
- package/bundle/node_modules/@ethersproject/hash/lib.esm/id.js +0 -8
- package/bundle/node_modules/@ethersproject/hash/lib.esm/namehash.js +0 -64
- package/bundle/node_modules/@ethersproject/hash/lib.esm/typed-data.js +0 -443
- package/bundle/node_modules/@ethersproject/keccak256/lib.esm/index.js +0 -8
- package/bundle/node_modules/@ethersproject/keccak256/node_modules/js-sha3/src/sha3.js +0 -660
- package/bundle/node_modules/@ethersproject/logger/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/logger/lib.esm/index.js +0 -352
- package/bundle/node_modules/@ethersproject/networks/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/networks/lib.esm/index.js +0 -248
- package/bundle/node_modules/@ethersproject/properties/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/properties/lib.esm/index.js +0 -127
- package/bundle/node_modules/@ethersproject/providers/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/providers/lib.esm/base-provider.js +0 -2007
- package/bundle/node_modules/@ethersproject/providers/lib.esm/formatter.js +0 -422
- package/bundle/node_modules/@ethersproject/providers/lib.esm/json-rpc-provider.js +0 -674
- package/bundle/node_modules/@ethersproject/providers/lib.esm/web3-provider.js +0 -132
- package/bundle/node_modules/@ethersproject/rlp/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/rlp/lib.esm/index.js +0 -120
- package/bundle/node_modules/@ethersproject/sha2/lib.esm/sha2.js +0 -8
- package/bundle/node_modules/@ethersproject/signing-key/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/signing-key/lib.esm/elliptic.js +0 -2430
- package/bundle/node_modules/@ethersproject/signing-key/lib.esm/index.js +0 -76
- package/bundle/node_modules/@ethersproject/strings/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/strings/lib.esm/utf8.js +0 -219
- package/bundle/node_modules/@ethersproject/transactions/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/transactions/lib.esm/index.js +0 -279
- package/bundle/node_modules/@ethersproject/web/lib.esm/_version.js +0 -3
- package/bundle/node_modules/@ethersproject/web/lib.esm/geturl.js +0 -69
- package/bundle/node_modules/@ethersproject/web/lib.esm/index.js +0 -404
- package/bundle/node_modules/bech32/index.js +0 -187
- package/bundle/node_modules/bn.js/lib/bn.js +0 -3361
- package/bundle/node_modules/hash.js/lib/hash/common.js +0 -97
- package/bundle/node_modules/hash.js/lib/hash/hmac.js +0 -51
- package/bundle/node_modules/hash.js/lib/hash/ripemd.js +0 -152
- package/bundle/node_modules/hash.js/lib/hash/sha/1.js +0 -81
- package/bundle/node_modules/hash.js/lib/hash/sha/224.js +0 -33
- package/bundle/node_modules/hash.js/lib/hash/sha/256.js +0 -113
- package/bundle/node_modules/hash.js/lib/hash/sha/384.js +0 -39
- package/bundle/node_modules/hash.js/lib/hash/sha/512.js +0 -336
- package/bundle/node_modules/hash.js/lib/hash/sha/common.js +0 -53
- package/bundle/node_modules/hash.js/lib/hash/sha.js +0 -14
- package/bundle/node_modules/hash.js/lib/hash/utils.js +0 -282
- package/bundle/node_modules/hash.js/lib/hash.js +0 -33
- package/bundle/node_modules/inherits/inherits_browser.js +0 -33
- package/bundle/node_modules/minimalistic-assert/index.js +0 -13
- package/bundle/packages/rln/dist/contract/errors.js +0 -62
- package/dist/contract/errors.d.ts +0 -30
- package/dist/contract/errors.js +0 -61
- package/dist/contract/errors.js.map +0 -1
- package/src/contract/errors.ts +0 -75
@@ -1,10 +1,19 @@
|
|
1
1
|
import { ethers } from "ethers";
|
2
2
|
import { IdentityCredential } from "../identity.js";
|
3
3
|
import { DecryptedCredentials } from "../keystore/types.js";
|
4
|
-
import { Member, MembershipInfo, RLNContractInitOptions } from "./types.js";
|
4
|
+
import { CustomQueryOptions, FetchMembersOptions, Member, MembershipInfo, RLNContractInitOptions } from "./types.js";
|
5
5
|
export declare class RLNBaseContract {
|
6
6
|
contract: ethers.Contract;
|
7
|
+
private deployBlock;
|
7
8
|
private rateLimit;
|
9
|
+
protected _members: Map<number, Member>;
|
10
|
+
private _membersFilter;
|
11
|
+
private _membershipErasedFilter;
|
12
|
+
private _membersExpiredFilter;
|
13
|
+
/**
|
14
|
+
* Constructor for RLNBaseContract.
|
15
|
+
* Allows injecting a mocked contract for testing purposes.
|
16
|
+
*/
|
8
17
|
constructor(options: RLNContractInitOptions);
|
9
18
|
/**
|
10
19
|
* Gets the current rate limit for this contract instance
|
@@ -48,26 +57,19 @@ export declare class RLNBaseContract {
|
|
48
57
|
* @param newRateLimit The new rate limit to use
|
49
58
|
*/
|
50
59
|
setRateLimit(newRateLimit: number): Promise<void>;
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
*/
|
65
|
-
private getMemberIndex;
|
66
|
-
getMembershipInfo(idCommitment: string): Promise<MembershipInfo>;
|
67
|
-
extendMembership(idCommitment: string): Promise<void>;
|
68
|
-
eraseMembership(idCommitment: string, eraseFromMembershipSet?: boolean): Promise<void>;
|
69
|
-
registerMembership(idCommitment: string, rateLimit?: number): Promise<void>;
|
70
|
-
withdraw(token: string, holder: string): Promise<void>;
|
60
|
+
get members(): Member[];
|
61
|
+
fetchMembers(options?: FetchMembersOptions): Promise<void>;
|
62
|
+
static queryFilter(contract: ethers.Contract, options: CustomQueryOptions): Promise<ethers.Event[]>;
|
63
|
+
processEvents(events: ethers.Event[]): void;
|
64
|
+
static splitToChunks(from: number, to: number, step: number): Array<[number, number]>;
|
65
|
+
static takeN<T>(array: T[], size: number): Iterable<T[]>;
|
66
|
+
static ignoreErrors<T>(promise: Promise<T>, defaultValue: T): Promise<T>;
|
67
|
+
subscribeToMembers(): void;
|
68
|
+
getMembershipInfo(idCommitmentBigInt: bigint): Promise<MembershipInfo | undefined>;
|
69
|
+
extendMembership(idCommitmentBigInt: bigint): Promise<ethers.ContractTransaction>;
|
70
|
+
eraseMembership(idCommitmentBigInt: bigint, eraseFromMembershipSet?: boolean): Promise<ethers.ContractTransaction>;
|
71
|
+
withdraw(token: string, from: string): Promise<void>;
|
72
|
+
registerMembership(idCommitmentBigInt: bigint, rateLimit?: number): Promise<ethers.ContractTransaction>;
|
71
73
|
registerWithIdentity(identity: IdentityCredential): Promise<DecryptedCredentials | undefined>;
|
72
74
|
registerWithPermitAndErase(identity: IdentityCredential, permit: {
|
73
75
|
owner: string;
|
@@ -81,8 +83,8 @@ export declare class RLNBaseContract {
|
|
81
83
|
* @throws Error if the rate limit is outside the allowed range
|
82
84
|
*/
|
83
85
|
private validateRateLimit;
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
private
|
86
|
+
private get membersFilter();
|
87
|
+
private get membershipErasedFilter();
|
88
|
+
private get membersExpiredFilter();
|
89
|
+
private getMemberIndex;
|
88
90
|
}
|
@@ -1,18 +1,51 @@
|
|
1
|
+
/* eslint-disable no-console */
|
1
2
|
import { Logger } from "@waku/utils";
|
2
3
|
import { ethers } from "ethers";
|
3
4
|
import { RLN_ABI } from "./abi.js";
|
4
5
|
import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from "./constants.js";
|
5
|
-
import { InvalidMembershipError, InvalidRateLimitError, MembershipExistsError, MembershipNotFoundError, RateLimitExceededError, RLNContractError, TransactionError } from "./errors.js";
|
6
6
|
import { MembershipState } from "./types.js";
|
7
7
|
const log = new Logger("waku:rln:contract:base");
|
8
8
|
export class RLNBaseContract {
|
9
9
|
contract;
|
10
|
+
deployBlock;
|
10
11
|
rateLimit;
|
12
|
+
_members = new Map();
|
13
|
+
_membersFilter;
|
14
|
+
_membershipErasedFilter;
|
15
|
+
_membersExpiredFilter;
|
16
|
+
/**
|
17
|
+
* Constructor for RLNBaseContract.
|
18
|
+
* Allows injecting a mocked contract for testing purposes.
|
19
|
+
*/
|
11
20
|
constructor(options) {
|
12
21
|
const { address, signer, rateLimit = DEFAULT_RATE_LIMIT, contract } = options;
|
13
|
-
|
22
|
+
log.info("Initializing RLNBaseContract", { address, rateLimit });
|
14
23
|
this.contract = contract || new ethers.Contract(address, RLN_ABI, signer);
|
15
24
|
this.rateLimit = rateLimit;
|
25
|
+
try {
|
26
|
+
log.info("Setting up event filters");
|
27
|
+
// Initialize event filters
|
28
|
+
this._membersFilter = this.contract.filters.MembershipRegistered();
|
29
|
+
this._membershipErasedFilter = this.contract.filters.MembershipErased();
|
30
|
+
this._membersExpiredFilter = this.contract.filters.MembershipExpired();
|
31
|
+
log.info("Event filters initialized successfully");
|
32
|
+
}
|
33
|
+
catch (error) {
|
34
|
+
log.error("Failed to initialize event filters", { error });
|
35
|
+
throw new Error("Failed to initialize event filters: " + error.message);
|
36
|
+
}
|
37
|
+
// Initialize members and subscriptions
|
38
|
+
this.fetchMembers()
|
39
|
+
.then(() => {
|
40
|
+
this.subscribeToMembers();
|
41
|
+
})
|
42
|
+
.catch((error) => {
|
43
|
+
log.error("Failed to initialize members", { error });
|
44
|
+
});
|
45
|
+
// Validate rate limit asynchronously
|
46
|
+
this.validateRateLimit(rateLimit).catch((error) => {
|
47
|
+
log.error("Failed to validate initial rate limit", { error });
|
48
|
+
});
|
16
49
|
}
|
17
50
|
/**
|
18
51
|
* Gets the current rate limit for this contract instance
|
@@ -80,221 +113,299 @@ export class RLNBaseContract {
|
|
80
113
|
* @param newRateLimit The new rate limit to use
|
81
114
|
*/
|
82
115
|
async setRateLimit(newRateLimit) {
|
83
|
-
this.validateRateLimit(newRateLimit);
|
116
|
+
await this.validateRateLimit(newRateLimit);
|
84
117
|
this.rateLimit = newRateLimit;
|
85
118
|
}
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
119
|
+
get members() {
|
120
|
+
const sortedMembers = Array.from(this._members.values()).sort((left, right) => left.index.toNumber() - right.index.toNumber());
|
121
|
+
return sortedMembers;
|
122
|
+
}
|
123
|
+
async fetchMembers(options = {}) {
|
124
|
+
const registeredMemberEvents = await RLNBaseContract.queryFilter(this.contract, {
|
125
|
+
fromBlock: this.deployBlock,
|
126
|
+
...options,
|
127
|
+
membersFilter: this.membersFilter
|
128
|
+
});
|
129
|
+
const removedMemberEvents = await RLNBaseContract.queryFilter(this.contract, {
|
130
|
+
fromBlock: this.deployBlock,
|
131
|
+
...options,
|
132
|
+
membersFilter: this.membershipErasedFilter
|
133
|
+
});
|
134
|
+
const expiredMemberEvents = await RLNBaseContract.queryFilter(this.contract, {
|
135
|
+
fromBlock: this.deployBlock,
|
136
|
+
...options,
|
137
|
+
membersFilter: this.membersExpiredFilter
|
138
|
+
});
|
139
|
+
const events = [
|
140
|
+
...registeredMemberEvents,
|
141
|
+
...removedMemberEvents,
|
142
|
+
...expiredMemberEvents
|
143
|
+
];
|
144
|
+
this.processEvents(events);
|
145
|
+
}
|
146
|
+
static async queryFilter(contract, options) {
|
147
|
+
const FETCH_CHUNK = 5;
|
148
|
+
const BLOCK_RANGE = 3000;
|
149
|
+
const { fromBlock, membersFilter, fetchRange = BLOCK_RANGE, fetchChunks = FETCH_CHUNK } = options;
|
150
|
+
if (fromBlock === undefined) {
|
151
|
+
return contract.queryFilter(membersFilter);
|
108
152
|
}
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
153
|
+
if (!contract.provider) {
|
154
|
+
throw Error("No provider found on the contract.");
|
155
|
+
}
|
156
|
+
const toBlock = await contract.provider.getBlockNumber();
|
157
|
+
if (toBlock - fromBlock < fetchRange) {
|
158
|
+
return contract.queryFilter(membersFilter, fromBlock, toBlock);
|
159
|
+
}
|
160
|
+
const events = [];
|
161
|
+
const chunks = RLNBaseContract.splitToChunks(fromBlock, toBlock, fetchRange);
|
162
|
+
for (const portion of RLNBaseContract.takeN(chunks, fetchChunks)) {
|
163
|
+
const promises = portion.map(([left, right]) => RLNBaseContract.ignoreErrors(contract.queryFilter(membersFilter, left, right), []));
|
164
|
+
const fetchedEvents = await Promise.all(promises);
|
165
|
+
events.push(fetchedEvents.flatMap((v) => v));
|
166
|
+
}
|
167
|
+
return events.flatMap((v) => v);
|
168
|
+
}
|
169
|
+
processEvents(events) {
|
170
|
+
const toRemoveTable = new Map();
|
171
|
+
const toInsertTable = new Map();
|
172
|
+
events.forEach((evt) => {
|
173
|
+
if (!evt.args) {
|
174
|
+
return;
|
113
175
|
}
|
114
|
-
|
176
|
+
if (evt.event === "MembershipErased" ||
|
177
|
+
evt.event === "MembershipExpired") {
|
178
|
+
let index = evt.args.index;
|
179
|
+
if (!index) {
|
180
|
+
return;
|
181
|
+
}
|
182
|
+
if (typeof index === "number" || typeof index === "string") {
|
183
|
+
index = ethers.BigNumber.from(index);
|
184
|
+
}
|
185
|
+
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
186
|
+
if (toRemoveVal != undefined) {
|
187
|
+
toRemoveVal.push(index.toNumber());
|
188
|
+
toRemoveTable.set(evt.blockNumber, toRemoveVal);
|
189
|
+
}
|
190
|
+
else {
|
191
|
+
toRemoveTable.set(evt.blockNumber, [index.toNumber()]);
|
192
|
+
}
|
193
|
+
}
|
194
|
+
else if (evt.event === "MembershipRegistered") {
|
195
|
+
let eventsPerBlock = toInsertTable.get(evt.blockNumber);
|
196
|
+
if (eventsPerBlock == undefined) {
|
197
|
+
eventsPerBlock = [];
|
198
|
+
}
|
199
|
+
eventsPerBlock.push(evt);
|
200
|
+
toInsertTable.set(evt.blockNumber, eventsPerBlock);
|
201
|
+
}
|
202
|
+
});
|
203
|
+
}
|
204
|
+
static splitToChunks(from, to, step) {
|
205
|
+
const chunks = [];
|
206
|
+
let left = from;
|
207
|
+
while (left < to) {
|
208
|
+
const right = left + step < to ? left + step : to;
|
209
|
+
chunks.push([left, right]);
|
210
|
+
left = right;
|
115
211
|
}
|
212
|
+
return chunks;
|
116
213
|
}
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
214
|
+
static *takeN(array, size) {
|
215
|
+
let start = 0;
|
216
|
+
while (start < array.length) {
|
217
|
+
const portion = array.slice(start, start + size);
|
218
|
+
yield portion;
|
219
|
+
start += size;
|
220
|
+
}
|
123
221
|
}
|
124
|
-
|
125
|
-
* Gets the member index if it exists, or null if it doesn't
|
126
|
-
* Throws only on actual errors (invalid input, network issues, etc)
|
127
|
-
*/
|
128
|
-
async getMemberIndex(idCommitment) {
|
222
|
+
static async ignoreErrors(promise, defaultValue) {
|
129
223
|
try {
|
130
|
-
|
131
|
-
if (!isValid) {
|
132
|
-
return null;
|
133
|
-
}
|
134
|
-
const membershipInfo = await this.contract.memberships(idCommitment);
|
135
|
-
return ethers.BigNumber.from(membershipInfo.index);
|
224
|
+
return await promise;
|
136
225
|
}
|
137
|
-
catch (
|
138
|
-
|
139
|
-
|
226
|
+
catch (err) {
|
227
|
+
if (err instanceof Error) {
|
228
|
+
log.info(`Ignoring an error during query: ${err.message}`);
|
229
|
+
}
|
230
|
+
else {
|
231
|
+
log.info(`Ignoring an unknown error during query`);
|
232
|
+
}
|
233
|
+
return defaultValue;
|
140
234
|
}
|
141
235
|
}
|
142
|
-
|
236
|
+
subscribeToMembers() {
|
237
|
+
this.contract.on(this.membersFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
238
|
+
this.processEvents([event]);
|
239
|
+
});
|
240
|
+
this.contract.on(this.membershipErasedFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
241
|
+
this.processEvents([event]);
|
242
|
+
});
|
243
|
+
this.contract.on(this.membersExpiredFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
244
|
+
this.processEvents([event]);
|
245
|
+
});
|
246
|
+
}
|
247
|
+
async getMembershipInfo(idCommitmentBigInt) {
|
143
248
|
try {
|
144
|
-
const
|
249
|
+
const membershipData = await this.contract.memberships(idCommitmentBigInt);
|
145
250
|
const currentBlock = await this.contract.provider.getBlockNumber();
|
251
|
+
console.log("membershipData", membershipData);
|
252
|
+
const [depositAmount, activeDuration, gracePeriodStartTimestamp, gracePeriodDuration, rateLimit, index, holder, token] = membershipData;
|
253
|
+
const gracePeriodEnd = gracePeriodStartTimestamp.add(gracePeriodDuration);
|
146
254
|
let state;
|
147
|
-
if (currentBlock <
|
255
|
+
if (currentBlock < gracePeriodStartTimestamp.toNumber()) {
|
148
256
|
state = MembershipState.Active;
|
149
257
|
}
|
150
|
-
else if (currentBlock <
|
258
|
+
else if (currentBlock < gracePeriodEnd.toNumber()) {
|
151
259
|
state = MembershipState.GracePeriod;
|
152
260
|
}
|
153
261
|
else {
|
154
262
|
state = MembershipState.Expired;
|
155
263
|
}
|
156
|
-
const index = await this.getMemberIndex(idCommitment);
|
157
|
-
if (index === null) {
|
158
|
-
throw new MembershipNotFoundError(idCommitment);
|
159
|
-
}
|
160
264
|
return {
|
161
265
|
index,
|
162
|
-
idCommitment,
|
163
|
-
rateLimit: rateLimit
|
164
|
-
startBlock:
|
165
|
-
endBlock:
|
166
|
-
state
|
266
|
+
idCommitment: idCommitmentBigInt.toString(),
|
267
|
+
rateLimit: Number(rateLimit),
|
268
|
+
startBlock: gracePeriodStartTimestamp.toNumber(),
|
269
|
+
endBlock: gracePeriodEnd.toNumber(),
|
270
|
+
state,
|
271
|
+
depositAmount,
|
272
|
+
activeDuration,
|
273
|
+
gracePeriodDuration,
|
274
|
+
holder,
|
275
|
+
token
|
167
276
|
};
|
168
277
|
}
|
169
278
|
catch (error) {
|
170
|
-
|
171
|
-
|
172
|
-
}
|
173
|
-
log.error(`Error getting membership info: ${error.message}`);
|
174
|
-
throw new InvalidMembershipError(idCommitment);
|
279
|
+
log.error("Error in getMembershipInfo:", error);
|
280
|
+
return undefined;
|
175
281
|
}
|
176
282
|
}
|
177
|
-
async extendMembership(
|
178
|
-
const tx = await this.contract.extendMemberships([
|
179
|
-
await
|
180
|
-
|
181
|
-
endBlock: event.args.endBlock
|
182
|
-
}));
|
283
|
+
async extendMembership(idCommitmentBigInt) {
|
284
|
+
const tx = await this.contract.extendMemberships([idCommitmentBigInt]);
|
285
|
+
await tx.wait();
|
286
|
+
return tx;
|
183
287
|
}
|
184
|
-
async eraseMembership(
|
185
|
-
|
186
|
-
await this.
|
187
|
-
|
188
|
-
|
189
|
-
}));
|
288
|
+
async eraseMembership(idCommitmentBigInt, eraseFromMembershipSet = true) {
|
289
|
+
console.log(Object.keys(this.contract));
|
290
|
+
const tx = await this.contract.eraseMemberships([idCommitmentBigInt], eraseFromMembershipSet);
|
291
|
+
await tx.wait();
|
292
|
+
return tx;
|
190
293
|
}
|
191
|
-
async
|
192
|
-
if (rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
|
193
|
-
rateLimit > RATE_LIMIT_PARAMS.MAX_RATE) {
|
194
|
-
throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`);
|
195
|
-
}
|
196
|
-
const tx = await this.contract.register(idCommitment, rateLimit, []);
|
197
|
-
await this.confirmTransaction(tx, "MembershipRegistered", (event) => ({
|
198
|
-
idCommitment: event.args.idCommitment,
|
199
|
-
membershipRateLimit: event.args.membershipRateLimit,
|
200
|
-
index: event.args.index
|
201
|
-
}));
|
202
|
-
}
|
203
|
-
async withdraw(token, holder) {
|
294
|
+
async withdraw(token, from) {
|
204
295
|
try {
|
205
|
-
const tx = await this.contract.withdraw(token,
|
206
|
-
await
|
207
|
-
token: event.args.token,
|
208
|
-
holder: event.args.holder,
|
209
|
-
amount: event.args.amount
|
210
|
-
}));
|
296
|
+
const tx = await this.contract.withdraw(token, from);
|
297
|
+
await tx.wait();
|
211
298
|
}
|
212
299
|
catch (error) {
|
213
300
|
log.error(`Error in withdraw: ${error.message}`);
|
214
|
-
throw error;
|
215
301
|
}
|
216
302
|
}
|
303
|
+
async registerMembership(idCommitmentBigInt, rateLimit = DEFAULT_RATE_LIMIT) {
|
304
|
+
if (rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
|
305
|
+
rateLimit > RATE_LIMIT_PARAMS.MAX_RATE) {
|
306
|
+
throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`);
|
307
|
+
}
|
308
|
+
return this.contract.register(idCommitmentBigInt, rateLimit, []);
|
309
|
+
}
|
217
310
|
async registerWithIdentity(identity) {
|
218
311
|
try {
|
219
312
|
log.info(`Registering identity with rate limit: ${this.rateLimit} messages/epoch`);
|
220
313
|
// Check if the ID commitment is already registered
|
221
|
-
const existingIndex = await this.getMemberIndex(identity.IDCommitmentBigInt
|
222
|
-
if (existingIndex
|
223
|
-
throw new
|
314
|
+
const existingIndex = await this.getMemberIndex(identity.IDCommitmentBigInt);
|
315
|
+
if (existingIndex) {
|
316
|
+
throw new Error(`ID commitment is already registered with index ${existingIndex}`);
|
224
317
|
}
|
225
318
|
// Check if there's enough remaining rate limit
|
226
319
|
const remainingRateLimit = await this.getRemainingTotalRateLimit();
|
227
320
|
if (remainingRateLimit < this.rateLimit) {
|
228
|
-
throw new
|
321
|
+
throw new Error(`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`);
|
229
322
|
}
|
230
323
|
const estimatedGas = await this.contract.estimateGas.register(identity.IDCommitmentBigInt, this.rateLimit, []);
|
231
324
|
const gasLimit = estimatedGas.add(10000);
|
232
|
-
const
|
233
|
-
const
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
325
|
+
const txRegisterResponse = await this.contract.register(identity.IDCommitmentBigInt, this.rateLimit, [], { gasLimit });
|
326
|
+
const txRegisterReceipt = await txRegisterResponse.wait();
|
327
|
+
if (txRegisterReceipt.status === 0) {
|
328
|
+
throw new Error("Transaction failed on-chain");
|
329
|
+
}
|
330
|
+
const memberRegistered = txRegisterReceipt.events?.find((event) => event.event === "MembershipRegistered");
|
331
|
+
if (!memberRegistered || !memberRegistered.args) {
|
332
|
+
log.error("Failed to register membership: No MembershipRegistered event found");
|
333
|
+
return undefined;
|
334
|
+
}
|
335
|
+
const decodedData = {
|
336
|
+
idCommitment: memberRegistered.args.idCommitment,
|
337
|
+
membershipRateLimit: memberRegistered.args.membershipRateLimit,
|
338
|
+
index: memberRegistered.args.index
|
339
|
+
};
|
238
340
|
log.info(`Successfully registered membership with index ${decodedData.index} ` +
|
239
341
|
`and rate limit ${decodedData.membershipRateLimit}`);
|
240
342
|
const network = await this.contract.provider.getNetwork();
|
241
343
|
const address = this.contract.address;
|
242
|
-
const membershipId = decodedData.index
|
344
|
+
const membershipId = Number(decodedData.index);
|
243
345
|
return {
|
244
346
|
identity,
|
245
347
|
membership: {
|
246
348
|
address,
|
247
|
-
treeIndex:
|
349
|
+
treeIndex: membershipId,
|
248
350
|
chainId: network.chainId.toString(),
|
249
351
|
rateLimit: decodedData.membershipRateLimit.toNumber()
|
250
352
|
}
|
251
353
|
};
|
252
354
|
}
|
253
355
|
catch (error) {
|
254
|
-
if (error instanceof RLNContractError) {
|
255
|
-
throw error;
|
256
|
-
}
|
257
356
|
if (error instanceof Error) {
|
258
357
|
const errorMessage = error.message;
|
259
358
|
log.error("registerWithIdentity - error message:", errorMessage);
|
260
359
|
log.error("registerWithIdentity - error stack:", error.stack);
|
261
|
-
//
|
360
|
+
// Try to extract more specific error information
|
262
361
|
if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
|
263
|
-
throw new
|
362
|
+
throw new Error("Registration failed: Cannot exceed maximum total rate limit");
|
264
363
|
}
|
265
364
|
else if (errorMessage.includes("InvalidIdCommitment")) {
|
266
|
-
throw new
|
365
|
+
throw new Error("Registration failed: Invalid ID commitment");
|
267
366
|
}
|
268
367
|
else if (errorMessage.includes("InvalidMembershipRateLimit")) {
|
269
|
-
throw new
|
368
|
+
throw new Error("Registration failed: Invalid membership rate limit");
|
270
369
|
}
|
271
370
|
else if (errorMessage.includes("execution reverted")) {
|
272
|
-
throw new
|
371
|
+
throw new Error("Contract execution reverted. Check contract requirements.");
|
372
|
+
}
|
373
|
+
else {
|
374
|
+
throw new Error(`Error in registerWithIdentity: ${errorMessage}`);
|
273
375
|
}
|
274
|
-
throw new RLNContractError(`Error in registerWithIdentity: ${errorMessage}`);
|
275
376
|
}
|
276
|
-
|
377
|
+
else {
|
378
|
+
throw new Error("Unknown error in registerWithIdentity", {
|
379
|
+
cause: error
|
380
|
+
});
|
381
|
+
}
|
277
382
|
}
|
278
383
|
}
|
279
384
|
async registerWithPermitAndErase(identity, permit, idCommitmentsToErase) {
|
280
385
|
try {
|
281
386
|
log.info(`Registering identity with permit and rate limit: ${this.rateLimit} messages/epoch`);
|
282
|
-
const
|
283
|
-
const
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
387
|
+
const txRegisterResponse = await this.contract.registerWithPermit(permit.owner, permit.deadline, permit.v, permit.r, permit.s, identity.IDCommitmentBigInt, this.rateLimit, idCommitmentsToErase.map((id) => ethers.BigNumber.from(id)));
|
388
|
+
const txRegisterReceipt = await txRegisterResponse.wait();
|
389
|
+
const memberRegistered = txRegisterReceipt.events?.find((event) => event.event === "MembershipRegistered");
|
390
|
+
if (!memberRegistered || !memberRegistered.args) {
|
391
|
+
log.error("Failed to register membership with permit: No MembershipRegistered event found");
|
392
|
+
return undefined;
|
393
|
+
}
|
394
|
+
const decodedData = {
|
395
|
+
idCommitment: memberRegistered.args.idCommitment,
|
396
|
+
membershipRateLimit: memberRegistered.args.membershipRateLimit,
|
397
|
+
index: memberRegistered.args.index
|
398
|
+
};
|
288
399
|
log.info(`Successfully registered membership with permit. Index: ${decodedData.index}, ` +
|
289
400
|
`Rate limit: ${decodedData.membershipRateLimit}, Erased ${idCommitmentsToErase.length} commitments`);
|
290
401
|
const network = await this.contract.provider.getNetwork();
|
291
402
|
const address = this.contract.address;
|
292
|
-
const membershipId = decodedData.index
|
403
|
+
const membershipId = Number(decodedData.index);
|
293
404
|
return {
|
294
405
|
identity,
|
295
406
|
membership: {
|
296
407
|
address,
|
297
|
-
treeIndex:
|
408
|
+
treeIndex: membershipId,
|
298
409
|
chainId: network.chainId.toString(),
|
299
410
|
rateLimit: decodedData.membershipRateLimit.toNumber()
|
300
411
|
}
|
@@ -302,29 +413,54 @@ export class RLNBaseContract {
|
|
302
413
|
}
|
303
414
|
catch (error) {
|
304
415
|
log.error(`Error in registerWithPermitAndErase: ${error.message}`);
|
305
|
-
|
416
|
+
return undefined;
|
306
417
|
}
|
307
418
|
}
|
308
419
|
/**
|
309
420
|
* Validates that the rate limit is within the allowed range
|
310
421
|
* @throws Error if the rate limit is outside the allowed range
|
311
422
|
*/
|
312
|
-
validateRateLimit(rateLimit) {
|
313
|
-
|
314
|
-
|
315
|
-
|
423
|
+
async validateRateLimit(rateLimit) {
|
424
|
+
const [minRate, maxRate] = await Promise.all([
|
425
|
+
this.contract.minMembershipRateLimit(),
|
426
|
+
this.contract.maxMembershipRateLimit()
|
427
|
+
]);
|
428
|
+
const minRateNum = ethers.BigNumber.from(minRate).toNumber();
|
429
|
+
const maxRateNum = ethers.BigNumber.from(maxRate).toNumber();
|
430
|
+
if (rateLimit < minRateNum || rateLimit > maxRateNum) {
|
431
|
+
throw new Error(`Rate limit must be between ${minRateNum} and ${maxRateNum} messages per epoch`);
|
316
432
|
}
|
317
433
|
}
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
434
|
+
get membersFilter() {
|
435
|
+
if (!this._membersFilter) {
|
436
|
+
throw Error("Members filter was not initialized.");
|
437
|
+
}
|
438
|
+
return this._membersFilter;
|
439
|
+
}
|
440
|
+
get membershipErasedFilter() {
|
441
|
+
if (!this._membershipErasedFilter) {
|
442
|
+
throw Error("MembershipErased filter was not initialized.");
|
443
|
+
}
|
444
|
+
return this._membershipErasedFilter;
|
445
|
+
}
|
446
|
+
get membersExpiredFilter() {
|
447
|
+
if (!this._membersExpiredFilter) {
|
448
|
+
throw Error("MembersExpired filter was not initialized.");
|
449
|
+
}
|
450
|
+
return this._membersExpiredFilter;
|
451
|
+
}
|
452
|
+
async getMemberIndex(idCommitmentBigInt) {
|
453
|
+
try {
|
454
|
+
const events = await this.contract.queryFilter(this.contract.filters.MembershipRegistered(idCommitmentBigInt));
|
455
|
+
if (events.length === 0)
|
456
|
+
return undefined;
|
457
|
+
// Get the most recent registration event
|
458
|
+
const event = events[events.length - 1];
|
459
|
+
return event.args?.index;
|
460
|
+
}
|
461
|
+
catch (error) {
|
462
|
+
return undefined;
|
326
463
|
}
|
327
|
-
return transform(event);
|
328
464
|
}
|
329
465
|
}
|
330
466
|
//# sourceMappingURL=rln_base_contract.js.map
|