@ocap/resolver 1.19.3 → 1.19.5
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/lib/index.js +33 -52
- package/lib/token-distribution.js +17 -10
- package/package.json +12 -12
package/lib/index.js
CHANGED
|
@@ -692,22 +692,28 @@ module.exports = class OCAPResolver {
|
|
|
692
692
|
}
|
|
693
693
|
|
|
694
694
|
verifyAccountRisk(args, ctx) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
695
|
+
if (process.env.TOKEN_FLOW_ENABLED === 'true') {
|
|
696
|
+
return tokenFlow.verifyAccountRisk(
|
|
697
|
+
{
|
|
698
|
+
...args,
|
|
699
|
+
tokenAddress: toAddress(args.tokenAddress || this.config.token.address),
|
|
700
|
+
accountAddress: toAddress(args.accountAddress || ''),
|
|
701
|
+
accountLimit: process.env.VERIFY_RISK_ACCOUNT_LIMIT,
|
|
702
|
+
txLimit: process.env.VERIFY_RISK_TX_LIMIT,
|
|
703
|
+
tolerance: process.env.VERIFY_RISK_TOLERANCE,
|
|
704
|
+
},
|
|
705
|
+
this,
|
|
706
|
+
ctx
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
return null;
|
|
707
710
|
}
|
|
708
711
|
|
|
709
712
|
listTokenFlows(args, ctx) {
|
|
710
|
-
|
|
713
|
+
if (process.env.TOKEN_FLOW_ENABLED === 'true') {
|
|
714
|
+
return tokenFlow.listTokenFlows(args, this, ctx);
|
|
715
|
+
}
|
|
716
|
+
return [];
|
|
711
717
|
}
|
|
712
718
|
|
|
713
719
|
async search(args) {
|
|
@@ -1040,11 +1046,11 @@ module.exports = class OCAPResolver {
|
|
|
1040
1046
|
if (limit && paging.total > limit) {
|
|
1041
1047
|
throw new CustomError('EXCEED_LIMIT', `Total exceeds limit ${limit}`);
|
|
1042
1048
|
}
|
|
1043
|
-
if (paging.total
|
|
1049
|
+
if (paging.total <= pageSize) {
|
|
1044
1050
|
return firstPage;
|
|
1045
1051
|
}
|
|
1046
1052
|
|
|
1047
|
-
const totalPage = Math.
|
|
1053
|
+
const totalPage = Math.ceil(paging.total / pageSize) - 1;
|
|
1048
1054
|
const cursors = new Array(totalPage).fill(true).map((_, i) => (i + 1) * pageSize);
|
|
1049
1055
|
const step = process.env.RESOLVER_BATCH_CONCURRENCY || 3;
|
|
1050
1056
|
let results = firstPage;
|
|
@@ -1276,23 +1282,14 @@ module.exports = class OCAPResolver {
|
|
|
1276
1282
|
* @param {number} [param.concurrency=3] Number of concurrent requests
|
|
1277
1283
|
* @param {number} [param.chunkSize=2000] Maximum number of items to return in each next() call
|
|
1278
1284
|
* @param {number} [param.pageSize=100] Number of items per page
|
|
1279
|
-
* @param {
|
|
1285
|
+
* @param {string} param.timeKey Key to access time in response
|
|
1280
1286
|
* @param {string} param.dataKey Key to access data in response
|
|
1281
1287
|
* @returns {Promise<Array>} Array of fetched items
|
|
1282
1288
|
*/
|
|
1283
|
-
listChunks(fn, { concurrency = 3, chunkSize = 2000, pageSize = 100,
|
|
1284
|
-
let totalPage;
|
|
1285
|
-
let curPage;
|
|
1289
|
+
listChunks(fn, { total, concurrency = 3, chunkSize = 2000, pageSize = 100, timeKey, dataKey }) {
|
|
1286
1290
|
let done = false;
|
|
1287
1291
|
let time;
|
|
1288
|
-
|
|
1289
|
-
const fetchFirstPage = async () => {
|
|
1290
|
-
const { paging, page, [dataKey]: list } = await fn({ size: pageSize, cursor: '0' });
|
|
1291
|
-
const total = paging?.total || page?.total;
|
|
1292
|
-
curPage = 1;
|
|
1293
|
-
totalPage = Math.ceil(total / pageSize);
|
|
1294
|
-
return list;
|
|
1295
|
-
};
|
|
1292
|
+
const totalPage = Math.ceil(total / pageSize);
|
|
1296
1293
|
|
|
1297
1294
|
const next = async () => {
|
|
1298
1295
|
if (done) {
|
|
@@ -1301,28 +1298,10 @@ module.exports = class OCAPResolver {
|
|
|
1301
1298
|
|
|
1302
1299
|
let results = [];
|
|
1303
1300
|
|
|
1304
|
-
// first page
|
|
1305
|
-
if (!totalPage) {
|
|
1306
|
-
const data = await fetchFirstPage();
|
|
1307
|
-
// only 1 page
|
|
1308
|
-
if (data.length < pageSize) {
|
|
1309
|
-
done = true;
|
|
1310
|
-
return data;
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
time = getTime(data[data.length - 1]);
|
|
1314
|
-
results = results.concat(data);
|
|
1315
|
-
|
|
1316
|
-
// limit
|
|
1317
|
-
if (data.length >= chunkSize) {
|
|
1318
|
-
return results;
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
1301
|
// next pages
|
|
1323
|
-
for (; curPage < totalPage; curPage += concurrency) {
|
|
1302
|
+
for (let curPage = 0; curPage < totalPage; curPage += concurrency) {
|
|
1324
1303
|
const batchResults = await Promise.all(
|
|
1325
|
-
new Array(concurrency).fill(true).map(async (_, i) => {
|
|
1304
|
+
new Array(Math.min(concurrency, totalPage - curPage)).fill(true).map(async (_, i) => {
|
|
1326
1305
|
const { [dataKey]: list } = await fn({
|
|
1327
1306
|
size: pageSize,
|
|
1328
1307
|
cursor: i * pageSize,
|
|
@@ -1340,7 +1319,7 @@ module.exports = class OCAPResolver {
|
|
|
1340
1319
|
}
|
|
1341
1320
|
|
|
1342
1321
|
results = results.concat(flatResults);
|
|
1343
|
-
time = results.length ?
|
|
1322
|
+
time = results.length ? results[results.length - 1][timeKey] : null;
|
|
1344
1323
|
|
|
1345
1324
|
// limit
|
|
1346
1325
|
if (results.length >= chunkSize) {
|
|
@@ -1358,7 +1337,7 @@ module.exports = class OCAPResolver {
|
|
|
1358
1337
|
};
|
|
1359
1338
|
}
|
|
1360
1339
|
|
|
1361
|
-
listTransactionsChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
|
|
1340
|
+
async listTransactionsChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
|
|
1362
1341
|
return this.listChunks(
|
|
1363
1342
|
({ size, time, cursor }) =>
|
|
1364
1343
|
this.listTransactions({
|
|
@@ -1373,14 +1352,15 @@ module.exports = class OCAPResolver {
|
|
|
1373
1352
|
}),
|
|
1374
1353
|
{
|
|
1375
1354
|
dataKey: 'transactions',
|
|
1376
|
-
|
|
1355
|
+
timeKey: 'time',
|
|
1356
|
+
total: await this.indexdb.tx.count(),
|
|
1377
1357
|
chunkSize,
|
|
1378
1358
|
pageSize,
|
|
1379
1359
|
}
|
|
1380
1360
|
);
|
|
1381
1361
|
}
|
|
1382
1362
|
|
|
1383
|
-
listStakeChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
|
|
1363
|
+
async listStakeChunks(args = {}, { chunkSize = 2000, pageSize = 100 } = {}) {
|
|
1384
1364
|
return this.listChunks(
|
|
1385
1365
|
({ size, time, cursor }) =>
|
|
1386
1366
|
this.listStakes({
|
|
@@ -1395,7 +1375,8 @@ module.exports = class OCAPResolver {
|
|
|
1395
1375
|
}),
|
|
1396
1376
|
{
|
|
1397
1377
|
dataKey: 'stakes',
|
|
1398
|
-
|
|
1378
|
+
timeKey: 'renaissanceTime',
|
|
1379
|
+
total: await this.indexdb.stake.count(),
|
|
1399
1380
|
chunkSize,
|
|
1400
1381
|
pageSize,
|
|
1401
1382
|
}
|
|
@@ -40,7 +40,7 @@ class TokenDistributionManager {
|
|
|
40
40
|
return data && createIndexedTokenDistribution(data);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
async saveDistribution(distribution) {
|
|
43
|
+
async saveDistribution(distribution, isEnsureLatest = true) {
|
|
44
44
|
const data = createIndexedTokenDistribution(distribution);
|
|
45
45
|
const indexdbDistribution = await this.getDistribution(data.tokenAddress);
|
|
46
46
|
|
|
@@ -48,8 +48,10 @@ class TokenDistributionManager {
|
|
|
48
48
|
await this.indexdb.tokenDistribution.insert(data);
|
|
49
49
|
} else {
|
|
50
50
|
// ensure txTime is latest
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
if (isEnsureLatest) {
|
|
52
|
+
const latestTime = Math.max(new Date(indexdbDistribution.txTime).getTime(), new Date(data.txTime).getTime());
|
|
53
|
+
data.txTime = new Date(latestTime).toISOString();
|
|
54
|
+
}
|
|
53
55
|
await this.indexdb.tokenDistribution.update(data.tokenAddress, data);
|
|
54
56
|
}
|
|
55
57
|
|
|
@@ -100,14 +102,14 @@ class TokenDistributionManager {
|
|
|
100
102
|
await Promise.all(handlePromises);
|
|
101
103
|
|
|
102
104
|
// update indexdb
|
|
103
|
-
await this.saveDistribution(distribution);
|
|
105
|
+
await this.saveDistribution(distribution, false);
|
|
104
106
|
nextData = await next();
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
// We cannot distinguish between revokedStake and stake from tx receipts here,
|
|
108
110
|
// so we need to read all stake transactions and recalculate token distribution based on their revokeTokens and tokens
|
|
109
111
|
await this.splitStake(distribution, force);
|
|
110
|
-
await this.saveDistribution(distribution);
|
|
112
|
+
await this.saveDistribution(distribution, false);
|
|
111
113
|
|
|
112
114
|
const result = createIndexedTokenDistribution(distribution);
|
|
113
115
|
|
|
@@ -120,20 +122,25 @@ class TokenDistributionManager {
|
|
|
120
122
|
* Split out revokedStake / gasStake from stake
|
|
121
123
|
*
|
|
122
124
|
* @param {Object} distribution
|
|
123
|
-
* @param {boolean} force If force is false, only process transactions after txTime in indexdb. Default is false
|
|
124
125
|
* @returns {Promise<Object>}
|
|
125
126
|
*/
|
|
126
|
-
async splitStake(distribution
|
|
127
|
+
async splitStake(distribution) {
|
|
128
|
+
const { logger } = this.resolver;
|
|
127
129
|
const { tokenAddress } = distribution;
|
|
128
130
|
|
|
129
|
-
const { next } = await this.resolver.listStakeChunks(
|
|
130
|
-
timeFilter: !force ? { startDateTime: distribution.txTime } : {},
|
|
131
|
-
});
|
|
131
|
+
const { next } = await this.resolver.listStakeChunks();
|
|
132
132
|
|
|
133
133
|
let nextData = await next();
|
|
134
134
|
|
|
135
135
|
// Process transactions in chunks and update indexdb
|
|
136
136
|
while (nextData.length) {
|
|
137
|
+
logger?.info('Updating stake distribution in chunks', {
|
|
138
|
+
chunkSize: nextData.length,
|
|
139
|
+
startTime: nextData[0].renaissanceTime,
|
|
140
|
+
startAddress: nextData[0].address,
|
|
141
|
+
endTime: nextData[nextData.length - 1].renaissanceTime,
|
|
142
|
+
});
|
|
143
|
+
|
|
137
144
|
nextData.forEach((stakeState) => {
|
|
138
145
|
const isGasStake = this.isGasStake(stakeState);
|
|
139
146
|
const token = stakeState.tokens.find((x) => x.address === tokenAddress);
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.19.
|
|
6
|
+
"version": "1.19.5",
|
|
7
7
|
"description": "GraphQL resolver built upon ocap statedb and GQL layer",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
"jest": "^29.7.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@arcblock/did": "1.19.
|
|
26
|
-
"@arcblock/did-util": "1.19.
|
|
27
|
-
"@arcblock/validator": "1.19.
|
|
28
|
-
"@ocap/config": "1.19.
|
|
29
|
-
"@ocap/indexdb": "1.19.
|
|
30
|
-
"@ocap/mcrypto": "1.19.
|
|
31
|
-
"@ocap/message": "1.19.
|
|
32
|
-
"@ocap/state": "1.19.
|
|
33
|
-
"@ocap/tx-protocols": "1.19.
|
|
34
|
-
"@ocap/util": "1.19.
|
|
25
|
+
"@arcblock/did": "1.19.5",
|
|
26
|
+
"@arcblock/did-util": "1.19.5",
|
|
27
|
+
"@arcblock/validator": "1.19.5",
|
|
28
|
+
"@ocap/config": "1.19.5",
|
|
29
|
+
"@ocap/indexdb": "1.19.5",
|
|
30
|
+
"@ocap/mcrypto": "1.19.5",
|
|
31
|
+
"@ocap/message": "1.19.5",
|
|
32
|
+
"@ocap/state": "1.19.5",
|
|
33
|
+
"@ocap/tx-protocols": "1.19.5",
|
|
34
|
+
"@ocap/util": "1.19.5",
|
|
35
35
|
"debug": "^4.3.6",
|
|
36
36
|
"lodash": "^4.17.21"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "9f93acb129f6fee316149f3921a98b88dcccfac3"
|
|
39
39
|
}
|