@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.mjs CHANGED
@@ -223,6 +223,8 @@ var ERROR = {
223
223
  ERROR_CIRCUIT_NOT_FOUND: "ERROR_CIRCUIT_NOT_FOUND",
224
224
  ERROR_OPERATOR_INVALID_ADDRESS: "ERROR_OPERATOR_INVALID_ADDRESS",
225
225
  ERROR_OPERATOR_NOT_FOUND: "ERROR_OPERATOR_NOT_FOUND",
226
+ ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND: "ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND",
227
+ ERROR_QUERY_MISS_RATE_FAILED: "ERROR_QUERY_MISS_RATE_FAILED",
226
228
  ERROR_OPERATORS_NOT_FOUND: "ERROR_OPERATORS_NOT_FOUND",
227
229
  ERROR_PROOF_NOT_FOUND: "ERROR_PROOF_NOT_FOUND",
228
230
  ERROR_ROUND_INVALID_ADDRESS: "ERROR_ROUND_INVALID_ADDRESS",
@@ -649,6 +651,64 @@ var Operator = class {
649
651
  return handleError(error);
650
652
  }
651
653
  }
654
+ async getOperatorDelayOperationsByAddress(address, after, limit) {
655
+ try {
656
+ if (!isValidAddress(address)) {
657
+ return {
658
+ code: 400,
659
+ error: {
660
+ message: "Invalid operator address format",
661
+ type: ERROR.ERROR_OPERATOR_INVALID_ADDRESS
662
+ }
663
+ };
664
+ }
665
+ const OPERATORS_QUERY = `query ($limit: Int, $after: Cursor) {
666
+ operatorDelayOperations(first: $limit, after: $after, filter: {operatorAddress: {equalTo: "${address}"}}, orderBy: [TIMESTAMP_DESC]) {
667
+ pageInfo {
668
+ endCursor
669
+ hasNextPage
670
+ }
671
+ totalCount
672
+ edges {
673
+ cursor
674
+ node {
675
+ blockHeight
676
+ delayProcessDmsgCount
677
+ delayDuration
678
+ delayReason
679
+ delayType
680
+ id
681
+ nodeId
682
+ operatorAddress
683
+ timestamp
684
+ roundAddress
685
+ }
686
+ }
687
+ }
688
+ }`;
689
+ const response = await this.http.fetchGraphql(
690
+ OPERATORS_QUERY,
691
+ after,
692
+ limit
693
+ );
694
+ if (!response || !response.data || !response.data.operatorDelayOperations || !response.data.operatorDelayOperations.edges || response.data.operatorDelayOperations.edges.length === 0) {
695
+ return {
696
+ code: 404,
697
+ error: {
698
+ message: `No operatorDelayOperations found for address ${address}`,
699
+ type: ERROR.ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND
700
+ }
701
+ };
702
+ }
703
+ const operator = {
704
+ code: 200,
705
+ data: response.data
706
+ };
707
+ return operator;
708
+ } catch (error) {
709
+ return handleError(error);
710
+ }
711
+ }
652
712
  async getOperators(after, limit) {
653
713
  try {
654
714
  const OPERATORS_QUERY = `query ($limit: Int, $after: Cursor) {
@@ -752,6 +812,228 @@ var Operator = class {
752
812
  return handleError(error);
753
813
  }
754
814
  }
815
+ async queryMissRate(address, durationDay) {
816
+ try {
817
+ const now = /* @__PURE__ */ new Date();
818
+ const startTime = new Date(
819
+ now.getTime() - durationDay * 24 * 60 * 60 * 1e3
820
+ );
821
+ const startTimestamp = Math.floor(startTime.getTime() / 1e3);
822
+ const endNanosTimestamp = Math.floor(startTime.getTime() * 1e6);
823
+ const txTimestamp = Math.floor(startTime.getTime());
824
+ const QUERY = `query ($limit: Int, $after: Cursor) {
825
+ operatorDelayOperations(
826
+ first: $limit,
827
+ after: $after,
828
+ filter: {
829
+ operatorAddress: {equalTo: "${address}"},
830
+ timestamp: { greaterThanOrEqualTo: "${startTimestamp}" }
831
+ },
832
+ orderBy: [TIMESTAMP_DESC]
833
+ ) {
834
+ edges {
835
+ node {
836
+ blockHeight
837
+ delayProcessDmsgCount
838
+ delayDuration
839
+ delayReason
840
+ delayType
841
+ id
842
+ nodeId
843
+ operatorAddress
844
+ timestamp
845
+ roundAddress
846
+ }
847
+ }
848
+ }
849
+ }`;
850
+ const ROUNDS_QUERY = `query ($limit: Int, $after: Cursor) {
851
+ rounds(first: $limit, after: $after,
852
+ filter: {
853
+ operator: {equalTo: "${address}"},
854
+ votingEnd: { greaterThanOrEqualTo: "${endNanosTimestamp}" }
855
+ },
856
+ orderBy: [TIMESTAMP_DESC]
857
+ ){
858
+ pageInfo {
859
+ endCursor
860
+ hasNextPage
861
+ }
862
+ totalCount
863
+ edges {
864
+ node {
865
+ id
866
+ blockHeight
867
+ txHash
868
+ caller
869
+ admin
870
+ operator
871
+ contractAddress
872
+ circuitName
873
+ timestamp
874
+ votingStart
875
+ votingEnd
876
+ status
877
+ period
878
+ actionType
879
+ roundTitle
880
+ roundDescription
881
+ roundLink
882
+ coordinatorPubkeyX
883
+ coordinatorPubkeyY
884
+ voteOptionMap
885
+ results
886
+ allResult
887
+ gasStationEnable
888
+ totalGrant
889
+ baseGrant
890
+ totalBond
891
+ circuitType
892
+ circuitPower
893
+ certificationSystem
894
+ codeId
895
+ maciType
896
+ voiceCreditAmount
897
+ preDeactivateRoot
898
+ }
899
+ cursor
900
+ }
901
+ }
902
+ }
903
+ `;
904
+ const roundsResponse = await this.http.fetchGraphql(
905
+ ROUNDS_QUERY,
906
+ "",
907
+ 9999
908
+ );
909
+ const roundContractAddresses = roundsResponse?.data?.rounds?.edges?.map(
910
+ (edge) => edge.node.contractAddress
911
+ ) || [];
912
+ const TRANSACTIONS_QUERY = `query transactions($limit: Int, $after: Cursor) {
913
+ transactions(first: $limit, after: $after,
914
+ filter: {
915
+ timestamp: { greaterThanOrEqualTo: "${txTimestamp}" },
916
+ type: { equalTo: "op:procDeactivate" },
917
+ contractAddress: { in: ${JSON.stringify(roundContractAddresses)} }
918
+ },
919
+ orderBy: [TIMESTAMP_DESC]
920
+ ){
921
+ pageInfo {
922
+ endCursor
923
+ hasNextPage
924
+ }
925
+ totalCount
926
+ edges {
927
+ cursor
928
+ node {
929
+ id
930
+ blockHeight
931
+ txHash
932
+ timestamp
933
+ type
934
+ status
935
+ circuitName
936
+ fee
937
+ gasUsed
938
+ gasWanted
939
+ caller
940
+ contractAddress
941
+ }
942
+ }
943
+ }
944
+ }`;
945
+ const [delayResponse, transactionsResponse] = await Promise.all([
946
+ this.http.fetchGraphql(
947
+ QUERY,
948
+ "",
949
+ 9999
950
+ ),
951
+ this.http.fetchGraphql(
952
+ TRANSACTIONS_QUERY,
953
+ "",
954
+ 9999
955
+ )
956
+ ]);
957
+ const dailyStats = /* @__PURE__ */ new Map();
958
+ const endDate = /* @__PURE__ */ new Date();
959
+ for (let i = 0; i < durationDay; i++) {
960
+ const date = new Date(endDate.getTime() - i * 24 * 60 * 60 * 1e3).toISOString().split("T")[0];
961
+ dailyStats.set(date, {
962
+ delayCount: 0,
963
+ deactivateDelay: {
964
+ count: 0,
965
+ dmsgCount: 0
966
+ },
967
+ tallyDelay: {
968
+ count: 0
969
+ },
970
+ totalDelayDuration: 0,
971
+ avgDelayDuration: 0,
972
+ tallyCount: 0,
973
+ deactivateCount: 0,
974
+ missRate: 0
975
+ });
976
+ }
977
+ delayResponse.data.operatorDelayOperations.edges.forEach(({ node }) => {
978
+ const date = new Date(parseInt(node.timestamp) * 1e3).toISOString().split("T")[0];
979
+ if (dailyStats.has(date)) {
980
+ const stats = dailyStats.get(date);
981
+ stats.delayCount++;
982
+ stats.totalDelayDuration += parseInt(node.delayDuration);
983
+ if (node.delayType === "deactivate_delay") {
984
+ stats.deactivateDelay.count++;
985
+ stats.deactivateDelay.dmsgCount += node.delayProcessDmsgCount;
986
+ } else if (node.delayType === "tally_delay") {
987
+ stats.tallyDelay.count++;
988
+ }
989
+ }
990
+ });
991
+ if (roundsResponse?.data?.rounds?.edges) {
992
+ roundsResponse.data.rounds.edges.forEach(({ node }) => {
993
+ const date = new Date(parseInt(node.votingEnd) / 1e6).toISOString().split("T")[0];
994
+ if (dailyStats.has(date)) {
995
+ const stats = dailyStats.get(date);
996
+ stats.tallyCount++;
997
+ }
998
+ });
999
+ }
1000
+ if (transactionsResponse?.data?.transactions?.edges) {
1001
+ transactionsResponse.data.transactions.edges.forEach(({ node }) => {
1002
+ const date = new Date(parseInt(node.timestamp)).toISOString().split("T")[0];
1003
+ if (dailyStats.has(date)) {
1004
+ const stats = dailyStats.get(date);
1005
+ stats.deactivateCount++;
1006
+ }
1007
+ });
1008
+ }
1009
+ return {
1010
+ code: 200,
1011
+ data: {
1012
+ missRate: Array.from(dailyStats.entries()).map(([date, stats]) => ({
1013
+ date,
1014
+ delayCount: stats.delayCount,
1015
+ deactivateDelay: stats.deactivateDelay,
1016
+ tallyDelay: stats.tallyDelay,
1017
+ totalDelayDuration: stats.totalDelayDuration,
1018
+ avgDelayDuration: stats.delayCount > 0 ? stats.totalDelayDuration / stats.delayCount : 0,
1019
+ tallyCount: stats.tallyCount,
1020
+ deactivateCount: stats.deactivateCount,
1021
+ missRate: stats.deactivateCount + stats.tallyCount > 0 ? parseFloat(
1022
+ ((stats.deactivateDelay.count + stats.tallyDelay.count) / (stats.deactivateCount + stats.tallyCount)).toFixed(2)
1023
+ ) : 0
1024
+ })).sort((a, b) => b.date.localeCompare(a.date))
1025
+ }
1026
+ };
1027
+ } catch (error) {
1028
+ return {
1029
+ code: 404,
1030
+ error: {
1031
+ message: "Query miss rate failed",
1032
+ type: ERROR.ERROR_QUERY_MISS_RATE_FAILED
1033
+ }
1034
+ };
1035
+ }
1036
+ }
755
1037
  };
756
1038
 
757
1039
  // src/libs/query/round.ts
@@ -1579,6 +1861,16 @@ var Indexer = class {
1579
1861
  async getOperatorByAddress(address) {
1580
1862
  return await this.operator.getOperatorByAddress(address);
1581
1863
  }
1864
+ async getOperatorDelayOperationsByAddress(address, after, limit) {
1865
+ return await this.operator.getOperatorDelayOperationsByAddress(
1866
+ address,
1867
+ after,
1868
+ limit
1869
+ );
1870
+ }
1871
+ async queryMissRate(address, durationDay) {
1872
+ return await this.operator.queryMissRate(address, durationDay);
1873
+ }
1582
1874
  /**
1583
1875
  * @method getOperators
1584
1876
  * @description Get multiple operators.
@@ -3720,7 +4012,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3720
4012
  `Invalid proof system ${proofSystem}, only support GROTH16 and PLONK`
3721
4013
  );
3722
4014
  }
3723
- if (Number(maxVoter) <= 25 && Number(maxOption) <= 5) {
4015
+ if (maxVoter <= 25 && maxOption <= 5) {
3724
4016
  parameters = CIRCUIT_INFO["2-1-1-5"].parameter;
3725
4017
  if (proofSystem === "groth16" /* GROTH16 */) {
3726
4018
  groth16ProcessVkey = CIRCUIT_INFO["2-1-1-5"]["groth16"].process_vkey;
@@ -3729,7 +4021,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3729
4021
  plonkProcessVkey = CIRCUIT_INFO["2-1-1-5"]["plonk"]?.process_vkey;
3730
4022
  plonkTallyVkey = CIRCUIT_INFO["2-1-1-5"]["plonk"]?.tally_vkey;
3731
4023
  }
3732
- } else if (Number(maxVoter) <= 625 && Number(maxOption) <= 25) {
4024
+ } else if (maxVoter <= 625 && maxOption <= 25) {
3733
4025
  parameters = CIRCUIT_INFO["4-2-2-25"].parameter;
3734
4026
  if (proofSystem === "groth16" /* GROTH16 */) {
3735
4027
  groth16ProcessVkey = CIRCUIT_INFO["4-2-2-25"]["groth16"].process_vkey;
@@ -3738,7 +4030,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3738
4030
  plonkProcessVkey = CIRCUIT_INFO["4-2-2-25"]["plonk"]?.process_vkey;
3739
4031
  plonkTallyVkey = CIRCUIT_INFO["4-2-2-25"]["plonk"]?.tally_vkey;
3740
4032
  }
3741
- } else if (Number(maxVoter) <= 15625 && Number(maxOption) <= 125) {
4033
+ } else if (maxVoter <= 15625 && maxOption <= 125) {
3742
4034
  parameters = CIRCUIT_INFO["6-3-3-125"].parameter;
3743
4035
  if (proofSystem === "groth16" /* GROTH16 */) {
3744
4036
  groth16ProcessVkey = CIRCUIT_INFO["6-3-3-125"]["groth16"].process_vkey;
@@ -3747,7 +4039,7 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3747
4039
  plonkProcessVkey = CIRCUIT_INFO["6-3-3-125"]["plonk"]?.process_vkey;
3748
4040
  plonkTallyVkey = CIRCUIT_INFO["6-3-3-125"]["plonk"]?.tally_vkey;
3749
4041
  }
3750
- } else if (Number(maxVoter) <= 1953125 && Number(maxOption) <= 125) {
4042
+ } else if (maxVoter <= 1953125 && maxOption <= 125) {
3751
4043
  parameters = CIRCUIT_INFO["9-4-3-625"].parameter;
3752
4044
  if (proofSystem === "groth16" /* GROTH16 */) {
3753
4045
  if (circuitType === "0" /* IP1V */) {
@@ -3801,6 +4093,20 @@ function getContractParams(type, circuitType, proofSystem, maxVoter, maxOption)
3801
4093
  };
3802
4094
  }
3803
4095
  }
4096
+ function getAMaciRoundCircuitFee(maxVoter, maxOption) {
4097
+ let requiredFee = {
4098
+ denom: "peaka",
4099
+ amount: "0"
4100
+ };
4101
+ if (maxVoter <= 25 && maxOption <= 5) {
4102
+ requiredFee.amount = "50000000000000000000";
4103
+ } else if (maxVoter <= 625 && maxOption <= 25) {
4104
+ requiredFee.amount = "100000000000000000000";
4105
+ } else {
4106
+ throw new Error("Number of voters or options is too large.");
4107
+ }
4108
+ return requiredFee;
4109
+ }
3804
4110
 
3805
4111
  // src/libs/contract/contract.ts
3806
4112
  var Contract = class {
@@ -3841,26 +4147,32 @@ var Contract = class {
3841
4147
  wallet: signer,
3842
4148
  contractAddress: this.registryAddress
3843
4149
  });
4150
+ const requiredFee = getAMaciRoundCircuitFee(maxVoter, maxOption);
3844
4151
  preDeactivateRoot = preDeactivateRoot || "0";
3845
- const res = await client.createRound({
3846
- operator,
3847
- preDeactivateRoot,
3848
- voiceCreditAmount,
3849
- whitelist,
3850
- roundInfo: {
3851
- title,
3852
- description: description || "",
3853
- link: link || ""
3854
- },
3855
- votingTime: {
3856
- start_time,
3857
- end_time
4152
+ const res = await client.createRound(
4153
+ {
4154
+ operator,
4155
+ preDeactivateRoot,
4156
+ voiceCreditAmount,
4157
+ whitelist,
4158
+ roundInfo: {
4159
+ title,
4160
+ description: description || "",
4161
+ link: link || ""
4162
+ },
4163
+ votingTime: {
4164
+ start_time,
4165
+ end_time
4166
+ },
4167
+ maxVoter: maxVoter.toString(),
4168
+ maxOption: maxOption.toString(),
4169
+ certificationSystem: "0",
4170
+ circuitType
3858
4171
  },
3859
- maxVoter,
3860
- maxOption,
3861
- certificationSystem: "0",
3862
- circuitType
3863
- });
4172
+ "auto",
4173
+ void 0,
4174
+ [requiredFee]
4175
+ );
3864
4176
  let contractAddress = "";
3865
4177
  res.events.map((event) => {
3866
4178
  if (event.type === "wasm") {
@@ -3960,8 +4272,8 @@ var Contract = class {
3960
4272
  "2" /* ORACLE_MACI */,
3961
4273
  circuitType,
3962
4274
  "groth16" /* GROTH16 */,
3963
- "0",
3964
- "0"
4275
+ 0,
4276
+ 0
3965
4277
  );
3966
4278
  const instantiateResponse = await client.instantiate(
3967
4279
  address,
@@ -4524,6 +4836,50 @@ var MACI = class {
4524
4836
  const circuitType = await this.getRoundCircuitType({ contractAddress });
4525
4837
  return circuitType === "1";
4526
4838
  }
4839
+ async queryRoundClaimable({
4840
+ contractAddress
4841
+ }) {
4842
+ try {
4843
+ const roundInfo = await this.getRoundInfo({ contractAddress });
4844
+ if (roundInfo.maciType !== "aMACI") {
4845
+ return {
4846
+ claimable: null,
4847
+ balance: null
4848
+ };
4849
+ }
4850
+ const votingEndTime = new Date(Number(roundInfo.votingEnd) / 10 ** 6);
4851
+ const currentTime = /* @__PURE__ */ new Date();
4852
+ const threeDaysInMs = 3 * 24 * 60 * 60 * 1e3;
4853
+ if (currentTime.getTime() - votingEndTime.getTime() <= threeDaysInMs) {
4854
+ return {
4855
+ claimable: null,
4856
+ balance: null
4857
+ };
4858
+ }
4859
+ const roundBalance = await this.indexer.balanceOf(contractAddress);
4860
+ if (isErrorResponse(roundBalance)) {
4861
+ throw new Error(
4862
+ `Failed to query round balance: ${roundBalance.error.type} ${roundBalance.error.message}`
4863
+ );
4864
+ }
4865
+ if (roundBalance.data.balance && roundBalance.data.balance !== "0" && roundBalance.data.balance !== "") {
4866
+ return {
4867
+ claimable: true,
4868
+ balance: roundBalance.data.balance
4869
+ };
4870
+ }
4871
+ return {
4872
+ claimable: false,
4873
+ balance: roundBalance.data.balance
4874
+ };
4875
+ } catch (error) {
4876
+ console.error("Error in queryRoundClaimable:", error);
4877
+ return {
4878
+ claimable: null,
4879
+ balance: null
4880
+ };
4881
+ }
4882
+ }
4527
4883
  async queryRoundGasStation({ contractAddress }) {
4528
4884
  const roundInfo = await this.getRoundInfo({ contractAddress });
4529
4885
  return roundInfo.gasStationEnable;