@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.mjs CHANGED
@@ -335,6 +335,7 @@ function getDefaultParams(network = "mainnet") {
335
335
  rpcEndpoint: "https://vota-rpc.dorafactory.org",
336
336
  restEndpoint: "https://vota-rest.dorafactory.org",
337
337
  apiEndpoint: "https://vota-api.dorafactory.org",
338
+ saasApiEndpoint: "https://vota-maci-api.dorafactory.org",
338
339
  certificateApiEndpoint: "https://vota-certificate-api.dorafactory.org/api/v1",
339
340
  registryAddress: "dora1smg5qp5trjdkcekdjssqpjehdjf6n4cjss0clyvqcud3t3u3948s8rmgg4",
340
341
  saasAddress: "dora1ksxvvve2nsw5uyvg7y6lnnxcqxadjepc78z0qa8enm5zhayxaqgqpsewf8",
@@ -354,6 +355,7 @@ function getDefaultParams(network = "mainnet") {
354
355
  rpcEndpoint: "https://vota-testnet-rpc.dorafactory.org",
355
356
  restEndpoint: "https://vota-testnet-rest.dorafactory.org",
356
357
  apiEndpoint: "https://vota-testnet-api.dorafactory.org",
358
+ saasApiEndpoint: "https://vota-testnet-maci-api.dorafactory.org",
357
359
  certificateApiEndpoint: "https://vota-testnet-certificate-api.dorafactory.org/api/v1",
358
360
  registryAddress: "dora13c8aecstyxrhax9znvvh5zey89edrmd2k5va57pxvpe3fxtfsfeqlhsjnd",
359
361
  saasAddress: "dora1dgnszrwnwxgr5djprrr6w4q45z8s3ghsew869g6tlp4ruqah39nqnemjya",
@@ -444,8 +446,62 @@ var Circuit = class {
444
446
  }
445
447
  };
446
448
 
447
- // src/utils/index.ts
448
- import { decode } from "bech32";
449
+ // src/utils/base64.ts
450
+ function fromBase64(base64String) {
451
+ return Uint8Array.from(atob(base64String), (char) => char.charCodeAt(0));
452
+ }
453
+ var CHUNK_SIZE = 8192;
454
+ function toBase64(bytes) {
455
+ if (bytes.length < CHUNK_SIZE) {
456
+ return btoa(String.fromCharCode(...bytes));
457
+ }
458
+ let output = "";
459
+ for (var i = 0; i < bytes.length; i += CHUNK_SIZE) {
460
+ const chunk = bytes.slice(i, i + CHUNK_SIZE);
461
+ output += String.fromCharCode(...chunk);
462
+ }
463
+ return btoa(output);
464
+ }
465
+ var toB64 = toBase64;
466
+ var fromB64 = fromBase64;
467
+
468
+ // src/utils/hex.ts
469
+ function fromHex(hexStr) {
470
+ const normalized = hexStr.startsWith("0x") ? hexStr.slice(2) : hexStr;
471
+ const padded = normalized.length % 2 === 0 ? normalized : `0${normalized}}`;
472
+ const intArr = padded.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) ?? [];
473
+ return Uint8Array.from(intArr);
474
+ }
475
+ function toHex(bytes) {
476
+ return bytes.reduce(
477
+ (str, byte) => str + byte.toString(16).padStart(2, "0"),
478
+ ""
479
+ );
480
+ }
481
+ var toHEX = toHex;
482
+ var fromHEX = fromHex;
483
+
484
+ // src/utils/decode-address.ts
485
+ import { sha256 } from "@noble/hashes/sha256";
486
+ function addressToUint256(address) {
487
+ const addressBytes = new TextEncoder().encode(address);
488
+ const hashResult = sha256(addressBytes);
489
+ const uint256Bytes = new Uint8Array(32);
490
+ for (let i = 0; i < hashResult.length && i < 32; i++) {
491
+ uint256Bytes[31 - i] = hashResult[i];
492
+ }
493
+ let result = 0n;
494
+ for (let i = 0; i < uint256Bytes.length; i++) {
495
+ result = (result << 8n) + BigInt(uint256Bytes[i]);
496
+ }
497
+ return result;
498
+ }
499
+ function bigintToHex(value) {
500
+ return "0x" + value.toString(16).padStart(64, "0");
501
+ }
502
+
503
+ // src/utils/validate-address.ts
504
+ import { bech32 } from "bech32";
449
505
 
450
506
  // src/libs/crypto/keys.ts
451
507
  import CryptoJS2 from "crypto-js";
@@ -501,11 +557,7 @@ var destringizing = (o, path = []) => {
501
557
  // src/libs/crypto/keys.ts
502
558
  import { poseidonEncrypt } from "@zk-kit/poseidon-cipher";
503
559
  import * as BabyJub from "@zk-kit/baby-jubjub";
504
- import {
505
- derivePublicKey,
506
- signMessage,
507
- deriveSecretScalar
508
- } from "@zk-kit/eddsa-poseidon";
560
+ import { derivePublicKey, signMessage, deriveSecretScalar } from "@zk-kit/eddsa-poseidon";
509
561
  import { solidityPackedSha256 as solidityPackedSha2562 } from "ethers";
510
562
  import { mulPointEscalar as mulPointEscalar2 } from "@zk-kit/baby-jubjub";
511
563
  import { packPublicKey, unpackPublicKey } from "@zk-kit/eddsa-poseidon";
@@ -522,9 +574,7 @@ import assert from "assert";
522
574
  var SNARK_FIELD_SIZE = r;
523
575
  var NOTHING_UP_MY_SLEEVE = BigInt(keccak256(toUtf8Bytes("Maci"))) % SNARK_FIELD_SIZE;
524
576
  assert(
525
- NOTHING_UP_MY_SLEEVE === BigInt(
526
- "8370432830353022751713833565135785980866757267633941821328460903436894336785"
527
- )
577
+ NOTHING_UP_MY_SLEEVE === BigInt("8370432830353022751713833565135785980866757267633941821328460903436894336785")
528
578
  );
529
579
  var PAD_KEY_HASH = BigInt(
530
580
  "1309255631273308531193241901289907343161346846555918942743921933037802809814"
@@ -742,9 +792,7 @@ var Tree = class _Tree {
742
792
  while (idx > 0) {
743
793
  const parentIdx = Math.floor((idx - 1) / this.DEGREE);
744
794
  const childrenIdx0 = parentIdx * this.DEGREE + 1;
745
- this.nodes[parentIdx] = poseidon(
746
- this.nodes.slice(childrenIdx0, childrenIdx0 + 5)
747
- );
795
+ this.nodes[parentIdx] = poseidon(this.nodes.slice(childrenIdx0, childrenIdx0 + 5));
748
796
  idx = parentIdx;
749
797
  }
750
798
  }
@@ -830,9 +878,7 @@ var genRandomBabyJubValue = () => {
830
878
  const min = 6350874878119819312338956282401532410528162663560392320966563075034087161851n;
831
879
  let rand;
832
880
  while (true) {
833
- rand = BigInt(
834
- `0x${CryptoJS.lib.WordArray.random(32).toString(CryptoJS.enc.Hex)}`
835
- );
881
+ rand = BigInt(`0x${CryptoJS.lib.WordArray.random(32).toString(CryptoJS.enc.Hex)}`);
836
882
  if (rand >= min) {
837
883
  break;
838
884
  }
@@ -865,9 +911,7 @@ var genKeypair = (pkey) => {
865
911
  var genEcdhSharedKey = (privKey, pubKey) => mulPointEscalar2(pubKey, formatPrivKeyForBabyJub(privKey));
866
912
  var genMessageFactory = (stateIdx, signPriKey, signPubKey, coordPubKey) => (encPriKey, nonce, voIdx, newVotes, isLastCmd, salt) => {
867
913
  if (!salt) {
868
- salt = BigInt(
869
- `0x${CryptoJS2.lib.WordArray.random(7).toString(CryptoJS2.enc.Hex)}`
870
- );
914
+ salt = BigInt(`0x${CryptoJS2.lib.WordArray.random(7).toString(CryptoJS2.enc.Hex)}`);
871
915
  }
872
916
  const packaged = BigInt(nonce) + (BigInt(stateIdx) << 32n) + (BigInt(voIdx) << 64n) + (BigInt(newVotes) << 96n) + (BigInt(salt) << 192n);
873
917
  let newPubKey = [...signPubKey];
@@ -877,11 +921,7 @@ var genMessageFactory = (stateIdx, signPriKey, signPubKey, coordPubKey) => (encP
877
921
  const hash = poseidon([packaged, ...newPubKey]);
878
922
  const signature = signMessage(bigInt2Buffer(signPriKey), hash);
879
923
  const command = [packaged, ...newPubKey, ...signature.R8, signature.S];
880
- const message = poseidonEncrypt(
881
- command,
882
- genEcdhSharedKey(encPriKey, coordPubKey),
883
- 0n
884
- );
924
+ const message = poseidonEncrypt(command, genEcdhSharedKey(encPriKey, coordPubKey), 0n);
885
925
  return message;
886
926
  };
887
927
  var batchGenMessage = (stateIdx, keypair, coordPubKey, plan) => {
@@ -895,13 +935,7 @@ var batchGenMessage = (stateIdx, keypair, coordPubKey, plan) => {
895
935
  for (let i = plan.length - 1; i >= 0; i--) {
896
936
  const p = plan[i];
897
937
  const encAccount = genKeypair();
898
- const msg = genMessage(
899
- BigInt(encAccount.privKey),
900
- i + 1,
901
- p[0],
902
- p[1],
903
- i === plan.length - 1
904
- );
938
+ const msg = genMessage(BigInt(encAccount.privKey), i + 1, p[0], p[1], i === plan.length - 1);
905
939
  payload.push({
906
940
  msg,
907
941
  encPubkeys: encAccount.pubKey
@@ -953,10 +987,7 @@ var genAddKeyInput = (depth, {
953
987
  const c1 = [deactivateLeaf[0], deactivateLeaf[1]];
954
988
  const c2 = [deactivateLeaf[2], deactivateLeaf[3]];
955
989
  const { d1, d2 } = rerandomize(coordPubKey, { c1, c2 }, randomVal);
956
- const nullifier = poseidon([
957
- BigInt(oldKey.formatedPrivKey),
958
- 1444992409218394441042n
959
- ]);
990
+ const nullifier = poseidon([BigInt(oldKey.formatedPrivKey), 1444992409218394441042n]);
960
991
  const tree = new Tree(5, depth, 0n);
961
992
  const leaves = deactivates.map((d) => poseidon(d));
962
993
  tree.initLeaves(leaves);
@@ -1003,19 +1034,12 @@ function randomUint256() {
1003
1034
  return buffer.join("");
1004
1035
  }
1005
1036
  var genRandomKey = () => {
1006
- const key = [
1007
- randomUint256(),
1008
- randomUint256(),
1009
- randomUint256(),
1010
- randomUint256()
1011
- ].join("");
1037
+ const key = [randomUint256(), randomUint256(), randomUint256(), randomUint256()].join("");
1012
1038
  return ["-----BEGIN MACI KEY-----", key, "-----END MACI KEY-----"].join("\n");
1013
1039
  };
1014
1040
 
1015
1041
  // src/libs/crypto/sign.ts
1016
- import {
1017
- isOfflineDirectSigner
1018
- } from "@cosmjs/proto-signing";
1042
+ import { isOfflineDirectSigner } from "@cosmjs/proto-signing";
1019
1043
  async function signMessage2(signer, address, message, network) {
1020
1044
  const accounts = await signer.getAccounts();
1021
1045
  const account = accounts.find((acc) => acc.address === address);
@@ -1066,19 +1090,127 @@ async function genKeypairFromSign({
1066
1090
  if (!address) {
1067
1091
  [{ address }] = await signer.getAccounts();
1068
1092
  }
1069
- const sig = await signMessage2(
1070
- signer,
1071
- address,
1072
- "Generate_MACI_Private_Key",
1073
- network
1074
- );
1093
+ const sig = await signMessage2(signer, address, "Generate_MACI_Private_Key", network);
1075
1094
  return genKeypairFromSignature(sig.signature);
1076
1095
  }
1077
1096
 
1078
- // src/utils/index.ts
1097
+ // src/libs/crypto/curve.ts
1098
+ import { Scalar, buildBn128, buildBls12381 } from "ffjavascript";
1099
+ var bls12381r = Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16);
1100
+ var bn128r = Scalar.e(
1101
+ "21888242871839275222246405745257275088548364400416034343698204186575808495617"
1102
+ );
1103
+ var bls12381q = Scalar.e(
1104
+ "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
1105
+ 16
1106
+ );
1107
+ var bn128q = Scalar.e(
1108
+ "21888242871839275222246405745257275088696311157297823662689037894645226208583"
1109
+ );
1110
+ async function getCurveFromR(r2) {
1111
+ let curve;
1112
+ if (Scalar.eq(r2, bn128r)) {
1113
+ curve = await buildBn128();
1114
+ } else if (Scalar.eq(r2, bls12381r)) {
1115
+ curve = await buildBls12381();
1116
+ } else {
1117
+ throw new Error(`Curve not supported: ${Scalar.toString(r2)}`);
1118
+ }
1119
+ return curve;
1120
+ }
1121
+ async function getCurveFromQ(q) {
1122
+ let curve;
1123
+ if (Scalar.eq(q, bn128q)) {
1124
+ curve = await buildBn128();
1125
+ } else if (Scalar.eq(q, bls12381q)) {
1126
+ curve = await buildBls12381();
1127
+ } else {
1128
+ throw new Error(`Curve not supported: ${Scalar.toString(q)}`);
1129
+ }
1130
+ return curve;
1131
+ }
1132
+ async function getCurveFromName(name) {
1133
+ let curve;
1134
+ const normName = normalizeName(name);
1135
+ if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
1136
+ curve = await buildBn128();
1137
+ } else if (["BLS12381"].indexOf(normName) >= 0) {
1138
+ curve = await buildBls12381();
1139
+ } else {
1140
+ throw new Error(`Curve not supported: ${name}`);
1141
+ }
1142
+ return curve;
1143
+ function normalizeName(n) {
1144
+ return (n.toUpperCase().match(/[A-Za-z0-9]+/g) || []).join("");
1145
+ }
1146
+ }
1147
+
1148
+ // src/libs/crypto/adapter.ts
1149
+ import { utils } from "ffjavascript";
1150
+ var { unstringifyBigInts } = utils;
1151
+ var Bytes2Str = (arr) => {
1152
+ let str = "";
1153
+ for (let i = 0; i < arr.length; i++) {
1154
+ let tmp = arr[i].toString(16);
1155
+ if (tmp.length == 1) {
1156
+ tmp = "0" + tmp;
1157
+ }
1158
+ str += tmp;
1159
+ }
1160
+ return str;
1161
+ };
1162
+ var BN128Curve = null;
1163
+ var adaptToUncompressed = async (proof) => {
1164
+ const p = unstringifyBigInts(proof);
1165
+ let curve = BN128Curve;
1166
+ if (!curve) {
1167
+ BN128Curve = await getCurveFromName("BN128");
1168
+ curve = BN128Curve;
1169
+ }
1170
+ const pi_a = curve.G1.toUncompressed(curve.G1.fromObject(p.pi_a));
1171
+ const pi_b = curve.G2.toUncompressed(curve.G2.fromObject(p.pi_b));
1172
+ const pi_c = curve.G1.toUncompressed(curve.G1.fromObject(p.pi_c));
1173
+ return {
1174
+ a: Bytes2Str(Array.from(pi_a)),
1175
+ b: Bytes2Str(Array.from(pi_b)),
1176
+ c: Bytes2Str(Array.from(pi_c))
1177
+ };
1178
+ };
1179
+
1180
+ // src/libs/crypto/rerandomize.ts
1181
+ import * as BabyJub2 from "@zk-kit/baby-jubjub";
1182
+ var F = BabyJub2.Fr;
1183
+ var encodeToMessage = (original, randomKey = genKeypair()) => {
1184
+ const xIncrement = F.e(F.sub(randomKey.pubKey[0], original));
1185
+ return {
1186
+ point: {
1187
+ x: randomKey.pubKey[0],
1188
+ y: randomKey.pubKey[1]
1189
+ },
1190
+ xIncrement
1191
+ };
1192
+ };
1193
+ var encryptOdevity = (isOdd, pubKey, randomVal = genRandomBabyJubValue()) => {
1194
+ let i = 0n;
1195
+ let message = encodeToMessage(123n, genKeypair(randomVal + i));
1196
+ while (message.point.x % 2n === 1n !== isOdd) {
1197
+ i++;
1198
+ message = encodeToMessage(123n, genKeypair(randomVal + i));
1199
+ }
1200
+ const c1Point = BabyJub2.mulPointEscalar(BabyJub2.Base8, randomVal);
1201
+ const pky = BabyJub2.mulPointEscalar(pubKey, randomVal);
1202
+ const c2Point = BabyJub2.addPoint([message.point.x, message.point.y], pky);
1203
+ return {
1204
+ c1: { x: c1Point[0], y: c1Point[1] },
1205
+ c2: { x: c2Point[0], y: c2Point[1] },
1206
+ xIncrement: message.xIncrement
1207
+ };
1208
+ };
1209
+
1210
+ // src/utils/validate-address.ts
1079
1211
  function verifyIsBech32(address) {
1080
1212
  try {
1081
- decode(address);
1213
+ bech32.decode(address);
1082
1214
  } catch (error) {
1083
1215
  return error instanceof Error ? error : new Error("Unknown error");
1084
1216
  }
@@ -1087,6 +1219,46 @@ function verifyIsBech32(address) {
1087
1219
  function isValidAddress(address) {
1088
1220
  return address.startsWith("dora") && verifyIsBech32(address) === void 0;
1089
1221
  }
1222
+ function hexToDecimalString(hexString) {
1223
+ const decimalString = BigInt("0x" + hexString).toString(10);
1224
+ return decimalString;
1225
+ }
1226
+ function hexToBigInt(hexString) {
1227
+ return BigInt("0x" + hexString);
1228
+ }
1229
+ function padWithZerosIfNeeded(inputString) {
1230
+ if (inputString.length === 64) {
1231
+ return inputString;
1232
+ } else if (inputString.length < 64) {
1233
+ const zerosToAdd = 64 - inputString.length;
1234
+ const zeroPadding = "0".repeat(zerosToAdd);
1235
+ return zeroPadding + inputString;
1236
+ }
1237
+ throw new Error("Invalid input string length");
1238
+ }
1239
+ function decompressPublicKey(compressedPubkey) {
1240
+ const x = compressedPubkey.slice(0, 64);
1241
+ const y = compressedPubkey.slice(64);
1242
+ return {
1243
+ x: hexToDecimalString(x),
1244
+ y: hexToDecimalString(y)
1245
+ };
1246
+ }
1247
+ function compressPublicKey(decompressedPubkey) {
1248
+ const x = decompressedPubkey[0];
1249
+ const y = decompressedPubkey[1];
1250
+ const compressedPubkey = padWithZerosIfNeeded(x.toString(16)) + padWithZerosIfNeeded(y.toString(16));
1251
+ return compressedPubkey;
1252
+ }
1253
+ function transformPubkey(oldPubkey) {
1254
+ const x = oldPubkey.slice(0, 64);
1255
+ const y = oldPubkey.slice(64);
1256
+ const pubkey = [hexToBigInt(x), hexToBigInt(y)];
1257
+ console.log(pubkey);
1258
+ console.log([hexToDecimalString(x), hexToDecimalString(y)]);
1259
+ const packedPubkey = packPubKey(pubkey);
1260
+ return packedPubkey;
1261
+ }
1090
1262
 
1091
1263
  // src/libs/query/operator.ts
1092
1264
  var Operator = class {
@@ -8476,6 +8648,257 @@ var MACI = class {
8476
8648
  }
8477
8649
  };
8478
8650
 
8651
+ // src/libs/api/client.ts
8652
+ var MaciApiClient = class {
8653
+ constructor(config) {
8654
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
8655
+ this.apiKey = config.apiKey;
8656
+ this.customFetch = config.customFetch || fetch;
8657
+ this.timeout = config.timeout || 12e4;
8658
+ this.apiKeyHeader = config.apiKeyHeader || "x-api-key";
8659
+ }
8660
+ /**
8661
+ * Update API key
8662
+ */
8663
+ setApiKey(apiKey) {
8664
+ this.apiKey = apiKey;
8665
+ }
8666
+ /**
8667
+ * Update base URL
8668
+ */
8669
+ setBaseUrl(baseUrl) {
8670
+ this.baseUrl = baseUrl.replace(/\/$/, "");
8671
+ }
8672
+ /**
8673
+ * Internal fetch method with timeout and error handling
8674
+ */
8675
+ async fetch(path, options) {
8676
+ const controller = new AbortController();
8677
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8678
+ try {
8679
+ const headers = {
8680
+ "Content-Type": "application/json"
8681
+ };
8682
+ if (options?.headers) {
8683
+ Object.assign(headers, options.headers);
8684
+ }
8685
+ if (this.apiKey) {
8686
+ if (this.apiKeyHeader === "x-api-key") {
8687
+ headers["x-api-key"] = this.apiKey;
8688
+ } else {
8689
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
8690
+ }
8691
+ }
8692
+ const response = await this.customFetch(`${this.baseUrl}${path}`, {
8693
+ ...options,
8694
+ headers,
8695
+ signal: controller.signal
8696
+ });
8697
+ clearTimeout(timeoutId);
8698
+ if (!response.ok) {
8699
+ const errorData = await response.json().catch(() => ({}));
8700
+ throw new HttpError(
8701
+ errorData.error || `HTTP error! status: ${response.status}`,
8702
+ response.status
8703
+ );
8704
+ }
8705
+ if (response.status === 204) {
8706
+ return null;
8707
+ }
8708
+ return await response.json();
8709
+ } catch (error) {
8710
+ clearTimeout(timeoutId);
8711
+ if (error instanceof HttpError) {
8712
+ throw error;
8713
+ }
8714
+ if (error.name === "AbortError") {
8715
+ throw new HttpError("Request timeout", 408);
8716
+ }
8717
+ throw new HttpError(`Failed to fetch: ${error.message}`, 500);
8718
+ }
8719
+ }
8720
+ /**
8721
+ * Health check
8722
+ */
8723
+ async health() {
8724
+ return this.fetch("/health", { method: "GET" });
8725
+ }
8726
+ // ==================== Admin APIs ====================
8727
+ /**
8728
+ * Create API key (Admin)
8729
+ */
8730
+ async createApiKey(data) {
8731
+ return this.fetch("/admin/keys", {
8732
+ method: "POST",
8733
+ body: JSON.stringify(data)
8734
+ });
8735
+ }
8736
+ /**
8737
+ * Create tenant (Admin)
8738
+ */
8739
+ async createTenant(data) {
8740
+ return this.fetch("/admin/tenants", {
8741
+ method: "POST",
8742
+ body: JSON.stringify(data)
8743
+ });
8744
+ }
8745
+ // ==================== Usage API ====================
8746
+ /**
8747
+ * Get usage for current API key
8748
+ */
8749
+ async getUsage(params) {
8750
+ const queryString = params ? "?" + new URLSearchParams(params).toString() : "";
8751
+ return this.fetch(`/v1/usage${queryString}`, { method: "GET" });
8752
+ }
8753
+ // ==================== Core MACI APIs ====================
8754
+ /**
8755
+ * Signup
8756
+ */
8757
+ async signup(data) {
8758
+ return this.fetch("/v1/signup", {
8759
+ method: "POST",
8760
+ body: JSON.stringify(data)
8761
+ });
8762
+ }
8763
+ /**
8764
+ * Vote
8765
+ */
8766
+ async vote(data) {
8767
+ return this.fetch("/v1/vote", {
8768
+ method: "POST",
8769
+ body: JSON.stringify(data)
8770
+ });
8771
+ }
8772
+ /**
8773
+ * Create Round
8774
+ */
8775
+ async createRound(data) {
8776
+ return this.fetch("/v1/create-round", {
8777
+ method: "POST",
8778
+ body: JSON.stringify(data)
8779
+ });
8780
+ }
8781
+ /**
8782
+ * Create AMaci Round
8783
+ */
8784
+ async createAmaciRound(data) {
8785
+ return this.fetch("/v1/create-amaci-round", {
8786
+ method: "POST",
8787
+ body: JSON.stringify(data)
8788
+ });
8789
+ }
8790
+ /**
8791
+ * Set Round Info
8792
+ */
8793
+ async setRoundInfo(data) {
8794
+ return this.fetch("/v1/set-round-info", {
8795
+ method: "POST",
8796
+ body: JSON.stringify(data)
8797
+ });
8798
+ }
8799
+ /**
8800
+ * Set Vote Options
8801
+ */
8802
+ async setVoteOptions(data) {
8803
+ return this.fetch("/v1/set-vote-options", {
8804
+ method: "POST",
8805
+ body: JSON.stringify(data)
8806
+ });
8807
+ }
8808
+ /**
8809
+ * Deactivate
8810
+ */
8811
+ async deactivate(data) {
8812
+ return this.fetch("/v1/deactivate", {
8813
+ method: "POST",
8814
+ body: JSON.stringify(data)
8815
+ });
8816
+ }
8817
+ /**
8818
+ * Add New Key
8819
+ */
8820
+ async addNewKey(data) {
8821
+ return this.fetch("/v1/add-new-key", {
8822
+ method: "POST",
8823
+ body: JSON.stringify(data)
8824
+ });
8825
+ }
8826
+ /**
8827
+ * Pre Add New Key
8828
+ */
8829
+ async preAddNewKey(data) {
8830
+ return this.fetch("/v1/pre-add-new-key", {
8831
+ method: "POST",
8832
+ body: JSON.stringify(data)
8833
+ });
8834
+ }
8835
+ // ==================== Allowlist APIs ====================
8836
+ /**
8837
+ * Get allowlist list
8838
+ */
8839
+ async getAllowlists(params) {
8840
+ const queryString = params ? "?" + new URLSearchParams(params).toString() : "";
8841
+ return this.fetch(`/v1/allowlists/${queryString}`, { method: "GET" });
8842
+ }
8843
+ /**
8844
+ * Create allowlist
8845
+ */
8846
+ async createAllowlist(data) {
8847
+ return this.fetch("/v1/allowlists/", {
8848
+ method: "POST",
8849
+ body: JSON.stringify(data)
8850
+ });
8851
+ }
8852
+ /**
8853
+ * Get allowlist details
8854
+ */
8855
+ async getAllowlistDetail(params) {
8856
+ return this.fetch(`/v1/allowlists/${params.id}`, { method: "GET" });
8857
+ }
8858
+ /**
8859
+ * Update allowlist
8860
+ */
8861
+ async updateAllowlist(params, data) {
8862
+ return this.fetch(`/v1/allowlists/${params.id}`, {
8863
+ method: "PUT",
8864
+ body: JSON.stringify(data)
8865
+ });
8866
+ }
8867
+ /**
8868
+ * Delete allowlist
8869
+ */
8870
+ async deleteAllowlist(params) {
8871
+ return this.fetch(`/v1/allowlists/${params.id}`, { method: "DELETE" });
8872
+ }
8873
+ /**
8874
+ * Get round allowlist snapshot
8875
+ */
8876
+ async getRoundAllowlistSnapshot(params) {
8877
+ return this.fetch(`/v1/allowlists/snapshots/${params.contractAddress}`, {
8878
+ method: "GET"
8879
+ });
8880
+ }
8881
+ // ==================== Certificate APIs ====================
8882
+ /**
8883
+ * Request certificate
8884
+ */
8885
+ async requestCertificate(data) {
8886
+ return this.fetch("/v1/certificates/request", {
8887
+ method: "POST",
8888
+ body: JSON.stringify(data)
8889
+ });
8890
+ }
8891
+ // ==================== Pre-deactivate APIs ====================
8892
+ /**
8893
+ * Get pre-deactivate data by contract address
8894
+ */
8895
+ async getPreDeactivate(params) {
8896
+ return this.fetch(`/v1/pre-deactivate/${params.contractAddress}`, {
8897
+ method: "GET"
8898
+ });
8899
+ }
8900
+ };
8901
+
8479
8902
  // src/maci.ts
8480
8903
  var MaciClient2 = class {
8481
8904
  /**
@@ -8488,6 +8911,8 @@ var MaciClient2 = class {
8488
8911
  rpcEndpoint,
8489
8912
  restEndpoint,
8490
8913
  apiEndpoint,
8914
+ saasApiEndpoint,
8915
+ saasApiKey,
8491
8916
  registryAddress,
8492
8917
  saasAddress,
8493
8918
  apiSaasAddress,
@@ -8506,6 +8931,7 @@ var MaciClient2 = class {
8506
8931
  this.rpcEndpoint = rpcEndpoint || defaultParams.rpcEndpoint;
8507
8932
  this.restEndpoint = restEndpoint || defaultParams.restEndpoint;
8508
8933
  this.apiEndpoint = apiEndpoint || defaultParams.apiEndpoint;
8934
+ this.saasApiEndpoint = saasApiEndpoint;
8509
8935
  this.certificateApiEndpoint = certificateApiEndpoint || defaultParams.certificateApiEndpoint;
8510
8936
  this.registryAddress = registryAddress || defaultParams.registryAddress;
8511
8937
  this.saasAddress = saasAddress || defaultParams.saasAddress;
@@ -8515,15 +8941,11 @@ var MaciClient2 = class {
8515
8941
  this.feegrantOperator = feegrantOperator || defaultParams.oracleFeegrantOperator;
8516
8942
  this.whitelistBackendPubkey = whitelistBackendPubkey || defaultParams.oracleWhitelistBackendPubkey;
8517
8943
  this.maciKeypair = maciKeypair ?? genKeypair();
8518
- this.http = new Http(
8519
- this.apiEndpoint,
8520
- this.restEndpoint,
8521
- customFetch,
8522
- defaultOptions
8523
- );
8944
+ this.http = new Http(this.apiEndpoint, this.restEndpoint, customFetch, defaultOptions);
8524
8945
  this.indexer = new Indexer({
8525
8946
  restEndpoint: this.restEndpoint,
8526
8947
  apiEndpoint: this.apiEndpoint,
8948
+ // Indexer GraphQL API
8527
8949
  registryAddress: this.registryAddress,
8528
8950
  http: this.http
8529
8951
  });
@@ -8548,6 +8970,13 @@ var MaciClient2 = class {
8548
8970
  oracleCertificate: this.oracleCertificate,
8549
8971
  maciKeypair: this.maciKeypair
8550
8972
  });
8973
+ if (this.saasApiEndpoint) {
8974
+ this.saasApiClient = new MaciApiClient({
8975
+ baseUrl: this.saasApiEndpoint,
8976
+ apiKey: saasApiKey,
8977
+ customFetch
8978
+ });
8979
+ }
8551
8980
  }
8552
8981
  getSigner(signer) {
8553
8982
  if (signer) {
@@ -8558,6 +8987,28 @@ var MaciClient2 = class {
8558
8987
  }
8559
8988
  throw new Error("No signer provided, please provide a signer");
8560
8989
  }
8990
+ /**
8991
+ * Set SaaS API key for MaciApiClient
8992
+ */
8993
+ setSaasApiKey(apiKey) {
8994
+ if (!this.saasApiClient) {
8995
+ throw new Error(
8996
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
8997
+ );
8998
+ }
8999
+ this.saasApiClient.setApiKey(apiKey);
9000
+ }
9001
+ /**
9002
+ * Get SaaS API client instance
9003
+ */
9004
+ getSaasApiClient() {
9005
+ if (!this.saasApiClient) {
9006
+ throw new Error(
9007
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
9008
+ );
9009
+ }
9010
+ return this.saasApiClient;
9011
+ }
8561
9012
  getMaciKeypair() {
8562
9013
  return this.maciKeypair;
8563
9014
  }
@@ -8760,9 +9211,7 @@ var MaciClient2 = class {
8760
9211
  async getRounds(after, limit) {
8761
9212
  const rounds = await this.indexer.getRounds(after || "", limit || 10);
8762
9213
  if (isErrorResponse(rounds)) {
8763
- throw new Error(
8764
- `Failed to get rounds: ${rounds.code} ${rounds.error.message}`
8765
- );
9214
+ throw new Error(`Failed to get rounds: ${rounds.code} ${rounds.error.message}`);
8766
9215
  }
8767
9216
  return rounds;
8768
9217
  }
@@ -8775,15 +9224,10 @@ var MaciClient2 = class {
8775
9224
  async queryRoundIsQv({ contractAddress }) {
8776
9225
  return await this.maci.queryRoundIsQv({ contractAddress });
8777
9226
  }
8778
- async queryRoundClaimable({
8779
- contractAddress
8780
- }) {
9227
+ async queryRoundClaimable({ contractAddress }) {
8781
9228
  return await this.maci.queryRoundClaimable({ contractAddress });
8782
9229
  }
8783
- async queryAMaciChargeFee({
8784
- maxVoter,
8785
- maxOption
8786
- }) {
9230
+ async queryAMaciChargeFee({ maxVoter, maxOption }) {
8787
9231
  return await this.maci.queryAMaciChargeFee({
8788
9232
  maxVoter,
8789
9233
  maxOption
@@ -8793,12 +9237,7 @@ var MaciClient2 = class {
8793
9237
  return await this.maci.queryRoundGasStation({ contractAddress });
8794
9238
  }
8795
9239
  parseRoundStatus(votingStart, votingEnd, status, currentTime) {
8796
- return this.maci.parseRoundStatus(
8797
- votingStart,
8798
- votingEnd,
8799
- status,
8800
- currentTime
8801
- );
9240
+ return this.maci.parseRoundStatus(votingStart, votingEnd, status, currentTime);
8802
9241
  }
8803
9242
  async queryRoundBalance({ contractAddress }) {
8804
9243
  return await this.maci.queryRoundBalance({ contractAddress });
@@ -9058,12 +9497,947 @@ var MaciClient2 = class {
9058
9497
  fee
9059
9498
  });
9060
9499
  }
9500
+ // ==================== SaaS API Client Methods ====================
9501
+ /**
9502
+ * Create AMaci round via SaaS API
9503
+ * @param params - Round creation parameters
9504
+ */
9505
+ async saasCreateAmaciRound(params) {
9506
+ if (!this.saasApiClient) {
9507
+ throw new Error("SaaS API client not initialized");
9508
+ }
9509
+ return await this.saasApiClient.createAmaciRound(params);
9510
+ }
9511
+ /**
9512
+ * Set round info via SaaS API
9513
+ * @param params - Round info parameters
9514
+ */
9515
+ async saasSetRoundInfo(params) {
9516
+ if (!this.saasApiClient) {
9517
+ throw new Error("SaaS API client not initialized");
9518
+ }
9519
+ return await this.saasApiClient.setRoundInfo(params);
9520
+ }
9521
+ /**
9522
+ * Set vote options via SaaS API
9523
+ * @param params - Vote options parameters
9524
+ */
9525
+ async saasSetVoteOptions(params) {
9526
+ if (!this.saasApiClient) {
9527
+ throw new Error("SaaS API client not initialized");
9528
+ }
9529
+ return await this.saasApiClient.setVoteOptions(params);
9530
+ }
9531
+ };
9532
+
9533
+ // src/voter.ts
9534
+ import CryptoJS3 from "crypto-js";
9535
+ import { solidityPackedSha256 as solidityPackedSha2563 } from "ethers";
9536
+ import { groth16 } from "snarkjs";
9537
+
9538
+ // src/libs/keypairs/eddsa-poseidon/keypair.ts
9539
+ import { blake2b } from "@noble/hashes/blake2b";
9540
+ import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
9541
+ import { HDKey } from "@scure/bip32";
9542
+ import { sha256 as sha2563 } from "@noble/hashes/sha256";
9543
+ import {
9544
+ signMessage as signMessage4,
9545
+ verifySignature as verifySignature2,
9546
+ packSignature
9547
+ } from "@zk-kit/eddsa-poseidon";
9548
+
9549
+ // src/libs/cryptography/keypair.ts
9550
+ var Signer = class {
9551
+ /**
9552
+ * Sign messages with a specific payload. By combining the message bytes with the payload before hashing and signing,
9553
+ * it ensures that a signed message is tied to a specific purpose and domain separator is provided
9554
+ */
9555
+ async signWithPayload(message) {
9556
+ const signature = await this.sign(message);
9557
+ return {
9558
+ message,
9559
+ signature
9560
+ };
9561
+ }
9562
+ };
9563
+ var Keypair3 = class extends Signer {
9564
+ };
9565
+
9566
+ // src/libs/cryptography/mnemonics.ts
9567
+ import { mnemonicToSeedSync as bip39MnemonicToSeedSync } from "@scure/bip39";
9568
+ function isValidBIP32Path(path) {
9569
+ if (!new RegExp("^m\\/(44|54|74)'\\/118'\\/[0-9]+'\\/[0-9]+\\/[0-9]+$").test(path)) {
9570
+ return false;
9571
+ }
9572
+ return true;
9573
+ }
9574
+ function mnemonicToSeed(mnemonics) {
9575
+ return bip39MnemonicToSeedSync(mnemonics, "");
9576
+ }
9577
+
9578
+ // src/libs/keypairs/eddsa-poseidon/publickey.ts
9579
+ import { sha256 as sha2562 } from "@noble/hashes/sha256";
9580
+
9581
+ // src/libs/cryptography/publickey.ts
9582
+ var PublicKey = class {
9583
+ /**
9584
+ * Checks if two public keys are equal
9585
+ */
9586
+ equals(publicKey) {
9587
+ return this.toPackedData() === publicKey.toPackedData();
9588
+ }
9589
+ };
9590
+
9591
+ // src/libs/keypairs/eddsa-poseidon/publickey.ts
9592
+ import {
9593
+ verifySignature,
9594
+ unpackSignature
9595
+ } from "@zk-kit/eddsa-poseidon";
9596
+ var EdDSAPoseidonPublicKey = class extends PublicKey {
9597
+ /**
9598
+ * Create a new EdDSAPoseidonPublicKey object
9599
+ * @param value public key as packed bigint, Point array, Uint8Array or string
9600
+ */
9601
+ constructor(value) {
9602
+ super();
9603
+ if (typeof value === "bigint") {
9604
+ this.packedData = value;
9605
+ this.rawPoint = unpackPubKey(value);
9606
+ } else if (Array.isArray(value) && value.length === 2) {
9607
+ this.rawPoint = value;
9608
+ this.packedData = packPubKey(this.rawPoint);
9609
+ } else if (typeof value === "string") {
9610
+ this.packedData = BigInt(value);
9611
+ this.rawPoint = unpackPubKey(this.packedData);
9612
+ } else if (value instanceof Uint8Array) {
9613
+ const hex = Array.from(value).map((b) => b.toString(16).padStart(2, "0")).join("");
9614
+ this.packedData = BigInt("0x" + hex);
9615
+ this.rawPoint = unpackPubKey(this.packedData);
9616
+ } else {
9617
+ const bytes = new Uint8Array(value);
9618
+ const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
9619
+ this.packedData = BigInt("0x" + hex);
9620
+ this.rawPoint = unpackPubKey(this.packedData);
9621
+ }
9622
+ }
9623
+ /**
9624
+ * Checks if two EdDSAPoseidon public keys are equal
9625
+ */
9626
+ equals(publicKey) {
9627
+ return super.equals(publicKey);
9628
+ }
9629
+ /**
9630
+ * Return the Point representation of the EdDSAPoseidon public key
9631
+ */
9632
+ toPoints() {
9633
+ return this.rawPoint;
9634
+ }
9635
+ /**
9636
+ * Return the packed bigint representation of the EdDSAPoseidon public key
9637
+ */
9638
+ toPackedData() {
9639
+ return this.packedData;
9640
+ }
9641
+ /**
9642
+ * Verifies that the signature is valid for for the provided message
9643
+ */
9644
+ verify(message, signature) {
9645
+ try {
9646
+ return verifySignature(message, signature, this.rawPoint);
9647
+ } catch (error) {
9648
+ return false;
9649
+ }
9650
+ }
9651
+ /**
9652
+ * Verifies that the signature is valid for the provided address and amount
9653
+ */
9654
+ verifyPayload({
9655
+ amount,
9656
+ contractAddress,
9657
+ signature
9658
+ }) {
9659
+ const payload = {
9660
+ amount,
9661
+ contract_address: addressToUint256(contractAddress).toString(),
9662
+ pubkey_x: this.toPoints()[0].toString(),
9663
+ pubkey_y: this.toPoints()[1].toString()
9664
+ };
9665
+ const signatureBytes = fromBase64(signature);
9666
+ const rawSignature = unpackSignature(new Buffer(signatureBytes));
9667
+ const payloadHash = sha2562(new TextEncoder().encode(JSON.stringify(payload)));
9668
+ return this.verify(payloadHash, rawSignature);
9669
+ }
9670
+ /**
9671
+ * Verifies that the signature is valid for the provided address and amount
9672
+ */
9673
+ verifyCredential({
9674
+ amount,
9675
+ contractAddress,
9676
+ signature
9677
+ }) {
9678
+ const messageHash = hash5([
9679
+ BigInt(amount),
9680
+ BigInt(addressToUint256(contractAddress)),
9681
+ this.toPoints()[0],
9682
+ this.toPoints()[1],
9683
+ BigInt(0)
9684
+ ]);
9685
+ const signatureBytes = fromBase64(signature);
9686
+ const rawSignature = unpackSignature(new Buffer(signatureBytes));
9687
+ return this.verify(bigInt2Buffer(messageHash), rawSignature);
9688
+ }
9689
+ };
9690
+
9691
+ // src/libs/keypairs/eddsa-poseidon/keypair.ts
9692
+ import { mulPointEscalar as mulPointEscalar4 } from "@zk-kit/baby-jubjub";
9693
+ var DEFAULT_EDDSA_POSEIDON_DERIVATION_PATH = "m/44'/118'/0'/0/0";
9694
+ var EdDSAPoseidonKeypair = class _EdDSAPoseidonKeypair extends Keypair3 {
9695
+ /**
9696
+ * Create a new EdDSA-Poseidon keypair instance.
9697
+ *
9698
+ * If no keypair data is provided, a new random keypair will be generated
9699
+ * using cryptographically secure random number generation.
9700
+ *
9701
+ * @param keypair Optional existing EdDSA-Poseidon keypair data to initialize with
9702
+ */
9703
+ constructor(keypair) {
9704
+ super();
9705
+ if (keypair) {
9706
+ this.keypair = keypair;
9707
+ } else {
9708
+ const generatedKeypair = genKeypair();
9709
+ const secretKey = generatedKeypair.privKey;
9710
+ const unPackedPublicKey = generatedKeypair.pubKey;
9711
+ const publicKey = packPubKey(unPackedPublicKey);
9712
+ const formatedPrivKey = formatPrivKeyForBabyJub(secretKey);
9713
+ this.keypair = { publicKey, secretKey, formatedPrivKey };
9714
+ }
9715
+ }
9716
+ /**
9717
+ * Get the signature scheme identifier for this keypair.
9718
+ *
9719
+ * @returns The signature scheme type 'EDDSA_POSEIDON'
9720
+ */
9721
+ getKeyScheme() {
9722
+ return "EDDSA_POSEIDON";
9723
+ }
9724
+ /**
9725
+ * Generate a new random EdDSA-Poseidon keypair.
9726
+ *
9727
+ * This is a convenience static method that creates a new instance
9728
+ * with randomly generated cryptographic keys.
9729
+ *
9730
+ * @returns A new EdDSAPoseidonKeypair instance with random keys
9731
+ */
9732
+ static generate() {
9733
+ return new _EdDSAPoseidonKeypair();
9734
+ }
9735
+ /**
9736
+ * Create a keypair from an existing secret key.
9737
+ *
9738
+ * This method reconstructs a keypair from a previously generated secret key.
9739
+ * The secret key can be provided as either a hex string (with or without '0x' prefix)
9740
+ * or as a bigint value. For generating keypairs from mnemonic seeds, use the
9741
+ * {@link EdDSAPoseidonKeypair.deriveKeypair} method instead.
9742
+ *
9743
+ * @param secretKey The secret key as a hex string or bigint
9744
+ * @param options Configuration options for key reconstruction
9745
+ * @param options.skipValidation If true, skips cryptographic validation of the secret key
9746
+ *
9747
+ * @returns A new EdDSAPoseidonKeypair instance created from the secret key
9748
+ * @throws Error if the provided secret key is invalid and validation is not skipped
9749
+ */
9750
+ static fromSecretKey(secretKey, options) {
9751
+ if (typeof secretKey === "string") {
9752
+ const cleanSecretKey = secretKey.startsWith("0x") ? secretKey.slice(2) : secretKey;
9753
+ const decoded = buffer2Bigint(hexToBytes(cleanSecretKey));
9754
+ return this.fromSecretKey(decoded, options);
9755
+ }
9756
+ const unPackedPublicKey = genPubKey(secretKey);
9757
+ const publicKey = packPubKey(unPackedPublicKey);
9758
+ if (!options || !options.skipValidation) {
9759
+ const encoder = new TextEncoder();
9760
+ const signData = encoder.encode("dora validation");
9761
+ const msgHash = bytesToHex(blake2b(signData, { dkLen: 16 }));
9762
+ const signature = signMessage4(bigInt2Buffer(secretKey), msgHash);
9763
+ if (!verifySignature2(msgHash, signature, unPackedPublicKey)) {
9764
+ throw new Error("Provided secretKey is invalid");
9765
+ }
9766
+ }
9767
+ const formatedPrivKey = formatPrivKeyForBabyJub(secretKey);
9768
+ return new _EdDSAPoseidonKeypair({
9769
+ publicKey,
9770
+ secretKey,
9771
+ formatedPrivKey
9772
+ });
9773
+ }
9774
+ /**
9775
+ * Get the public key associated with this keypair.
9776
+ *
9777
+ * @returns An EdDSAPoseidonPublicKey instance containing the public key data
9778
+ */
9779
+ getPublicKey() {
9780
+ return new EdDSAPoseidonPublicKey(this.keypair.publicKey);
9781
+ }
9782
+ /**
9783
+ * Get the secret key as a hexadecimal string.
9784
+ *
9785
+ * Returns the secret key component of this keypair encoded as a hex string.
9786
+ * This can be used to serialize the secret key for storage or transmission.
9787
+ *
9788
+ * @returns The secret key encoded as a hexadecimal string
9789
+ */
9790
+ getSecretKey() {
9791
+ return bytesToHex(bigInt2Buffer(this.keypair.secretKey));
9792
+ }
9793
+ getFormatedPrivKey() {
9794
+ return this.keypair.formatedPrivKey;
9795
+ }
9796
+ /**
9797
+ * Sign a message using this keypair's secret key.
9798
+ *
9799
+ * Creates a cryptographic signature for the provided message using the
9800
+ * EdDSA-Poseidon signature algorithm. The signature can later be verified
9801
+ * using the corresponding public key.
9802
+ *
9803
+ * @param message The message to sign (as BigNumberish - can be bigint, string, or number)
9804
+ * @returns The cryptographic signature of the message
9805
+ */
9806
+ sign(message) {
9807
+ const sig = signMessage4(bigInt2Buffer(this.keypair.secretKey), message);
9808
+ return sig;
9809
+ }
9810
+ /**
9811
+ * Derive an EdDSA-Poseidon keypair from a mnemonic phrase and derivation path.
9812
+ *
9813
+ * This method implements hierarchical deterministic (HD) key derivation following
9814
+ * the BIP-32 standard. The mnemonic phrase must be normalized and validated against
9815
+ * the English wordlist before use.
9816
+ *
9817
+ * @param mnemonics The mnemonic phrase (12, 15, 18, 21, or 24 words)
9818
+ * @param path Optional BIP-32 derivation path. If not provided, uses the default path.
9819
+ * Must be in the form m/44'/118'/{account_index}'/{change_index}/{address_index}
9820
+ *
9821
+ * @returns A new EdDSAPoseidonKeypair derived from the mnemonic and path
9822
+ * @throws Error if the derivation path is invalid or key derivation fails
9823
+ */
9824
+ static deriveKeypair(mnemonics, path) {
9825
+ if (path == null) {
9826
+ path = DEFAULT_EDDSA_POSEIDON_DERIVATION_PATH;
9827
+ }
9828
+ if (!isValidBIP32Path(path)) {
9829
+ throw new Error("Invalid derivation path");
9830
+ }
9831
+ const seed = mnemonicToSeed(mnemonics);
9832
+ const hdKey = HDKey.fromMasterSeed(seed);
9833
+ const derivedKey = hdKey.derive(path);
9834
+ if (!derivedKey.privateKey) {
9835
+ throw new Error("Invalid key");
9836
+ }
9837
+ const privateKeyHex = Buffer.from(derivedKey.privateKey).toString(
9838
+ "hex"
9839
+ );
9840
+ const secretKey = BigInt("0x" + privateKeyHex) % SNARK_FIELD_SIZE;
9841
+ const unPackedPubKey = genPubKey(secretKey);
9842
+ const pubKey = packPubKey(unPackedPubKey);
9843
+ return new _EdDSAPoseidonKeypair({
9844
+ publicKey: pubKey,
9845
+ secretKey,
9846
+ formatedPrivKey: formatPrivKeyForBabyJub(secretKey)
9847
+ });
9848
+ }
9849
+ /**
9850
+ * Sign a payload containing contract address and amount information.
9851
+ *
9852
+ * This method creates a structured payload with the contract address, amount,
9853
+ * and public key coordinates, then generates a cryptographic signature over
9854
+ * the JSON-serialized payload using SHA-256 hashing.
9855
+ *
9856
+ * The resulting signature can be used as a certificate or proof of authorization
9857
+ * for the specified contract address and amount.
9858
+ *
9859
+ * @param params The payload parameters
9860
+ * @param params.amount The amount value as a string
9861
+ * @param params.contractAddress The contract address to include in the payload
9862
+ *
9863
+ * @returns Base64-encoded signature of the payload
9864
+ */
9865
+ signPayload({
9866
+ amount,
9867
+ contractAddress
9868
+ }) {
9869
+ const payload = {
9870
+ amount,
9871
+ contract_address: addressToUint256(contractAddress).toString(),
9872
+ pubkey_x: this.getPublicKey().toPoints()[0].toString(),
9873
+ pubkey_y: this.getPublicKey().toPoints()[1].toString()
9874
+ };
9875
+ const bytes = new TextEncoder().encode(JSON.stringify(payload));
9876
+ const msgHash = sha2563(bytes);
9877
+ const signature = this.sign(msgHash);
9878
+ return toBase64(new Uint8Array(packSignature(signature)));
9879
+ }
9880
+ /**
9881
+ * Sign a credential containing contract address and amount using Poseidon hashing.
9882
+ *
9883
+ * This method creates a cryptographic credential by signing a structured message
9884
+ * using the Poseidon hash function (hash5). The message includes the amount,
9885
+ * contract address (converted to uint256), public key coordinates, and a zero nonce.
9886
+ *
9887
+ * This type of credential is optimized for zero-knowledge proof systems where
9888
+ * Poseidon hashing is more efficient than traditional hash functions.
9889
+ *
9890
+ * @param params The credential parameters
9891
+ * @param params.amount The amount value as a string (will be converted to BigInt)
9892
+ * @param params.contractAddress The contract address (will be converted to uint256)
9893
+ *
9894
+ * @returns Base64-encoded signature of the credential
9895
+ */
9896
+ signCredential({
9897
+ amount,
9898
+ contractAddress
9899
+ }) {
9900
+ const messageHash = hash5([
9901
+ BigInt(amount),
9902
+ BigInt(addressToUint256(contractAddress)),
9903
+ this.getPublicKey().toPoints()[0],
9904
+ this.getPublicKey().toPoints()[1],
9905
+ BigInt(0)
9906
+ // Nonce field (currently set to 0)
9907
+ ]);
9908
+ const signature = this.sign(messageHash);
9909
+ return toBase64(new Uint8Array(packSignature(signature)));
9910
+ }
9911
+ /**
9912
+ * Generates an Elliptic-Curve Diffie–Hellman (ECDH) shared key given a private
9913
+ * key and a public key.
9914
+ * @param pubKey A public key generated using genPubKey()
9915
+ * @returns The ECDH shared key.
9916
+ */
9917
+ genEcdhSharedKey(pubKey) {
9918
+ return mulPointEscalar4(
9919
+ pubKey,
9920
+ this.keypair.formatedPrivKey
9921
+ );
9922
+ }
9923
+ genDeactivateRoot(accounts, stateTreeDepth) {
9924
+ const unpackedAccounts = accounts.length > 0 && typeof accounts[0] === "bigint" ? accounts.map((account) => unpackPubKey(account)) : accounts;
9925
+ const deactivates = unpackedAccounts.map((account) => {
9926
+ const sharedKey = this.genEcdhSharedKey(account);
9927
+ const deactivate = encryptOdevity(
9928
+ false,
9929
+ // isOdd: According to circuit rules, odd values indicate active accounts and even values indicate inactive accounts. Set to false here to ensure valid signup
9930
+ this.getPublicKey().toPoints(),
9931
+ genRandomBabyJubValue()
9932
+ );
9933
+ return [
9934
+ deactivate.c1.x,
9935
+ deactivate.c1.y,
9936
+ deactivate.c2.x,
9937
+ deactivate.c2.y,
9938
+ poseidon(sharedKey)
9939
+ ];
9940
+ });
9941
+ const degree = 5;
9942
+ const depth = stateTreeDepth + 2;
9943
+ const zero = 0n;
9944
+ const tree = new Tree(degree, depth, zero);
9945
+ const leaves = deactivates.map((deactivate) => poseidon(deactivate));
9946
+ tree.initLeaves(leaves);
9947
+ return {
9948
+ deactivates,
9949
+ root: tree.root,
9950
+ leaves,
9951
+ tree
9952
+ // Return tree instance for later retrieval of path elements
9953
+ };
9954
+ }
9955
+ };
9956
+
9957
+ // src/libs/account/keypair.ts
9958
+ var getDerivePathForMACI = (derivePathParams = {}) => {
9959
+ const { accountIndex = 0, isExternal = false, addressIndex = 0 } = derivePathParams;
9960
+ return `m/44'/118'/${accountIndex}'/${isExternal ? 1 : 0}/${addressIndex}`;
9961
+ };
9962
+ var getKeyPair = (mnemonics, derivePathParams = {}) => {
9963
+ const derivePath = getDerivePathForMACI(derivePathParams);
9964
+ return EdDSAPoseidonKeypair.deriveKeypair(mnemonics, derivePath);
9965
+ };
9966
+
9967
+ // src/libs/account/crypto.ts
9968
+ import { generateMnemonic as genMnemonic } from "@scure/bip39";
9969
+ import { wordlist } from "@scure/bip39/wordlists/english";
9970
+ var generateMnemonic = (numberOfWords = 24) => {
9971
+ const strength = numberOfWords === 12 ? 128 : 256;
9972
+ return genMnemonic(wordlist, strength);
9973
+ };
9974
+
9975
+ // src/libs/account/index.ts
9976
+ var MaciAccount = class {
9977
+ /**
9978
+ * Support the following ways to init the SuiToolkit:
9979
+ * 1. mnemonics
9980
+ * 2. secretKey (base64 or hex)
9981
+ * If none of them is provided, will generate a random mnemonics with 24 words.
9982
+ *
9983
+ * @param mnemonics, 12 or 24 mnemonics words, separated by space
9984
+ * @param secretKey, base64 or hex string or Bech32 string, when mnemonics is provided, secretKey will be ignored
9985
+ */
9986
+ constructor({ mnemonic, secretKey } = {}) {
9987
+ this.mnemonic = mnemonic || "";
9988
+ this.secretKey = secretKey || "";
9989
+ if (!this.mnemonic && !this.secretKey) {
9990
+ this.mnemonic = generateMnemonic(24);
9991
+ }
9992
+ this.currentKeypair = this.secretKey ? this.parseSecretKey(this.secretKey) : getKeyPair(this.mnemonic);
9993
+ this.currentPubkey = this.currentKeypair.getPublicKey();
9994
+ }
9995
+ /**
9996
+ * Check if the secretKey starts with bench32 format
9997
+ */
9998
+ parseSecretKey(secretKey) {
9999
+ return EdDSAPoseidonKeypair.fromSecretKey(secretKey);
10000
+ }
10001
+ /**
10002
+ * if derivePathParams is not provided or mnemonics is empty, it will return the currentKeyPair.
10003
+ * else:
10004
+ * it will generate keyPair from the mnemonic with the given derivePathParams.
10005
+ */
10006
+ getKeyPair(derivePathParams) {
10007
+ if (!derivePathParams || !this.mnemonic) return this.currentKeypair;
10008
+ return getKeyPair(this.mnemonic, derivePathParams);
10009
+ }
10010
+ /**
10011
+ * Switch the current account with the given derivePathParams.
10012
+ * This is only useful when the mnemonic is provided. For secretKey mode, it will always use the same account.
10013
+ */
10014
+ switchAccount(derivePathParams) {
10015
+ if (this.mnemonic) {
10016
+ this.currentKeypair = getKeyPair(this.mnemonic, derivePathParams);
10017
+ this.currentPubkey = this.currentKeypair.getPublicKey();
10018
+ }
10019
+ }
10020
+ };
10021
+
10022
+ // src/voter.ts
10023
+ import { poseidonEncrypt as poseidonEncrypt2 } from "@zk-kit/poseidon-cipher";
10024
+ var VoterClient = class _VoterClient {
10025
+ /**
10026
+ * @constructor
10027
+ * @param {VoterClientParams} params - The parameters for the Maci Voter Client instance.
10028
+ */
10029
+ constructor({
10030
+ network,
10031
+ mnemonic,
10032
+ secretKey,
10033
+ apiEndpoint,
10034
+ restEndpoint,
10035
+ saasApiEndpoint,
10036
+ saasApiKey,
10037
+ registryAddress,
10038
+ customFetch,
10039
+ defaultOptions
10040
+ }) {
10041
+ this.network = network;
10042
+ this.accountManager = new MaciAccount({ mnemonic, secretKey });
10043
+ const defaultParams = getDefaultParams(network);
10044
+ this.restEndpoint = restEndpoint || defaultParams.restEndpoint;
10045
+ this.apiEndpoint = apiEndpoint || defaultParams.apiEndpoint;
10046
+ this.saasApiEndpoint = saasApiEndpoint || defaultParams.saasApiEndpoint;
10047
+ this.registryAddress = registryAddress || defaultParams.registryAddress;
10048
+ this.http = new Http(this.apiEndpoint, this.restEndpoint, customFetch, defaultOptions);
10049
+ this.indexer = new Indexer({
10050
+ restEndpoint: this.restEndpoint,
10051
+ apiEndpoint: this.apiEndpoint,
10052
+ // Indexer GraphQL API
10053
+ registryAddress: this.registryAddress,
10054
+ http: this.http
10055
+ });
10056
+ this.saasApiClient = new MaciApiClient({
10057
+ baseUrl: this.saasApiEndpoint,
10058
+ apiKey: saasApiKey,
10059
+ customFetch
10060
+ });
10061
+ }
10062
+ /**
10063
+ * Set SaaS API key for MaciApiClient
10064
+ */
10065
+ setSaasApiKey(apiKey) {
10066
+ if (!this.saasApiClient) {
10067
+ throw new Error(
10068
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
10069
+ );
10070
+ }
10071
+ this.saasApiClient.setApiKey(apiKey);
10072
+ }
10073
+ /**
10074
+ * Get SaaS API client instance
10075
+ */
10076
+ getSaasApiClient() {
10077
+ if (!this.saasApiClient) {
10078
+ throw new Error(
10079
+ "SaaS API client not initialized. Please provide saasApiEndpoint in constructor."
10080
+ );
10081
+ }
10082
+ return this.saasApiClient;
10083
+ }
10084
+ /**
10085
+ * else:
10086
+ * it will generate signer from the mnemonic with the given derivePathParams.
10087
+ * @param derivePathParams, such as { accountIndex: 2, isExternal: false, addressIndex: 10 }, comply with the BIP44 standard
10088
+ */
10089
+ getSigner(derivePathParams) {
10090
+ return this.accountManager.getKeyPair(derivePathParams);
10091
+ }
10092
+ packMaciPubkey(pubkey) {
10093
+ return packPubKey(pubkey || this.accountManager.currentPubkey.toPoints());
10094
+ }
10095
+ unpackMaciPubkey(pubkey) {
10096
+ return unpackPubKey(BigInt(pubkey));
10097
+ }
10098
+ getPubkey(derivePathParams) {
10099
+ return this.accountManager.getKeyPair(derivePathParams).getPublicKey();
10100
+ }
10101
+ buildVotePayload({
10102
+ stateIdx,
10103
+ operatorPubkey,
10104
+ selectedOptions,
10105
+ derivePathParams
10106
+ }) {
10107
+ const idxSet = /* @__PURE__ */ new Set();
10108
+ for (const option of selectedOptions) {
10109
+ if (idxSet.has(option.idx)) {
10110
+ throw new Error(`Duplicate option index (${option.idx}) is not allowed`);
10111
+ }
10112
+ idxSet.add(option.idx);
10113
+ }
10114
+ const options = selectedOptions.filter((o) => !!o.vc).sort((a, b) => a.idx - b.idx);
10115
+ const plan = options.map((o) => {
10116
+ return [o.idx, o.vc];
10117
+ });
10118
+ const payload = this.batchGenMessage(stateIdx, operatorPubkey, plan, derivePathParams);
10119
+ return stringizing(payload);
10120
+ }
10121
+ batchGenMessage(stateIdx, operatorPubkey, plan, derivePathParams) {
10122
+ const genMessage = this.genMessageFactory(stateIdx, operatorPubkey, derivePathParams);
10123
+ const payload = [];
10124
+ for (let i = plan.length - 1; i >= 0; i--) {
10125
+ const p = plan[i];
10126
+ const encAccount = genKeypair();
10127
+ const msg = genMessage(BigInt(encAccount.privKey), i + 1, p[0], p[1], i === plan.length - 1);
10128
+ payload.push({
10129
+ msg,
10130
+ encPubkeys: encAccount.pubKey
10131
+ });
10132
+ }
10133
+ return payload;
10134
+ }
10135
+ genMessageFactory(stateIdx, operatorPubkey, derivePathParams) {
10136
+ return (encPriKey, nonce, voIdx, newVotes, isLastCmd, salt) => {
10137
+ if (!salt) {
10138
+ salt = BigInt(`0x${CryptoJS3.lib.WordArray.random(7).toString(CryptoJS3.enc.Hex)}`);
10139
+ }
10140
+ const packaged = BigInt(nonce) + (BigInt(stateIdx) << 32n) + (BigInt(voIdx) << 64n) + (BigInt(newVotes) << 96n) + (BigInt(salt) << 192n);
10141
+ const signer = this.getSigner(derivePathParams);
10142
+ let newPubKey = [...signer.getPublicKey().toPoints()];
10143
+ if (isLastCmd) {
10144
+ newPubKey = [0n, 0n];
10145
+ }
10146
+ const hash = poseidon([packaged, ...newPubKey]);
10147
+ const signature = signer.sign(hash);
10148
+ const command = [packaged, ...newPubKey, ...signature.R8, signature.S];
10149
+ const coordPubkey = this.unpackMaciPubkey(operatorPubkey);
10150
+ const message = poseidonEncrypt2(command, genEcdhSharedKey(encPriKey, coordPubkey), 0n);
10151
+ return message;
10152
+ };
10153
+ }
10154
+ async getStateIdxByPubKey({
10155
+ contractAddress,
10156
+ pubKey
10157
+ }) {
10158
+ const response = await this.indexer.getSignUpEventByPubKey(contractAddress, pubKey);
10159
+ if (isErrorResponse(response)) {
10160
+ return -1;
10161
+ }
10162
+ return response.data.signUpEvents[0].stateIdx;
10163
+ }
10164
+ async buildAddNewKeyPayload({
10165
+ stateTreeDepth,
10166
+ operatorPubkey,
10167
+ deactivates,
10168
+ wasmFile,
10169
+ zkeyFile,
10170
+ derivePathParams
10171
+ }) {
10172
+ const [coordPubkeyX, coordPubkeyY] = this.unpackMaciPubkey(operatorPubkey);
10173
+ const addKeyInput = await this.genAddKeyInput(stateTreeDepth + 2, {
10174
+ coordPubKey: [coordPubkeyX, coordPubkeyY],
10175
+ deactivates: deactivates.map((d) => d.map(BigInt)),
10176
+ derivePathParams
10177
+ });
10178
+ if (addKeyInput === null) {
10179
+ throw Error("genAddKeyInput failed");
10180
+ }
10181
+ const { proof } = await groth16.fullProve(addKeyInput, wasmFile, zkeyFile);
10182
+ const proofHex = await adaptToUncompressed(proof);
10183
+ return {
10184
+ proof: proofHex,
10185
+ d: [
10186
+ addKeyInput.d1[0].toString(),
10187
+ addKeyInput.d1[1].toString(),
10188
+ addKeyInput.d2[0].toString(),
10189
+ addKeyInput.d2[1].toString()
10190
+ ],
10191
+ nullifier: addKeyInput.nullifier.toString()
10192
+ };
10193
+ }
10194
+ async buildPreAddNewKeyPayload({
10195
+ stateTreeDepth,
10196
+ coordinatorPubkey,
10197
+ deactivates,
10198
+ wasmFile,
10199
+ zkeyFile,
10200
+ derivePathParams
10201
+ }) {
10202
+ const [coordPubkeyX, coordPubkeyY] = this.unpackMaciPubkey(coordinatorPubkey);
10203
+ const addKeyInput = await this.genPreAddKeyInput(stateTreeDepth + 2, {
10204
+ coordPubKey: [coordPubkeyX, coordPubkeyY],
10205
+ deactivates: deactivates.map((d) => d.map(BigInt)),
10206
+ derivePathParams
10207
+ });
10208
+ if (addKeyInput === null) {
10209
+ throw Error("genPreAddKeyInput failed, cannot find deactivate idx");
10210
+ }
10211
+ const { proof } = await groth16.fullProve(addKeyInput, wasmFile, zkeyFile);
10212
+ const proofHex = await adaptToUncompressed(proof);
10213
+ return {
10214
+ proof: proofHex,
10215
+ d: [
10216
+ addKeyInput.d1[0].toString(),
10217
+ addKeyInput.d1[1].toString(),
10218
+ addKeyInput.d2[0].toString(),
10219
+ addKeyInput.d2[1].toString()
10220
+ ],
10221
+ nullifier: addKeyInput.nullifier.toString()
10222
+ };
10223
+ }
10224
+ async genAddKeyInput(depth, {
10225
+ coordPubKey,
10226
+ deactivates,
10227
+ derivePathParams
10228
+ }) {
10229
+ const signer = this.getSigner(derivePathParams);
10230
+ const sharedKeyHash = poseidon(signer.genEcdhSharedKey(coordPubKey));
10231
+ const randomVal = genRandomSalt();
10232
+ const deactivateIdx = deactivates.findIndex((d) => d[4] === sharedKeyHash);
10233
+ if (deactivateIdx < 0) {
10234
+ return null;
10235
+ }
10236
+ const deactivateLeaf = deactivates[deactivateIdx];
10237
+ const c1 = [deactivateLeaf[0], deactivateLeaf[1]];
10238
+ const c2 = [deactivateLeaf[2], deactivateLeaf[3]];
10239
+ const { d1, d2 } = rerandomize(coordPubKey, { c1, c2 }, randomVal);
10240
+ const nullifier = poseidon([signer.getFormatedPrivKey(), 1444992409218394441042n]);
10241
+ const tree = new Tree(5, depth, 0n);
10242
+ const leaves = deactivates.map((d) => poseidon(d));
10243
+ tree.initLeaves(leaves);
10244
+ const deactivateRoot = tree.root;
10245
+ const deactivateLeafPathElements = tree.pathElementOf(deactivateIdx);
10246
+ const inputHash = BigInt(
10247
+ solidityPackedSha2563(
10248
+ new Array(7).fill("uint256"),
10249
+ stringizing([
10250
+ deactivateRoot,
10251
+ poseidon(coordPubKey),
10252
+ nullifier,
10253
+ d1[0],
10254
+ d1[1],
10255
+ d2[0],
10256
+ d2[1]
10257
+ ])
10258
+ )
10259
+ ) % SNARK_FIELD_SIZE;
10260
+ const input = {
10261
+ inputHash,
10262
+ coordPubKey,
10263
+ deactivateRoot,
10264
+ deactivateIndex: deactivateIdx,
10265
+ deactivateLeaf: poseidon(deactivateLeaf),
10266
+ c1,
10267
+ c2,
10268
+ randomVal,
10269
+ d1,
10270
+ d2,
10271
+ deactivateLeafPathElements,
10272
+ nullifier,
10273
+ oldPrivateKey: signer.getFormatedPrivKey()
10274
+ };
10275
+ return input;
10276
+ }
10277
+ async genPreAddKeyInput(depth, {
10278
+ coordPubKey,
10279
+ deactivates,
10280
+ derivePathParams
10281
+ }) {
10282
+ const signer = this.getSigner(derivePathParams);
10283
+ const sharedKeyHash = poseidon(signer.genEcdhSharedKey(coordPubKey));
10284
+ const randomVal = genRandomSalt();
10285
+ const deactivateIdx = deactivates.findIndex((d) => d[4] === sharedKeyHash);
10286
+ if (deactivateIdx < 0) {
10287
+ return null;
10288
+ }
10289
+ const deactivateLeaf = deactivates[deactivateIdx];
10290
+ const c1 = [deactivateLeaf[0], deactivateLeaf[1]];
10291
+ const c2 = [deactivateLeaf[2], deactivateLeaf[3]];
10292
+ const { d1, d2 } = rerandomize(coordPubKey, { c1, c2 }, randomVal);
10293
+ const nullifier = poseidon([signer.getFormatedPrivKey(), 1444992409218394441042n]);
10294
+ const tree = new Tree(5, depth, 0n);
10295
+ const leaves = deactivates.map((d) => poseidon(d));
10296
+ tree.initLeaves(leaves);
10297
+ const deactivateRoot = tree.root;
10298
+ const deactivateLeafPathElements = tree.pathElementOf(deactivateIdx);
10299
+ const inputHash = BigInt(
10300
+ solidityPackedSha2563(
10301
+ new Array(7).fill("uint256"),
10302
+ stringizing([
10303
+ deactivateRoot,
10304
+ poseidon(coordPubKey),
10305
+ nullifier,
10306
+ d1[0],
10307
+ d1[1],
10308
+ d2[0],
10309
+ d2[1]
10310
+ ])
10311
+ )
10312
+ ) % SNARK_FIELD_SIZE;
10313
+ const input = {
10314
+ inputHash,
10315
+ coordPubKey,
10316
+ deactivateRoot,
10317
+ deactivateIndex: deactivateIdx,
10318
+ deactivateLeaf: poseidon(deactivateLeaf),
10319
+ c1,
10320
+ c2,
10321
+ randomVal,
10322
+ d1,
10323
+ d2,
10324
+ deactivateLeafPathElements,
10325
+ nullifier,
10326
+ oldPrivateKey: signer.getFormatedPrivKey()
10327
+ };
10328
+ return input;
10329
+ }
10330
+ async buildDeactivatePayload({
10331
+ stateIdx,
10332
+ operatorPubkey,
10333
+ derivePathParams
10334
+ }) {
10335
+ const payload = this.batchGenMessage(stateIdx, operatorPubkey, [[0, 0]], derivePathParams);
10336
+ return stringizing(payload[0]);
10337
+ }
10338
+ // ==================== SaaS API Client Methods ====================
10339
+ /**
10340
+ * Get pre-deactivate data via SaaS API
10341
+ * @param contractAddress - Contract address
10342
+ */
10343
+ async saasGetPreDeactivate(contractAddress) {
10344
+ if (!this.saasApiClient) {
10345
+ throw new Error("SaaS API client not initialized");
10346
+ }
10347
+ return await this.saasApiClient.getPreDeactivate({ contractAddress });
10348
+ }
10349
+ /**
10350
+ * Pre add new key via SaaS API
10351
+ * @param params - Pre add new key parameters
10352
+ */
10353
+ async saasSubmitPreAddNewKey(params) {
10354
+ if (!this.saasApiClient) {
10355
+ throw new Error("SaaS API client not initialized");
10356
+ }
10357
+ return await this.saasApiClient.preAddNewKey(params);
10358
+ }
10359
+ /**
10360
+ * Vote via SaaS API
10361
+ * @param params - Vote parameters
10362
+ */
10363
+ async saasSubmitVote(params) {
10364
+ if (!this.saasApiClient) {
10365
+ throw new Error("SaaS API client not initialized");
10366
+ }
10367
+ return await this.saasApiClient.vote(params);
10368
+ }
10369
+ // ==================== Maci Voter Methods ====================
10370
+ async saasPreCreateNewAccount({
10371
+ contractAddress,
10372
+ stateTreeDepth,
10373
+ coordinatorPubkey,
10374
+ deactivates,
10375
+ wasmFile,
10376
+ zkeyFile,
10377
+ derivePathParams
10378
+ }) {
10379
+ const addNewKeyPayload = await this.buildPreAddNewKeyPayload({
10380
+ stateTreeDepth,
10381
+ coordinatorPubkey,
10382
+ deactivates,
10383
+ wasmFile,
10384
+ zkeyFile,
10385
+ derivePathParams
10386
+ });
10387
+ const newVoterClient = new _VoterClient({
10388
+ network: this.network,
10389
+ restEndpoint: this.restEndpoint,
10390
+ apiEndpoint: this.apiEndpoint,
10391
+ saasApiEndpoint: this.saasApiEndpoint,
10392
+ registryAddress: this.registryAddress
10393
+ });
10394
+ const addNewKeyResult = await newVoterClient.saasSubmitPreAddNewKey({
10395
+ contractAddress,
10396
+ proof: addNewKeyPayload.proof,
10397
+ d: addNewKeyPayload.d,
10398
+ nullifier: addNewKeyPayload.nullifier,
10399
+ newPubkey: newVoterClient.getPubkey().toPoints().map((p) => p.toString())
10400
+ });
10401
+ return {
10402
+ result: addNewKeyResult,
10403
+ account: newVoterClient
10404
+ };
10405
+ }
10406
+ async saasVote({
10407
+ contractAddress,
10408
+ // stateIdx,
10409
+ operatorPubkey,
10410
+ selectedOptions,
10411
+ derivePathParams
10412
+ }) {
10413
+ const stateIdx = await this.getStateIdxByPubKey({
10414
+ contractAddress,
10415
+ pubKey: this.getPubkey(derivePathParams).toPoints()
10416
+ });
10417
+ if (stateIdx === -1) {
10418
+ throw new Error("State index is not set, Please signup or addNewKey first");
10419
+ }
10420
+ const payload = this.buildVotePayload({
10421
+ stateIdx,
10422
+ operatorPubkey,
10423
+ selectedOptions,
10424
+ derivePathParams
10425
+ });
10426
+ const voteResult = await this.saasSubmitVote({
10427
+ contractAddress,
10428
+ payload
10429
+ });
10430
+ return voteResult;
10431
+ }
9061
10432
  };
9062
10433
  export {
9063
10434
  Circuit,
10435
+ EdDSAPoseidonKeypair,
10436
+ EdDSAPoseidonPublicKey,
9064
10437
  G1Point,
9065
10438
  G2Point,
9066
10439
  Http,
10440
+ MaciApiClient,
9067
10441
  MaciCertSystemType,
9068
10442
  MaciCircuitType,
9069
10443
  MaciClient2 as MaciClient,
@@ -9077,12 +10451,23 @@ export {
9077
10451
  Transaction,
9078
10452
  Tree,
9079
10453
  UserAccount,
10454
+ VoterClient,
10455
+ adaptToUncompressed,
10456
+ addressToUint256,
9080
10457
  batchGenMessage,
9081
10458
  bigInt2Buffer,
10459
+ bigintToHex,
9082
10460
  buffer2Bigint,
9083
10461
  circuits,
10462
+ compressPublicKey,
10463
+ decompressPublicKey,
9084
10464
  destringizing,
10465
+ encryptOdevity,
9085
10466
  formatPrivKeyForBabyJub,
10467
+ fromB64,
10468
+ fromBase64,
10469
+ fromHEX,
10470
+ fromHex,
9086
10471
  genAddKeyInput,
9087
10472
  genEcdhSharedKey,
9088
10473
  genKeypair,
@@ -9095,6 +10480,9 @@ export {
9095
10480
  genRandomKey,
9096
10481
  genRandomSalt,
9097
10482
  getAMaciRoundCircuitFee,
10483
+ getCurveFromName,
10484
+ getCurveFromQ,
10485
+ getCurveFromR,
9098
10486
  getDefaultParams,
9099
10487
  hash12,
9100
10488
  hash2,
@@ -9105,6 +10493,8 @@ export {
9105
10493
  hashLeftRight,
9106
10494
  hashN,
9107
10495
  hashOne,
10496
+ hexToBigInt,
10497
+ hexToDecimalString,
9108
10498
  isValidAddress,
9109
10499
  packPubKey,
9110
10500
  poseidon,
@@ -9113,9 +10503,15 @@ export {
9113
10503
  poseidonT5,
9114
10504
  poseidonT6,
9115
10505
  privateKeyFromTxt,
10506
+ rerandomize,
9116
10507
  sha256Hash,
9117
10508
  signMessage2 as signMessage,
9118
10509
  stringizing,
10510
+ toB64,
10511
+ toBase64,
10512
+ toHEX,
10513
+ toHex,
10514
+ transformPubkey,
9119
10515
  unpackPubKey
9120
10516
  };
9121
10517
  //# sourceMappingURL=index.mjs.map