@ocap/indexdb 1.6.5 → 1.6.10
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/db.js +48 -6
- package/lib/index.js +6 -0
- package/lib/util.js +514 -0
- package/package.json +11 -6
package/lib/db.js
CHANGED
@@ -1,15 +1,57 @@
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
1
2
|
const Ready = require('@ocap/util/lib/ready');
|
3
|
+
const { indexes } = require('@ocap/state');
|
2
4
|
|
3
5
|
class BaseIndexDB extends Ready {
|
4
6
|
constructor() {
|
5
7
|
super();
|
6
8
|
|
7
|
-
this.readyMarks = {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
this.readyMarks = indexes.reduce((acc, x) => ({ ...acc, [x]: false }), {});
|
10
|
+
this.readyListenersAttached = false;
|
11
|
+
}
|
12
|
+
|
13
|
+
attachReadyListeners() {
|
14
|
+
if (this.readyListenersAttached) {
|
15
|
+
return;
|
16
|
+
}
|
17
|
+
|
18
|
+
for (const index of indexes) {
|
19
|
+
if (typeof this[index] === 'undefined') {
|
20
|
+
throw new Error(`Missing index ${index} in indexdb adapter: ${this.name}`);
|
21
|
+
}
|
22
|
+
|
23
|
+
this[index].onReady(() => this.markReady(index));
|
24
|
+
}
|
25
|
+
|
26
|
+
this.readyListenersAttached = true;
|
27
|
+
}
|
28
|
+
|
29
|
+
listTransactions({ addressFilter = {}, paging = {}, timeFilter = {}, typeFilter = {} } = {}) {
|
30
|
+
throw new Error('listTransactions should be implemented in adapter');
|
31
|
+
}
|
32
|
+
|
33
|
+
listAssets({ ownerAddress, paging } = {}) {
|
34
|
+
throw new Error('listAssets should be implemented in adapter');
|
35
|
+
}
|
36
|
+
|
37
|
+
listFactories({ ownerAddress, paging } = {}) {
|
38
|
+
throw new Error('listFactories should be implemented in adapter');
|
39
|
+
}
|
40
|
+
|
41
|
+
listTopAccounts({ paging, tokenAddress } = {}) {
|
42
|
+
throw new Error('listTopAccounts should be implemented in adapter');
|
43
|
+
}
|
44
|
+
|
45
|
+
listTokens({ paging }) {
|
46
|
+
throw new Error('listTokens should be implemented in adapter');
|
47
|
+
}
|
48
|
+
|
49
|
+
listStakes({ paging = {}, addressFilter = {}, timeFilter = {}, assetFilter = {} } = {}) {
|
50
|
+
throw new Error('listStakes should be implemented in adapter');
|
51
|
+
}
|
52
|
+
|
53
|
+
listBlocks() {
|
54
|
+
return [];
|
13
55
|
}
|
14
56
|
}
|
15
57
|
|
package/lib/index.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
/* eslint-disable no-underscore-dangle */
|
2
2
|
const Kareem = require('kareem');
|
3
|
+
const omit = require('lodash/omit');
|
3
4
|
const Ready = require('@ocap/util/lib/ready');
|
4
5
|
|
5
6
|
class BaseIndex extends Ready {
|
@@ -21,6 +22,11 @@ class BaseIndex extends Ready {
|
|
21
22
|
hooks.execPreSync(x, args);
|
22
23
|
const result = await this[`_${x}`](...args);
|
23
24
|
hooks.execPostSync(x, result);
|
25
|
+
|
26
|
+
if (['insert', 'update'].includes(x)) {
|
27
|
+
this.emit(x, omit(result, '$loki'));
|
28
|
+
}
|
29
|
+
|
24
30
|
return result;
|
25
31
|
},
|
26
32
|
});
|
package/lib/util.js
ADDED
@@ -0,0 +1,514 @@
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
2
|
+
const get = require('lodash/get');
|
3
|
+
const uniq = require('lodash/uniq');
|
4
|
+
const pick = require('lodash/pick');
|
5
|
+
const createSortedList = require('@ocap/util/lib/create-sorted-list');
|
6
|
+
const { BN } = require('@ocap/util');
|
7
|
+
|
8
|
+
const formatTokenMeta = (token, tokenStates) => {
|
9
|
+
if (!tokenStates) {
|
10
|
+
return token;
|
11
|
+
}
|
12
|
+
|
13
|
+
const tokenState = tokenStates.find((x) => x.address === token.address);
|
14
|
+
token.decimal = tokenState.decimal;
|
15
|
+
token.unit = tokenState.unit;
|
16
|
+
token.symbol = tokenState.symbol;
|
17
|
+
|
18
|
+
return token;
|
19
|
+
};
|
20
|
+
|
21
|
+
const createIndexedAccount = async (x, getTokenFn) => {
|
22
|
+
const tasks = Object.keys(x.tokens || {}).map((address) => getTokenFn(address));
|
23
|
+
const tokenStates = await Promise.all(tasks);
|
24
|
+
|
25
|
+
return {
|
26
|
+
address: x.address,
|
27
|
+
balance: x.balance || '0',
|
28
|
+
moniker: x.moniker,
|
29
|
+
nonce: x.nonce,
|
30
|
+
numAssets: x.numAssets || 0,
|
31
|
+
numTxs: x.numTxs || 0,
|
32
|
+
recentNumTxs: [],
|
33
|
+
renaissanceTime: x.context.renaissanceTime,
|
34
|
+
tokens: Object.keys(x.tokens || {}).map((address) =>
|
35
|
+
formatTokenMeta({ address, balance: x.tokens[address] }, tokenStates)
|
36
|
+
), // eslint-disable-line function-paren-newline
|
37
|
+
genesisTime: x.context.genesisTime,
|
38
|
+
migratedTo: x.migratedTo[0] || '',
|
39
|
+
migratedFrom: x.migratedFrom[0] || '',
|
40
|
+
};
|
41
|
+
};
|
42
|
+
|
43
|
+
const createIndexedAsset = (x) => ({
|
44
|
+
address: x.address,
|
45
|
+
issuer: x.issuer,
|
46
|
+
moniker: x.moniker,
|
47
|
+
owner: x.owner,
|
48
|
+
parent: x.parent,
|
49
|
+
readonly: x.readonly,
|
50
|
+
transferrable: x.transferrable,
|
51
|
+
ttl: x.ttl,
|
52
|
+
consumedTime: x.consumedTime,
|
53
|
+
genesisTime: x.context.genesisTime,
|
54
|
+
renaissanceTime: x.context.renaissanceTime,
|
55
|
+
data: x.data,
|
56
|
+
display: x.display,
|
57
|
+
endpoint: x.endpoint,
|
58
|
+
tags: x.tags,
|
59
|
+
});
|
60
|
+
|
61
|
+
const createIndexedDelegation = (x, ctx) => ({
|
62
|
+
address: x.address,
|
63
|
+
data: x.data,
|
64
|
+
genesisTime: x.context.genesisTime,
|
65
|
+
renaissanceTime: x.context.renaissanceTime,
|
66
|
+
ops: x.ops,
|
67
|
+
from: get(ctx, 'senderState.address', ''),
|
68
|
+
to: get(ctx, 'receiverState.address', ''),
|
69
|
+
});
|
70
|
+
|
71
|
+
const createIndexedToken = (x) => ({
|
72
|
+
address: x.address,
|
73
|
+
issuer: x.issuer,
|
74
|
+
name: x.name,
|
75
|
+
description: x.description,
|
76
|
+
symbol: x.symbol,
|
77
|
+
unit: x.unit,
|
78
|
+
decimal: x.decimal,
|
79
|
+
icon: x.icon,
|
80
|
+
totalSupply: x.totalSupply,
|
81
|
+
initialSupply: x.initialSupply,
|
82
|
+
foreignToken: x.foreignToken,
|
83
|
+
data: x.data,
|
84
|
+
genesisTime: x.context.genesisTime,
|
85
|
+
renaissanceTime: x.context.renaissanceTime,
|
86
|
+
});
|
87
|
+
|
88
|
+
const createIndexedFactory = async (factory, context) => {
|
89
|
+
if (context.factoryTokens && context.factoryTokens.length > 0) {
|
90
|
+
factory.input.tokens = factory.input.tokens.map((token) => formatTokenMeta(token, context.tokenStates));
|
91
|
+
}
|
92
|
+
return {
|
93
|
+
...pick(factory, [
|
94
|
+
'address',
|
95
|
+
'owner',
|
96
|
+
'name',
|
97
|
+
'description',
|
98
|
+
'settlement',
|
99
|
+
'limit',
|
100
|
+
'trustedIssuers',
|
101
|
+
'input',
|
102
|
+
'output',
|
103
|
+
'hooks',
|
104
|
+
'data',
|
105
|
+
'numMinted',
|
106
|
+
'lastSettlement',
|
107
|
+
'balance',
|
108
|
+
'display',
|
109
|
+
]),
|
110
|
+
tokens: Object.keys(factory.tokens || {}).map((address) =>
|
111
|
+
formatTokenMeta({ address, balance: factory.tokens[address] }, context.tokenStates)
|
112
|
+
), // eslint-disable-line function-paren-newline
|
113
|
+
genesisTime: factory.context.genesisTime,
|
114
|
+
renaissanceTime: factory.context.renaissanceTime,
|
115
|
+
};
|
116
|
+
};
|
117
|
+
|
118
|
+
// These fields are used internally to filter transactions by some entity
|
119
|
+
const createIndexedTransaction = (tx, ctx) => {
|
120
|
+
tx.accounts = [tx.tx.from, tx.sender, tx.receiver];
|
121
|
+
tx.assets = [];
|
122
|
+
tx.tokens = [];
|
123
|
+
tx.factories = [];
|
124
|
+
tx.stakes = [];
|
125
|
+
tx.rollups = [];
|
126
|
+
|
127
|
+
tx.valid = tx.code === 'OK';
|
128
|
+
|
129
|
+
// accounts
|
130
|
+
if (ctx.senderState) {
|
131
|
+
tx.accounts.push(ctx.senderState.address);
|
132
|
+
}
|
133
|
+
if (ctx.receiverState) {
|
134
|
+
tx.accounts.push(ctx.receiverState.address);
|
135
|
+
}
|
136
|
+
if (ctx.vaultState) {
|
137
|
+
tx.accounts.push(ctx.vaultState.address);
|
138
|
+
}
|
139
|
+
if (ctx.updatedAccounts && Array.isArray(ctx.updatedAccounts)) {
|
140
|
+
tx.accounts.push(...ctx.updatedAccounts.map((x) => x.address));
|
141
|
+
}
|
142
|
+
if (ctx.delegatorState) {
|
143
|
+
tx.accounts.push(ctx.delegatorState.address);
|
144
|
+
}
|
145
|
+
if (Array.isArray(ctx.delegatorStates)) {
|
146
|
+
tx.accounts.push(...ctx.delegatorStates.map((x) => x.address));
|
147
|
+
}
|
148
|
+
if (Array.isArray(ctx.signerStates)) {
|
149
|
+
tx.accounts.push(...ctx.signerStates.map((x) => x.address));
|
150
|
+
}
|
151
|
+
if (Array.isArray(ctx.receiverStates)) {
|
152
|
+
tx.accounts.push(...ctx.receiverStates.map((x) => x.address));
|
153
|
+
}
|
154
|
+
|
155
|
+
// assets
|
156
|
+
if (ctx.assetState) {
|
157
|
+
tx.assets.push(ctx.assetState.address);
|
158
|
+
}
|
159
|
+
if (ctx.assetStates && Array.isArray(ctx.assetStates)) {
|
160
|
+
tx.assets.push(...ctx.assetStates.map((x) => x.address));
|
161
|
+
}
|
162
|
+
|
163
|
+
// tokens
|
164
|
+
if (ctx.tokenState) {
|
165
|
+
tx.tokens.push(ctx.tokenState.address);
|
166
|
+
}
|
167
|
+
if (ctx.tokenStates && Array.isArray(ctx.tokenStates)) {
|
168
|
+
tx.tokens.push(...ctx.tokenStates.map((x) => x.address));
|
169
|
+
}
|
170
|
+
|
171
|
+
// factories
|
172
|
+
if (ctx.factoryState) {
|
173
|
+
tx.factories.push(ctx.factoryState.address);
|
174
|
+
}
|
175
|
+
|
176
|
+
// stakes
|
177
|
+
if (ctx.stakeState) {
|
178
|
+
tx.stakes.push(ctx.stakeState.address);
|
179
|
+
}
|
180
|
+
if (Array.isArray(ctx.stakeStates)) {
|
181
|
+
tx.stakes.push(...ctx.stakeStates.map((x) => x.address));
|
182
|
+
}
|
183
|
+
|
184
|
+
// rollups
|
185
|
+
if (ctx.rollupState) {
|
186
|
+
tx.rollups.push(ctx.rollupState.address);
|
187
|
+
}
|
188
|
+
|
189
|
+
const pickedFields = ['address', 'symbol', 'decimal', 'unit'];
|
190
|
+
if (Array.isArray(ctx.tokenStates)) {
|
191
|
+
tx.tokenSymbols = ctx.tokenStates.map((t) => pick(t, pickedFields));
|
192
|
+
} else if (ctx.tokenState) {
|
193
|
+
tx.tokenSymbols = [pick(ctx.tokenState, pickedFields)];
|
194
|
+
} else {
|
195
|
+
tx.tokenSymbols = [];
|
196
|
+
}
|
197
|
+
|
198
|
+
tx.accounts = [...tx.accounts, ...tx.stakes];
|
199
|
+
|
200
|
+
return tx;
|
201
|
+
};
|
202
|
+
|
203
|
+
const createIndexedStake = async (x, ctx) => {
|
204
|
+
return {
|
205
|
+
...pick(x, [
|
206
|
+
'address',
|
207
|
+
'sender',
|
208
|
+
'receiver',
|
209
|
+
'assets',
|
210
|
+
'revocable',
|
211
|
+
'data',
|
212
|
+
'message',
|
213
|
+
'revokeWaitingPeriod',
|
214
|
+
'revokedAssets',
|
215
|
+
]),
|
216
|
+
tokens: Object.keys(x.tokens || {}).map((address) =>
|
217
|
+
formatTokenMeta({ address, balance: x.tokens[address] }, ctx.tokenStates)
|
218
|
+
),
|
219
|
+
revokedTokens: Object.keys(x.revokedTokens || {}).map((address) =>
|
220
|
+
formatTokenMeta({ address, balance: x.revokedTokens[address] }, ctx.tokenStates)
|
221
|
+
),
|
222
|
+
genesisTime: x.context.genesisTime,
|
223
|
+
renaissanceTime: x.context.renaissanceTime,
|
224
|
+
};
|
225
|
+
};
|
226
|
+
|
227
|
+
const createIndexedRollup = async (x, ctx) => {
|
228
|
+
const rollup = {
|
229
|
+
...pick(x, [
|
230
|
+
'address',
|
231
|
+
'paused',
|
232
|
+
'tokenAddress',
|
233
|
+
'contractAddress',
|
234
|
+
'seedValidators',
|
235
|
+
'validators',
|
236
|
+
'minStakeAmount',
|
237
|
+
'maxStakeAmount',
|
238
|
+
'minSignerCount',
|
239
|
+
'maxSignerCount',
|
240
|
+
'minBlockSize',
|
241
|
+
'maxBlockSize',
|
242
|
+
'minBlockInterval',
|
243
|
+
'minBlockConfirmation',
|
244
|
+
'minDepositAmount',
|
245
|
+
'maxDepositAmount',
|
246
|
+
'minWithdrawAmount',
|
247
|
+
'maxWithdrawAmount',
|
248
|
+
'depositFeeRate',
|
249
|
+
'withdrawFeeRate',
|
250
|
+
'proposerFeeShare',
|
251
|
+
'publisherFeeShare',
|
252
|
+
'minDepositFee',
|
253
|
+
'maxDepositFee',
|
254
|
+
'minWithdrawFee',
|
255
|
+
'maxWithdrawFee',
|
256
|
+
'issuer',
|
257
|
+
'blockHeight',
|
258
|
+
'blockHash',
|
259
|
+
'leaveWaitingPeriod',
|
260
|
+
'publishWaitingPeriod',
|
261
|
+
'publishSlashRate',
|
262
|
+
'migrateHistory',
|
263
|
+
'data',
|
264
|
+
]),
|
265
|
+
genesisTime: x.context.genesisTime,
|
266
|
+
renaissanceTime: x.context.renaissanceTime,
|
267
|
+
};
|
268
|
+
|
269
|
+
if (ctx.tokenStates) {
|
270
|
+
const tokenState = ctx.tokenStates.find((t) => t.address === x.tokenAddress);
|
271
|
+
rollup.tokenInfo = formatTokenMeta({ address: x.tokenAddress, value: '0' }, ctx.tokenStates);
|
272
|
+
rollup.foreignToken = tokenState.foreignToken;
|
273
|
+
}
|
274
|
+
|
275
|
+
return rollup;
|
276
|
+
};
|
277
|
+
|
278
|
+
const createIndexedRollupBlock = async (x, ctx) => {
|
279
|
+
return {
|
280
|
+
...pick(x, [
|
281
|
+
'hash',
|
282
|
+
'height',
|
283
|
+
'merkleRoot',
|
284
|
+
'previousHash',
|
285
|
+
'txsHash',
|
286
|
+
'txs',
|
287
|
+
'proposer',
|
288
|
+
'signatures',
|
289
|
+
'rollup',
|
290
|
+
'mintedAmount',
|
291
|
+
'burnedAmount',
|
292
|
+
'rewardAmount',
|
293
|
+
'minReward',
|
294
|
+
'data',
|
295
|
+
]),
|
296
|
+
genesisTime: x.context.genesisTime,
|
297
|
+
renaissanceTime: x.context.renaissanceTime,
|
298
|
+
tokenInfo: formatTokenMeta({ address: ctx.rollupState.tokenAddress, value: '0' }, ctx.tokenStates),
|
299
|
+
validators: (x.signaturesList || x.signatures || []).map((v) => v.signer),
|
300
|
+
};
|
301
|
+
};
|
302
|
+
|
303
|
+
const formatTxBeforeInsert = (row) => {
|
304
|
+
const tx = { ...row };
|
305
|
+
tx.sender = tx.sender || '';
|
306
|
+
tx.receiver = tx.receiver || '';
|
307
|
+
|
308
|
+
// index assets
|
309
|
+
tx.assets = tx.assets || [];
|
310
|
+
if (['transfer', 'transfer_v2'].includes(tx.type) && tx.tx.itxJson.assets) {
|
311
|
+
tx.assets.push(...tx.tx.itxJson.assets);
|
312
|
+
} else if (['transfer_v3', 'stake'].includes(tx.type)) {
|
313
|
+
tx.assets.push(...createSortedList(tx.tx.itxJson.inputs.map((x) => x.assets)));
|
314
|
+
} else if (['revoke_stake'].includes(tx.type)) {
|
315
|
+
tx.assets.push(...createSortedList(tx.tx.itxJson.outputs.map((x) => x.assets)));
|
316
|
+
} else if (['exchange', 'exchange_v2'].includes(tx.type)) {
|
317
|
+
tx.assets.push(...(tx.tx.itxJson.sender.assets || []), ...(tx.tx.itxJson.receiver.assets || []));
|
318
|
+
} else if (['create_asset', 'update_asset', 'acquire_asset_v2', 'mint_asset'].includes(tx.type)) {
|
319
|
+
tx.assets.push(tx.tx.itxJson.address);
|
320
|
+
}
|
321
|
+
|
322
|
+
// index factories
|
323
|
+
tx.factories = tx.factories || [];
|
324
|
+
if (['acquire_asset_v2', 'acquire_asset_v3', 'mint_asset', 'create_factory'].includes(tx.type)) {
|
325
|
+
tx.factories.push(tx.tx.itxJson.factory);
|
326
|
+
}
|
327
|
+
|
328
|
+
// index tokens
|
329
|
+
tx.tokens = tx.tokens || [];
|
330
|
+
if (tx.type === 'transfer_v2' && tx.tx.itxJson.tokens) {
|
331
|
+
tx.tokens.push(...tx.tx.itxJson.tokens.map((x) => x.address));
|
332
|
+
} else if (['transfer_v3', 'stake'].includes(tx.type)) {
|
333
|
+
tx.tokens.push(...createSortedList(tx.tx.itxJson.inputs.map((x) => x.tokens.map((t) => t.address))));
|
334
|
+
} else if (['revoke_stake'].includes(tx.type)) {
|
335
|
+
tx.tokens.push(...createSortedList(tx.tx.itxJson.outputs.map((x) => x.tokens.map((t) => t.address))));
|
336
|
+
} else if (tx.type === 'exchange_v2') {
|
337
|
+
tx.tokens.push(
|
338
|
+
...(tx.tx.itxJson.sender.tokens || []).map((x) => x.address),
|
339
|
+
...(tx.tx.itxJson.receiver.tokens || []).map((x) => x.address)
|
340
|
+
);
|
341
|
+
}
|
342
|
+
|
343
|
+
tx.accounts = tx.accounts || [];
|
344
|
+
tx.stakes = tx.stakes || [];
|
345
|
+
|
346
|
+
tx.assets = uniq(tx.assets).filter(Boolean);
|
347
|
+
tx.factories = uniq(tx.factories).filter(Boolean);
|
348
|
+
tx.tokens = uniq(tx.tokens).filter(Boolean);
|
349
|
+
tx.accounts = uniq(tx.accounts).filter(Boolean);
|
350
|
+
tx.stakes = uniq(tx.stakes).filter(Boolean);
|
351
|
+
tx.rollups = uniq(tx.rollups).filter(Boolean);
|
352
|
+
|
353
|
+
return tx;
|
354
|
+
};
|
355
|
+
|
356
|
+
const formatTxAfterRead = (tx) => {
|
357
|
+
delete tx.assets;
|
358
|
+
delete tx.factories;
|
359
|
+
delete tx.tokens;
|
360
|
+
delete tx.accounts;
|
361
|
+
delete tx.stakes;
|
362
|
+
delete tx.rollups;
|
363
|
+
|
364
|
+
return tx;
|
365
|
+
};
|
366
|
+
|
367
|
+
const parseDateTime = (str) => {
|
368
|
+
if (!str) {
|
369
|
+
return '';
|
370
|
+
}
|
371
|
+
|
372
|
+
const parsed = Date.parse(str);
|
373
|
+
if (isNaN(parsed)) {
|
374
|
+
return '';
|
375
|
+
}
|
376
|
+
|
377
|
+
return new Date(parsed).toISOString();
|
378
|
+
};
|
379
|
+
|
380
|
+
const PAGE_SIZE_DEFAULT = 20;
|
381
|
+
const PAGE_SIZE_MAX = 100;
|
382
|
+
|
383
|
+
const formatPagination = ({ paging, defaultSortField, supportedSortFields = [] }) => {
|
384
|
+
if (!defaultSortField) {
|
385
|
+
throw new Error('argument defaultSortField is required');
|
386
|
+
}
|
387
|
+
|
388
|
+
const pagination = paging || { size: PAGE_SIZE_DEFAULT };
|
389
|
+
if (Array.isArray(pagination.order)) {
|
390
|
+
[pagination.order] = pagination.order;
|
391
|
+
}
|
392
|
+
|
393
|
+
if (!pagination.order) {
|
394
|
+
pagination.order = { field: defaultSortField, type: 'desc' };
|
395
|
+
}
|
396
|
+
|
397
|
+
if (!pagination.order.field) {
|
398
|
+
pagination.order.field = defaultSortField;
|
399
|
+
}
|
400
|
+
|
401
|
+
if (supportedSortFields.length > 0 && !supportedSortFields.includes(pagination.order.field)) {
|
402
|
+
pagination.order.field = defaultSortField;
|
403
|
+
}
|
404
|
+
|
405
|
+
if (!pagination.order.type) {
|
406
|
+
pagination.order.type = 'desc';
|
407
|
+
}
|
408
|
+
|
409
|
+
if (pagination.size === null || typeof pagination.size === 'undefined') {
|
410
|
+
pagination.size = PAGE_SIZE_DEFAULT;
|
411
|
+
}
|
412
|
+
|
413
|
+
// Since Elasticsearch does not support cursor based pagination, we just use offset as cursor
|
414
|
+
if (pagination.cursor) {
|
415
|
+
pagination.cursor = Number(pagination.cursor);
|
416
|
+
} else {
|
417
|
+
pagination.cursor = 0;
|
418
|
+
}
|
419
|
+
|
420
|
+
pagination.size = Math.min(pagination.size, PAGE_SIZE_MAX);
|
421
|
+
|
422
|
+
return pagination;
|
423
|
+
};
|
424
|
+
|
425
|
+
const formatNextPagination = (total, pagination) => {
|
426
|
+
const nextCursor = pagination.cursor + pagination.size;
|
427
|
+
if (total > nextCursor) {
|
428
|
+
return { cursor: nextCursor, next: true, total };
|
429
|
+
}
|
430
|
+
|
431
|
+
return { cursor: '0', next: false, total };
|
432
|
+
};
|
433
|
+
|
434
|
+
const isDefaultTokenChanged = (tx, token) => {
|
435
|
+
const itx = tx.tx.itxJson;
|
436
|
+
if (
|
437
|
+
[
|
438
|
+
'fg:t:transfer',
|
439
|
+
'fg:t:transfer_v2',
|
440
|
+
'fg:t:transfer_v3',
|
441
|
+
'fg:t:acquire_asset_v2',
|
442
|
+
'fg:t:acquire_asset_v3',
|
443
|
+
'fg:t:exchange',
|
444
|
+
'fg:t:exchange_v2',
|
445
|
+
'fg:t:deposit_token',
|
446
|
+
'fg:t:withdraw_token',
|
447
|
+
'fg:t:faucet',
|
448
|
+
'fg:t:poke',
|
449
|
+
'fg:t:setup_swap',
|
450
|
+
'fg:t:retrieve_swap',
|
451
|
+
'fg:t:stake',
|
452
|
+
'fg:t:revoke_stake',
|
453
|
+
].includes(itx.type_url) === false
|
454
|
+
) {
|
455
|
+
return false;
|
456
|
+
}
|
457
|
+
|
458
|
+
const ZERO = new BN(0);
|
459
|
+
const isDefaultToken = (id) => [token.address, ''].includes(id);
|
460
|
+
const isPositive = (v) => new BN(v || 0).gt(ZERO);
|
461
|
+
const isChangedByInput = (input) =>
|
462
|
+
isPositive(input.value) || input.tokens.some((x) => isDefaultToken(x.address) && isPositive(x.value));
|
463
|
+
|
464
|
+
switch (itx.type_url) {
|
465
|
+
case 'fg:t:transfer':
|
466
|
+
return isPositive(itx.value);
|
467
|
+
case 'fg:t:transfer_v2':
|
468
|
+
return isChangedByInput(itx);
|
469
|
+
case 'fg:t:transfer_v3':
|
470
|
+
case 'fg:t:acquire_asset_v3':
|
471
|
+
return itx.inputs.some(isChangedByInput);
|
472
|
+
case 'fg:t:acquire_asset_v2':
|
473
|
+
return tx.receipts.some((r) => r.changes.some((c) => isDefaultToken(c.target) && isPositive(c.value)));
|
474
|
+
case 'fg:t:exchange':
|
475
|
+
return isPositive(itx.sender.value) || isPositive(itx.receiver.value);
|
476
|
+
case 'fg:t:exchange_v2':
|
477
|
+
return isChangedByInput(itx.sender) || isChangedByInput(itx.receiver);
|
478
|
+
case 'fg:t:deposit_token':
|
479
|
+
case 'fg:t:withdraw_token':
|
480
|
+
return isPositive(itx.value);
|
481
|
+
case 'fg:t:setup_swap':
|
482
|
+
case 'fg:t:retrieve_swap':
|
483
|
+
return isPositive(itx.value);
|
484
|
+
case 'fg:t:poke':
|
485
|
+
return true;
|
486
|
+
case 'fg:t:faucet':
|
487
|
+
return !itx.token;
|
488
|
+
case 'fg:t:stake':
|
489
|
+
return itx.inputs.some(isChangedByInput);
|
490
|
+
case 'fg:t:revoke_stake':
|
491
|
+
return itx.outputs.some(isChangedByInput);
|
492
|
+
default:
|
493
|
+
return false;
|
494
|
+
}
|
495
|
+
};
|
496
|
+
|
497
|
+
module.exports = {
|
498
|
+
createIndexedAccount,
|
499
|
+
createIndexedAsset,
|
500
|
+
createIndexedFactory,
|
501
|
+
createIndexedDelegation,
|
502
|
+
createIndexedToken,
|
503
|
+
createIndexedTransaction,
|
504
|
+
createIndexedStake,
|
505
|
+
createIndexedRollup,
|
506
|
+
createIndexedRollupBlock,
|
507
|
+
formatPagination,
|
508
|
+
formatNextPagination,
|
509
|
+
formatTxAfterRead,
|
510
|
+
formatTxBeforeInsert,
|
511
|
+
parseDateTime,
|
512
|
+
formatTokenMeta,
|
513
|
+
isDefaultTokenChanged,
|
514
|
+
};
|
package/package.json
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
"publishConfig": {
|
4
4
|
"access": "public"
|
5
5
|
},
|
6
|
-
"version": "1.6.
|
6
|
+
"version": "1.6.10",
|
7
7
|
"description": "Defines the basic interface for OCAP IndexDB",
|
8
8
|
"main": "lib/main.js",
|
9
9
|
"files": [
|
@@ -12,18 +12,23 @@
|
|
12
12
|
"scripts": {
|
13
13
|
"lint": "eslint tests lib",
|
14
14
|
"lint:fix": "eslint --fix tests lib",
|
15
|
-
"test": "
|
15
|
+
"test": "jest --forceExit --detectOpenHandles",
|
16
16
|
"coverage": "npm run test -- --coverage"
|
17
17
|
},
|
18
18
|
"keywords": [],
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
20
|
+
"contributors": [
|
21
|
+
"wangshijun <shijun@arcblock.io> (https://github.com/wangshijun)"
|
22
|
+
],
|
20
23
|
"license": "MIT",
|
21
24
|
"devDependencies": {
|
22
|
-
"jest": "^
|
25
|
+
"jest": "^27.3.1"
|
23
26
|
},
|
24
27
|
"dependencies": {
|
25
|
-
"@ocap/
|
26
|
-
"
|
28
|
+
"@ocap/state": "1.6.10",
|
29
|
+
"@ocap/util": "1.6.10",
|
30
|
+
"kareem": "^2.3.2",
|
31
|
+
"lodash": "^4.17.21"
|
27
32
|
},
|
28
|
-
"gitHead": "
|
33
|
+
"gitHead": "ab272e8db3a15c6571cc7fae7cc3d3e0fdd4bdb1"
|
29
34
|
}
|