@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/dist/browser.d.mts +99 -6
- package/dist/browser.d.ts +99 -6
- package/dist/browser.js +411 -26
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +411 -26
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +99 -6
- package/dist/index.d.ts +99 -6
- package/dist/index.js +411 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +411 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/libs/contract/contract.ts +32 -21
- package/src/libs/contract/types.ts +4 -4
- package/src/libs/contract/utils.ts +26 -6
- package/src/libs/errors/types.ts +3 -0
- package/src/libs/http/http.ts +2 -1
- package/src/libs/indexer/indexer.ts +21 -0
- package/src/libs/maci/maci.ts +82 -0
- package/src/libs/oracle-certificate/oracle-certificate.ts +16 -0
- package/src/libs/oracle-certificate/types.ts +9 -0
- package/src/libs/query/operator.ts +338 -0
- package/src/types/index.ts +86 -0
|
@@ -5,6 +5,12 @@ import {
|
|
|
5
5
|
RoundsCountGraphqlResponse,
|
|
6
6
|
OperatorResponse,
|
|
7
7
|
OperatorsResponse,
|
|
8
|
+
OperatorDelayOperationsResponse,
|
|
9
|
+
OperatorDelayOperationsGraphqlResponse,
|
|
10
|
+
MissRateResponse,
|
|
11
|
+
MissRateType,
|
|
12
|
+
TransactionsGraphqlResponse,
|
|
13
|
+
RoundsGraphqlResponse,
|
|
8
14
|
} from '../../types';
|
|
9
15
|
import { isValidAddress } from '../../utils';
|
|
10
16
|
import { handleError, ErrorType } from '../errors';
|
|
@@ -131,6 +137,79 @@ export class Operator {
|
|
|
131
137
|
}
|
|
132
138
|
}
|
|
133
139
|
|
|
140
|
+
async getOperatorDelayOperationsByAddress(
|
|
141
|
+
address: string,
|
|
142
|
+
after: string,
|
|
143
|
+
limit?: number
|
|
144
|
+
): Promise<OperatorDelayOperationsResponse> {
|
|
145
|
+
try {
|
|
146
|
+
if (!isValidAddress(address)) {
|
|
147
|
+
return {
|
|
148
|
+
code: 400,
|
|
149
|
+
error: {
|
|
150
|
+
message: 'Invalid operator address format',
|
|
151
|
+
type: ERROR.ERROR_OPERATOR_INVALID_ADDRESS,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const OPERATORS_QUERY = `query ($limit: Int, $after: Cursor) {
|
|
157
|
+
operatorDelayOperations(first: $limit, after: $after, filter: {operatorAddress: {equalTo: "${address}"}}, orderBy: [TIMESTAMP_DESC]) {
|
|
158
|
+
pageInfo {
|
|
159
|
+
endCursor
|
|
160
|
+
hasNextPage
|
|
161
|
+
}
|
|
162
|
+
totalCount
|
|
163
|
+
edges {
|
|
164
|
+
cursor
|
|
165
|
+
node {
|
|
166
|
+
blockHeight
|
|
167
|
+
delayProcessDmsgCount
|
|
168
|
+
delayDuration
|
|
169
|
+
delayReason
|
|
170
|
+
delayType
|
|
171
|
+
id
|
|
172
|
+
nodeId
|
|
173
|
+
operatorAddress
|
|
174
|
+
timestamp
|
|
175
|
+
roundAddress
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}`;
|
|
180
|
+
|
|
181
|
+
const response =
|
|
182
|
+
await this.http.fetchGraphql<OperatorDelayOperationsGraphqlResponse>(
|
|
183
|
+
OPERATORS_QUERY,
|
|
184
|
+
after,
|
|
185
|
+
limit
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (
|
|
189
|
+
!response ||
|
|
190
|
+
!response.data ||
|
|
191
|
+
!response.data.operatorDelayOperations ||
|
|
192
|
+
!response.data.operatorDelayOperations.edges ||
|
|
193
|
+
response.data.operatorDelayOperations.edges.length === 0
|
|
194
|
+
) {
|
|
195
|
+
return {
|
|
196
|
+
code: 404,
|
|
197
|
+
error: {
|
|
198
|
+
message: `No operatorDelayOperations found for address ${address}`,
|
|
199
|
+
type: ERROR.ERROR_OPERATOR_DELAY_HISTORY_NOT_FOUND,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const operator: OperatorDelayOperationsResponse = {
|
|
204
|
+
code: 200,
|
|
205
|
+
data: response.data,
|
|
206
|
+
};
|
|
207
|
+
return operator;
|
|
208
|
+
} catch (error) {
|
|
209
|
+
return handleError(error as ErrorType);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
134
213
|
async getOperators(
|
|
135
214
|
after: string,
|
|
136
215
|
limit?: number
|
|
@@ -260,4 +339,263 @@ export class Operator {
|
|
|
260
339
|
return handleError(error as ErrorType);
|
|
261
340
|
}
|
|
262
341
|
}
|
|
342
|
+
|
|
343
|
+
async queryMissRate(
|
|
344
|
+
address: string,
|
|
345
|
+
durationDay: number
|
|
346
|
+
): Promise<MissRateResponse> {
|
|
347
|
+
try {
|
|
348
|
+
const now = new Date();
|
|
349
|
+
const startTime = new Date(
|
|
350
|
+
now.getTime() - durationDay * 24 * 60 * 60 * 1000
|
|
351
|
+
);
|
|
352
|
+
const startTimestamp = Math.floor(startTime.getTime() / 1000);
|
|
353
|
+
const endNanosTimestamp = Math.floor(startTime.getTime() * 1000000);
|
|
354
|
+
const txTimestamp = Math.floor(startTime.getTime());
|
|
355
|
+
|
|
356
|
+
const QUERY = `query ($limit: Int, $after: Cursor) {
|
|
357
|
+
operatorDelayOperations(
|
|
358
|
+
first: $limit,
|
|
359
|
+
after: $after,
|
|
360
|
+
filter: {
|
|
361
|
+
operatorAddress: {equalTo: "${address}"},
|
|
362
|
+
timestamp: { greaterThanOrEqualTo: "${startTimestamp}" }
|
|
363
|
+
},
|
|
364
|
+
orderBy: [TIMESTAMP_DESC]
|
|
365
|
+
) {
|
|
366
|
+
edges {
|
|
367
|
+
node {
|
|
368
|
+
blockHeight
|
|
369
|
+
delayProcessDmsgCount
|
|
370
|
+
delayDuration
|
|
371
|
+
delayReason
|
|
372
|
+
delayType
|
|
373
|
+
id
|
|
374
|
+
nodeId
|
|
375
|
+
operatorAddress
|
|
376
|
+
timestamp
|
|
377
|
+
roundAddress
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}`;
|
|
382
|
+
|
|
383
|
+
const ROUNDS_QUERY = `query ($limit: Int, $after: Cursor) {
|
|
384
|
+
rounds(first: $limit, after: $after,
|
|
385
|
+
filter: {
|
|
386
|
+
operator: {equalTo: "${address}"},
|
|
387
|
+
votingEnd: { greaterThanOrEqualTo: "${endNanosTimestamp}" }
|
|
388
|
+
},
|
|
389
|
+
orderBy: [TIMESTAMP_DESC]
|
|
390
|
+
){
|
|
391
|
+
pageInfo {
|
|
392
|
+
endCursor
|
|
393
|
+
hasNextPage
|
|
394
|
+
}
|
|
395
|
+
totalCount
|
|
396
|
+
edges {
|
|
397
|
+
node {
|
|
398
|
+
id
|
|
399
|
+
blockHeight
|
|
400
|
+
txHash
|
|
401
|
+
caller
|
|
402
|
+
admin
|
|
403
|
+
operator
|
|
404
|
+
contractAddress
|
|
405
|
+
circuitName
|
|
406
|
+
timestamp
|
|
407
|
+
votingStart
|
|
408
|
+
votingEnd
|
|
409
|
+
status
|
|
410
|
+
period
|
|
411
|
+
actionType
|
|
412
|
+
roundTitle
|
|
413
|
+
roundDescription
|
|
414
|
+
roundLink
|
|
415
|
+
coordinatorPubkeyX
|
|
416
|
+
coordinatorPubkeyY
|
|
417
|
+
voteOptionMap
|
|
418
|
+
results
|
|
419
|
+
allResult
|
|
420
|
+
gasStationEnable
|
|
421
|
+
totalGrant
|
|
422
|
+
baseGrant
|
|
423
|
+
totalBond
|
|
424
|
+
circuitType
|
|
425
|
+
circuitPower
|
|
426
|
+
certificationSystem
|
|
427
|
+
codeId
|
|
428
|
+
maciType
|
|
429
|
+
voiceCreditAmount
|
|
430
|
+
preDeactivateRoot
|
|
431
|
+
}
|
|
432
|
+
cursor
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
`;
|
|
437
|
+
|
|
438
|
+
const roundsResponse =
|
|
439
|
+
await this.http.fetchGraphql<RoundsGraphqlResponse>(
|
|
440
|
+
ROUNDS_QUERY,
|
|
441
|
+
'',
|
|
442
|
+
9999
|
|
443
|
+
);
|
|
444
|
+
const roundContractAddresses =
|
|
445
|
+
roundsResponse?.data?.rounds?.edges?.map(
|
|
446
|
+
(edge) => edge.node.contractAddress
|
|
447
|
+
) || [];
|
|
448
|
+
|
|
449
|
+
const TRANSACTIONS_QUERY = `query transactions($limit: Int, $after: Cursor) {
|
|
450
|
+
transactions(first: $limit, after: $after,
|
|
451
|
+
filter: {
|
|
452
|
+
timestamp: { greaterThanOrEqualTo: "${txTimestamp}" },
|
|
453
|
+
type: { equalTo: "op:procDeactivate" },
|
|
454
|
+
contractAddress: { in: ${JSON.stringify(roundContractAddresses)} }
|
|
455
|
+
},
|
|
456
|
+
orderBy: [TIMESTAMP_DESC]
|
|
457
|
+
){
|
|
458
|
+
pageInfo {
|
|
459
|
+
endCursor
|
|
460
|
+
hasNextPage
|
|
461
|
+
}
|
|
462
|
+
totalCount
|
|
463
|
+
edges {
|
|
464
|
+
cursor
|
|
465
|
+
node {
|
|
466
|
+
id
|
|
467
|
+
blockHeight
|
|
468
|
+
txHash
|
|
469
|
+
timestamp
|
|
470
|
+
type
|
|
471
|
+
status
|
|
472
|
+
circuitName
|
|
473
|
+
fee
|
|
474
|
+
gasUsed
|
|
475
|
+
gasWanted
|
|
476
|
+
caller
|
|
477
|
+
contractAddress
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}`;
|
|
482
|
+
|
|
483
|
+
const [delayResponse, transactionsResponse] = await Promise.all([
|
|
484
|
+
this.http.fetchGraphql<OperatorDelayOperationsGraphqlResponse>(
|
|
485
|
+
QUERY,
|
|
486
|
+
'',
|
|
487
|
+
9999
|
|
488
|
+
),
|
|
489
|
+
this.http.fetchGraphql<TransactionsGraphqlResponse>(
|
|
490
|
+
TRANSACTIONS_QUERY,
|
|
491
|
+
'',
|
|
492
|
+
9999
|
|
493
|
+
),
|
|
494
|
+
]);
|
|
495
|
+
|
|
496
|
+
const dailyStats = new Map<string, MissRateType>();
|
|
497
|
+
|
|
498
|
+
const endDate = new Date();
|
|
499
|
+
for (let i = 0; i < durationDay; i++) {
|
|
500
|
+
const date = new Date(endDate.getTime() - i * 24 * 60 * 60 * 1000)
|
|
501
|
+
.toISOString()
|
|
502
|
+
.split('T')[0];
|
|
503
|
+
dailyStats.set(date, {
|
|
504
|
+
delayCount: 0,
|
|
505
|
+
deactivateDelay: {
|
|
506
|
+
count: 0,
|
|
507
|
+
dmsgCount: 0,
|
|
508
|
+
},
|
|
509
|
+
tallyDelay: {
|
|
510
|
+
count: 0,
|
|
511
|
+
},
|
|
512
|
+
totalDelayDuration: 0,
|
|
513
|
+
avgDelayDuration: 0,
|
|
514
|
+
tallyCount: 0,
|
|
515
|
+
deactivateCount: 0,
|
|
516
|
+
missRate: 0,
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
delayResponse.data.operatorDelayOperations.edges.forEach(({ node }) => {
|
|
521
|
+
const date = new Date(parseInt(node.timestamp) * 1000)
|
|
522
|
+
.toISOString()
|
|
523
|
+
.split('T')[0];
|
|
524
|
+
|
|
525
|
+
if (dailyStats.has(date)) {
|
|
526
|
+
const stats = dailyStats.get(date)!;
|
|
527
|
+
stats.delayCount++;
|
|
528
|
+
stats.totalDelayDuration += parseInt(node.delayDuration);
|
|
529
|
+
if (node.delayType === 'deactivate_delay') {
|
|
530
|
+
stats.deactivateDelay.count++;
|
|
531
|
+
stats.deactivateDelay.dmsgCount += node.delayProcessDmsgCount;
|
|
532
|
+
} else if (node.delayType === 'tally_delay') {
|
|
533
|
+
stats.tallyDelay.count++;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
if (roundsResponse?.data?.rounds?.edges) {
|
|
539
|
+
roundsResponse.data.rounds.edges.forEach(({ node }) => {
|
|
540
|
+
const date = new Date(parseInt(node.votingEnd) / 1000000)
|
|
541
|
+
.toISOString()
|
|
542
|
+
.split('T')[0];
|
|
543
|
+
if (dailyStats.has(date)) {
|
|
544
|
+
const stats = dailyStats.get(date)!;
|
|
545
|
+
stats.tallyCount++;
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (transactionsResponse?.data?.transactions?.edges) {
|
|
551
|
+
transactionsResponse.data.transactions.edges.forEach(({ node }) => {
|
|
552
|
+
const date = new Date(parseInt(node.timestamp))
|
|
553
|
+
.toISOString()
|
|
554
|
+
.split('T')[0];
|
|
555
|
+
if (dailyStats.has(date)) {
|
|
556
|
+
const stats = dailyStats.get(date)!;
|
|
557
|
+
stats.deactivateCount++;
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return {
|
|
563
|
+
code: 200,
|
|
564
|
+
data: {
|
|
565
|
+
missRate: Array.from(dailyStats.entries())
|
|
566
|
+
.map(([date, stats]) => ({
|
|
567
|
+
date,
|
|
568
|
+
delayCount: stats.delayCount,
|
|
569
|
+
deactivateDelay: stats.deactivateDelay,
|
|
570
|
+
tallyDelay: stats.tallyDelay,
|
|
571
|
+
totalDelayDuration: stats.totalDelayDuration,
|
|
572
|
+
avgDelayDuration:
|
|
573
|
+
stats.delayCount > 0
|
|
574
|
+
? stats.totalDelayDuration / stats.delayCount
|
|
575
|
+
: 0,
|
|
576
|
+
tallyCount: stats.tallyCount,
|
|
577
|
+
deactivateCount: stats.deactivateCount,
|
|
578
|
+
missRate:
|
|
579
|
+
stats.deactivateCount + stats.tallyCount > 0
|
|
580
|
+
? parseFloat(
|
|
581
|
+
(
|
|
582
|
+
(stats.deactivateDelay.count + stats.tallyDelay.count) /
|
|
583
|
+
(stats.deactivateCount + stats.tallyCount)
|
|
584
|
+
).toFixed(2)
|
|
585
|
+
)
|
|
586
|
+
: 0,
|
|
587
|
+
}))
|
|
588
|
+
.sort((a, b) => b.date.localeCompare(a.date)),
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
} catch (error) {
|
|
592
|
+
return {
|
|
593
|
+
code: 404,
|
|
594
|
+
error: {
|
|
595
|
+
message: 'Query miss rate failed',
|
|
596
|
+
type: ERROR.ERROR_QUERY_MISS_RATE_FAILED,
|
|
597
|
+
},
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
}
|
|
263
601
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -114,6 +114,19 @@ export type ProofType = {
|
|
|
114
114
|
}[];
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
+
export type OperatorDelayType = {
|
|
118
|
+
blockHeight: string;
|
|
119
|
+
delayProcessDmsgCount: number;
|
|
120
|
+
delayDuration: string;
|
|
121
|
+
delayReason: string;
|
|
122
|
+
delayType: string;
|
|
123
|
+
id: string;
|
|
124
|
+
nodeId: string;
|
|
125
|
+
operatorAddress: string;
|
|
126
|
+
timestamp: string;
|
|
127
|
+
roundAddress: string;
|
|
128
|
+
};
|
|
129
|
+
|
|
117
130
|
export type OperatorType = {
|
|
118
131
|
id: string;
|
|
119
132
|
validatorAddress: string;
|
|
@@ -192,6 +205,36 @@ export type OperatorResponse =
|
|
|
192
205
|
}>
|
|
193
206
|
| ErrorResponse;
|
|
194
207
|
|
|
208
|
+
export type MissRateResponse =
|
|
209
|
+
| SuccessResponse<{
|
|
210
|
+
missRate: (MissRateType & {
|
|
211
|
+
date: string;
|
|
212
|
+
})[];
|
|
213
|
+
}>
|
|
214
|
+
| ErrorResponse;
|
|
215
|
+
|
|
216
|
+
// export type ClaimableResponse =
|
|
217
|
+
// | SuccessResponse<{
|
|
218
|
+
// claimable: ClaimableType;
|
|
219
|
+
// }>
|
|
220
|
+
// | ErrorResponse;
|
|
221
|
+
|
|
222
|
+
export type OperatorDelayOperationsResponse =
|
|
223
|
+
| SuccessResponse<{
|
|
224
|
+
operatorDelayOperations: {
|
|
225
|
+
pageInfo: {
|
|
226
|
+
endCursor: string;
|
|
227
|
+
hasNextPage: boolean;
|
|
228
|
+
};
|
|
229
|
+
edges: {
|
|
230
|
+
cursor: string;
|
|
231
|
+
node: OperatorDelayType;
|
|
232
|
+
}[];
|
|
233
|
+
totalCount: number;
|
|
234
|
+
};
|
|
235
|
+
}>
|
|
236
|
+
| ErrorResponse;
|
|
237
|
+
|
|
195
238
|
export type OperatorsResponse =
|
|
196
239
|
| SuccessResponse<{
|
|
197
240
|
operators: {
|
|
@@ -235,6 +278,33 @@ export type RoundsCountGraphqlResponse = {
|
|
|
235
278
|
};
|
|
236
279
|
};
|
|
237
280
|
|
|
281
|
+
export type VoteCountGraphqlResponse = {
|
|
282
|
+
data: {
|
|
283
|
+
signupsCount: {
|
|
284
|
+
totalCount: number;
|
|
285
|
+
};
|
|
286
|
+
messagesCount: {
|
|
287
|
+
totalCount: number;
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
export type OperatorDelayOperationsGraphqlResponse = {
|
|
293
|
+
data: {
|
|
294
|
+
operatorDelayOperations: {
|
|
295
|
+
pageInfo: {
|
|
296
|
+
endCursor: string;
|
|
297
|
+
hasNextPage: boolean;
|
|
298
|
+
};
|
|
299
|
+
edges: {
|
|
300
|
+
cursor: string;
|
|
301
|
+
node: OperatorDelayType;
|
|
302
|
+
}[];
|
|
303
|
+
totalCount: number;
|
|
304
|
+
};
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
|
|
238
308
|
export type TransactionGraphqlResponse = {
|
|
239
309
|
data: {
|
|
240
310
|
transaction: TransactionType;
|
|
@@ -348,3 +418,19 @@ export type SignUpEventsGraphqlResponse = {
|
|
|
348
418
|
};
|
|
349
419
|
};
|
|
350
420
|
};
|
|
421
|
+
|
|
422
|
+
export type MissRateType = {
|
|
423
|
+
delayCount: number;
|
|
424
|
+
deactivateDelay: {
|
|
425
|
+
count: number;
|
|
426
|
+
dmsgCount: number;
|
|
427
|
+
};
|
|
428
|
+
tallyDelay: {
|
|
429
|
+
count: number;
|
|
430
|
+
};
|
|
431
|
+
totalDelayDuration: number;
|
|
432
|
+
avgDelayDuration: number;
|
|
433
|
+
tallyCount: number;
|
|
434
|
+
deactivateCount: number;
|
|
435
|
+
missRate: number;
|
|
436
|
+
};
|