@dorafactory/maci-sdk 0.1.3-pre.21 → 0.1.3-pre.23

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 (77) hide show
  1. package/dist/index.d.ts +7 -2
  2. package/dist/index.js +1485 -65
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +1470 -74
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/libs/account/crypto.d.ts +1 -0
  7. package/dist/libs/account/index.d.ts +35 -0
  8. package/dist/libs/account/keypair.d.ts +21 -0
  9. package/dist/libs/account/util.d.ts +25 -0
  10. package/dist/libs/api/client.d.ts +173 -0
  11. package/dist/libs/api/index.d.ts +3 -0
  12. package/dist/libs/const.d.ts +1 -0
  13. package/dist/libs/crypto/adapter.d.ts +6 -0
  14. package/dist/libs/crypto/curve.d.ts +3 -0
  15. package/dist/libs/crypto/index.d.ts +3 -0
  16. package/dist/libs/crypto/keys.d.ts +8 -1
  17. package/dist/libs/crypto/rerandomize.d.ts +12 -0
  18. package/dist/libs/crypto/sign.d.ts +1 -1
  19. package/dist/libs/cryptography/index.d.ts +0 -0
  20. package/dist/libs/cryptography/keypair.d.ts +30 -0
  21. package/dist/libs/cryptography/mnemonics.d.ts +27 -0
  22. package/dist/libs/cryptography/publickey.d.ts +23 -0
  23. package/dist/libs/cryptography/signature-scheme.d.ts +1 -0
  24. package/dist/libs/index.d.ts +1 -0
  25. package/dist/libs/keypairs/eddsa-poseidon/index.d.ts +2 -0
  26. package/dist/libs/keypairs/eddsa-poseidon/keypair.d.ts +187 -0
  27. package/dist/libs/keypairs/eddsa-poseidon/publickey.d.ts +48 -0
  28. package/dist/maci.d.ts +90 -31
  29. package/dist/types/index.d.ts +23 -0
  30. package/dist/utils/base64.d.ts +6 -0
  31. package/dist/utils/bech32.d.ts +2 -0
  32. package/dist/utils/decode-address.d.ts +10 -0
  33. package/dist/utils/fetch.d.ts +1 -0
  34. package/dist/utils/hex.d.ts +6 -0
  35. package/dist/utils/index.d.ts +4 -24
  36. package/dist/utils/validate-address.d.ts +24 -0
  37. package/dist/voter.d.ts +230 -0
  38. package/package.json +13 -61
  39. package/src/index.ts +11 -13
  40. package/src/libs/account/crypto.ts +7 -0
  41. package/src/libs/account/index.ts +70 -0
  42. package/src/libs/account/keypair.ts +29 -0
  43. package/src/libs/account/util.ts +55 -0
  44. package/src/libs/api/client.ts +406 -0
  45. package/src/libs/api/index.ts +3 -0
  46. package/src/libs/api/types.d.ts +1493 -0
  47. package/src/libs/const.ts +37 -54
  48. package/src/libs/crypto/adapter.ts +41 -0
  49. package/src/libs/crypto/babyjub.ts +4 -7
  50. package/src/libs/crypto/constants.ts +2 -5
  51. package/src/libs/crypto/curve.ts +55 -0
  52. package/src/libs/crypto/hashing.ts +4 -6
  53. package/src/libs/crypto/index.ts +3 -0
  54. package/src/libs/crypto/keys.ts +15 -48
  55. package/src/libs/crypto/rerandomize.ts +77 -0
  56. package/src/libs/crypto/sign.ts +8 -17
  57. package/src/libs/crypto/tree.ts +1 -3
  58. package/src/libs/cryptography/index.ts +0 -0
  59. package/src/libs/cryptography/keypair.ts +44 -0
  60. package/src/libs/cryptography/mnemonics.ts +47 -0
  61. package/src/libs/cryptography/publickey.ts +44 -0
  62. package/src/libs/cryptography/signature-scheme.ts +1 -0
  63. package/src/libs/index.ts +1 -0
  64. package/src/libs/keypairs/eddsa-poseidon/index.ts +6 -0
  65. package/src/libs/keypairs/eddsa-poseidon/keypair.ts +452 -0
  66. package/src/libs/keypairs/eddsa-poseidon/publickey.ts +141 -0
  67. package/src/maci.ts +157 -101
  68. package/src/types/index.ts +30 -4
  69. package/src/types/lib.d.ts +7 -0
  70. package/src/utils/base64.ts +28 -0
  71. package/src/utils/bech32.ts +29 -0
  72. package/src/utils/decode-address.ts +35 -0
  73. package/src/utils/fetch.ts +28 -0
  74. package/src/utils/hex.ts +23 -0
  75. package/src/utils/index.ts +15 -79
  76. package/src/utils/validate-address.ts +82 -0
  77. package/src/voter.ts +654 -0
package/dist/index.js CHANGED
@@ -31,9 +31,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  Circuit: () => Circuit,
34
+ EdDSAPoseidonKeypair: () => EdDSAPoseidonKeypair,
35
+ EdDSAPoseidonPublicKey: () => EdDSAPoseidonPublicKey,
34
36
  G1Point: () => G1Point,
35
37
  G2Point: () => G2Point,
36
38
  Http: () => Http,
39
+ MaciApiClient: () => MaciApiClient,
37
40
  MaciCertSystemType: () => MaciCertSystemType,
38
41
  MaciCircuitType: () => MaciCircuitType,
39
42
  MaciClient: () => MaciClient2,
@@ -47,12 +50,23 @@ __export(index_exports, {
47
50
  Transaction: () => Transaction,
48
51
  Tree: () => Tree,
49
52
  UserAccount: () => UserAccount,
53
+ VoterClient: () => VoterClient,
54
+ adaptToUncompressed: () => adaptToUncompressed,
55
+ addressToUint256: () => addressToUint256,
50
56
  batchGenMessage: () => batchGenMessage,
51
57
  bigInt2Buffer: () => bigInt2Buffer,
58
+ bigintToHex: () => bigintToHex,
52
59
  buffer2Bigint: () => buffer2Bigint,
53
60
  circuits: () => circuits,
61
+ compressPublicKey: () => compressPublicKey,
62
+ decompressPublicKey: () => decompressPublicKey,
54
63
  destringizing: () => destringizing,
64
+ encryptOdevity: () => encryptOdevity,
55
65
  formatPrivKeyForBabyJub: () => formatPrivKeyForBabyJub,
66
+ fromB64: () => fromB64,
67
+ fromBase64: () => fromBase64,
68
+ fromHEX: () => fromHEX,
69
+ fromHex: () => fromHex,
56
70
  genAddKeyInput: () => genAddKeyInput,
57
71
  genEcdhSharedKey: () => genEcdhSharedKey,
58
72
  genKeypair: () => genKeypair,
@@ -65,6 +79,9 @@ __export(index_exports, {
65
79
  genRandomKey: () => genRandomKey,
66
80
  genRandomSalt: () => genRandomSalt,
67
81
  getAMaciRoundCircuitFee: () => getAMaciRoundCircuitFee,
82
+ getCurveFromName: () => getCurveFromName,
83
+ getCurveFromQ: () => getCurveFromQ,
84
+ getCurveFromR: () => getCurveFromR,
68
85
  getDefaultParams: () => getDefaultParams,
69
86
  hash12: () => hash12,
70
87
  hash2: () => hash2,
@@ -75,6 +92,8 @@ __export(index_exports, {
75
92
  hashLeftRight: () => hashLeftRight,
76
93
  hashN: () => hashN,
77
94
  hashOne: () => hashOne,
95
+ hexToBigInt: () => hexToBigInt,
96
+ hexToDecimalString: () => hexToDecimalString,
78
97
  isValidAddress: () => isValidAddress,
79
98
  packPubKey: () => packPubKey,
80
99
  poseidon: () => poseidon,
@@ -83,9 +102,15 @@ __export(index_exports, {
83
102
  poseidonT5: () => poseidonT5,
84
103
  poseidonT6: () => poseidonT6,
85
104
  privateKeyFromTxt: () => privateKeyFromTxt,
105
+ rerandomize: () => rerandomize,
86
106
  sha256Hash: () => sha256Hash,
87
107
  signMessage: () => signMessage2,
88
108
  stringizing: () => stringizing,
109
+ toB64: () => toB64,
110
+ toBase64: () => toBase64,
111
+ toHEX: () => toHEX,
112
+ toHex: () => toHex,
113
+ transformPubkey: () => transformPubkey,
89
114
  unpackPubKey: () => unpackPubKey
90
115
  });
91
116
  module.exports = __toCommonJS(index_exports);
@@ -427,6 +452,7 @@ function getDefaultParams(network = "mainnet") {
427
452
  rpcEndpoint: "https://vota-rpc.dorafactory.org",
428
453
  restEndpoint: "https://vota-rest.dorafactory.org",
429
454
  apiEndpoint: "https://vota-api.dorafactory.org",
455
+ saasApiEndpoint: "https://vota-maci-api.dorafactory.org",
430
456
  certificateApiEndpoint: "https://vota-certificate-api.dorafactory.org/api/v1",
431
457
  registryAddress: "dora1smg5qp5trjdkcekdjssqpjehdjf6n4cjss0clyvqcud3t3u3948s8rmgg4",
432
458
  saasAddress: "dora1ksxvvve2nsw5uyvg7y6lnnxcqxadjepc78z0qa8enm5zhayxaqgqpsewf8",
@@ -446,6 +472,7 @@ function getDefaultParams(network = "mainnet") {
446
472
  rpcEndpoint: "https://vota-testnet-rpc.dorafactory.org",
447
473
  restEndpoint: "https://vota-testnet-rest.dorafactory.org",
448
474
  apiEndpoint: "https://vota-testnet-api.dorafactory.org",
475
+ saasApiEndpoint: "https://vota-testnet-maci-api.dorafactory.org",
449
476
  certificateApiEndpoint: "https://vota-testnet-certificate-api.dorafactory.org/api/v1",
450
477
  registryAddress: "dora13c8aecstyxrhax9znvvh5zey89edrmd2k5va57pxvpe3fxtfsfeqlhsjnd",
451
478
  saasAddress: "dora1dgnszrwnwxgr5djprrr6w4q45z8s3ghsew869g6tlp4ruqah39nqnemjya",
@@ -536,7 +563,61 @@ var Circuit = class {
536
563
  }
537
564
  };
538
565
 
539
- // src/utils/index.ts
566
+ // src/utils/base64.ts
567
+ function fromBase64(base64String) {
568
+ return Uint8Array.from(atob(base64String), (char) => char.charCodeAt(0));
569
+ }
570
+ var CHUNK_SIZE = 8192;
571
+ function toBase64(bytes) {
572
+ if (bytes.length < CHUNK_SIZE) {
573
+ return btoa(String.fromCharCode(...bytes));
574
+ }
575
+ let output = "";
576
+ for (var i = 0; i < bytes.length; i += CHUNK_SIZE) {
577
+ const chunk = bytes.slice(i, i + CHUNK_SIZE);
578
+ output += String.fromCharCode(...chunk);
579
+ }
580
+ return btoa(output);
581
+ }
582
+ var toB64 = toBase64;
583
+ var fromB64 = fromBase64;
584
+
585
+ // src/utils/hex.ts
586
+ function fromHex(hexStr) {
587
+ const normalized = hexStr.startsWith("0x") ? hexStr.slice(2) : hexStr;
588
+ const padded = normalized.length % 2 === 0 ? normalized : `0${normalized}}`;
589
+ const intArr = padded.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) ?? [];
590
+ return Uint8Array.from(intArr);
591
+ }
592
+ function toHex(bytes) {
593
+ return bytes.reduce(
594
+ (str, byte) => str + byte.toString(16).padStart(2, "0"),
595
+ ""
596
+ );
597
+ }
598
+ var toHEX = toHex;
599
+ var fromHEX = fromHex;
600
+
601
+ // src/utils/decode-address.ts
602
+ var import_sha256 = require("@noble/hashes/sha256");
603
+ function addressToUint256(address) {
604
+ const addressBytes = new TextEncoder().encode(address);
605
+ const hashResult = (0, import_sha256.sha256)(addressBytes);
606
+ const uint256Bytes = new Uint8Array(32);
607
+ for (let i = 0; i < hashResult.length && i < 32; i++) {
608
+ uint256Bytes[31 - i] = hashResult[i];
609
+ }
610
+ let result = 0n;
611
+ for (let i = 0; i < uint256Bytes.length; i++) {
612
+ result = (result << 8n) + BigInt(uint256Bytes[i]);
613
+ }
614
+ return result;
615
+ }
616
+ function bigintToHex(value) {
617
+ return "0x" + value.toString(16).padStart(64, "0");
618
+ }
619
+
620
+ // src/utils/validate-address.ts
540
621
  var import_bech32 = require("bech32");
541
622
 
542
623
  // src/libs/crypto/keys.ts
@@ -610,9 +691,7 @@ var import_assert = __toESM(require("assert"));
610
691
  var SNARK_FIELD_SIZE = import_baby_jubjub.r;
611
692
  var NOTHING_UP_MY_SLEEVE = BigInt((0, import_ethers.keccak256)((0, import_ethers.toUtf8Bytes)("Maci"))) % SNARK_FIELD_SIZE;
612
693
  (0, import_assert.default)(
613
- NOTHING_UP_MY_SLEEVE === BigInt(
614
- "8370432830353022751713833565135785980866757267633941821328460903436894336785"
615
- )
694
+ NOTHING_UP_MY_SLEEVE === BigInt("8370432830353022751713833565135785980866757267633941821328460903436894336785")
616
695
  );
617
696
  var PAD_KEY_HASH = BigInt(
618
697
  "1309255631273308531193241901289907343161346846555918942743921933037802809814"
@@ -830,9 +909,7 @@ var Tree = class _Tree {
830
909
  while (idx > 0) {
831
910
  const parentIdx = Math.floor((idx - 1) / this.DEGREE);
832
911
  const childrenIdx0 = parentIdx * this.DEGREE + 1;
833
- this.nodes[parentIdx] = poseidon(
834
- this.nodes.slice(childrenIdx0, childrenIdx0 + 5)
835
- );
912
+ this.nodes[parentIdx] = poseidon(this.nodes.slice(childrenIdx0, childrenIdx0 + 5));
836
913
  idx = parentIdx;
837
914
  }
838
915
  }
@@ -918,9 +995,7 @@ var genRandomBabyJubValue = () => {
918
995
  const min = 6350874878119819312338956282401532410528162663560392320966563075034087161851n;
919
996
  let rand;
920
997
  while (true) {
921
- rand = BigInt(
922
- `0x${import_crypto_js.default.lib.WordArray.random(32).toString(import_crypto_js.default.enc.Hex)}`
923
- );
998
+ rand = BigInt(`0x${import_crypto_js.default.lib.WordArray.random(32).toString(import_crypto_js.default.enc.Hex)}`);
924
999
  if (rand >= min) {
925
1000
  break;
926
1001
  }
@@ -953,9 +1028,7 @@ var genKeypair = (pkey) => {
953
1028
  var genEcdhSharedKey = (privKey, pubKey) => (0, import_baby_jubjub2.mulPointEscalar)(pubKey, formatPrivKeyForBabyJub(privKey));
954
1029
  var genMessageFactory = (stateIdx, signPriKey, signPubKey, coordPubKey) => (encPriKey, nonce, voIdx, newVotes, isLastCmd, salt) => {
955
1030
  if (!salt) {
956
- salt = BigInt(
957
- `0x${import_crypto_js2.default.lib.WordArray.random(7).toString(import_crypto_js2.default.enc.Hex)}`
958
- );
1031
+ salt = BigInt(`0x${import_crypto_js2.default.lib.WordArray.random(7).toString(import_crypto_js2.default.enc.Hex)}`);
959
1032
  }
960
1033
  const packaged = BigInt(nonce) + (BigInt(stateIdx) << 32n) + (BigInt(voIdx) << 64n) + (BigInt(newVotes) << 96n) + (BigInt(salt) << 192n);
961
1034
  let newPubKey = [...signPubKey];
@@ -965,11 +1038,7 @@ var genMessageFactory = (stateIdx, signPriKey, signPubKey, coordPubKey) => (encP
965
1038
  const hash = poseidon([packaged, ...newPubKey]);
966
1039
  const signature = (0, import_eddsa_poseidon.signMessage)(bigInt2Buffer(signPriKey), hash);
967
1040
  const command = [packaged, ...newPubKey, ...signature.R8, signature.S];
968
- const message = (0, import_poseidon_cipher2.poseidonEncrypt)(
969
- command,
970
- genEcdhSharedKey(encPriKey, coordPubKey),
971
- 0n
972
- );
1041
+ const message = (0, import_poseidon_cipher2.poseidonEncrypt)(command, genEcdhSharedKey(encPriKey, coordPubKey), 0n);
973
1042
  return message;
974
1043
  };
975
1044
  var batchGenMessage = (stateIdx, keypair, coordPubKey, plan) => {
@@ -983,13 +1052,7 @@ var batchGenMessage = (stateIdx, keypair, coordPubKey, plan) => {
983
1052
  for (let i = plan.length - 1; i >= 0; i--) {
984
1053
  const p = plan[i];
985
1054
  const encAccount = genKeypair();
986
- const msg = genMessage(
987
- BigInt(encAccount.privKey),
988
- i + 1,
989
- p[0],
990
- p[1],
991
- i === plan.length - 1
992
- );
1055
+ const msg = genMessage(BigInt(encAccount.privKey), i + 1, p[0], p[1], i === plan.length - 1);
993
1056
  payload.push({
994
1057
  msg,
995
1058
  encPubkeys: encAccount.pubKey
@@ -1041,10 +1104,7 @@ var genAddKeyInput = (depth, {
1041
1104
  const c1 = [deactivateLeaf[0], deactivateLeaf[1]];
1042
1105
  const c2 = [deactivateLeaf[2], deactivateLeaf[3]];
1043
1106
  const { d1, d2 } = rerandomize(coordPubKey, { c1, c2 }, randomVal);
1044
- const nullifier = poseidon([
1045
- BigInt(oldKey.formatedPrivKey),
1046
- 1444992409218394441042n
1047
- ]);
1107
+ const nullifier = poseidon([BigInt(oldKey.formatedPrivKey), 1444992409218394441042n]);
1048
1108
  const tree = new Tree(5, depth, 0n);
1049
1109
  const leaves = deactivates.map((d) => poseidon(d));
1050
1110
  tree.initLeaves(leaves);
@@ -1091,12 +1151,7 @@ function randomUint256() {
1091
1151
  return buffer.join("");
1092
1152
  }
1093
1153
  var genRandomKey = () => {
1094
- const key = [
1095
- randomUint256(),
1096
- randomUint256(),
1097
- randomUint256(),
1098
- randomUint256()
1099
- ].join("");
1154
+ const key = [randomUint256(), randomUint256(), randomUint256(), randomUint256()].join("");
1100
1155
  return ["-----BEGIN MACI KEY-----", key, "-----END MACI KEY-----"].join("\n");
1101
1156
  };
1102
1157
 
@@ -1152,19 +1207,127 @@ async function genKeypairFromSign({
1152
1207
  if (!address) {
1153
1208
  [{ address }] = await signer.getAccounts();
1154
1209
  }
1155
- const sig = await signMessage2(
1156
- signer,
1157
- address,
1158
- "Generate_MACI_Private_Key",
1159
- network
1160
- );
1210
+ const sig = await signMessage2(signer, address, "Generate_MACI_Private_Key", network);
1161
1211
  return genKeypairFromSignature(sig.signature);
1162
1212
  }
1163
1213
 
1164
- // src/utils/index.ts
1214
+ // src/libs/crypto/curve.ts
1215
+ var import_ffjavascript = require("ffjavascript");
1216
+ var bls12381r = import_ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16);
1217
+ var bn128r = import_ffjavascript.Scalar.e(
1218
+ "21888242871839275222246405745257275088548364400416034343698204186575808495617"
1219
+ );
1220
+ var bls12381q = import_ffjavascript.Scalar.e(
1221
+ "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
1222
+ 16
1223
+ );
1224
+ var bn128q = import_ffjavascript.Scalar.e(
1225
+ "21888242871839275222246405745257275088696311157297823662689037894645226208583"
1226
+ );
1227
+ async function getCurveFromR(r2) {
1228
+ let curve;
1229
+ if (import_ffjavascript.Scalar.eq(r2, bn128r)) {
1230
+ curve = await (0, import_ffjavascript.buildBn128)();
1231
+ } else if (import_ffjavascript.Scalar.eq(r2, bls12381r)) {
1232
+ curve = await (0, import_ffjavascript.buildBls12381)();
1233
+ } else {
1234
+ throw new Error(`Curve not supported: ${import_ffjavascript.Scalar.toString(r2)}`);
1235
+ }
1236
+ return curve;
1237
+ }
1238
+ async function getCurveFromQ(q) {
1239
+ let curve;
1240
+ if (import_ffjavascript.Scalar.eq(q, bn128q)) {
1241
+ curve = await (0, import_ffjavascript.buildBn128)();
1242
+ } else if (import_ffjavascript.Scalar.eq(q, bls12381q)) {
1243
+ curve = await (0, import_ffjavascript.buildBls12381)();
1244
+ } else {
1245
+ throw new Error(`Curve not supported: ${import_ffjavascript.Scalar.toString(q)}`);
1246
+ }
1247
+ return curve;
1248
+ }
1249
+ async function getCurveFromName(name) {
1250
+ let curve;
1251
+ const normName = normalizeName(name);
1252
+ if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
1253
+ curve = await (0, import_ffjavascript.buildBn128)();
1254
+ } else if (["BLS12381"].indexOf(normName) >= 0) {
1255
+ curve = await (0, import_ffjavascript.buildBls12381)();
1256
+ } else {
1257
+ throw new Error(`Curve not supported: ${name}`);
1258
+ }
1259
+ return curve;
1260
+ function normalizeName(n) {
1261
+ return (n.toUpperCase().match(/[A-Za-z0-9]+/g) || []).join("");
1262
+ }
1263
+ }
1264
+
1265
+ // src/libs/crypto/adapter.ts
1266
+ var import_ffjavascript2 = require("ffjavascript");
1267
+ var { unstringifyBigInts } = import_ffjavascript2.utils;
1268
+ var Bytes2Str = (arr) => {
1269
+ let str = "";
1270
+ for (let i = 0; i < arr.length; i++) {
1271
+ let tmp = arr[i].toString(16);
1272
+ if (tmp.length == 1) {
1273
+ tmp = "0" + tmp;
1274
+ }
1275
+ str += tmp;
1276
+ }
1277
+ return str;
1278
+ };
1279
+ var BN128Curve = null;
1280
+ var adaptToUncompressed = async (proof) => {
1281
+ const p = unstringifyBigInts(proof);
1282
+ let curve = BN128Curve;
1283
+ if (!curve) {
1284
+ BN128Curve = await getCurveFromName("BN128");
1285
+ curve = BN128Curve;
1286
+ }
1287
+ const pi_a = curve.G1.toUncompressed(curve.G1.fromObject(p.pi_a));
1288
+ const pi_b = curve.G2.toUncompressed(curve.G2.fromObject(p.pi_b));
1289
+ const pi_c = curve.G1.toUncompressed(curve.G1.fromObject(p.pi_c));
1290
+ return {
1291
+ a: Bytes2Str(Array.from(pi_a)),
1292
+ b: Bytes2Str(Array.from(pi_b)),
1293
+ c: Bytes2Str(Array.from(pi_c))
1294
+ };
1295
+ };
1296
+
1297
+ // src/libs/crypto/rerandomize.ts
1298
+ var BabyJub2 = __toESM(require("@zk-kit/baby-jubjub"));
1299
+ var F = BabyJub2.Fr;
1300
+ var encodeToMessage = (original, randomKey = genKeypair()) => {
1301
+ const xIncrement = F.e(F.sub(randomKey.pubKey[0], original));
1302
+ return {
1303
+ point: {
1304
+ x: randomKey.pubKey[0],
1305
+ y: randomKey.pubKey[1]
1306
+ },
1307
+ xIncrement
1308
+ };
1309
+ };
1310
+ var encryptOdevity = (isOdd, pubKey, randomVal = genRandomBabyJubValue()) => {
1311
+ let i = 0n;
1312
+ let message = encodeToMessage(123n, genKeypair(randomVal + i));
1313
+ while (message.point.x % 2n === 1n !== isOdd) {
1314
+ i++;
1315
+ message = encodeToMessage(123n, genKeypair(randomVal + i));
1316
+ }
1317
+ const c1Point = BabyJub2.mulPointEscalar(BabyJub2.Base8, randomVal);
1318
+ const pky = BabyJub2.mulPointEscalar(pubKey, randomVal);
1319
+ const c2Point = BabyJub2.addPoint([message.point.x, message.point.y], pky);
1320
+ return {
1321
+ c1: { x: c1Point[0], y: c1Point[1] },
1322
+ c2: { x: c2Point[0], y: c2Point[1] },
1323
+ xIncrement: message.xIncrement
1324
+ };
1325
+ };
1326
+
1327
+ // src/utils/validate-address.ts
1165
1328
  function verifyIsBech32(address) {
1166
1329
  try {
1167
- (0, import_bech32.decode)(address);
1330
+ import_bech32.bech32.decode(address);
1168
1331
  } catch (error) {
1169
1332
  return error instanceof Error ? error : new Error("Unknown error");
1170
1333
  }
@@ -1173,6 +1336,46 @@ function verifyIsBech32(address) {
1173
1336
  function isValidAddress(address) {
1174
1337
  return address.startsWith("dora") && verifyIsBech32(address) === void 0;
1175
1338
  }
1339
+ function hexToDecimalString(hexString) {
1340
+ const decimalString = BigInt("0x" + hexString).toString(10);
1341
+ return decimalString;
1342
+ }
1343
+ function hexToBigInt(hexString) {
1344
+ return BigInt("0x" + hexString);
1345
+ }
1346
+ function padWithZerosIfNeeded(inputString) {
1347
+ if (inputString.length === 64) {
1348
+ return inputString;
1349
+ } else if (inputString.length < 64) {
1350
+ const zerosToAdd = 64 - inputString.length;
1351
+ const zeroPadding = "0".repeat(zerosToAdd);
1352
+ return zeroPadding + inputString;
1353
+ }
1354
+ throw new Error("Invalid input string length");
1355
+ }
1356
+ function decompressPublicKey(compressedPubkey) {
1357
+ const x = compressedPubkey.slice(0, 64);
1358
+ const y = compressedPubkey.slice(64);
1359
+ return {
1360
+ x: hexToDecimalString(x),
1361
+ y: hexToDecimalString(y)
1362
+ };
1363
+ }
1364
+ function compressPublicKey(decompressedPubkey) {
1365
+ const x = decompressedPubkey[0];
1366
+ const y = decompressedPubkey[1];
1367
+ const compressedPubkey = padWithZerosIfNeeded(x.toString(16)) + padWithZerosIfNeeded(y.toString(16));
1368
+ return compressedPubkey;
1369
+ }
1370
+ function transformPubkey(oldPubkey) {
1371
+ const x = oldPubkey.slice(0, 64);
1372
+ const y = oldPubkey.slice(64);
1373
+ const pubkey = [hexToBigInt(x), hexToBigInt(y)];
1374
+ console.log(pubkey);
1375
+ console.log([hexToDecimalString(x), hexToDecimalString(y)]);
1376
+ const packedPubkey = packPubKey(pubkey);
1377
+ return packedPubkey;
1378
+ }
1176
1379
 
1177
1380
  // src/libs/query/operator.ts
1178
1381
  var Operator = class {
@@ -8559,6 +8762,257 @@ var MACI = class {
8559
8762
  }
8560
8763
  };
8561
8764
 
8765
+ // src/libs/api/client.ts
8766
+ var MaciApiClient = class {
8767
+ constructor(config) {
8768
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
8769
+ this.apiKey = config.apiKey;
8770
+ this.customFetch = config.customFetch || fetch;
8771
+ this.timeout = config.timeout || 12e4;
8772
+ this.apiKeyHeader = config.apiKeyHeader || "x-api-key";
8773
+ }
8774
+ /**
8775
+ * Update API key
8776
+ */
8777
+ setApiKey(apiKey) {
8778
+ this.apiKey = apiKey;
8779
+ }
8780
+ /**
8781
+ * Update base URL
8782
+ */
8783
+ setBaseUrl(baseUrl) {
8784
+ this.baseUrl = baseUrl.replace(/\/$/, "");
8785
+ }
8786
+ /**
8787
+ * Internal fetch method with timeout and error handling
8788
+ */
8789
+ async fetch(path, options) {
8790
+ const controller = new AbortController();
8791
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8792
+ try {
8793
+ const headers = {
8794
+ "Content-Type": "application/json"
8795
+ };
8796
+ if (options?.headers) {
8797
+ Object.assign(headers, options.headers);
8798
+ }
8799
+ if (this.apiKey) {
8800
+ if (this.apiKeyHeader === "x-api-key") {
8801
+ headers["x-api-key"] = this.apiKey;
8802
+ } else {
8803
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
8804
+ }
8805
+ }
8806
+ const response = await this.customFetch(`${this.baseUrl}${path}`, {
8807
+ ...options,
8808
+ headers,
8809
+ signal: controller.signal
8810
+ });
8811
+ clearTimeout(timeoutId);
8812
+ if (!response.ok) {
8813
+ const errorData = await response.json().catch(() => ({}));
8814
+ throw new HttpError(
8815
+ errorData.error || `HTTP error! status: ${response.status}`,
8816
+ response.status
8817
+ );
8818
+ }
8819
+ if (response.status === 204) {
8820
+ return null;
8821
+ }
8822
+ return await response.json();
8823
+ } catch (error) {
8824
+ clearTimeout(timeoutId);
8825
+ if (error instanceof HttpError) {
8826
+ throw error;
8827
+ }
8828
+ if (error.name === "AbortError") {
8829
+ throw new HttpError("Request timeout", 408);
8830
+ }
8831
+ throw new HttpError(`Failed to fetch: ${error.message}`, 500);
8832
+ }
8833
+ }
8834
+ /**
8835
+ * Health check
8836
+ */
8837
+ async health() {
8838
+ return this.fetch("/health", { method: "GET" });
8839
+ }
8840
+ // ==================== Admin APIs ====================
8841
+ /**
8842
+ * Create API key (Admin)
8843
+ */
8844
+ async createApiKey(data) {
8845
+ return this.fetch("/admin/keys", {
8846
+ method: "POST",
8847
+ body: JSON.stringify(data)
8848
+ });
8849
+ }
8850
+ /**
8851
+ * Create tenant (Admin)
8852
+ */
8853
+ async createTenant(data) {
8854
+ return this.fetch("/admin/tenants", {
8855
+ method: "POST",
8856
+ body: JSON.stringify(data)
8857
+ });
8858
+ }
8859
+ // ==================== Usage API ====================
8860
+ /**
8861
+ * Get usage for current API key
8862
+ */
8863
+ async getUsage(params) {
8864
+ const queryString = params ? "?" + new URLSearchParams(params).toString() : "";
8865
+ return this.fetch(`/v1/usage${queryString}`, { method: "GET" });
8866
+ }
8867
+ // ==================== Core MACI APIs ====================
8868
+ /**
8869
+ * Signup
8870
+ */
8871
+ async signup(data) {
8872
+ return this.fetch("/v1/signup", {
8873
+ method: "POST",
8874
+ body: JSON.stringify(data)
8875
+ });
8876
+ }
8877
+ /**
8878
+ * Vote
8879
+ */
8880
+ async vote(data) {
8881
+ return this.fetch("/v1/vote", {
8882
+ method: "POST",
8883
+ body: JSON.stringify(data)
8884
+ });
8885
+ }
8886
+ /**
8887
+ * Create Round
8888
+ */
8889
+ async createRound(data) {
8890
+ return this.fetch("/v1/create-round", {
8891
+ method: "POST",
8892
+ body: JSON.stringify(data)
8893
+ });
8894
+ }
8895
+ /**
8896
+ * Create AMaci Round
8897
+ */
8898
+ async createAmaciRound(data) {
8899
+ return this.fetch("/v1/create-amaci-round", {
8900
+ method: "POST",
8901
+ body: JSON.stringify(data)
8902
+ });
8903
+ }
8904
+ /**
8905
+ * Set Round Info
8906
+ */
8907
+ async setRoundInfo(data) {
8908
+ return this.fetch("/v1/set-round-info", {
8909
+ method: "POST",
8910
+ body: JSON.stringify(data)
8911
+ });
8912
+ }
8913
+ /**
8914
+ * Set Vote Options
8915
+ */
8916
+ async setVoteOptions(data) {
8917
+ return this.fetch("/v1/set-vote-options", {
8918
+ method: "POST",
8919
+ body: JSON.stringify(data)
8920
+ });
8921
+ }
8922
+ /**
8923
+ * Deactivate
8924
+ */
8925
+ async deactivate(data) {
8926
+ return this.fetch("/v1/deactivate", {
8927
+ method: "POST",
8928
+ body: JSON.stringify(data)
8929
+ });
8930
+ }
8931
+ /**
8932
+ * Add New Key
8933
+ */
8934
+ async addNewKey(data) {
8935
+ return this.fetch("/v1/add-new-key", {
8936
+ method: "POST",
8937
+ body: JSON.stringify(data)
8938
+ });
8939
+ }
8940
+ /**
8941
+ * Pre Add New Key
8942
+ */
8943
+ async preAddNewKey(data) {
8944
+ return this.fetch("/v1/pre-add-new-key", {
8945
+ method: "POST",
8946
+ body: JSON.stringify(data)
8947
+ });
8948
+ }
8949
+ // ==================== Allowlist APIs ====================
8950
+ /**
8951
+ * Get allowlist list
8952
+ */
8953
+ async getAllowlists(params) {
8954
+ const queryString = params ? "?" + new URLSearchParams(params).toString() : "";
8955
+ return this.fetch(`/v1/allowlists/${queryString}`, { method: "GET" });
8956
+ }
8957
+ /**
8958
+ * Create allowlist
8959
+ */
8960
+ async createAllowlist(data) {
8961
+ return this.fetch("/v1/allowlists/", {
8962
+ method: "POST",
8963
+ body: JSON.stringify(data)
8964
+ });
8965
+ }
8966
+ /**
8967
+ * Get allowlist details
8968
+ */
8969
+ async getAllowlistDetail(params) {
8970
+ return this.fetch(`/v1/allowlists/${params.id}`, { method: "GET" });
8971
+ }
8972
+ /**
8973
+ * Update allowlist
8974
+ */
8975
+ async updateAllowlist(params, data) {
8976
+ return this.fetch(`/v1/allowlists/${params.id}`, {
8977
+ method: "PUT",
8978
+ body: JSON.stringify(data)
8979
+ });
8980
+ }
8981
+ /**
8982
+ * Delete allowlist
8983
+ */
8984
+ async deleteAllowlist(params) {
8985
+ return this.fetch(`/v1/allowlists/${params.id}`, { method: "DELETE" });
8986
+ }
8987
+ /**
8988
+ * Get round allowlist snapshot
8989
+ */
8990
+ async getRoundAllowlistSnapshot(params) {
8991
+ return this.fetch(`/v1/allowlists/snapshots/${params.contractAddress}`, {
8992
+ method: "GET"
8993
+ });
8994
+ }
8995
+ // ==================== Certificate APIs ====================
8996
+ /**
8997
+ * Request certificate
8998
+ */
8999
+ async requestCertificate(data) {
9000
+ return this.fetch("/v1/certificates/request", {
9001
+ method: "POST",
9002
+ body: JSON.stringify(data)
9003
+ });
9004
+ }
9005
+ // ==================== Pre-deactivate APIs ====================
9006
+ /**
9007
+ * Get pre-deactivate data by contract address
9008
+ */
9009
+ async getPreDeactivate(params) {
9010
+ return this.fetch(`/v1/pre-deactivate/${params.contractAddress}`, {
9011
+ method: "GET"
9012
+ });
9013
+ }
9014
+ };
9015
+
8562
9016
  // src/maci.ts
8563
9017
  var MaciClient2 = class {
8564
9018
  /**
@@ -8571,6 +9025,8 @@ var MaciClient2 = class {
8571
9025
  rpcEndpoint,
8572
9026
  restEndpoint,
8573
9027
  apiEndpoint,
9028
+ saasApiEndpoint,
9029
+ saasApiKey,
8574
9030
  registryAddress,
8575
9031
  saasAddress,
8576
9032
  apiSaasAddress,
@@ -8589,6 +9045,7 @@ var MaciClient2 = class {
8589
9045
  this.rpcEndpoint = rpcEndpoint || defaultParams.rpcEndpoint;
8590
9046
  this.restEndpoint = restEndpoint || defaultParams.restEndpoint;
8591
9047
  this.apiEndpoint = apiEndpoint || defaultParams.apiEndpoint;
9048
+ this.saasApiEndpoint = saasApiEndpoint;
8592
9049
  this.certificateApiEndpoint = certificateApiEndpoint || defaultParams.certificateApiEndpoint;
8593
9050
  this.registryAddress = registryAddress || defaultParams.registryAddress;
8594
9051
  this.saasAddress = saasAddress || defaultParams.saasAddress;
@@ -8598,15 +9055,11 @@ var MaciClient2 = class {
8598
9055
  this.feegrantOperator = feegrantOperator || defaultParams.oracleFeegrantOperator;
8599
9056
  this.whitelistBackendPubkey = whitelistBackendPubkey || defaultParams.oracleWhitelistBackendPubkey;
8600
9057
  this.maciKeypair = maciKeypair ?? genKeypair();
8601
- this.http = new Http(
8602
- this.apiEndpoint,
8603
- this.restEndpoint,
8604
- customFetch,
8605
- defaultOptions
8606
- );
9058
+ this.http = new Http(this.apiEndpoint, this.restEndpoint, customFetch, defaultOptions);
8607
9059
  this.indexer = new Indexer({
8608
9060
  restEndpoint: this.restEndpoint,
8609
9061
  apiEndpoint: this.apiEndpoint,
9062
+ // Indexer GraphQL API
8610
9063
  registryAddress: this.registryAddress,
8611
9064
  http: this.http
8612
9065
  });
@@ -8631,6 +9084,13 @@ var MaciClient2 = class {
8631
9084
  oracleCertificate: this.oracleCertificate,
8632
9085
  maciKeypair: this.maciKeypair
8633
9086
  });
9087
+ if (this.saasApiEndpoint) {
9088
+ this.saasApiClient = new MaciApiClient({
9089
+ baseUrl: this.saasApiEndpoint,
9090
+ apiKey: saasApiKey,
9091
+ customFetch
9092
+ });
9093
+ }
8634
9094
  }
8635
9095
  getSigner(signer) {
8636
9096
  if (signer) {
@@ -8641,6 +9101,28 @@ var MaciClient2 = class {
8641
9101
  }
8642
9102
  throw new Error("No signer provided, please provide a signer");
8643
9103
  }
9104
+ /**
9105
+ * Set SaaS API key for MaciApiClient
9106
+ */
9107
+ setSaasApiKey(apiKey) {
9108
+ if (!this.saasApiClient) {
9109
+ throw new Error(
9110
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
9111
+ );
9112
+ }
9113
+ this.saasApiClient.setApiKey(apiKey);
9114
+ }
9115
+ /**
9116
+ * Get SaaS API client instance
9117
+ */
9118
+ getSaasApiClient() {
9119
+ if (!this.saasApiClient) {
9120
+ throw new Error(
9121
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
9122
+ );
9123
+ }
9124
+ return this.saasApiClient;
9125
+ }
8644
9126
  getMaciKeypair() {
8645
9127
  return this.maciKeypair;
8646
9128
  }
@@ -8843,9 +9325,7 @@ var MaciClient2 = class {
8843
9325
  async getRounds(after, limit) {
8844
9326
  const rounds = await this.indexer.getRounds(after || "", limit || 10);
8845
9327
  if (isErrorResponse(rounds)) {
8846
- throw new Error(
8847
- `Failed to get rounds: ${rounds.code} ${rounds.error.message}`
8848
- );
9328
+ throw new Error(`Failed to get rounds: ${rounds.code} ${rounds.error.message}`);
8849
9329
  }
8850
9330
  return rounds;
8851
9331
  }
@@ -8858,15 +9338,10 @@ var MaciClient2 = class {
8858
9338
  async queryRoundIsQv({ contractAddress }) {
8859
9339
  return await this.maci.queryRoundIsQv({ contractAddress });
8860
9340
  }
8861
- async queryRoundClaimable({
8862
- contractAddress
8863
- }) {
9341
+ async queryRoundClaimable({ contractAddress }) {
8864
9342
  return await this.maci.queryRoundClaimable({ contractAddress });
8865
9343
  }
8866
- async queryAMaciChargeFee({
8867
- maxVoter,
8868
- maxOption
8869
- }) {
9344
+ async queryAMaciChargeFee({ maxVoter, maxOption }) {
8870
9345
  return await this.maci.queryAMaciChargeFee({
8871
9346
  maxVoter,
8872
9347
  maxOption
@@ -8876,12 +9351,7 @@ var MaciClient2 = class {
8876
9351
  return await this.maci.queryRoundGasStation({ contractAddress });
8877
9352
  }
8878
9353
  parseRoundStatus(votingStart, votingEnd, status, currentTime) {
8879
- return this.maci.parseRoundStatus(
8880
- votingStart,
8881
- votingEnd,
8882
- status,
8883
- currentTime
8884
- );
9354
+ return this.maci.parseRoundStatus(votingStart, votingEnd, status, currentTime);
8885
9355
  }
8886
9356
  async queryRoundBalance({ contractAddress }) {
8887
9357
  return await this.maci.queryRoundBalance({ contractAddress });
@@ -9141,13 +9611,941 @@ var MaciClient2 = class {
9141
9611
  fee
9142
9612
  });
9143
9613
  }
9614
+ // ==================== SaaS API Client Methods ====================
9615
+ /**
9616
+ * Create AMaci round via SaaS API
9617
+ * @param params - Round creation parameters
9618
+ */
9619
+ async saasCreateAmaciRound(params) {
9620
+ if (!this.saasApiClient) {
9621
+ throw new Error("SaaS API client not initialized");
9622
+ }
9623
+ return await this.saasApiClient.createAmaciRound(params);
9624
+ }
9625
+ /**
9626
+ * Set round info via SaaS API
9627
+ * @param params - Round info parameters
9628
+ */
9629
+ async saasSetRoundInfo(params) {
9630
+ if (!this.saasApiClient) {
9631
+ throw new Error("SaaS API client not initialized");
9632
+ }
9633
+ return await this.saasApiClient.setRoundInfo(params);
9634
+ }
9635
+ /**
9636
+ * Set vote options via SaaS API
9637
+ * @param params - Vote options parameters
9638
+ */
9639
+ async saasSetVoteOptions(params) {
9640
+ if (!this.saasApiClient) {
9641
+ throw new Error("SaaS API client not initialized");
9642
+ }
9643
+ return await this.saasApiClient.setVoteOptions(params);
9644
+ }
9645
+ };
9646
+
9647
+ // src/voter.ts
9648
+ var import_crypto_js3 = __toESM(require("crypto-js"));
9649
+ var import_ethers4 = require("ethers");
9650
+ var import_snarkjs = require("snarkjs");
9651
+
9652
+ // src/libs/keypairs/eddsa-poseidon/keypair.ts
9653
+ var import_blake2b = require("@noble/hashes/blake2b");
9654
+ var import_utils9 = require("@noble/hashes/utils");
9655
+ var import_bip32 = require("@scure/bip32");
9656
+ var import_sha2563 = require("@noble/hashes/sha256");
9657
+ var import_eddsa_poseidon4 = require("@zk-kit/eddsa-poseidon");
9658
+
9659
+ // src/libs/cryptography/keypair.ts
9660
+ var Signer = class {
9661
+ /**
9662
+ * Sign messages with a specific payload. By combining the message bytes with the payload before hashing and signing,
9663
+ * it ensures that a signed message is tied to a specific purpose and domain separator is provided
9664
+ */
9665
+ async signWithPayload(message) {
9666
+ const signature = await this.sign(message);
9667
+ return {
9668
+ message,
9669
+ signature
9670
+ };
9671
+ }
9672
+ };
9673
+ var Keypair3 = class extends Signer {
9674
+ };
9675
+
9676
+ // src/libs/cryptography/mnemonics.ts
9677
+ var import_bip39 = require("@scure/bip39");
9678
+ function isValidBIP32Path(path) {
9679
+ if (!new RegExp("^m\\/(44|54|74)'\\/118'\\/[0-9]+'\\/[0-9]+\\/[0-9]+$").test(path)) {
9680
+ return false;
9681
+ }
9682
+ return true;
9683
+ }
9684
+ function mnemonicToSeed(mnemonics) {
9685
+ return (0, import_bip39.mnemonicToSeedSync)(mnemonics, "");
9686
+ }
9687
+
9688
+ // src/libs/keypairs/eddsa-poseidon/publickey.ts
9689
+ var import_sha2562 = require("@noble/hashes/sha256");
9690
+
9691
+ // src/libs/cryptography/publickey.ts
9692
+ var PublicKey = class {
9693
+ /**
9694
+ * Checks if two public keys are equal
9695
+ */
9696
+ equals(publicKey) {
9697
+ return this.toPackedData() === publicKey.toPackedData();
9698
+ }
9699
+ };
9700
+
9701
+ // src/libs/keypairs/eddsa-poseidon/publickey.ts
9702
+ var import_eddsa_poseidon3 = require("@zk-kit/eddsa-poseidon");
9703
+ var EdDSAPoseidonPublicKey = class extends PublicKey {
9704
+ /**
9705
+ * Create a new EdDSAPoseidonPublicKey object
9706
+ * @param value public key as packed bigint, Point array, Uint8Array or string
9707
+ */
9708
+ constructor(value) {
9709
+ super();
9710
+ if (typeof value === "bigint") {
9711
+ this.packedData = value;
9712
+ this.rawPoint = unpackPubKey(value);
9713
+ } else if (Array.isArray(value) && value.length === 2) {
9714
+ this.rawPoint = value;
9715
+ this.packedData = packPubKey(this.rawPoint);
9716
+ } else if (typeof value === "string") {
9717
+ this.packedData = BigInt(value);
9718
+ this.rawPoint = unpackPubKey(this.packedData);
9719
+ } else if (value instanceof Uint8Array) {
9720
+ const hex = Array.from(value).map((b) => b.toString(16).padStart(2, "0")).join("");
9721
+ this.packedData = BigInt("0x" + hex);
9722
+ this.rawPoint = unpackPubKey(this.packedData);
9723
+ } else {
9724
+ const bytes = new Uint8Array(value);
9725
+ const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
9726
+ this.packedData = BigInt("0x" + hex);
9727
+ this.rawPoint = unpackPubKey(this.packedData);
9728
+ }
9729
+ }
9730
+ /**
9731
+ * Checks if two EdDSAPoseidon public keys are equal
9732
+ */
9733
+ equals(publicKey) {
9734
+ return super.equals(publicKey);
9735
+ }
9736
+ /**
9737
+ * Return the Point representation of the EdDSAPoseidon public key
9738
+ */
9739
+ toPoints() {
9740
+ return this.rawPoint;
9741
+ }
9742
+ /**
9743
+ * Return the packed bigint representation of the EdDSAPoseidon public key
9744
+ */
9745
+ toPackedData() {
9746
+ return this.packedData;
9747
+ }
9748
+ /**
9749
+ * Verifies that the signature is valid for for the provided message
9750
+ */
9751
+ verify(message, signature) {
9752
+ try {
9753
+ return (0, import_eddsa_poseidon3.verifySignature)(message, signature, this.rawPoint);
9754
+ } catch (error) {
9755
+ return false;
9756
+ }
9757
+ }
9758
+ /**
9759
+ * Verifies that the signature is valid for the provided address and amount
9760
+ */
9761
+ verifyPayload({
9762
+ amount,
9763
+ contractAddress,
9764
+ signature
9765
+ }) {
9766
+ const payload = {
9767
+ amount,
9768
+ contract_address: addressToUint256(contractAddress).toString(),
9769
+ pubkey_x: this.toPoints()[0].toString(),
9770
+ pubkey_y: this.toPoints()[1].toString()
9771
+ };
9772
+ const signatureBytes = fromBase64(signature);
9773
+ const rawSignature = (0, import_eddsa_poseidon3.unpackSignature)(new Buffer(signatureBytes));
9774
+ const payloadHash = (0, import_sha2562.sha256)(new TextEncoder().encode(JSON.stringify(payload)));
9775
+ return this.verify(payloadHash, rawSignature);
9776
+ }
9777
+ /**
9778
+ * Verifies that the signature is valid for the provided address and amount
9779
+ */
9780
+ verifyCredential({
9781
+ amount,
9782
+ contractAddress,
9783
+ signature
9784
+ }) {
9785
+ const messageHash = hash5([
9786
+ BigInt(amount),
9787
+ BigInt(addressToUint256(contractAddress)),
9788
+ this.toPoints()[0],
9789
+ this.toPoints()[1],
9790
+ BigInt(0)
9791
+ ]);
9792
+ const signatureBytes = fromBase64(signature);
9793
+ const rawSignature = (0, import_eddsa_poseidon3.unpackSignature)(new Buffer(signatureBytes));
9794
+ return this.verify(bigInt2Buffer(messageHash), rawSignature);
9795
+ }
9796
+ };
9797
+
9798
+ // src/libs/keypairs/eddsa-poseidon/keypair.ts
9799
+ var import_baby_jubjub3 = require("@zk-kit/baby-jubjub");
9800
+ var DEFAULT_EDDSA_POSEIDON_DERIVATION_PATH = "m/44'/118'/0'/0/0";
9801
+ var EdDSAPoseidonKeypair = class _EdDSAPoseidonKeypair extends Keypair3 {
9802
+ /**
9803
+ * Create a new EdDSA-Poseidon keypair instance.
9804
+ *
9805
+ * If no keypair data is provided, a new random keypair will be generated
9806
+ * using cryptographically secure random number generation.
9807
+ *
9808
+ * @param keypair Optional existing EdDSA-Poseidon keypair data to initialize with
9809
+ */
9810
+ constructor(keypair) {
9811
+ super();
9812
+ if (keypair) {
9813
+ this.keypair = keypair;
9814
+ } else {
9815
+ const generatedKeypair = genKeypair();
9816
+ const secretKey = generatedKeypair.privKey;
9817
+ const unPackedPublicKey = generatedKeypair.pubKey;
9818
+ const publicKey = packPubKey(unPackedPublicKey);
9819
+ const formatedPrivKey = formatPrivKeyForBabyJub(secretKey);
9820
+ this.keypair = { publicKey, secretKey, formatedPrivKey };
9821
+ }
9822
+ }
9823
+ /**
9824
+ * Get the signature scheme identifier for this keypair.
9825
+ *
9826
+ * @returns The signature scheme type 'EDDSA_POSEIDON'
9827
+ */
9828
+ getKeyScheme() {
9829
+ return "EDDSA_POSEIDON";
9830
+ }
9831
+ /**
9832
+ * Generate a new random EdDSA-Poseidon keypair.
9833
+ *
9834
+ * This is a convenience static method that creates a new instance
9835
+ * with randomly generated cryptographic keys.
9836
+ *
9837
+ * @returns A new EdDSAPoseidonKeypair instance with random keys
9838
+ */
9839
+ static generate() {
9840
+ return new _EdDSAPoseidonKeypair();
9841
+ }
9842
+ /**
9843
+ * Create a keypair from an existing secret key.
9844
+ *
9845
+ * This method reconstructs a keypair from a previously generated secret key.
9846
+ * The secret key can be provided as either a hex string (with or without '0x' prefix)
9847
+ * or as a bigint value. For generating keypairs from mnemonic seeds, use the
9848
+ * {@link EdDSAPoseidonKeypair.deriveKeypair} method instead.
9849
+ *
9850
+ * @param secretKey The secret key as a hex string or bigint
9851
+ * @param options Configuration options for key reconstruction
9852
+ * @param options.skipValidation If true, skips cryptographic validation of the secret key
9853
+ *
9854
+ * @returns A new EdDSAPoseidonKeypair instance created from the secret key
9855
+ * @throws Error if the provided secret key is invalid and validation is not skipped
9856
+ */
9857
+ static fromSecretKey(secretKey, options) {
9858
+ if (typeof secretKey === "string") {
9859
+ const cleanSecretKey = secretKey.startsWith("0x") ? secretKey.slice(2) : secretKey;
9860
+ const decoded = buffer2Bigint((0, import_utils9.hexToBytes)(cleanSecretKey));
9861
+ return this.fromSecretKey(decoded, options);
9862
+ }
9863
+ const unPackedPublicKey = genPubKey(secretKey);
9864
+ const publicKey = packPubKey(unPackedPublicKey);
9865
+ if (!options || !options.skipValidation) {
9866
+ const encoder = new TextEncoder();
9867
+ const signData = encoder.encode("dora validation");
9868
+ const msgHash = (0, import_utils9.bytesToHex)((0, import_blake2b.blake2b)(signData, { dkLen: 16 }));
9869
+ const signature = (0, import_eddsa_poseidon4.signMessage)(bigInt2Buffer(secretKey), msgHash);
9870
+ if (!(0, import_eddsa_poseidon4.verifySignature)(msgHash, signature, unPackedPublicKey)) {
9871
+ throw new Error("Provided secretKey is invalid");
9872
+ }
9873
+ }
9874
+ const formatedPrivKey = formatPrivKeyForBabyJub(secretKey);
9875
+ return new _EdDSAPoseidonKeypair({
9876
+ publicKey,
9877
+ secretKey,
9878
+ formatedPrivKey
9879
+ });
9880
+ }
9881
+ /**
9882
+ * Get the public key associated with this keypair.
9883
+ *
9884
+ * @returns An EdDSAPoseidonPublicKey instance containing the public key data
9885
+ */
9886
+ getPublicKey() {
9887
+ return new EdDSAPoseidonPublicKey(this.keypair.publicKey);
9888
+ }
9889
+ /**
9890
+ * Get the secret key as a hexadecimal string.
9891
+ *
9892
+ * Returns the secret key component of this keypair encoded as a hex string.
9893
+ * This can be used to serialize the secret key for storage or transmission.
9894
+ *
9895
+ * @returns The secret key encoded as a hexadecimal string
9896
+ */
9897
+ getSecretKey() {
9898
+ return (0, import_utils9.bytesToHex)(bigInt2Buffer(this.keypair.secretKey));
9899
+ }
9900
+ getFormatedPrivKey() {
9901
+ return this.keypair.formatedPrivKey;
9902
+ }
9903
+ /**
9904
+ * Sign a message using this keypair's secret key.
9905
+ *
9906
+ * Creates a cryptographic signature for the provided message using the
9907
+ * EdDSA-Poseidon signature algorithm. The signature can later be verified
9908
+ * using the corresponding public key.
9909
+ *
9910
+ * @param message The message to sign (as BigNumberish - can be bigint, string, or number)
9911
+ * @returns The cryptographic signature of the message
9912
+ */
9913
+ sign(message) {
9914
+ const sig = (0, import_eddsa_poseidon4.signMessage)(bigInt2Buffer(this.keypair.secretKey), message);
9915
+ return sig;
9916
+ }
9917
+ /**
9918
+ * Derive an EdDSA-Poseidon keypair from a mnemonic phrase and derivation path.
9919
+ *
9920
+ * This method implements hierarchical deterministic (HD) key derivation following
9921
+ * the BIP-32 standard. The mnemonic phrase must be normalized and validated against
9922
+ * the English wordlist before use.
9923
+ *
9924
+ * @param mnemonics The mnemonic phrase (12, 15, 18, 21, or 24 words)
9925
+ * @param path Optional BIP-32 derivation path. If not provided, uses the default path.
9926
+ * Must be in the form m/44'/118'/{account_index}'/{change_index}/{address_index}
9927
+ *
9928
+ * @returns A new EdDSAPoseidonKeypair derived from the mnemonic and path
9929
+ * @throws Error if the derivation path is invalid or key derivation fails
9930
+ */
9931
+ static deriveKeypair(mnemonics, path) {
9932
+ if (path == null) {
9933
+ path = DEFAULT_EDDSA_POSEIDON_DERIVATION_PATH;
9934
+ }
9935
+ if (!isValidBIP32Path(path)) {
9936
+ throw new Error("Invalid derivation path");
9937
+ }
9938
+ const seed = mnemonicToSeed(mnemonics);
9939
+ const hdKey = import_bip32.HDKey.fromMasterSeed(seed);
9940
+ const derivedKey = hdKey.derive(path);
9941
+ if (!derivedKey.privateKey) {
9942
+ throw new Error("Invalid key");
9943
+ }
9944
+ const privateKeyHex = Buffer.from(derivedKey.privateKey).toString(
9945
+ "hex"
9946
+ );
9947
+ const secretKey = BigInt("0x" + privateKeyHex) % SNARK_FIELD_SIZE;
9948
+ const unPackedPubKey = genPubKey(secretKey);
9949
+ const pubKey = packPubKey(unPackedPubKey);
9950
+ return new _EdDSAPoseidonKeypair({
9951
+ publicKey: pubKey,
9952
+ secretKey,
9953
+ formatedPrivKey: formatPrivKeyForBabyJub(secretKey)
9954
+ });
9955
+ }
9956
+ /**
9957
+ * Sign a payload containing contract address and amount information.
9958
+ *
9959
+ * This method creates a structured payload with the contract address, amount,
9960
+ * and public key coordinates, then generates a cryptographic signature over
9961
+ * the JSON-serialized payload using SHA-256 hashing.
9962
+ *
9963
+ * The resulting signature can be used as a certificate or proof of authorization
9964
+ * for the specified contract address and amount.
9965
+ *
9966
+ * @param params The payload parameters
9967
+ * @param params.amount The amount value as a string
9968
+ * @param params.contractAddress The contract address to include in the payload
9969
+ *
9970
+ * @returns Base64-encoded signature of the payload
9971
+ */
9972
+ signPayload({
9973
+ amount,
9974
+ contractAddress
9975
+ }) {
9976
+ const payload = {
9977
+ amount,
9978
+ contract_address: addressToUint256(contractAddress).toString(),
9979
+ pubkey_x: this.getPublicKey().toPoints()[0].toString(),
9980
+ pubkey_y: this.getPublicKey().toPoints()[1].toString()
9981
+ };
9982
+ const bytes = new TextEncoder().encode(JSON.stringify(payload));
9983
+ const msgHash = (0, import_sha2563.sha256)(bytes);
9984
+ const signature = this.sign(msgHash);
9985
+ return toBase64(new Uint8Array((0, import_eddsa_poseidon4.packSignature)(signature)));
9986
+ }
9987
+ /**
9988
+ * Sign a credential containing contract address and amount using Poseidon hashing.
9989
+ *
9990
+ * This method creates a cryptographic credential by signing a structured message
9991
+ * using the Poseidon hash function (hash5). The message includes the amount,
9992
+ * contract address (converted to uint256), public key coordinates, and a zero nonce.
9993
+ *
9994
+ * This type of credential is optimized for zero-knowledge proof systems where
9995
+ * Poseidon hashing is more efficient than traditional hash functions.
9996
+ *
9997
+ * @param params The credential parameters
9998
+ * @param params.amount The amount value as a string (will be converted to BigInt)
9999
+ * @param params.contractAddress The contract address (will be converted to uint256)
10000
+ *
10001
+ * @returns Base64-encoded signature of the credential
10002
+ */
10003
+ signCredential({
10004
+ amount,
10005
+ contractAddress
10006
+ }) {
10007
+ const messageHash = hash5([
10008
+ BigInt(amount),
10009
+ BigInt(addressToUint256(contractAddress)),
10010
+ this.getPublicKey().toPoints()[0],
10011
+ this.getPublicKey().toPoints()[1],
10012
+ BigInt(0)
10013
+ // Nonce field (currently set to 0)
10014
+ ]);
10015
+ const signature = this.sign(messageHash);
10016
+ return toBase64(new Uint8Array((0, import_eddsa_poseidon4.packSignature)(signature)));
10017
+ }
10018
+ /**
10019
+ * Generates an Elliptic-Curve Diffie–Hellman (ECDH) shared key given a private
10020
+ * key and a public key.
10021
+ * @param pubKey A public key generated using genPubKey()
10022
+ * @returns The ECDH shared key.
10023
+ */
10024
+ genEcdhSharedKey(pubKey) {
10025
+ return (0, import_baby_jubjub3.mulPointEscalar)(
10026
+ pubKey,
10027
+ this.keypair.formatedPrivKey
10028
+ );
10029
+ }
10030
+ genDeactivateRoot(accounts, stateTreeDepth) {
10031
+ const unpackedAccounts = accounts.length > 0 && typeof accounts[0] === "bigint" ? accounts.map((account) => unpackPubKey(account)) : accounts;
10032
+ const deactivates = unpackedAccounts.map((account) => {
10033
+ const sharedKey = this.genEcdhSharedKey(account);
10034
+ const deactivate = encryptOdevity(
10035
+ false,
10036
+ // isOdd: According to circuit rules, odd values indicate active accounts and even values indicate inactive accounts. Set to false here to ensure valid signup
10037
+ this.getPublicKey().toPoints(),
10038
+ genRandomBabyJubValue()
10039
+ );
10040
+ return [
10041
+ deactivate.c1.x,
10042
+ deactivate.c1.y,
10043
+ deactivate.c2.x,
10044
+ deactivate.c2.y,
10045
+ poseidon(sharedKey)
10046
+ ];
10047
+ });
10048
+ const degree = 5;
10049
+ const depth = stateTreeDepth + 2;
10050
+ const zero = 0n;
10051
+ const tree = new Tree(degree, depth, zero);
10052
+ const leaves = deactivates.map((deactivate) => poseidon(deactivate));
10053
+ tree.initLeaves(leaves);
10054
+ return {
10055
+ deactivates,
10056
+ root: tree.root,
10057
+ leaves,
10058
+ tree
10059
+ // Return tree instance for later retrieval of path elements
10060
+ };
10061
+ }
10062
+ };
10063
+
10064
+ // src/libs/account/keypair.ts
10065
+ var getDerivePathForMACI = (derivePathParams = {}) => {
10066
+ const { accountIndex = 0, isExternal = false, addressIndex = 0 } = derivePathParams;
10067
+ return `m/44'/118'/${accountIndex}'/${isExternal ? 1 : 0}/${addressIndex}`;
10068
+ };
10069
+ var getKeyPair = (mnemonics, derivePathParams = {}) => {
10070
+ const derivePath = getDerivePathForMACI(derivePathParams);
10071
+ return EdDSAPoseidonKeypair.deriveKeypair(mnemonics, derivePath);
10072
+ };
10073
+
10074
+ // src/libs/account/crypto.ts
10075
+ var import_bip392 = require("@scure/bip39");
10076
+ var import_english = require("@scure/bip39/wordlists/english");
10077
+ var generateMnemonic = (numberOfWords = 24) => {
10078
+ const strength = numberOfWords === 12 ? 128 : 256;
10079
+ return (0, import_bip392.generateMnemonic)(import_english.wordlist, strength);
10080
+ };
10081
+
10082
+ // src/libs/account/index.ts
10083
+ var MaciAccount = class {
10084
+ /**
10085
+ * Support the following ways to init the SuiToolkit:
10086
+ * 1. mnemonics
10087
+ * 2. secretKey (base64 or hex)
10088
+ * If none of them is provided, will generate a random mnemonics with 24 words.
10089
+ *
10090
+ * @param mnemonics, 12 or 24 mnemonics words, separated by space
10091
+ * @param secretKey, base64 or hex string or Bech32 string, when mnemonics is provided, secretKey will be ignored
10092
+ */
10093
+ constructor({ mnemonic, secretKey } = {}) {
10094
+ this.mnemonic = mnemonic || "";
10095
+ this.secretKey = secretKey || "";
10096
+ if (!this.mnemonic && !this.secretKey) {
10097
+ this.mnemonic = generateMnemonic(24);
10098
+ }
10099
+ this.currentKeypair = this.secretKey ? this.parseSecretKey(this.secretKey) : getKeyPair(this.mnemonic);
10100
+ this.currentPubkey = this.currentKeypair.getPublicKey();
10101
+ }
10102
+ /**
10103
+ * Check if the secretKey starts with bench32 format
10104
+ */
10105
+ parseSecretKey(secretKey) {
10106
+ return EdDSAPoseidonKeypair.fromSecretKey(secretKey);
10107
+ }
10108
+ /**
10109
+ * if derivePathParams is not provided or mnemonics is empty, it will return the currentKeyPair.
10110
+ * else:
10111
+ * it will generate keyPair from the mnemonic with the given derivePathParams.
10112
+ */
10113
+ getKeyPair(derivePathParams) {
10114
+ if (!derivePathParams || !this.mnemonic) return this.currentKeypair;
10115
+ return getKeyPair(this.mnemonic, derivePathParams);
10116
+ }
10117
+ /**
10118
+ * Switch the current account with the given derivePathParams.
10119
+ * This is only useful when the mnemonic is provided. For secretKey mode, it will always use the same account.
10120
+ */
10121
+ switchAccount(derivePathParams) {
10122
+ if (this.mnemonic) {
10123
+ this.currentKeypair = getKeyPair(this.mnemonic, derivePathParams);
10124
+ this.currentPubkey = this.currentKeypair.getPublicKey();
10125
+ }
10126
+ }
10127
+ };
10128
+
10129
+ // src/voter.ts
10130
+ var import_poseidon_cipher3 = require("@zk-kit/poseidon-cipher");
10131
+ var VoterClient = class _VoterClient {
10132
+ /**
10133
+ * @constructor
10134
+ * @param {VoterClientParams} params - The parameters for the Maci Voter Client instance.
10135
+ */
10136
+ constructor({
10137
+ network,
10138
+ mnemonic,
10139
+ secretKey,
10140
+ apiEndpoint,
10141
+ restEndpoint,
10142
+ saasApiEndpoint,
10143
+ saasApiKey,
10144
+ registryAddress,
10145
+ customFetch,
10146
+ defaultOptions
10147
+ }) {
10148
+ this.network = network;
10149
+ this.accountManager = new MaciAccount({ mnemonic, secretKey });
10150
+ const defaultParams = getDefaultParams(network);
10151
+ this.restEndpoint = restEndpoint || defaultParams.restEndpoint;
10152
+ this.apiEndpoint = apiEndpoint || defaultParams.apiEndpoint;
10153
+ this.saasApiEndpoint = saasApiEndpoint || defaultParams.saasApiEndpoint;
10154
+ this.registryAddress = registryAddress || defaultParams.registryAddress;
10155
+ this.http = new Http(this.apiEndpoint, this.restEndpoint, customFetch, defaultOptions);
10156
+ this.indexer = new Indexer({
10157
+ restEndpoint: this.restEndpoint,
10158
+ apiEndpoint: this.apiEndpoint,
10159
+ // Indexer GraphQL API
10160
+ registryAddress: this.registryAddress,
10161
+ http: this.http
10162
+ });
10163
+ this.saasApiClient = new MaciApiClient({
10164
+ baseUrl: this.saasApiEndpoint,
10165
+ apiKey: saasApiKey,
10166
+ customFetch
10167
+ });
10168
+ }
10169
+ /**
10170
+ * Set SaaS API key for MaciApiClient
10171
+ */
10172
+ setSaasApiKey(apiKey) {
10173
+ if (!this.saasApiClient) {
10174
+ throw new Error(
10175
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
10176
+ );
10177
+ }
10178
+ this.saasApiClient.setApiKey(apiKey);
10179
+ }
10180
+ /**
10181
+ * Get SaaS API client instance
10182
+ */
10183
+ getSaasApiClient() {
10184
+ if (!this.saasApiClient) {
10185
+ throw new Error(
10186
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
10187
+ );
10188
+ }
10189
+ return this.saasApiClient;
10190
+ }
10191
+ /**
10192
+ * else:
10193
+ * it will generate signer from the mnemonic with the given derivePathParams.
10194
+ * @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
10195
+ */
10196
+ getSigner(derivePathParams) {
10197
+ return this.accountManager.getKeyPair(derivePathParams);
10198
+ }
10199
+ packMaciPubkey(pubkey) {
10200
+ return packPubKey(pubkey || this.accountManager.currentPubkey.toPoints());
10201
+ }
10202
+ unpackMaciPubkey(pubkey) {
10203
+ return unpackPubKey(BigInt(pubkey));
10204
+ }
10205
+ getPubkey(derivePathParams) {
10206
+ return this.accountManager.getKeyPair(derivePathParams).getPublicKey();
10207
+ }
10208
+ buildVotePayload({
10209
+ stateIdx,
10210
+ operatorPubkey,
10211
+ selectedOptions,
10212
+ derivePathParams
10213
+ }) {
10214
+ const idxSet = /* @__PURE__ */ new Set();
10215
+ for (const option of selectedOptions) {
10216
+ if (idxSet.has(option.idx)) {
10217
+ throw new Error(`Duplicate option index (${option.idx}) is not allowed`);
10218
+ }
10219
+ idxSet.add(option.idx);
10220
+ }
10221
+ const options = selectedOptions.filter((o) => !!o.vc).sort((a, b) => a.idx - b.idx);
10222
+ const plan = options.map((o) => {
10223
+ return [o.idx, o.vc];
10224
+ });
10225
+ const payload = this.batchGenMessage(stateIdx, operatorPubkey, plan, derivePathParams);
10226
+ return stringizing(payload);
10227
+ }
10228
+ batchGenMessage(stateIdx, operatorPubkey, plan, derivePathParams) {
10229
+ const genMessage = this.genMessageFactory(stateIdx, operatorPubkey, derivePathParams);
10230
+ const payload = [];
10231
+ for (let i = plan.length - 1; i >= 0; i--) {
10232
+ const p = plan[i];
10233
+ const encAccount = genKeypair();
10234
+ const msg = genMessage(BigInt(encAccount.privKey), i + 1, p[0], p[1], i === plan.length - 1);
10235
+ payload.push({
10236
+ msg,
10237
+ encPubkeys: encAccount.pubKey
10238
+ });
10239
+ }
10240
+ return payload;
10241
+ }
10242
+ genMessageFactory(stateIdx, operatorPubkey, derivePathParams) {
10243
+ return (encPriKey, nonce, voIdx, newVotes, isLastCmd, salt) => {
10244
+ if (!salt) {
10245
+ salt = BigInt(`0x${import_crypto_js3.default.lib.WordArray.random(7).toString(import_crypto_js3.default.enc.Hex)}`);
10246
+ }
10247
+ const packaged = BigInt(nonce) + (BigInt(stateIdx) << 32n) + (BigInt(voIdx) << 64n) + (BigInt(newVotes) << 96n) + (BigInt(salt) << 192n);
10248
+ const signer = this.getSigner(derivePathParams);
10249
+ let newPubKey = [...signer.getPublicKey().toPoints()];
10250
+ if (isLastCmd) {
10251
+ newPubKey = [0n, 0n];
10252
+ }
10253
+ const hash = poseidon([packaged, ...newPubKey]);
10254
+ const signature = signer.sign(hash);
10255
+ const command = [packaged, ...newPubKey, ...signature.R8, signature.S];
10256
+ const coordPubkey = this.unpackMaciPubkey(operatorPubkey);
10257
+ const message = (0, import_poseidon_cipher3.poseidonEncrypt)(command, genEcdhSharedKey(encPriKey, coordPubkey), 0n);
10258
+ return message;
10259
+ };
10260
+ }
10261
+ async getStateIdxByPubKey({
10262
+ contractAddress,
10263
+ pubKey
10264
+ }) {
10265
+ const response = await this.indexer.getSignUpEventByPubKey(contractAddress, pubKey);
10266
+ if (isErrorResponse(response)) {
10267
+ return -1;
10268
+ }
10269
+ return response.data.signUpEvents[0].stateIdx;
10270
+ }
10271
+ async buildAddNewKeyPayload({
10272
+ stateTreeDepth,
10273
+ operatorPubkey,
10274
+ deactivates,
10275
+ wasmFile,
10276
+ zkeyFile,
10277
+ derivePathParams
10278
+ }) {
10279
+ const [coordPubkeyX, coordPubkeyY] = this.unpackMaciPubkey(operatorPubkey);
10280
+ const addKeyInput = await this.genAddKeyInput(stateTreeDepth + 2, {
10281
+ coordPubKey: [coordPubkeyX, coordPubkeyY],
10282
+ deactivates: deactivates.map((d) => d.map(BigInt)),
10283
+ derivePathParams
10284
+ });
10285
+ if (addKeyInput === null) {
10286
+ throw Error("genAddKeyInput failed");
10287
+ }
10288
+ const { proof } = await import_snarkjs.groth16.fullProve(addKeyInput, wasmFile, zkeyFile);
10289
+ const proofHex = await adaptToUncompressed(proof);
10290
+ return {
10291
+ proof: proofHex,
10292
+ d: [
10293
+ addKeyInput.d1[0].toString(),
10294
+ addKeyInput.d1[1].toString(),
10295
+ addKeyInput.d2[0].toString(),
10296
+ addKeyInput.d2[1].toString()
10297
+ ],
10298
+ nullifier: addKeyInput.nullifier.toString()
10299
+ };
10300
+ }
10301
+ async buildPreAddNewKeyPayload({
10302
+ stateTreeDepth,
10303
+ coordinatorPubkey,
10304
+ deactivates,
10305
+ wasmFile,
10306
+ zkeyFile,
10307
+ derivePathParams
10308
+ }) {
10309
+ const [coordPubkeyX, coordPubkeyY] = this.unpackMaciPubkey(coordinatorPubkey);
10310
+ const addKeyInput = await this.genPreAddKeyInput(stateTreeDepth + 2, {
10311
+ coordPubKey: [coordPubkeyX, coordPubkeyY],
10312
+ deactivates: deactivates.map((d) => d.map(BigInt)),
10313
+ derivePathParams
10314
+ });
10315
+ if (addKeyInput === null) {
10316
+ throw Error("genPreAddKeyInput failed, cannot find deactivate idx");
10317
+ }
10318
+ const { proof } = await import_snarkjs.groth16.fullProve(addKeyInput, wasmFile, zkeyFile);
10319
+ const proofHex = await adaptToUncompressed(proof);
10320
+ return {
10321
+ proof: proofHex,
10322
+ d: [
10323
+ addKeyInput.d1[0].toString(),
10324
+ addKeyInput.d1[1].toString(),
10325
+ addKeyInput.d2[0].toString(),
10326
+ addKeyInput.d2[1].toString()
10327
+ ],
10328
+ nullifier: addKeyInput.nullifier.toString()
10329
+ };
10330
+ }
10331
+ async genAddKeyInput(depth, {
10332
+ coordPubKey,
10333
+ deactivates,
10334
+ derivePathParams
10335
+ }) {
10336
+ const signer = this.getSigner(derivePathParams);
10337
+ const sharedKeyHash = poseidon(signer.genEcdhSharedKey(coordPubKey));
10338
+ const randomVal = genRandomSalt();
10339
+ const deactivateIdx = deactivates.findIndex((d) => d[4] === sharedKeyHash);
10340
+ if (deactivateIdx < 0) {
10341
+ return null;
10342
+ }
10343
+ const deactivateLeaf = deactivates[deactivateIdx];
10344
+ const c1 = [deactivateLeaf[0], deactivateLeaf[1]];
10345
+ const c2 = [deactivateLeaf[2], deactivateLeaf[3]];
10346
+ const { d1, d2 } = rerandomize(coordPubKey, { c1, c2 }, randomVal);
10347
+ const nullifier = poseidon([signer.getFormatedPrivKey(), 1444992409218394441042n]);
10348
+ const tree = new Tree(5, depth, 0n);
10349
+ const leaves = deactivates.map((d) => poseidon(d));
10350
+ tree.initLeaves(leaves);
10351
+ const deactivateRoot = tree.root;
10352
+ const deactivateLeafPathElements = tree.pathElementOf(deactivateIdx);
10353
+ const inputHash = BigInt(
10354
+ (0, import_ethers4.solidityPackedSha256)(
10355
+ new Array(7).fill("uint256"),
10356
+ stringizing([
10357
+ deactivateRoot,
10358
+ poseidon(coordPubKey),
10359
+ nullifier,
10360
+ d1[0],
10361
+ d1[1],
10362
+ d2[0],
10363
+ d2[1]
10364
+ ])
10365
+ )
10366
+ ) % SNARK_FIELD_SIZE;
10367
+ const input = {
10368
+ inputHash,
10369
+ coordPubKey,
10370
+ deactivateRoot,
10371
+ deactivateIndex: deactivateIdx,
10372
+ deactivateLeaf: poseidon(deactivateLeaf),
10373
+ c1,
10374
+ c2,
10375
+ randomVal,
10376
+ d1,
10377
+ d2,
10378
+ deactivateLeafPathElements,
10379
+ nullifier,
10380
+ oldPrivateKey: signer.getFormatedPrivKey()
10381
+ };
10382
+ return input;
10383
+ }
10384
+ async genPreAddKeyInput(depth, {
10385
+ coordPubKey,
10386
+ deactivates,
10387
+ derivePathParams
10388
+ }) {
10389
+ const signer = this.getSigner(derivePathParams);
10390
+ const sharedKeyHash = poseidon(signer.genEcdhSharedKey(coordPubKey));
10391
+ const randomVal = genRandomSalt();
10392
+ const deactivateIdx = deactivates.findIndex((d) => d[4] === sharedKeyHash);
10393
+ if (deactivateIdx < 0) {
10394
+ return null;
10395
+ }
10396
+ const deactivateLeaf = deactivates[deactivateIdx];
10397
+ const c1 = [deactivateLeaf[0], deactivateLeaf[1]];
10398
+ const c2 = [deactivateLeaf[2], deactivateLeaf[3]];
10399
+ const { d1, d2 } = rerandomize(coordPubKey, { c1, c2 }, randomVal);
10400
+ const nullifier = poseidon([signer.getFormatedPrivKey(), 1444992409218394441042n]);
10401
+ const tree = new Tree(5, depth, 0n);
10402
+ const leaves = deactivates.map((d) => poseidon(d));
10403
+ tree.initLeaves(leaves);
10404
+ const deactivateRoot = tree.root;
10405
+ const deactivateLeafPathElements = tree.pathElementOf(deactivateIdx);
10406
+ const inputHash = BigInt(
10407
+ (0, import_ethers4.solidityPackedSha256)(
10408
+ new Array(7).fill("uint256"),
10409
+ stringizing([
10410
+ deactivateRoot,
10411
+ poseidon(coordPubKey),
10412
+ nullifier,
10413
+ d1[0],
10414
+ d1[1],
10415
+ d2[0],
10416
+ d2[1]
10417
+ ])
10418
+ )
10419
+ ) % SNARK_FIELD_SIZE;
10420
+ const input = {
10421
+ inputHash,
10422
+ coordPubKey,
10423
+ deactivateRoot,
10424
+ deactivateIndex: deactivateIdx,
10425
+ deactivateLeaf: poseidon(deactivateLeaf),
10426
+ c1,
10427
+ c2,
10428
+ randomVal,
10429
+ d1,
10430
+ d2,
10431
+ deactivateLeafPathElements,
10432
+ nullifier,
10433
+ oldPrivateKey: signer.getFormatedPrivKey()
10434
+ };
10435
+ return input;
10436
+ }
10437
+ async buildDeactivatePayload({
10438
+ stateIdx,
10439
+ operatorPubkey,
10440
+ derivePathParams
10441
+ }) {
10442
+ const payload = this.batchGenMessage(stateIdx, operatorPubkey, [[0, 0]], derivePathParams);
10443
+ return stringizing(payload[0]);
10444
+ }
10445
+ // ==================== SaaS API Client Methods ====================
10446
+ /**
10447
+ * Get pre-deactivate data via SaaS API
10448
+ * @param contractAddress - Contract address
10449
+ */
10450
+ async saasGetPreDeactivate(contractAddress) {
10451
+ if (!this.saasApiClient) {
10452
+ throw new Error("SaaS API client not initialized");
10453
+ }
10454
+ return await this.saasApiClient.getPreDeactivate({ contractAddress });
10455
+ }
10456
+ /**
10457
+ * Pre add new key via SaaS API
10458
+ * @param params - Pre add new key parameters
10459
+ */
10460
+ async saasSubmitPreAddNewKey(params) {
10461
+ if (!this.saasApiClient) {
10462
+ throw new Error("SaaS API client not initialized");
10463
+ }
10464
+ return await this.saasApiClient.preAddNewKey(params);
10465
+ }
10466
+ /**
10467
+ * Vote via SaaS API
10468
+ * @param params - Vote parameters
10469
+ */
10470
+ async saasSubmitVote(params) {
10471
+ if (!this.saasApiClient) {
10472
+ throw new Error("SaaS API client not initialized");
10473
+ }
10474
+ return await this.saasApiClient.vote(params);
10475
+ }
10476
+ // ==================== Maci Voter Methods ====================
10477
+ async saasPreCreateNewAccount({
10478
+ contractAddress,
10479
+ stateTreeDepth,
10480
+ coordinatorPubkey,
10481
+ deactivates,
10482
+ wasmFile,
10483
+ zkeyFile,
10484
+ derivePathParams
10485
+ }) {
10486
+ const addNewKeyPayload = await this.buildPreAddNewKeyPayload({
10487
+ stateTreeDepth,
10488
+ coordinatorPubkey,
10489
+ deactivates,
10490
+ wasmFile,
10491
+ zkeyFile,
10492
+ derivePathParams
10493
+ });
10494
+ const newVoterClient = new _VoterClient({
10495
+ network: this.network,
10496
+ restEndpoint: this.restEndpoint,
10497
+ apiEndpoint: this.apiEndpoint,
10498
+ saasApiEndpoint: this.saasApiEndpoint,
10499
+ registryAddress: this.registryAddress
10500
+ });
10501
+ const addNewKeyResult = await newVoterClient.saasSubmitPreAddNewKey({
10502
+ contractAddress,
10503
+ proof: addNewKeyPayload.proof,
10504
+ d: addNewKeyPayload.d,
10505
+ nullifier: addNewKeyPayload.nullifier,
10506
+ newPubkey: newVoterClient.getPubkey().toPoints().map((p) => p.toString())
10507
+ });
10508
+ return {
10509
+ result: addNewKeyResult,
10510
+ account: newVoterClient
10511
+ };
10512
+ }
10513
+ async saasVote({
10514
+ contractAddress,
10515
+ // stateIdx,
10516
+ operatorPubkey,
10517
+ selectedOptions,
10518
+ derivePathParams
10519
+ }) {
10520
+ const stateIdx = await this.getStateIdxByPubKey({
10521
+ contractAddress,
10522
+ pubKey: this.getPubkey(derivePathParams).toPoints()
10523
+ });
10524
+ if (stateIdx === -1) {
10525
+ throw new Error("State index is not set, Please signup or addNewKey first");
10526
+ }
10527
+ const payload = this.buildVotePayload({
10528
+ stateIdx,
10529
+ operatorPubkey,
10530
+ selectedOptions,
10531
+ derivePathParams
10532
+ });
10533
+ const voteResult = await this.saasSubmitVote({
10534
+ contractAddress,
10535
+ payload
10536
+ });
10537
+ return voteResult;
10538
+ }
9144
10539
  };
9145
10540
  // Annotate the CommonJS export names for ESM import in node:
9146
10541
  0 && (module.exports = {
9147
10542
  Circuit,
10543
+ EdDSAPoseidonKeypair,
10544
+ EdDSAPoseidonPublicKey,
9148
10545
  G1Point,
9149
10546
  G2Point,
9150
10547
  Http,
10548
+ MaciApiClient,
9151
10549
  MaciCertSystemType,
9152
10550
  MaciCircuitType,
9153
10551
  MaciClient,
@@ -9161,12 +10559,23 @@ var MaciClient2 = class {
9161
10559
  Transaction,
9162
10560
  Tree,
9163
10561
  UserAccount,
10562
+ VoterClient,
10563
+ adaptToUncompressed,
10564
+ addressToUint256,
9164
10565
  batchGenMessage,
9165
10566
  bigInt2Buffer,
10567
+ bigintToHex,
9166
10568
  buffer2Bigint,
9167
10569
  circuits,
10570
+ compressPublicKey,
10571
+ decompressPublicKey,
9168
10572
  destringizing,
10573
+ encryptOdevity,
9169
10574
  formatPrivKeyForBabyJub,
10575
+ fromB64,
10576
+ fromBase64,
10577
+ fromHEX,
10578
+ fromHex,
9170
10579
  genAddKeyInput,
9171
10580
  genEcdhSharedKey,
9172
10581
  genKeypair,
@@ -9179,6 +10588,9 @@ var MaciClient2 = class {
9179
10588
  genRandomKey,
9180
10589
  genRandomSalt,
9181
10590
  getAMaciRoundCircuitFee,
10591
+ getCurveFromName,
10592
+ getCurveFromQ,
10593
+ getCurveFromR,
9182
10594
  getDefaultParams,
9183
10595
  hash12,
9184
10596
  hash2,
@@ -9189,6 +10601,8 @@ var MaciClient2 = class {
9189
10601
  hashLeftRight,
9190
10602
  hashN,
9191
10603
  hashOne,
10604
+ hexToBigInt,
10605
+ hexToDecimalString,
9192
10606
  isValidAddress,
9193
10607
  packPubKey,
9194
10608
  poseidon,
@@ -9197,9 +10611,15 @@ var MaciClient2 = class {
9197
10611
  poseidonT5,
9198
10612
  poseidonT6,
9199
10613
  privateKeyFromTxt,
10614
+ rerandomize,
9200
10615
  sha256Hash,
9201
10616
  signMessage,
9202
10617
  stringizing,
10618
+ toB64,
10619
+ toBase64,
10620
+ toHEX,
10621
+ toHex,
10622
+ transformPubkey,
9203
10623
  unpackPubKey
9204
10624
  });
9205
10625
  //# sourceMappingURL=index.js.map