@dorafactory/maci-sdk 0.0.19 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dorafactory/maci-sdk",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "description": "SDK for interacting with maci",
5
5
  "keywords": [
6
6
  "maci",
@@ -27,7 +27,11 @@ import {
27
27
  CreateMaciRoundParams,
28
28
  CreateOracleMaciRoundParams,
29
29
  } from './types';
30
- import { getCircuitType, getContractParams } from './utils';
30
+ import {
31
+ getAMaciRoundCircuitFee,
32
+ getCircuitType,
33
+ getContractParams,
34
+ } from './utils';
31
35
  import { QTR_LIB } from './vars';
32
36
  import { MaciRoundType, MaciCertSystemType } from '../../types';
33
37
  import { decompressPublicKey } from '../../utils';
@@ -82,26 +86,33 @@ export class Contract {
82
86
  contractAddress: this.registryAddress,
83
87
  });
84
88
 
89
+ const requiredFee = getAMaciRoundCircuitFee(maxVoter, maxOption);
90
+
85
91
  preDeactivateRoot = preDeactivateRoot || '0';
86
- const res = await client.createRound({
87
- operator,
88
- preDeactivateRoot,
89
- voiceCreditAmount,
90
- whitelist,
91
- roundInfo: {
92
- title,
93
- description: description || '',
94
- link: link || '',
95
- },
96
- votingTime: {
97
- start_time,
98
- end_time,
92
+ const res = await client.createRound(
93
+ {
94
+ operator,
95
+ preDeactivateRoot,
96
+ voiceCreditAmount,
97
+ whitelist,
98
+ roundInfo: {
99
+ title,
100
+ description: description || '',
101
+ link: link || '',
102
+ },
103
+ votingTime: {
104
+ start_time,
105
+ end_time,
106
+ },
107
+ maxVoter: maxVoter.toString(),
108
+ maxOption: maxOption.toString(),
109
+ certificationSystem: '0',
110
+ circuitType,
99
111
  },
100
- maxVoter,
101
- maxOption,
102
- certificationSystem: '0',
103
- circuitType,
104
- });
112
+ 'auto',
113
+ undefined,
114
+ [requiredFee]
115
+ );
105
116
  let contractAddress = '';
106
117
  res.events.map((event) => {
107
118
  if (event.type === 'wasm') {
@@ -208,8 +219,8 @@ export class Contract {
208
219
  MaciRoundType.ORACLE_MACI,
209
220
  circuitType,
210
221
  MaciCertSystemType.GROTH16,
211
- '0',
212
- '0'
222
+ 0,
223
+ 0
213
224
  );
214
225
  const instantiateResponse = await client.instantiate(
215
226
  address,
@@ -18,8 +18,8 @@ export type CreateRoundParams = {
18
18
  };
19
19
 
20
20
  export type CreateAMaciRoundParams = {
21
- maxVoter: string;
22
- maxOption: string;
21
+ maxVoter: number;
22
+ maxOption: number;
23
23
  operator: string;
24
24
  whitelist: RegistryWhitelist;
25
25
  voiceCreditAmount: string;
@@ -27,8 +27,8 @@ export type CreateAMaciRoundParams = {
27
27
  } & CreateRoundParams;
28
28
 
29
29
  export type CreateMaciRoundParams = {
30
- maxVoter: string;
31
- maxOption: string;
30
+ maxVoter: number;
31
+ maxOption: number;
32
32
  operatorPubkey: string;
33
33
  whitelist: MaciWhitelist;
34
34
  certSystemType: MaciCertSystemType;
@@ -50,8 +50,8 @@ export function getContractParams(
50
50
  type: MaciRoundType,
51
51
  circuitType: MaciCircuitType,
52
52
  proofSystem: MaciCertSystemType,
53
- maxVoter: string,
54
- maxOption: string
53
+ maxVoter: number,
54
+ maxOption: number
55
55
  ) {
56
56
  let parameters: {
57
57
  state_tree_depth: string;
@@ -92,7 +92,7 @@ export function getContractParams(
92
92
  );
93
93
  }
94
94
 
95
- if (Number(maxVoter) <= 25 && Number(maxOption) <= 5) {
95
+ if (maxVoter <= 25 && maxOption <= 5) {
96
96
  // state_tree_depth: 2
97
97
  // vote_option_tree_depth: 1
98
98
  parameters = CIRCUIT_INFO['2-1-1-5'].parameter;
@@ -103,7 +103,7 @@ export function getContractParams(
103
103
  plonkProcessVkey = CIRCUIT_INFO['2-1-1-5']['plonk']?.process_vkey;
104
104
  plonkTallyVkey = CIRCUIT_INFO['2-1-1-5']['plonk']?.tally_vkey;
105
105
  }
106
- } else if (Number(maxVoter) <= 625 && Number(maxOption) <= 25) {
106
+ } else if (maxVoter <= 625 && maxOption <= 25) {
107
107
  // state_tree_depth: 4
108
108
  // vote_option_tree_depth: 2
109
109
  parameters = CIRCUIT_INFO['4-2-2-25'].parameter;
@@ -114,7 +114,7 @@ export function getContractParams(
114
114
  plonkProcessVkey = CIRCUIT_INFO['4-2-2-25']['plonk']?.process_vkey;
115
115
  plonkTallyVkey = CIRCUIT_INFO['4-2-2-25']['plonk']?.tally_vkey;
116
116
  }
117
- } else if (Number(maxVoter) <= 15625 && Number(maxOption) <= 125) {
117
+ } else if (maxVoter <= 15625 && maxOption <= 125) {
118
118
  // state_tree_depth: 6
119
119
  // vote_option_tree_depth: 3
120
120
  parameters = CIRCUIT_INFO['6-3-3-125'].parameter;
@@ -125,7 +125,7 @@ export function getContractParams(
125
125
  plonkProcessVkey = CIRCUIT_INFO['6-3-3-125']['plonk']?.process_vkey;
126
126
  plonkTallyVkey = CIRCUIT_INFO['6-3-3-125']['plonk']?.tally_vkey;
127
127
  }
128
- } else if (Number(maxVoter) <= 1953125 && Number(maxOption) <= 125) {
128
+ } else if (maxVoter <= 1953125 && maxOption <= 125) {
129
129
  // state_tree_depth: 9
130
130
  // vote_option_tree_depth: 3
131
131
  parameters = CIRCUIT_INFO['9-4-3-625'].parameter;
@@ -185,3 +185,23 @@ export function getContractParams(
185
185
  };
186
186
  }
187
187
  }
188
+
189
+ export function getAMaciRoundCircuitFee(maxVoter: number, maxOption: number) {
190
+ let requiredFee = {
191
+ denom: 'peaka',
192
+ amount: '0',
193
+ };
194
+ if (maxVoter <= 25 && maxOption <= 5) {
195
+ // state_tree_depth: 2
196
+ // vote_option_tree_depth: 1
197
+ requiredFee.amount = '50000000000000000000';
198
+ } else if (maxVoter <= 625 && maxOption <= 25) {
199
+ // state_tree_depth: 4
200
+ // vote_option_tree_depth: 2
201
+ requiredFee.amount = '100000000000000000000';
202
+ } else {
203
+ throw new Error('Number of voters or options is too large.');
204
+ }
205
+
206
+ return requiredFee;
207
+ }
@@ -3,6 +3,9 @@ export const ERROR = {
3
3
  ERROR_CIRCUIT_NOT_FOUND: 'ERROR_CIRCUIT_NOT_FOUND',
4
4
  ERROR_OPERATOR_INVALID_ADDRESS: 'ERROR_OPERATOR_INVALID_ADDRESS',
5
5
  ERROR_OPERATOR_NOT_FOUND: 'ERROR_OPERATOR_NOT_FOUND',
6
+ ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND:
7
+ 'ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND',
8
+ ERROR_QUERY_MISS_RATE_FAILED: 'ERROR_QUERY_MISS_RATE_FAILED',
6
9
  ERROR_OPERATORS_NOT_FOUND: 'ERROR_OPERATORS_NOT_FOUND',
7
10
  ERROR_PROOF_NOT_FOUND: 'ERROR_PROOF_NOT_FOUND',
8
11
  ERROR_ROUND_INVALID_ADDRESS: 'ERROR_ROUND_INVALID_ADDRESS',
@@ -116,11 +116,12 @@ export class Http {
116
116
  }
117
117
  }
118
118
 
119
- async fetchRest(path: string): Promise<any> {
119
+ async fetchRest(path: string, options?: any): Promise<any> {
120
120
  try {
121
121
  const fetchFn = this.getFetch();
122
122
  const response = await fetchFn(`${this.restEndpoint}${path}`, {
123
123
  ...this.defaultOptions,
124
+ ...options,
124
125
  });
125
126
 
126
127
  if (!response.ok) {
@@ -10,6 +10,8 @@ import {
10
10
  CircuitsResponse,
11
11
  ProofResponse,
12
12
  SignUpEventsResponse,
13
+ OperatorDelayOperationsResponse,
14
+ MissRateResponse,
13
15
  } from '../../types';
14
16
  import { IndexerParams } from './types';
15
17
  import { Http } from '../http';
@@ -155,6 +157,25 @@ export class Indexer {
155
157
  return await this.operator.getOperatorByAddress(address);
156
158
  }
157
159
 
160
+ async getOperatorDelayOperationsByAddress(
161
+ address: string,
162
+ after: string,
163
+ limit?: number
164
+ ): Promise<OperatorDelayOperationsResponse> {
165
+ return await this.operator.getOperatorDelayOperationsByAddress(
166
+ address,
167
+ after,
168
+ limit
169
+ );
170
+ }
171
+
172
+ async queryMissRate(
173
+ address: string,
174
+ durationDay: number
175
+ ): Promise<MissRateResponse> {
176
+ return await this.operator.queryMissRate(address, durationDay);
177
+ }
178
+
158
179
  /**
159
180
  * @method getOperators
160
181
  * @description Get multiple operators.
@@ -107,6 +107,28 @@ export class MACI {
107
107
  return response.data.signUpEvents[0].stateIdx;
108
108
  }
109
109
 
110
+ async feegrantAllowance({
111
+ address,
112
+ contractAddress,
113
+ }: {
114
+ address: string;
115
+ contractAddress: string;
116
+ }) {
117
+ try {
118
+ const response = await this.oracleCertificate.feegrantAllowance(
119
+ contractAddress,
120
+ address
121
+ );
122
+ return response;
123
+ } catch (error) {
124
+ return {
125
+ granter: contractAddress,
126
+ grantee: address,
127
+ spend_limit: [],
128
+ };
129
+ }
130
+ }
131
+
110
132
  // only for maci and oracle maci, amaci will set the voice credit when deploy the contract
111
133
  async queryWhitelistBalanceOf({
112
134
  signer,
@@ -231,6 +253,66 @@ export class MACI {
231
253
  return circuitType === '1';
232
254
  }
233
255
 
256
+ async queryRoundClaimable({
257
+ contractAddress,
258
+ }: {
259
+ contractAddress: string;
260
+ }): Promise<{
261
+ claimable: boolean | null;
262
+ balance: string | null;
263
+ }> {
264
+ try {
265
+ const roundInfo = await this.getRoundInfo({ contractAddress });
266
+
267
+ if (roundInfo.maciType !== 'aMACI') {
268
+ return {
269
+ claimable: null,
270
+ balance: null,
271
+ };
272
+ }
273
+
274
+ const votingEndTime = new Date(Number(roundInfo.votingEnd) / 10 ** 6);
275
+ const currentTime = new Date();
276
+ const threeDaysInMs = 3 * 24 * 60 * 60 * 1000;
277
+
278
+ if (currentTime.getTime() - votingEndTime.getTime() <= threeDaysInMs) {
279
+ return {
280
+ claimable: null,
281
+ balance: null,
282
+ };
283
+ }
284
+
285
+ const roundBalance = await this.indexer.balanceOf(contractAddress);
286
+ if (isErrorResponse(roundBalance)) {
287
+ throw new Error(
288
+ `Failed to query round balance: ${roundBalance.error.type} ${roundBalance.error.message}`
289
+ );
290
+ }
291
+
292
+ if (
293
+ roundBalance.data.balance &&
294
+ roundBalance.data.balance !== '0' &&
295
+ roundBalance.data.balance !== ''
296
+ ) {
297
+ return {
298
+ claimable: true,
299
+ balance: roundBalance.data.balance,
300
+ };
301
+ }
302
+
303
+ return {
304
+ claimable: false,
305
+ balance: roundBalance.data.balance,
306
+ };
307
+ } catch (error) {
308
+ console.error('Error in queryRoundClaimable:', error);
309
+ return {
310
+ claimable: null,
311
+ balance: null,
312
+ };
313
+ }
314
+ }
315
+
234
316
  async queryRoundGasStation({ contractAddress }: { contractAddress: string }) {
235
317
  const roundInfo = await this.getRoundInfo({ contractAddress });
236
318
 
@@ -3,6 +3,7 @@ import {
3
3
  OracleCertificateParams,
4
4
  SignatureRequest,
5
5
  SignatureResponse,
6
+ FeegrantAllowanceResponse,
6
7
  } from './types';
7
8
 
8
9
  export class OracleCertificate {
@@ -33,4 +34,19 @@ export class OracleCertificate {
33
34
 
34
35
  return signatureData;
35
36
  }
37
+
38
+ async feegrantAllowance(
39
+ granter: string,
40
+ grantee: string
41
+ ): Promise<FeegrantAllowanceResponse> {
42
+ const response = await this.http.fetchRest(
43
+ `/cosmos/feegrant/v1beta1/allowance/${granter}/${grantee}`
44
+ );
45
+
46
+ return {
47
+ granter,
48
+ grantee,
49
+ spend_limit: response.allowance.allowance.allowance.spend_limit,
50
+ };
51
+ }
36
52
  }
@@ -18,3 +18,12 @@ export type SignatureResponse = {
18
18
  amount: string;
19
19
  snapshotHeight: string;
20
20
  };
21
+
22
+ export type FeegrantAllowanceResponse = {
23
+ granter: string;
24
+ grantee: string;
25
+ spend_limit: {
26
+ denom: string;
27
+ amount: string;
28
+ }[];
29
+ };