@dorafactory/maci-sdk 0.0.20 → 0.0.21

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.js CHANGED
@@ -292,6 +292,8 @@ var ERROR = {
292
292
  ERROR_CIRCUIT_NOT_FOUND: "ERROR_CIRCUIT_NOT_FOUND",
293
293
  ERROR_OPERATOR_INVALID_ADDRESS: "ERROR_OPERATOR_INVALID_ADDRESS",
294
294
  ERROR_OPERATOR_NOT_FOUND: "ERROR_OPERATOR_NOT_FOUND",
295
+ ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND: "ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND",
296
+ ERROR_QUERY_MISS_RATE_FAILED: "ERROR_QUERY_MISS_RATE_FAILED",
295
297
  ERROR_OPERATORS_NOT_FOUND: "ERROR_OPERATORS_NOT_FOUND",
296
298
  ERROR_PROOF_NOT_FOUND: "ERROR_PROOF_NOT_FOUND",
297
299
  ERROR_ROUND_INVALID_ADDRESS: "ERROR_ROUND_INVALID_ADDRESS",
@@ -718,6 +720,64 @@ var Operator = class {
718
720
  return handleError(error);
719
721
  }
720
722
  }
723
+ async getOperatorDelayOperationsByAddress(address, after, limit) {
724
+ try {
725
+ if (!isValidAddress(address)) {
726
+ return {
727
+ code: 400,
728
+ error: {
729
+ message: "Invalid operator address format",
730
+ type: ERROR.ERROR_OPERATOR_INVALID_ADDRESS
731
+ }
732
+ };
733
+ }
734
+ const OPERATORS_QUERY = `query ($limit: Int, $after: Cursor) {
735
+ operatorDelayOperations(first: $limit, after: $after, filter: {operatorAddress: {equalTo: "${address}"}}, orderBy: [TIMESTAMP_DESC]) {
736
+ pageInfo {
737
+ endCursor
738
+ hasNextPage
739
+ }
740
+ totalCount
741
+ edges {
742
+ cursor
743
+ node {
744
+ blockHeight
745
+ delayProcessDmsgCount
746
+ delayDuration
747
+ delayReason
748
+ delayType
749
+ id
750
+ nodeId
751
+ operatorAddress
752
+ timestamp
753
+ roundAddress
754
+ }
755
+ }
756
+ }
757
+ }`;
758
+ const response = await this.http.fetchGraphql(
759
+ OPERATORS_QUERY,
760
+ after,
761
+ limit
762
+ );
763
+ if (!response || !response.data || !response.data.operatorDelayOperations || !response.data.operatorDelayOperations.edges || response.data.operatorDelayOperations.edges.length === 0) {
764
+ return {
765
+ code: 404,
766
+ error: {
767
+ message: `No operatorDelayOperations found for address ${address}`,
768
+ type: ERROR.ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND
769
+ }
770
+ };
771
+ }
772
+ const operator = {
773
+ code: 200,
774
+ data: response.data
775
+ };
776
+ return operator;
777
+ } catch (error) {
778
+ return handleError(error);
779
+ }
780
+ }
721
781
  async getOperators(after, limit) {
722
782
  try {
723
783
  const OPERATORS_QUERY = `query ($limit: Int, $after: Cursor) {
@@ -821,6 +881,228 @@ var Operator = class {
821
881
  return handleError(error);
822
882
  }
823
883
  }
884
+ async queryMissRate(address, durationDay) {
885
+ try {
886
+ const now = /* @__PURE__ */ new Date();
887
+ const startTime = new Date(
888
+ now.getTime() - durationDay * 24 * 60 * 60 * 1e3
889
+ );
890
+ const startTimestamp = Math.floor(startTime.getTime() / 1e3);
891
+ const endNanosTimestamp = Math.floor(startTime.getTime() * 1e6);
892
+ const txTimestamp = Math.floor(startTime.getTime());
893
+ const QUERY = `query ($limit: Int, $after: Cursor) {
894
+ operatorDelayOperations(
895
+ first: $limit,
896
+ after: $after,
897
+ filter: {
898
+ operatorAddress: {equalTo: "${address}"},
899
+ timestamp: { greaterThanOrEqualTo: "${startTimestamp}" }
900
+ },
901
+ orderBy: [TIMESTAMP_DESC]
902
+ ) {
903
+ edges {
904
+ node {
905
+ blockHeight
906
+ delayProcessDmsgCount
907
+ delayDuration
908
+ delayReason
909
+ delayType
910
+ id
911
+ nodeId
912
+ operatorAddress
913
+ timestamp
914
+ roundAddress
915
+ }
916
+ }
917
+ }
918
+ }`;
919
+ const ROUNDS_QUERY = `query ($limit: Int, $after: Cursor) {
920
+ rounds(first: $limit, after: $after,
921
+ filter: {
922
+ operator: {equalTo: "${address}"},
923
+ votingEnd: { greaterThanOrEqualTo: "${endNanosTimestamp}" }
924
+ },
925
+ orderBy: [TIMESTAMP_DESC]
926
+ ){
927
+ pageInfo {
928
+ endCursor
929
+ hasNextPage
930
+ }
931
+ totalCount
932
+ edges {
933
+ node {
934
+ id
935
+ blockHeight
936
+ txHash
937
+ caller
938
+ admin
939
+ operator
940
+ contractAddress
941
+ circuitName
942
+ timestamp
943
+ votingStart
944
+ votingEnd
945
+ status
946
+ period
947
+ actionType
948
+ roundTitle
949
+ roundDescription
950
+ roundLink
951
+ coordinatorPubkeyX
952
+ coordinatorPubkeyY
953
+ voteOptionMap
954
+ results
955
+ allResult
956
+ gasStationEnable
957
+ totalGrant
958
+ baseGrant
959
+ totalBond
960
+ circuitType
961
+ circuitPower
962
+ certificationSystem
963
+ codeId
964
+ maciType
965
+ voiceCreditAmount
966
+ preDeactivateRoot
967
+ }
968
+ cursor
969
+ }
970
+ }
971
+ }
972
+ `;
973
+ const roundsResponse = await this.http.fetchGraphql(
974
+ ROUNDS_QUERY,
975
+ "",
976
+ 9999
977
+ );
978
+ const roundContractAddresses = roundsResponse?.data?.rounds?.edges?.map(
979
+ (edge) => edge.node.contractAddress
980
+ ) || [];
981
+ const TRANSACTIONS_QUERY = `query transactions($limit: Int, $after: Cursor) {
982
+ transactions(first: $limit, after: $after,
983
+ filter: {
984
+ timestamp: { greaterThanOrEqualTo: "${txTimestamp}" },
985
+ type: { equalTo: "op:procDeactivate" },
986
+ contractAddress: { in: ${JSON.stringify(roundContractAddresses)} }
987
+ },
988
+ orderBy: [TIMESTAMP_DESC]
989
+ ){
990
+ pageInfo {
991
+ endCursor
992
+ hasNextPage
993
+ }
994
+ totalCount
995
+ edges {
996
+ cursor
997
+ node {
998
+ id
999
+ blockHeight
1000
+ txHash
1001
+ timestamp
1002
+ type
1003
+ status
1004
+ circuitName
1005
+ fee
1006
+ gasUsed
1007
+ gasWanted
1008
+ caller
1009
+ contractAddress
1010
+ }
1011
+ }
1012
+ }
1013
+ }`;
1014
+ const [delayResponse, transactionsResponse] = await Promise.all([
1015
+ this.http.fetchGraphql(
1016
+ QUERY,
1017
+ "",
1018
+ 9999
1019
+ ),
1020
+ this.http.fetchGraphql(
1021
+ TRANSACTIONS_QUERY,
1022
+ "",
1023
+ 9999
1024
+ )
1025
+ ]);
1026
+ const dailyStats = /* @__PURE__ */ new Map();
1027
+ const endDate = /* @__PURE__ */ new Date();
1028
+ for (let i = 0; i < durationDay; i++) {
1029
+ const date = new Date(endDate.getTime() - i * 24 * 60 * 60 * 1e3).toISOString().split("T")[0];
1030
+ dailyStats.set(date, {
1031
+ delayCount: 0,
1032
+ deactivateDelay: {
1033
+ count: 0,
1034
+ dmsgCount: 0
1035
+ },
1036
+ tallyDelay: {
1037
+ count: 0
1038
+ },
1039
+ totalDelayDuration: 0,
1040
+ avgDelayDuration: 0,
1041
+ tallyCount: 0,
1042
+ deactivateCount: 0,
1043
+ missRate: 0
1044
+ });
1045
+ }
1046
+ delayResponse.data.operatorDelayOperations.edges.forEach(({ node }) => {
1047
+ const date = new Date(parseInt(node.timestamp) * 1e3).toISOString().split("T")[0];
1048
+ if (dailyStats.has(date)) {
1049
+ const stats = dailyStats.get(date);
1050
+ stats.delayCount++;
1051
+ stats.totalDelayDuration += parseInt(node.delayDuration);
1052
+ if (node.delayType === "deactivate_delay") {
1053
+ stats.deactivateDelay.count++;
1054
+ stats.deactivateDelay.dmsgCount += node.delayProcessDmsgCount;
1055
+ } else if (node.delayType === "tally_delay") {
1056
+ stats.tallyDelay.count++;
1057
+ }
1058
+ }
1059
+ });
1060
+ if (roundsResponse?.data?.rounds?.edges) {
1061
+ roundsResponse.data.rounds.edges.forEach(({ node }) => {
1062
+ const date = new Date(parseInt(node.votingEnd) / 1e6).toISOString().split("T")[0];
1063
+ if (dailyStats.has(date)) {
1064
+ const stats = dailyStats.get(date);
1065
+ stats.tallyCount++;
1066
+ }
1067
+ });
1068
+ }
1069
+ if (transactionsResponse?.data?.transactions?.edges) {
1070
+ transactionsResponse.data.transactions.edges.forEach(({ node }) => {
1071
+ const date = new Date(parseInt(node.timestamp)).toISOString().split("T")[0];
1072
+ if (dailyStats.has(date)) {
1073
+ const stats = dailyStats.get(date);
1074
+ stats.deactivateCount++;
1075
+ }
1076
+ });
1077
+ }
1078
+ return {
1079
+ code: 200,
1080
+ data: {
1081
+ missRate: Array.from(dailyStats.entries()).map(([date, stats]) => ({
1082
+ date,
1083
+ delayCount: stats.delayCount,
1084
+ deactivateDelay: stats.deactivateDelay,
1085
+ tallyDelay: stats.tallyDelay,
1086
+ totalDelayDuration: stats.totalDelayDuration,
1087
+ avgDelayDuration: stats.delayCount > 0 ? stats.totalDelayDuration / stats.delayCount : 0,
1088
+ tallyCount: stats.tallyCount,
1089
+ deactivateCount: stats.deactivateCount,
1090
+ missRate: stats.deactivateCount + stats.tallyCount > 0 ? parseFloat(
1091
+ ((stats.deactivateDelay.count + stats.tallyDelay.count) / (stats.deactivateCount + stats.tallyCount)).toFixed(2)
1092
+ ) : 0
1093
+ })).sort((a, b) => b.date.localeCompare(a.date))
1094
+ }
1095
+ };
1096
+ } catch (error) {
1097
+ return {
1098
+ code: 404,
1099
+ error: {
1100
+ message: "Query miss rate failed",
1101
+ type: ERROR.ERROR_QUERY_MISS_RATE_FAILED
1102
+ }
1103
+ };
1104
+ }
1105
+ }
824
1106
  };
825
1107
 
826
1108
  // src/libs/query/round.ts
@@ -1648,6 +1930,16 @@ var Indexer = class {
1648
1930
  async getOperatorByAddress(address) {
1649
1931
  return await this.operator.getOperatorByAddress(address);
1650
1932
  }
1933
+ async getOperatorDelayOperationsByAddress(address, after, limit) {
1934
+ return await this.operator.getOperatorDelayOperationsByAddress(
1935
+ address,
1936
+ after,
1937
+ limit
1938
+ );
1939
+ }
1940
+ async queryMissRate(address, durationDay) {
1941
+ return await this.operator.queryMissRate(address, durationDay);
1942
+ }
1651
1943
  /**
1652
1944
  * @method getOperators
1653
1945
  * @description Get multiple operators.
@@ -3784,7 +4076,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3784
4076
  `Invalid proof system ${proofSystem}, only support GROTH16 and PLONK`
3785
4077
  );
3786
4078
  }
3787
- if (Number(maxVoter) <= 25 && Number(maxOption) <= 5) {
4079
+ if (maxVoter <= 25 && maxOption <= 5) {
3788
4080
  parameters = CIRCUIT_INFO["2-1-1-5"].parameter;
3789
4081
  if (proofSystem === "groth16" /* GROTH16 */) {
3790
4082
  groth16ProcessVkey = CIRCUIT_INFO["2-1-1-5"]["groth16"].process_vkey;
@@ -3793,7 +4085,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3793
4085
  plonkProcessVkey = CIRCUIT_INFO["2-1-1-5"]["plonk"]?.process_vkey;
3794
4086
  plonkTallyVkey = CIRCUIT_INFO["2-1-1-5"]["plonk"]?.tally_vkey;
3795
4087
  }
3796
- } else if (Number(maxVoter) <= 625 && Number(maxOption) <= 25) {
4088
+ } else if (maxVoter <= 625 && maxOption <= 25) {
3797
4089
  parameters = CIRCUIT_INFO["4-2-2-25"].parameter;
3798
4090
  if (proofSystem === "groth16" /* GROTH16 */) {
3799
4091
  groth16ProcessVkey = CIRCUIT_INFO["4-2-2-25"]["groth16"].process_vkey;
@@ -3802,7 +4094,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3802
4094
  plonkProcessVkey = CIRCUIT_INFO["4-2-2-25"]["plonk"]?.process_vkey;
3803
4095
  plonkTallyVkey = CIRCUIT_INFO["4-2-2-25"]["plonk"]?.tally_vkey;
3804
4096
  }
3805
- } else if (Number(maxVoter) <= 15625 && Number(maxOption) <= 125) {
4097
+ } else if (maxVoter <= 15625 && maxOption <= 125) {
3806
4098
  parameters = CIRCUIT_INFO["6-3-3-125"].parameter;
3807
4099
  if (proofSystem === "groth16" /* GROTH16 */) {
3808
4100
  groth16ProcessVkey = CIRCUIT_INFO["6-3-3-125"]["groth16"].process_vkey;
@@ -3811,7 +4103,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3811
4103
  plonkProcessVkey = CIRCUIT_INFO["6-3-3-125"]["plonk"]?.process_vkey;
3812
4104
  plonkTallyVkey = CIRCUIT_INFO["6-3-3-125"]["plonk"]?.tally_vkey;
3813
4105
  }
3814
- } else if (Number(maxVoter) <= 1953125 && Number(maxOption) <= 125) {
4106
+ } else if (maxVoter <= 1953125 && maxOption <= 125) {
3815
4107
  parameters = CIRCUIT_INFO["9-4-3-625"].parameter;
3816
4108
  if (proofSystem === "groth16" /* GROTH16 */) {
3817
4109
  if (circuitType === "0" /* IP1V */) {
@@ -3865,6 +4157,20 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3865
4157
  };
3866
4158
  }
3867
4159
  }
4160
+ function getAMaciRoundCircuitFee(maxVoter, maxOption) {
4161
+ let requiredFee = {
4162
+ denom: "peaka",
4163
+ amount: "0"
4164
+ };
4165
+ if (maxVoter <= 25 && maxOption <= 5) {
4166
+ requiredFee.amount = "50000000000000000000";
4167
+ } else if (maxVoter <= 625 && maxOption <= 25) {
4168
+ requiredFee.amount = "100000000000000000000";
4169
+ } else {
4170
+ throw new Error("Number of voters or options is too large.");
4171
+ }
4172
+ return requiredFee;
4173
+ }
3868
4174
 
3869
4175
  // src/libs/contract/contract.ts
3870
4176
  var Contract = class {
@@ -3905,26 +4211,32 @@ var Contract = class {
3905
4211
  wallet: signer,
3906
4212
  contractAddress: this.registryAddress
3907
4213
  });
4214
+ const requiredFee = getAMaciRoundCircuitFee(maxVoter, maxOption);
3908
4215
  preDeactivateRoot = preDeactivateRoot || "0";
3909
- const res = await client.createRound({
3910
- operator,
3911
- preDeactivateRoot,
3912
- voiceCreditAmount,
3913
- whitelist,
3914
- roundInfo: {
3915
- title,
3916
- description: description || "",
3917
- link: link || ""
3918
- },
3919
- votingTime: {
3920
- start_time,
3921
- end_time
4216
+ const res = await client.createRound(
4217
+ {
4218
+ operator,
4219
+ preDeactivateRoot,
4220
+ voiceCreditAmount,
4221
+ whitelist,
4222
+ roundInfo: {
4223
+ title,
4224
+ description: description || "",
4225
+ link: link || ""
4226
+ },
4227
+ votingTime: {
4228
+ start_time,
4229
+ end_time
4230
+ },
4231
+ maxVoter: maxVoter.toString(),
4232
+ maxOption: maxOption.toString(),
4233
+ certificationSystem: "0",
4234
+ circuitType
3922
4235
  },
3923
- maxVoter,
3924
- maxOption,
3925
- certificationSystem: "0",
3926
- circuitType
3927
- });
4236
+ "auto",
4237
+ void 0,
4238
+ [requiredFee]
4239
+ );
3928
4240
  let contractAddress = "";
3929
4241
  res.events.map((event) => {
3930
4242
  if (event.type === "wasm") {
@@ -4024,8 +4336,8 @@ var Contract = class {
4024
4336
  "2" /* ORACLE_MACI */,
4025
4337
  circuitType,
4026
4338
  "groth16" /* GROTH16 */,
4027
- "0",
4028
- "0"
4339
+ 0,
4340
+ 0
4029
4341
  );
4030
4342
  const instantiateResponse = await client.instantiate(
4031
4343
  address,
@@ -4580,6 +4892,50 @@ var MACI = class {
4580
4892
  const circuitType = await this.getRoundCircuitType({ contractAddress });
4581
4893
  return circuitType === "1";
4582
4894
  }
4895
+ async queryRoundClaimable({
4896
+ contractAddress
4897
+ }) {
4898
+ try {
4899
+ const roundInfo = await this.getRoundInfo({ contractAddress });
4900
+ if (roundInfo.maciType !== "aMACI") {
4901
+ return {
4902
+ claimable: null,
4903
+ balance: null
4904
+ };
4905
+ }
4906
+ const votingEndTime = new Date(Number(roundInfo.votingEnd) / 10 ** 6);
4907
+ const currentTime = /* @__PURE__ */ new Date();
4908
+ const threeDaysInMs = 3 * 24 * 60 * 60 * 1e3;
4909
+ if (currentTime.getTime() - votingEndTime.getTime() <= threeDaysInMs) {
4910
+ return {
4911
+ claimable: null,
4912
+ balance: null
4913
+ };
4914
+ }
4915
+ const roundBalance = await this.indexer.balanceOf(contractAddress);
4916
+ if (isErrorResponse(roundBalance)) {
4917
+ throw new Error(
4918
+ `Failed to query round balance: ${roundBalance.error.type} ${roundBalance.error.message}`
4919
+ );
4920
+ }
4921
+ if (roundBalance.data.balance && roundBalance.data.balance !== "0" && roundBalance.data.balance !== "") {
4922
+ return {
4923
+ claimable: true,
4924
+ balance: roundBalance.data.balance
4925
+ };
4926
+ }
4927
+ return {
4928
+ claimable: false,
4929
+ balance: roundBalance.data.balance
4930
+ };
4931
+ } catch (error) {
4932
+ console.error("Error in queryRoundClaimable:", error);
4933
+ return {
4934
+ claimable: null,
4935
+ balance: null
4936
+ };
4937
+ }
4938
+ }
4583
4939
  async queryRoundGasStation({ contractAddress }) {
4584
4940
  const roundInfo = await this.getRoundInfo({ contractAddress });
4585
4941
  return roundInfo.gasStationEnable;