@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.
- package/dist/index.d.ts +7 -2
- package/dist/index.js +1485 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1470 -74
- package/dist/index.mjs.map +1 -1
- package/dist/libs/account/crypto.d.ts +1 -0
- package/dist/libs/account/index.d.ts +35 -0
- package/dist/libs/account/keypair.d.ts +21 -0
- package/dist/libs/account/util.d.ts +25 -0
- package/dist/libs/api/client.d.ts +173 -0
- package/dist/libs/api/index.d.ts +3 -0
- package/dist/libs/const.d.ts +1 -0
- package/dist/libs/crypto/adapter.d.ts +6 -0
- package/dist/libs/crypto/curve.d.ts +3 -0
- package/dist/libs/crypto/index.d.ts +3 -0
- package/dist/libs/crypto/keys.d.ts +8 -1
- package/dist/libs/crypto/rerandomize.d.ts +12 -0
- package/dist/libs/crypto/sign.d.ts +1 -1
- package/dist/libs/cryptography/index.d.ts +0 -0
- package/dist/libs/cryptography/keypair.d.ts +30 -0
- package/dist/libs/cryptography/mnemonics.d.ts +27 -0
- package/dist/libs/cryptography/publickey.d.ts +23 -0
- package/dist/libs/cryptography/signature-scheme.d.ts +1 -0
- package/dist/libs/index.d.ts +1 -0
- package/dist/libs/keypairs/eddsa-poseidon/index.d.ts +2 -0
- package/dist/libs/keypairs/eddsa-poseidon/keypair.d.ts +187 -0
- package/dist/libs/keypairs/eddsa-poseidon/publickey.d.ts +48 -0
- package/dist/maci.d.ts +90 -31
- package/dist/types/index.d.ts +23 -0
- package/dist/utils/base64.d.ts +6 -0
- package/dist/utils/bech32.d.ts +2 -0
- package/dist/utils/decode-address.d.ts +10 -0
- package/dist/utils/fetch.d.ts +1 -0
- package/dist/utils/hex.d.ts +6 -0
- package/dist/utils/index.d.ts +4 -24
- package/dist/utils/validate-address.d.ts +24 -0
- package/dist/voter.d.ts +230 -0
- package/package.json +13 -61
- package/src/index.ts +11 -13
- package/src/libs/account/crypto.ts +7 -0
- package/src/libs/account/index.ts +70 -0
- package/src/libs/account/keypair.ts +29 -0
- package/src/libs/account/util.ts +55 -0
- package/src/libs/api/client.ts +406 -0
- package/src/libs/api/index.ts +3 -0
- package/src/libs/api/types.d.ts +1493 -0
- package/src/libs/const.ts +37 -54
- package/src/libs/crypto/adapter.ts +41 -0
- package/src/libs/crypto/babyjub.ts +4 -7
- package/src/libs/crypto/constants.ts +2 -5
- package/src/libs/crypto/curve.ts +55 -0
- package/src/libs/crypto/hashing.ts +4 -6
- package/src/libs/crypto/index.ts +3 -0
- package/src/libs/crypto/keys.ts +15 -48
- package/src/libs/crypto/rerandomize.ts +77 -0
- package/src/libs/crypto/sign.ts +8 -17
- package/src/libs/crypto/tree.ts +1 -3
- package/src/libs/cryptography/index.ts +0 -0
- package/src/libs/cryptography/keypair.ts +44 -0
- package/src/libs/cryptography/mnemonics.ts +47 -0
- package/src/libs/cryptography/publickey.ts +44 -0
- package/src/libs/cryptography/signature-scheme.ts +1 -0
- package/src/libs/index.ts +1 -0
- package/src/libs/keypairs/eddsa-poseidon/index.ts +6 -0
- package/src/libs/keypairs/eddsa-poseidon/keypair.ts +452 -0
- package/src/libs/keypairs/eddsa-poseidon/publickey.ts +141 -0
- package/src/maci.ts +157 -101
- package/src/types/index.ts +30 -4
- package/src/types/lib.d.ts +7 -0
- package/src/utils/base64.ts +28 -0
- package/src/utils/bech32.ts +29 -0
- package/src/utils/decode-address.ts +35 -0
- package/src/utils/fetch.ts +28 -0
- package/src/utils/hex.ts +23 -0
- package/src/utils/index.ts +15 -79
- package/src/utils/validate-address.ts +82 -0
- 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/
|
|
448
|
-
|
|
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/
|
|
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
|