@waku/rln 0.1.6-10590da.0 → 0.1.6-383e0b2.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 (97) hide show
  1. package/bundle/_virtual/index2.js +1 -1
  2. package/bundle/_virtual/utils.js +2 -2
  3. package/bundle/_virtual/utils2.js +2 -2
  4. package/bundle/index.js +1 -2
  5. package/bundle/node_modules/@ethersproject/keccak256/lib.esm/index.js +1 -1
  6. package/bundle/node_modules/{js-sha3 → @ethersproject/keccak256/node_modules/js-sha3}/src/sha3.js +2 -2
  7. package/bundle/node_modules/@noble/hashes/esm/_assert.js +32 -6
  8. package/bundle/node_modules/@noble/hashes/esm/_md.js +11 -22
  9. package/bundle/node_modules/@noble/hashes/esm/_u64.js +3 -4
  10. package/bundle/node_modules/@noble/hashes/esm/sha256.js +102 -5
  11. package/bundle/node_modules/@noble/hashes/esm/sha3.js +24 -30
  12. package/bundle/node_modules/@noble/hashes/esm/utils.js +18 -69
  13. package/bundle/node_modules/bn.js/lib/bn.js +0 -1
  14. package/bundle/node_modules/ethereum-cryptography/esm/sha256.js +1 -1
  15. package/bundle/packages/rln/dist/contract/constants.js +0 -1
  16. package/bundle/packages/rln/dist/contract/rln_base_contract.js +71 -127
  17. package/bundle/packages/rln/dist/credentials_manager.js +4 -9
  18. package/bundle/packages/rln/dist/identity.js +1 -1
  19. package/bundle/packages/rln/dist/keystore/cipher.js +3 -3
  20. package/bundle/packages/rln/dist/keystore/keystore.js +1 -1
  21. package/bundle/packages/rln/dist/utils/bytes.js +2 -6
  22. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/checksum.js +3 -3
  23. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/cipher.js +4 -4
  24. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/class.js +7 -7
  25. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/functional.js +7 -7
  26. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/index.js +6 -6
  27. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/kdf.js +5 -5
  28. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/password.js +1 -1
  29. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/schema-validation-generated.js +1 -1
  30. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/schema-validation.js +2 -2
  31. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/lib/types.js +1 -1
  32. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/aes.js +3 -3
  33. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/pbkdf2.js +7 -7
  34. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +3 -3
  35. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/scrypt.js +3 -3
  36. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/sha256.js +3 -3
  37. package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +7 -7
  38. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/_assert.js +1 -1
  39. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/_sha2.js +3 -3
  40. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/_u64.js +1 -1
  41. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/cryptoBrowser.js +1 -1
  42. package/bundle/packages/rln/node_modules/@noble/hashes/esm/_assert.js +43 -0
  43. package/bundle/packages/rln/node_modules/@noble/hashes/esm/_sha2.js +116 -0
  44. package/bundle/{node_modules → packages/rln/node_modules}/@noble/hashes/esm/hmac.js +10 -19
  45. package/bundle/{node_modules/@noble/hashes/esm/sha2.js → packages/rln/node_modules/@noble/hashes/esm/sha256.js} +50 -36
  46. package/bundle/packages/rln/node_modules/@noble/hashes/esm/utils.js +43 -0
  47. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/hmac.js +3 -3
  48. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/pbkdf2.js +4 -4
  49. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/scrypt.js +5 -5
  50. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/sha256.js +3 -3
  51. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/sha512.js +4 -4
  52. package/bundle/{node_modules/@chainsafe/bls-keystore → packages/rln}/node_modules/@noble/hashes/utils.js +2 -2
  53. package/dist/.tsbuildinfo +1 -1
  54. package/dist/contract/index.d.ts +0 -1
  55. package/dist/contract/index.js +0 -1
  56. package/dist/contract/index.js.map +1 -1
  57. package/dist/contract/rln_base_contract.d.ts +22 -32
  58. package/dist/contract/rln_base_contract.js +71 -127
  59. package/dist/contract/rln_base_contract.js.map +1 -1
  60. package/dist/contract/types.d.ts +0 -5
  61. package/dist/contract/types.js.map +1 -1
  62. package/dist/credentials_manager.js +2 -7
  63. package/dist/credentials_manager.js.map +1 -1
  64. package/dist/identity.js +1 -1
  65. package/dist/identity.js.map +1 -1
  66. package/dist/index.d.ts +1 -2
  67. package/dist/index.js +0 -1
  68. package/dist/index.js.map +1 -1
  69. package/dist/keystore/keystore.js.map +1 -1
  70. package/dist/keystore/types.d.ts +2 -2
  71. package/dist/utils/bytes.js +2 -6
  72. package/dist/utils/bytes.js.map +1 -1
  73. package/package.json +1 -1
  74. package/src/contract/index.ts +0 -1
  75. package/src/contract/rln_base_contract.ts +102 -166
  76. package/src/contract/types.ts +0 -5
  77. package/src/credentials_manager.ts +2 -9
  78. package/src/identity.ts +1 -1
  79. package/src/index.ts +1 -3
  80. package/src/keystore/keystore.ts +2 -4
  81. package/src/keystore/types.ts +2 -2
  82. package/src/utils/bytes.ts +2 -6
  83. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/index.js +0 -0
  84. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/md5.js +0 -0
  85. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/nil.js +0 -0
  86. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/parse.js +0 -0
  87. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/regex.js +0 -0
  88. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/rng.js +0 -0
  89. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/sha1.js +0 -0
  90. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/stringify.js +0 -0
  91. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v1.js +0 -0
  92. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v3.js +0 -0
  93. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v35.js +0 -0
  94. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v4.js +0 -0
  95. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v5.js +0 -0
  96. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/validate.js +0 -0
  97. /package/bundle/{node_modules → packages/rln/node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/version.js +0 -0
@@ -3,7 +3,7 @@ export type MembershipHash = string;
3
3
  export type Sha256Hash = string;
4
4
  export type Keccak256Hash = string;
5
5
  export type Password = string | Uint8Array;
6
- export type KeystoreMembershipInfo = {
6
+ export type MembershipInfo = {
7
7
  chainId: string;
8
8
  address: string;
9
9
  treeIndex: number;
@@ -11,7 +11,7 @@ export type KeystoreMembershipInfo = {
11
11
  };
12
12
  export type KeystoreEntity = {
13
13
  identity: IdentityCredential;
14
- membership: KeystoreMembershipInfo;
14
+ membership: MembershipInfo;
15
15
  };
16
16
  export type DecryptedCredentials = KeystoreEntity;
17
17
  export type EncryptedCredentials = {
@@ -45,12 +45,8 @@ export function writeUIntLE(buf, value, offset, byteLength, noAssert) {
45
45
  * @returns BigInt
46
46
  */
47
47
  export function buildBigIntFromUint8Array(array, byteOffset = 0) {
48
- // Use all bytes from byteOffset to the end, big-endian
49
- let hex = "";
50
- for (let i = byteOffset; i < array.length; i++) {
51
- hex += array[i].toString(16).padStart(2, "0");
52
- }
53
- return BigInt("0x" + hex);
48
+ const dataView = new DataView(array.buffer);
49
+ return dataView.getBigUint64(byteOffset, true);
54
50
  }
55
51
  /**
56
52
  * Fills with zeros to set length
@@ -1 +1 @@
1
- {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/utils/bytes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/utils/bytes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,GAAG,KAAmB;IAChD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,WAAW,IAAI,GAAG,CAAC,MAAM,CAAC;IAC5B,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxB,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC;IACvB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gDAAgD;AAChD,SAAS,QAAQ,CACf,GAAe,EACf,KAAa,EACb,MAAc,EACd,GAAW,EACX,GAAW,EACX,GAAW;IAEX,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG;QAC5B,MAAM,IAAI,UAAU,CAAC,mCAAmC,CAAC,CAAC;IAC5D,IAAI,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,oBAAoB,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,GAAe,EACf,KAAa,EACb,MAAc,EACd,UAAkB,EAClB,QAAkB;IAElB,KAAK,GAAG,CAAC,KAAK,CAAC;IACf,MAAM,GAAG,MAAM,KAAK,CAAC,CAAC;IACtB,UAAU,GAAG,UAAU,KAAK,CAAC,CAAC;IAC9B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QACjD,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,CAAC,GAAG,UAAU,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC;QAC1C,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;IACzC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAiB,EACjB,aAAqB,CAAC;IAEtB,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,MAAc;IACzD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@waku/rln","version":"0.1.6-10590da.0","description":"RLN (Rate Limiting Nullifier) implementation for Waku","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"type":"module","homepage":"https://github.com/waku-org/js-waku/tree/master/packages/rln#readme","repository":{"type":"git","url":"https://github.com/waku-org/js-waku.git"},"bugs":{"url":"https://github.com/waku-org/js-waku/issues"},"license":"MIT OR Apache-2.0","keywords":["waku","rln","rate-limiting","privacy","web3"],"scripts":{"build":"run-s build:**","build:copy":"mkdir -p dist/resources && cp -r src/resources/* dist/resources/","build:esm":"tsc","build:bundle":"rollup --config rollup.config.js","fix":"run-s fix:*","fix:lint":"eslint src *.js --fix","check":"run-s check:*","check:tsc":"tsc -p tsconfig.dev.json","check:lint":"eslint \"src/!(resources)/**/*.{ts,js}\" *.js","check:spelling":"cspell \"{README.md,src/**/*.ts}\"","test":"NODE_ENV=test run-s test:*","test:browser":"karma start karma.conf.cjs","watch:build":"tsc -p tsconfig.json -w","watch:test":"mocha --watch","prepublish":"npm run build","reset-hard":"git clean -dfx -e .idea && git reset --hard && npm i && npm run build"},"engines":{"node":">=20"},"devDependencies":{"@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.0.0","@rollup/plugin-node-resolve":"^15.2.3","@types/chai":"^5.0.1","@types/chai-spies":"^1.0.6","@types/deep-equal-in-any-order":"^1.0.4","@types/lodash":"^4.17.15","@types/sinon":"^17.0.3","@waku/build-utils":"^1.0.0","@waku/message-encryption":"0.0.34-10590da.0","deep-equal-in-any-order":"^2.0.6","fast-check":"^3.23.2","rollup-plugin-copy":"^3.5.0"},"files":["dist","bundle","src/**/*.ts","!**/*.spec.*","!**/*.json","CHANGELOG.md","LICENSE","README.md"],"dependencies":{"@chainsafe/bls-keystore":"3.0.0","@waku/core":"0.0.36-10590da.0","@waku/utils":"0.0.24-10590da.0","@noble/hashes":"^1.2.0","@waku/zerokit-rln-wasm":"^0.0.13","ethereum-cryptography":"^3.1.0","ethers":"^5.7.2","lodash":"^4.17.21","uuid":"^11.0.5","chai":"^5.1.2","chai-as-promised":"^8.0.1","chai-spies":"^1.1.0","chai-subset":"^1.6.0","sinon":"^19.0.2"}}
1
+ {"name":"@waku/rln","version":"0.1.6-383e0b2.0","description":"RLN (Rate Limiting Nullifier) implementation for Waku","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"type":"module","homepage":"https://github.com/waku-org/js-waku/tree/master/packages/rln#readme","repository":{"type":"git","url":"https://github.com/waku-org/js-waku.git"},"bugs":{"url":"https://github.com/waku-org/js-waku/issues"},"license":"MIT OR Apache-2.0","keywords":["waku","rln","rate-limiting","privacy","web3"],"scripts":{"build":"run-s build:**","build:copy":"mkdir -p dist/resources && cp -r src/resources/* dist/resources/","build:esm":"tsc","build:bundle":"rollup --config rollup.config.js","fix":"run-s fix:*","fix:lint":"eslint src *.js --fix","check":"run-s check:*","check:tsc":"tsc -p tsconfig.dev.json","check:lint":"eslint \"src/!(resources)/**/*.{ts,js}\" *.js","check:spelling":"cspell \"{README.md,src/**/*.ts}\"","test":"NODE_ENV=test run-s test:*","test:browser":"karma start karma.conf.cjs","watch:build":"tsc -p tsconfig.json -w","watch:test":"mocha --watch","prepublish":"npm run build","reset-hard":"git clean -dfx -e .idea && git reset --hard && npm i && npm run build"},"engines":{"node":">=20"},"devDependencies":{"@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.0.0","@rollup/plugin-node-resolve":"^15.2.3","@types/chai":"^5.0.1","@types/chai-spies":"^1.0.6","@types/deep-equal-in-any-order":"^1.0.4","@types/lodash":"^4.17.15","@types/sinon":"^17.0.3","@waku/build-utils":"^1.0.0","@waku/message-encryption":"0.0.34-383e0b2.0","deep-equal-in-any-order":"^2.0.6","fast-check":"^3.23.2","rollup-plugin-copy":"^3.5.0"},"files":["dist","bundle","src/**/*.ts","!**/*.spec.*","!**/*.json","CHANGELOG.md","LICENSE","README.md"],"dependencies":{"@chainsafe/bls-keystore":"3.0.0","@waku/core":"0.0.36-383e0b2.0","@waku/utils":"0.0.24-383e0b2.0","@noble/hashes":"^1.2.0","@waku/zerokit-rln-wasm":"^0.0.13","ethereum-cryptography":"^3.1.0","ethers":"^5.7.2","lodash":"^4.17.21","uuid":"^11.0.5","chai":"^5.1.2","chai-as-promised":"^8.0.1","chai-spies":"^1.1.0","chai-subset":"^1.6.0","sinon":"^19.0.2"}}
@@ -1,3 +1,2 @@
1
1
  export { RLNContract } from "./rln_contract.js";
2
2
  export * from "./constants.js";
3
- export * from "./types.js";
@@ -22,8 +22,6 @@ 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;
27
25
 
28
26
  protected _members: Map<number, Member> = new Map();
29
27
  private _membersFilter: ethers.EventFilter;
@@ -31,9 +29,19 @@ export class RLNBaseContract {
31
29
  private _membersExpiredFilter: ethers.EventFilter;
32
30
 
33
31
  /**
34
- * Private constructor for RLNBaseContract. Use static create() instead.
32
+ * Constructor for RLNBaseContract.
33
+ * Allows injecting a mocked contract for testing purposes.
35
34
  */
36
- protected constructor(options: RLNContractInitOptions) {
35
+ public constructor(options: RLNContractInitOptions) {
36
+ // Initialize members and subscriptions
37
+ this.fetchMembers()
38
+ .then(() => {
39
+ this.subscribeToMembers();
40
+ })
41
+ .catch((error) => {
42
+ log.error("Failed to initialize members", { error });
43
+ });
44
+
37
45
  const {
38
46
  address,
39
47
  signer,
@@ -41,51 +49,15 @@ export class RLNBaseContract {
41
49
  contract
42
50
  } = options;
43
51
 
44
- log.info("Initializing RLNBaseContract", { address, rateLimit });
52
+ this.validateRateLimit(rateLimit);
45
53
 
46
54
  this.contract = contract || new ethers.Contract(address, RLN_ABI, signer);
47
55
  this.rateLimit = rateLimit;
48
56
 
49
- try {
50
- log.info("Setting up event filters");
51
- // Initialize event filters
52
- this._membersFilter = this.contract.filters.MembershipRegistered();
53
- this._membershipErasedFilter = this.contract.filters.MembershipErased();
54
- this._membersExpiredFilter = this.contract.filters.MembershipExpired();
55
- log.info("Event filters initialized successfully");
56
- } catch (error) {
57
- log.error("Failed to initialize event filters", { error });
58
- throw new Error(
59
- "Failed to initialize event filters: " + (error as Error).message
60
- );
61
- }
62
-
63
- // Initialize members and subscriptions
64
- this.fetchMembers()
65
- .then(() => {
66
- this.subscribeToMembers();
67
- })
68
- .catch((error) => {
69
- log.error("Failed to initialize members", { error });
70
- });
71
- }
72
-
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;
57
+ // Initialize event filters
58
+ this._membersFilter = this.contract.filters.MembershipRegistered();
59
+ this._membershipErasedFilter = this.contract.filters.MembershipErased();
60
+ this._membersExpiredFilter = this.contract.filters.MembershipExpired();
89
61
  }
90
62
 
91
63
  /**
@@ -110,21 +82,21 @@ export class RLNBaseContract {
110
82
  }
111
83
 
112
84
  /**
113
- * Gets the minimum allowed rate limit (cached)
85
+ * Gets the minimum allowed rate limit from the contract
86
+ * @returns Promise<number> The minimum rate limit in messages per epoch
114
87
  */
115
- public getMinRateLimit(): number {
116
- if (this.minRateLimit === undefined)
117
- throw new Error("minRateLimit not initialized");
118
- return this.minRateLimit;
88
+ public async getMinRateLimit(): Promise<number> {
89
+ const minRate = await this.contract.minMembershipRateLimit();
90
+ return ethers.BigNumber.from(minRate).toNumber();
119
91
  }
120
92
 
121
93
  /**
122
- * Gets the maximum allowed rate limit (cached)
94
+ * Gets the maximum allowed rate limit from the contract
95
+ * @returns Promise<number> The maximum rate limit in messages per epoch
123
96
  */
124
- public getMaxRateLimit(): number {
125
- if (this.maxRateLimit === undefined)
126
- throw new Error("maxRateLimit not initialized");
127
- return this.maxRateLimit;
97
+ public async getMaxRateLimit(): Promise<number> {
98
+ const maxRate = await this.contract.maxMembershipRateLimit();
99
+ return ethers.BigNumber.from(maxRate).toNumber();
128
100
  }
129
101
 
130
102
  /**
@@ -161,7 +133,7 @@ export class RLNBaseContract {
161
133
  * Updates the rate limit for future registrations
162
134
  * @param newRateLimit The new rate limit to use
163
135
  */
164
- public setRateLimit(newRateLimit: number): void {
136
+ public async setRateLimit(newRateLimit: number): Promise<void> {
165
137
  this.validateRateLimit(newRateLimit);
166
138
  this.rateLimit = newRateLimit;
167
139
  }
@@ -352,7 +324,7 @@ export class RLNBaseContract {
352
324
  this.contract.on(
353
325
  this.membersFilter,
354
326
  (
355
- _idCommitment: bigint,
327
+ _idCommitment: string,
356
328
  _membershipRateLimit: ethers.BigNumber,
357
329
  _index: ethers.BigNumber,
358
330
  event: ethers.Event
@@ -364,7 +336,7 @@ export class RLNBaseContract {
364
336
  this.contract.on(
365
337
  this.membershipErasedFilter,
366
338
  (
367
- _idCommitment: bigint,
339
+ _idCommitment: string,
368
340
  _membershipRateLimit: ethers.BigNumber,
369
341
  _index: ethers.BigNumber,
370
342
  event: ethers.Event
@@ -376,7 +348,7 @@ export class RLNBaseContract {
376
348
  this.contract.on(
377
349
  this.membersExpiredFilter,
378
350
  (
379
- _idCommitment: bigint,
351
+ _idCommitment: string,
380
352
  _membershipRateLimit: ethers.BigNumber,
381
353
  _index: ethers.BigNumber,
382
354
  event: ethers.Event
@@ -386,89 +358,94 @@ export class RLNBaseContract {
386
358
  );
387
359
  }
388
360
 
361
+ /**
362
+ * Helper method to get remaining messages in current epoch
363
+ * @param membershipId The ID of the membership to check
364
+ * @returns number of remaining messages allowed in current epoch
365
+ */
366
+ public async getRemainingMessages(membershipId: number): Promise<number> {
367
+ try {
368
+ const [startTime, , rateLimit] =
369
+ await this.contract.getMembershipInfo(membershipId);
370
+
371
+ // Calculate current epoch
372
+ const currentTime = Math.floor(Date.now() / 1000);
373
+ const epochsPassed = Math.floor(
374
+ (currentTime - startTime) / RATE_LIMIT_PARAMS.EPOCH_LENGTH
375
+ );
376
+ const currentEpochStart =
377
+ startTime + epochsPassed * RATE_LIMIT_PARAMS.EPOCH_LENGTH;
378
+
379
+ // Get message count in current epoch using contract's function
380
+ const messageCount = await this.contract.getMessageCount(
381
+ membershipId,
382
+ currentEpochStart
383
+ );
384
+ return Math.max(
385
+ 0,
386
+ ethers.BigNumber.from(rateLimit)
387
+ .sub(ethers.BigNumber.from(messageCount))
388
+ .toNumber()
389
+ );
390
+ } catch (error) {
391
+ log.error(
392
+ `Error getting remaining messages: ${(error as Error).message}`
393
+ );
394
+ return 0; // Fail safe: assume no messages remaining on error
395
+ }
396
+ }
397
+
389
398
  public async getMembershipInfo(
390
- idCommitmentBigInt: bigint
399
+ idCommitment: string
391
400
  ): Promise<MembershipInfo | undefined> {
392
401
  try {
393
- const membershipData =
394
- await this.contract.memberships(idCommitmentBigInt);
402
+ const [startBlock, endBlock, rateLimit] =
403
+ await this.contract.getMembershipInfo(idCommitment);
395
404
  const currentBlock = await this.contract.provider.getBlockNumber();
396
- const [
397
- depositAmount,
398
- activeDuration,
399
- gracePeriodStartTimestamp,
400
- gracePeriodDuration,
401
- rateLimit,
402
- index,
403
- holder,
404
- token
405
- ] = membershipData;
406
-
407
- const gracePeriodEnd = gracePeriodStartTimestamp.add(gracePeriodDuration);
408
405
 
409
406
  let state: MembershipState;
410
- if (currentBlock < gracePeriodStartTimestamp.toNumber()) {
407
+ if (currentBlock < startBlock) {
411
408
  state = MembershipState.Active;
412
- } else if (currentBlock < gracePeriodEnd.toNumber()) {
409
+ } else if (currentBlock < endBlock) {
413
410
  state = MembershipState.GracePeriod;
414
411
  } else {
415
412
  state = MembershipState.Expired;
416
413
  }
417
414
 
415
+ const index = await this.getMemberIndex(idCommitment);
416
+ if (!index) return undefined;
417
+
418
418
  return {
419
419
  index,
420
- idCommitment: idCommitmentBigInt.toString(),
421
- rateLimit: Number(rateLimit),
422
- startBlock: gracePeriodStartTimestamp.toNumber(),
423
- endBlock: gracePeriodEnd.toNumber(),
424
- state,
425
- depositAmount,
426
- activeDuration,
427
- gracePeriodDuration,
428
- holder,
429
- token
420
+ idCommitment,
421
+ rateLimit: rateLimit.toNumber(),
422
+ startBlock: startBlock.toNumber(),
423
+ endBlock: endBlock.toNumber(),
424
+ state
430
425
  };
431
426
  } catch (error) {
432
- log.error("Error in getMembershipInfo:", error);
433
427
  return undefined;
434
428
  }
435
429
  }
436
430
 
437
431
  public async extendMembership(
438
- idCommitmentBigInt: bigint
432
+ idCommitment: string
439
433
  ): Promise<ethers.ContractTransaction> {
440
- const tx = await this.contract.extendMemberships([idCommitmentBigInt]);
441
- await tx.wait();
442
- return tx;
434
+ return this.contract.extendMemberships([idCommitment]);
443
435
  }
444
436
 
445
437
  public async eraseMembership(
446
- idCommitmentBigInt: bigint,
438
+ idCommitment: string,
447
439
  eraseFromMembershipSet: boolean = true
448
440
  ): Promise<ethers.ContractTransaction> {
449
- if (
450
- !(await this.isExpired(idCommitmentBigInt)) ||
451
- !(await this.isInGracePeriod(idCommitmentBigInt))
452
- ) {
453
- throw new Error("Membership is not expired or in grace period");
454
- }
455
-
456
- const estimatedGas = await this.contract.estimateGas[
457
- "eraseMemberships(uint256[],bool)"
458
- ]([idCommitmentBigInt], eraseFromMembershipSet);
459
- const gasLimit = estimatedGas.add(10000);
460
-
461
- const tx = await this.contract["eraseMemberships(uint256[],bool)"](
462
- [idCommitmentBigInt],
463
- eraseFromMembershipSet,
464
- { gasLimit }
441
+ return this.contract.eraseMemberships(
442
+ [idCommitment],
443
+ eraseFromMembershipSet
465
444
  );
466
- await tx.wait();
467
- return tx;
468
445
  }
469
446
 
470
447
  public async registerMembership(
471
- idCommitmentBigInt: bigint,
448
+ idCommitment: string,
472
449
  rateLimit: number = DEFAULT_RATE_LIMIT
473
450
  ): Promise<ethers.ContractTransaction> {
474
451
  if (
@@ -479,12 +456,12 @@ export class RLNBaseContract {
479
456
  `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`
480
457
  );
481
458
  }
482
- return this.contract.register(idCommitmentBigInt, rateLimit, []);
459
+ return this.contract.register(idCommitment, rateLimit, []);
483
460
  }
484
461
 
485
- public async withdraw(token: string, from: string): Promise<void> {
462
+ public async withdraw(token: string, holder: string): Promise<void> {
486
463
  try {
487
- const tx = await this.contract.withdraw(token, from);
464
+ const tx = await this.contract.withdraw(token, { from: holder });
488
465
  await tx.wait();
489
466
  } catch (error) {
490
467
  log.error(`Error in withdraw: ${(error as Error).message}`);
@@ -501,7 +478,7 @@ export class RLNBaseContract {
501
478
 
502
479
  // Check if the ID commitment is already registered
503
480
  const existingIndex = await this.getMemberIndex(
504
- identity.IDCommitmentBigInt
481
+ identity.IDCommitmentBigInt.toString()
505
482
  );
506
483
  if (existingIndex) {
507
484
  throw new Error(
@@ -539,7 +516,7 @@ export class RLNBaseContract {
539
516
  }
540
517
 
541
518
  const memberRegistered = txRegisterReceipt.events?.find(
542
- (event: ethers.Event) => event.event === "MembershipRegistered"
519
+ (event) => event.event === "MembershipRegistered"
543
520
  );
544
521
 
545
522
  if (!memberRegistered || !memberRegistered.args) {
@@ -633,7 +610,7 @@ export class RLNBaseContract {
633
610
  const txRegisterReceipt = await txRegisterResponse.wait();
634
611
 
635
612
  const memberRegistered = txRegisterReceipt.events?.find(
636
- (event: ethers.Event) => event.event === "MembershipRegistered"
613
+ (event) => event.event === "MembershipRegistered"
637
614
  );
638
615
 
639
616
  if (!memberRegistered || !memberRegistered.args) {
@@ -676,16 +653,16 @@ export class RLNBaseContract {
676
653
  }
677
654
 
678
655
  /**
679
- * Validates that the rate limit is within the allowed range (sync)
656
+ * Validates that the rate limit is within the allowed range
680
657
  * @throws Error if the rate limit is outside the allowed range
681
658
  */
682
659
  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) {
660
+ if (
661
+ rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
662
+ rateLimit > RATE_LIMIT_PARAMS.MAX_RATE
663
+ ) {
687
664
  throw new Error(
688
- `Rate limit must be between ${this.minRateLimit} and ${this.maxRateLimit} messages per epoch`
665
+ `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE} messages per epoch`
689
666
  );
690
667
  }
691
668
  }
@@ -712,11 +689,11 @@ export class RLNBaseContract {
712
689
  }
713
690
 
714
691
  private async getMemberIndex(
715
- idCommitmentBigInt: bigint
692
+ idCommitment: string
716
693
  ): Promise<ethers.BigNumber | undefined> {
717
694
  try {
718
695
  const events = await this.contract.queryFilter(
719
- this.contract.filters.MembershipRegistered(idCommitmentBigInt)
696
+ this.contract.filters.MembershipRegistered(idCommitment)
720
697
  );
721
698
  if (events.length === 0) return undefined;
722
699
 
@@ -727,45 +704,4 @@ export class RLNBaseContract {
727
704
  return undefined;
728
705
  }
729
706
  }
730
-
731
- public async getMembershipStatus(
732
- idCommitment: bigint
733
- ): Promise<"expired" | "grace" | "active"> {
734
- const [isExpired, isInGrace] = await Promise.all([
735
- this.contract.isExpired(idCommitment),
736
- this.contract.isInGracePeriod(idCommitment)
737
- ]);
738
-
739
- if (isExpired) return "expired";
740
- if (isInGrace) return "grace";
741
- return "active";
742
- }
743
-
744
- /**
745
- * Checks if a membership is expired for the given idCommitment
746
- * @param idCommitmentBigInt The idCommitment as bigint
747
- * @returns Promise<boolean> True if expired, false otherwise
748
- */
749
- public async isExpired(idCommitmentBigInt: bigint): Promise<boolean> {
750
- try {
751
- return await this.contract.isExpired(idCommitmentBigInt);
752
- } catch (error) {
753
- log.error("Error in isExpired:", error);
754
- return false;
755
- }
756
- }
757
-
758
- /**
759
- * Checks if a membership is in grace period for the given idCommitment
760
- * @param idCommitmentBigInt The idCommitment as bigint
761
- * @returns Promise<boolean> True if in grace period, false otherwise
762
- */
763
- public async isInGracePeriod(idCommitmentBigInt: bigint): Promise<boolean> {
764
- try {
765
- return await this.contract.isInGracePeriod(idCommitmentBigInt);
766
- } catch (error) {
767
- log.error("Error in isInGracePeriod:", error);
768
- return false;
769
- }
770
- }
771
707
  }
@@ -38,11 +38,6 @@ export interface MembershipInfo {
38
38
  startBlock: number;
39
39
  endBlock: number;
40
40
  state: MembershipState;
41
- depositAmount: ethers.BigNumber;
42
- activeDuration: number;
43
- gracePeriodDuration: number;
44
- holder: string;
45
- token: string;
46
41
  }
47
42
 
48
43
  export enum MembershipState {
@@ -80,7 +80,7 @@ export class RLNCredentialsManager {
80
80
 
81
81
  this.credentials = credentials;
82
82
  this.signer = signer!;
83
- this.contract = await RLNBaseContract.create({
83
+ this.contract = new RLNBaseContract({
84
84
  address: address!,
85
85
  signer: signer!,
86
86
  rateLimit: rateLimit ?? this.zerokit?.rateLimit
@@ -268,14 +268,7 @@ export class RLNCredentialsManager {
268
268
  const idCommitment = sha256(idSecretHash);
269
269
 
270
270
  // Convert IDCommitment to BigInt
271
- let idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment);
272
- const Q = BigInt(
273
- "21888242871839275222246405745257275088548364400416034343698204186575808495617"
274
- );
275
- if (idCommitmentBigInt >= Q) {
276
- log.warn("IDCommitment is greater than Q, truncating");
277
- idCommitmentBigInt = idCommitmentBigInt % Q;
278
- }
271
+ const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment);
279
272
 
280
273
  log.info("Successfully generated identity credential");
281
274
  return new IdentityCredential(
package/src/identity.ts CHANGED
@@ -18,7 +18,7 @@ export class IdentityCredential {
18
18
  const idNullifier = memKeys.subarray(32, 64);
19
19
  const idSecretHash = memKeys.subarray(64, 96);
20
20
  const idCommitment = memKeys.subarray(96, 128);
21
- const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment);
21
+ const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
22
22
 
23
23
  return new IdentityCredential(
24
24
  idTrapdoor,
package/src/index.ts CHANGED
@@ -34,9 +34,7 @@ export type {
34
34
  Keccak256Hash,
35
35
  KeystoreEntity,
36
36
  MembershipHash,
37
- KeystoreMembershipInfo,
37
+ MembershipInfo,
38
38
  Password,
39
39
  Sha256Hash
40
40
  } from "./keystore/types.js";
41
-
42
- export * from "./contract/index.js";
@@ -21,8 +21,8 @@ import { isCredentialValid, isKeystoreValid } from "./schema_validator.js";
21
21
  import type {
22
22
  Keccak256Hash,
23
23
  KeystoreEntity,
24
- KeystoreMembershipInfo,
25
24
  MembershipHash,
25
+ MembershipInfo,
26
26
  Password,
27
27
  Sha256Hash
28
28
  } from "./types.js";
@@ -310,9 +310,7 @@ export class Keystore {
310
310
 
311
311
  // follows nwaku implementation
312
312
  // https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L111
313
- private static computeMembershipHash(
314
- info: KeystoreMembershipInfo
315
- ): MembershipHash {
313
+ private static computeMembershipHash(info: MembershipInfo): MembershipHash {
316
314
  return bytesToHex(
317
315
  sha256(utf8ToBytes(`${info.chainId}${info.address}${info.treeIndex}`))
318
316
  ).toUpperCase();
@@ -7,7 +7,7 @@ export type Password = string | Uint8Array;
7
7
 
8
8
  // see reference
9
9
  // https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L111
10
- export type KeystoreMembershipInfo = {
10
+ export type MembershipInfo = {
11
11
  chainId: string;
12
12
  address: string;
13
13
  treeIndex: number;
@@ -16,7 +16,7 @@ export type KeystoreMembershipInfo = {
16
16
 
17
17
  export type KeystoreEntity = {
18
18
  identity: IdentityCredential;
19
- membership: KeystoreMembershipInfo;
19
+ membership: MembershipInfo;
20
20
  };
21
21
 
22
22
  export type DecryptedCredentials = KeystoreEntity;
@@ -65,12 +65,8 @@ export function buildBigIntFromUint8Array(
65
65
  array: Uint8Array,
66
66
  byteOffset: number = 0
67
67
  ): bigint {
68
- // Use all bytes from byteOffset to the end, big-endian
69
- let hex = "";
70
- for (let i = byteOffset; i < array.length; i++) {
71
- hex += array[i].toString(16).padStart(2, "0");
72
- }
73
- return BigInt("0x" + hex);
68
+ const dataView = new DataView(array.buffer);
69
+ return dataView.getBigUint64(byteOffset, true);
74
70
  }
75
71
 
76
72
  /**