@ocap/indexdb-memory 1.28.8 → 1.29.0
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/README.md +1 -2
- package/esm/db/base.d.mts +20 -0
- package/esm/db/base.mjs +430 -0
- package/esm/db/index.d.mts +27 -0
- package/esm/db/index.mjs +37 -0
- package/esm/main.d.mts +3 -0
- package/esm/main.mjs +8 -0
- package/esm/package.mjs +6 -0
- package/esm/table/base.d.mts +22 -0
- package/esm/table/base.mjs +52 -0
- package/esm/table/transaction.d.mts +9 -0
- package/esm/table/transaction.mjs +13 -0
- package/lib/_virtual/rolldown_runtime.cjs +29 -0
- package/lib/db/base.cjs +434 -0
- package/lib/db/base.d.cts +20 -0
- package/lib/db/index.cjs +40 -0
- package/lib/db/index.d.cts +27 -0
- package/lib/main.cjs +10 -0
- package/lib/main.d.cts +3 -0
- package/lib/package.cjs +18 -0
- package/lib/table/base.cjs +55 -0
- package/lib/table/base.d.cts +22 -0
- package/lib/table/transaction.cjs +15 -0
- package/lib/table/transaction.d.cts +9 -0
- package/package.json +40 -11
- package/lib/db/base.js +0 -631
- package/lib/db/index.js +0 -42
- package/lib/main.js +0 -3
- package/lib/table/base.js +0 -58
- package/lib/table/transaction.js +0 -10
package/README.md
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# [**@ocap/indexdb-memory**](https://github.com/arcblock/blockchain)
|
|
2
2
|
|
|
3
|
-
[](https://github.com/prettier/prettier)
|
|
4
3
|
|
|
5
4
|
> OCAP indexdb adapter that stores data in memory through lokijs
|
|
6
5
|
|
|
@@ -15,7 +14,7 @@ bun install @ocap/indexdb-memory
|
|
|
15
14
|
## Usage
|
|
16
15
|
|
|
17
16
|
```js
|
|
18
|
-
const MemoryIndexDB = require('@ocap/indexdb-memory');
|
|
17
|
+
const MemoryIndexDB = require('@ocap/indexdb-memory').default;
|
|
19
18
|
|
|
20
19
|
const indexdb = new MemoryIndexDB();
|
|
21
20
|
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseIndexDB } from "@ocap/indexdb";
|
|
2
|
+
import { IIndexDB, IListAccountsResult, IListAssetsResult, IListDelegationsResult, IListFactoriesResult, IListRollupBlocksResult, IListRollupValidatorsResult, IListRollupsResult, IListStakesResult, IListTokenFactoriesResult, IListTokensResult, IListTransactionsResult, TRequestListAssets, TRequestListDelegations, TRequestListFactories, TRequestListRollupBlocks, TRequestListRollupValidators, TRequestListRollups, TRequestListStakes, TRequestListTokenFactories, TRequestListTokens, TRequestListTopAccounts, TRequestListTransactions } from "@ocap/types";
|
|
3
|
+
|
|
4
|
+
//#region src/db/base.d.ts
|
|
5
|
+
declare class LocalBaseIndexDB extends BaseIndexDB implements IIndexDB {
|
|
6
|
+
listTransactions(params?: Partial<TRequestListTransactions>): IListTransactionsResult;
|
|
7
|
+
getRelatedAddresses(address: string): Promise<string[]>;
|
|
8
|
+
listAssets(params?: Partial<TRequestListAssets>): Promise<IListAssetsResult>;
|
|
9
|
+
listTopAccounts(params?: Partial<TRequestListTopAccounts>): Promise<IListAccountsResult>;
|
|
10
|
+
listTokens(params?: Partial<TRequestListTokens>): Promise<IListTokensResult>;
|
|
11
|
+
listTokenFactories(params?: Partial<TRequestListTokenFactories>): Promise<IListTokenFactoriesResult>;
|
|
12
|
+
listFactories(params?: Partial<TRequestListFactories>): Promise<IListFactoriesResult>;
|
|
13
|
+
listStakes(params?: Partial<TRequestListStakes>): IListStakesResult;
|
|
14
|
+
listRollups(params?: Partial<TRequestListRollups>): Promise<IListRollupsResult>;
|
|
15
|
+
listRollupBlocks(params?: Partial<TRequestListRollupBlocks>): IListRollupBlocksResult;
|
|
16
|
+
listRollupValidators(params?: Partial<TRequestListRollupValidators>): IListRollupValidatorsResult;
|
|
17
|
+
listDelegations(params?: Partial<TRequestListDelegations>): IListDelegationsResult;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { LocalBaseIndexDB as default };
|
package/esm/db/base.mjs
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { name } from "../package.mjs";
|
|
2
|
+
import { BaseIndexDB, formatDelegationAfterRead, formatNextPagination, formatPagination, parseDateTime } from "@ocap/indexdb";
|
|
3
|
+
import debugFactory from "debug";
|
|
4
|
+
import { toChecksumAddress } from "@arcblock/did/lib/type";
|
|
5
|
+
import { BN } from "@ocap/util";
|
|
6
|
+
import { DEFAULT_TOKEN_DECIMAL } from "@ocap/util/lib/constant";
|
|
7
|
+
import omit from "lodash/omit.js";
|
|
8
|
+
|
|
9
|
+
//#region src/db/base.ts
|
|
10
|
+
const debug = debugFactory(name);
|
|
11
|
+
const MAX_REQUEST_FACTORY_ADDRESS_SIZE = 100;
|
|
12
|
+
/** Helper to safely get collection from IIndexTable */
|
|
13
|
+
function getCollection(table) {
|
|
14
|
+
return table.collection;
|
|
15
|
+
}
|
|
16
|
+
function applyTimeFilter(query, timeFilter, defaultField, validFields) {
|
|
17
|
+
let { startDateTime, endDateTime, field = defaultField } = timeFilter;
|
|
18
|
+
startDateTime = parseDateTime(startDateTime);
|
|
19
|
+
endDateTime = parseDateTime(endDateTime);
|
|
20
|
+
if (!validFields.includes(field)) field = defaultField;
|
|
21
|
+
if (startDateTime && endDateTime) query.where((x) => x[field] > startDateTime && x[field] <= endDateTime);
|
|
22
|
+
else if (startDateTime) query.where((x) => x[field] > startDateTime);
|
|
23
|
+
else if (endDateTime) query.where((x) => x[field] <= endDateTime);
|
|
24
|
+
}
|
|
25
|
+
function applyArrayFilter(query, items, fieldName, isArrayField) {
|
|
26
|
+
if (!items.length) return;
|
|
27
|
+
if (isArrayField) query.where((x) => x[fieldName].some((f) => items.includes(f)));
|
|
28
|
+
else query.where((x) => items.includes(x[fieldName]));
|
|
29
|
+
}
|
|
30
|
+
function buildPagingResult(total, pagination, itemCount) {
|
|
31
|
+
return {
|
|
32
|
+
cursor: String(pagination.cursor + itemCount),
|
|
33
|
+
next: itemCount >= pagination.size,
|
|
34
|
+
total
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
var LocalBaseIndexDB = class extends BaseIndexDB {
|
|
38
|
+
listTransactions(params = {}) {
|
|
39
|
+
const { addressFilter = {}, paging = {}, timeFilter = {}, typeFilter = {}, assetFilter = {}, factoryFilter = {}, tokenFilter = {}, accountFilter = {}, validityFilter = {}, txFilter = {}, rollupFilter = {}, stakeFilter = {}, delegationFilter = {}, tokenFactoryFilter = {}, includeItxData = false } = params;
|
|
40
|
+
const query = getCollection(this.tx).chain();
|
|
41
|
+
const { sender, receiver, direction = "UNION" } = addressFilter;
|
|
42
|
+
const { types = [] } = typeFilter;
|
|
43
|
+
const { factories = [] } = factoryFilter;
|
|
44
|
+
const { assets = [] } = assetFilter;
|
|
45
|
+
const { tokens = [] } = tokenFilter;
|
|
46
|
+
const { accounts = [] } = accountFilter;
|
|
47
|
+
const { txs = [] } = txFilter;
|
|
48
|
+
const { rollups = [] } = rollupFilter;
|
|
49
|
+
const { stakes = [] } = stakeFilter;
|
|
50
|
+
const { delegations = [] } = delegationFilter;
|
|
51
|
+
const { tokenFactories = [] } = tokenFactoryFilter;
|
|
52
|
+
const pagination = formatPagination({
|
|
53
|
+
paging,
|
|
54
|
+
defaultSortField: "time"
|
|
55
|
+
});
|
|
56
|
+
debug("listTransactions", {
|
|
57
|
+
sender,
|
|
58
|
+
receiver,
|
|
59
|
+
pagination,
|
|
60
|
+
types,
|
|
61
|
+
factories,
|
|
62
|
+
assets,
|
|
63
|
+
tokens,
|
|
64
|
+
accounts,
|
|
65
|
+
rollups,
|
|
66
|
+
stakes,
|
|
67
|
+
delegations,
|
|
68
|
+
includeItxData
|
|
69
|
+
});
|
|
70
|
+
if (sender && receiver) {
|
|
71
|
+
if (direction === "MUTUAL") query.where((x) => x.sender === sender && x.receiver === receiver || x.sender === receiver && x.receiver === sender);
|
|
72
|
+
else if (direction === "ONE_WAY") query.where((x) => x.sender === sender && x.receiver === receiver);
|
|
73
|
+
else if (direction === "UNION") query.where((x) => x.sender === sender || x.receiver === receiver);
|
|
74
|
+
} else if (sender) query.where((x) => x.sender === sender);
|
|
75
|
+
else if (receiver) query.where((x) => x.receiver === receiver);
|
|
76
|
+
applyArrayFilter(query, types, "type", false);
|
|
77
|
+
applyArrayFilter(query, factories, "factories", true);
|
|
78
|
+
applyArrayFilter(query, assets, "assets", true);
|
|
79
|
+
applyArrayFilter(query, tokens, "tokens", true);
|
|
80
|
+
applyArrayFilter(query, accounts, "accounts", true);
|
|
81
|
+
applyArrayFilter(query, tokenFactories, "tokenFactories", true);
|
|
82
|
+
applyArrayFilter(query, txs, "hash", false);
|
|
83
|
+
applyArrayFilter(query, rollups, "rollups", true);
|
|
84
|
+
applyArrayFilter(query, stakes, "stakes", true);
|
|
85
|
+
applyArrayFilter(query, delegations, "delegations", true);
|
|
86
|
+
applyTimeFilter(query, timeFilter, "time", ["time"]);
|
|
87
|
+
const { validity } = validityFilter;
|
|
88
|
+
if (validity === "VALID") query.where((x) => x.valid === true);
|
|
89
|
+
else if (validity === "INVALID") query.where((x) => x.valid === false);
|
|
90
|
+
let transactions = query.simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data();
|
|
91
|
+
if (!includeItxData) transactions = transactions.map((tx) => {
|
|
92
|
+
if (tx.tx && tx.tx?.itxJson) return {
|
|
93
|
+
...tx,
|
|
94
|
+
tx: {
|
|
95
|
+
...tx.tx,
|
|
96
|
+
itxJson: omit(tx.tx.itxJson, ["data"])
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
return tx;
|
|
100
|
+
});
|
|
101
|
+
const total = query.count();
|
|
102
|
+
return {
|
|
103
|
+
transactions,
|
|
104
|
+
paging: buildPagingResult(total, pagination, transactions.length)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async getRelatedAddresses(address) {
|
|
108
|
+
let account = await this.account.get(address);
|
|
109
|
+
if (!account) return [];
|
|
110
|
+
const related = [address];
|
|
111
|
+
while (account?.migratedFrom && related.length <= 8) {
|
|
112
|
+
const migratedFrom = account.migratedFrom;
|
|
113
|
+
related.push(migratedFrom);
|
|
114
|
+
account = await this.account.get(migratedFrom);
|
|
115
|
+
}
|
|
116
|
+
return related.filter(Boolean);
|
|
117
|
+
}
|
|
118
|
+
async listAssets(params = {}) {
|
|
119
|
+
const { ownerAddress, factoryAddress, paging, timeFilter = {} } = params;
|
|
120
|
+
if (!ownerAddress && !factoryAddress) return {
|
|
121
|
+
assets: [],
|
|
122
|
+
account: null,
|
|
123
|
+
paging: {
|
|
124
|
+
cursor: "0",
|
|
125
|
+
next: false,
|
|
126
|
+
total: 0
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const pagination = formatPagination({
|
|
130
|
+
paging,
|
|
131
|
+
defaultSortField: "renaissanceTime"
|
|
132
|
+
});
|
|
133
|
+
const { field = "renaissanceTime" } = timeFilter;
|
|
134
|
+
if ([
|
|
135
|
+
"genesisTime",
|
|
136
|
+
"renaissanceTime",
|
|
137
|
+
"consumedTime"
|
|
138
|
+
].includes(field) === false) throw new Error("invalid field specified in timeFilter");
|
|
139
|
+
const query = getCollection(this.asset).chain();
|
|
140
|
+
if (ownerAddress) {
|
|
141
|
+
const possibleOwners = await this.getRelatedAddresses(ownerAddress);
|
|
142
|
+
if (possibleOwners.length) query.where((x) => possibleOwners.includes(x.owner));
|
|
143
|
+
else return {
|
|
144
|
+
assets: [],
|
|
145
|
+
account: null,
|
|
146
|
+
paging: {
|
|
147
|
+
cursor: "0",
|
|
148
|
+
next: false,
|
|
149
|
+
total: 0
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (factoryAddress) query.where((x) => x.parent === factoryAddress);
|
|
154
|
+
applyTimeFilter(query, timeFilter, "renaissanceTime", [
|
|
155
|
+
"genesisTime",
|
|
156
|
+
"renaissanceTime",
|
|
157
|
+
"consumedTime"
|
|
158
|
+
]);
|
|
159
|
+
debug("listAssets", {
|
|
160
|
+
ownerAddress,
|
|
161
|
+
factoryAddress,
|
|
162
|
+
timeFilter,
|
|
163
|
+
paging,
|
|
164
|
+
pagination
|
|
165
|
+
});
|
|
166
|
+
const assets = query.simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data();
|
|
167
|
+
const total = query.count();
|
|
168
|
+
return {
|
|
169
|
+
assets,
|
|
170
|
+
account: ownerAddress ? await this.account.get(ownerAddress) : null,
|
|
171
|
+
paging: formatNextPagination(total, pagination)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async listTopAccounts(params = {}) {
|
|
175
|
+
const { paging, tokenAddress } = params;
|
|
176
|
+
const query = getCollection(this.account).chain();
|
|
177
|
+
const pagination = formatPagination({
|
|
178
|
+
paging,
|
|
179
|
+
defaultSortField: "balance",
|
|
180
|
+
supportedSortFields: [
|
|
181
|
+
"genesisTime",
|
|
182
|
+
"renaissanceTime",
|
|
183
|
+
"balance",
|
|
184
|
+
"moniker"
|
|
185
|
+
]
|
|
186
|
+
});
|
|
187
|
+
debug("listTopAccounts", {
|
|
188
|
+
tokenAddress,
|
|
189
|
+
paging,
|
|
190
|
+
pagination
|
|
191
|
+
});
|
|
192
|
+
query.where((x) => {
|
|
193
|
+
const owned = x.tokens.find((t) => t.address === tokenAddress);
|
|
194
|
+
return owned ? owned.balance > "0" : false;
|
|
195
|
+
});
|
|
196
|
+
if (pagination.order.field === "balance") {
|
|
197
|
+
const descending = pagination.order.type === "desc";
|
|
198
|
+
query.sort((a, b) => {
|
|
199
|
+
const tokenA = a.tokens.find((t) => t.address === tokenAddress);
|
|
200
|
+
const tokenB = b.tokens.find((t) => t.address === tokenAddress);
|
|
201
|
+
const balanceA = new BN(tokenA ? tokenA.balance : "0");
|
|
202
|
+
const balanceB = new BN(tokenB ? tokenB.balance : "0");
|
|
203
|
+
if (balanceB.gt(balanceA)) return descending ? 1 : -1;
|
|
204
|
+
if (balanceB.eq(balanceA)) return 0;
|
|
205
|
+
return descending ? -1 : 1;
|
|
206
|
+
});
|
|
207
|
+
} else query.simplesort(pagination.order.field, pagination.order.type === "desc");
|
|
208
|
+
const accounts = query.offset(pagination.cursor).limit(pagination.size).data();
|
|
209
|
+
const total = query.count();
|
|
210
|
+
accounts.forEach((account) => {
|
|
211
|
+
const acc = account;
|
|
212
|
+
if (Array.isArray(acc.tokens) && acc.tokens.length) acc.tokens = acc.tokens.map((token) => {
|
|
213
|
+
token.decimal = typeof token.decimal === "undefined" ? DEFAULT_TOKEN_DECIMAL : token.decimal;
|
|
214
|
+
return token;
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
return {
|
|
218
|
+
accounts,
|
|
219
|
+
paging: formatNextPagination(total, pagination)
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
async listTokens(params = {}) {
|
|
223
|
+
const { issuerAddress, paging } = params;
|
|
224
|
+
const conditions = {};
|
|
225
|
+
if (issuerAddress) conditions.issuer = issuerAddress;
|
|
226
|
+
const pagination = formatPagination({
|
|
227
|
+
paging,
|
|
228
|
+
defaultSortField: "renaissanceTime",
|
|
229
|
+
supportedSortFields: [
|
|
230
|
+
"genesisTime",
|
|
231
|
+
"renaissanceTime",
|
|
232
|
+
"issuer",
|
|
233
|
+
"symbol",
|
|
234
|
+
"totalSupply"
|
|
235
|
+
]
|
|
236
|
+
});
|
|
237
|
+
debug("listTokens", {
|
|
238
|
+
issuerAddress,
|
|
239
|
+
paging,
|
|
240
|
+
conditions,
|
|
241
|
+
pagination
|
|
242
|
+
});
|
|
243
|
+
let tokens = getCollection(this.token).chain().find(conditions).simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data();
|
|
244
|
+
tokens = tokens.map((token) => {
|
|
245
|
+
const t = token;
|
|
246
|
+
t.decimal = typeof t.decimal === "undefined" ? DEFAULT_TOKEN_DECIMAL : t.decimal;
|
|
247
|
+
return t;
|
|
248
|
+
});
|
|
249
|
+
const total = this.token.count(Object.keys(conditions).length ? conditions : void 0);
|
|
250
|
+
return {
|
|
251
|
+
tokens,
|
|
252
|
+
paging: formatNextPagination(total, pagination)
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
async listTokenFactories(params = {}) {
|
|
256
|
+
const { owner, reserveAddress, tokenAddress, paging } = params;
|
|
257
|
+
const conditions = {};
|
|
258
|
+
if (owner) conditions.owner = owner;
|
|
259
|
+
if (reserveAddress) conditions.reserveAddress = reserveAddress;
|
|
260
|
+
if (tokenAddress) conditions.tokenAddress = tokenAddress;
|
|
261
|
+
const pagination = formatPagination({
|
|
262
|
+
paging,
|
|
263
|
+
defaultSortField: "renaissanceTime",
|
|
264
|
+
supportedSortFields: [
|
|
265
|
+
"genesisTime",
|
|
266
|
+
"renaissanceTime",
|
|
267
|
+
"reserveBalance",
|
|
268
|
+
"currentSupply"
|
|
269
|
+
]
|
|
270
|
+
});
|
|
271
|
+
debug("listTokenFactories", {
|
|
272
|
+
owner,
|
|
273
|
+
reserveAddress,
|
|
274
|
+
tokenAddress,
|
|
275
|
+
paging,
|
|
276
|
+
conditions,
|
|
277
|
+
pagination
|
|
278
|
+
});
|
|
279
|
+
return {
|
|
280
|
+
tokenFactories: getCollection(this.tokenFactory).chain().find(conditions).simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data(),
|
|
281
|
+
paging: formatNextPagination(this.tokenFactory.count(Object.keys(conditions).length ? conditions : void 0), pagination)
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async listFactories(params = {}) {
|
|
285
|
+
const { ownerAddress, addressList, paging } = params;
|
|
286
|
+
const conditions = {};
|
|
287
|
+
if (ownerAddress) conditions.owner = ownerAddress;
|
|
288
|
+
if (Array.isArray(addressList) && addressList.length > 0) {
|
|
289
|
+
if (addressList.length > MAX_REQUEST_FACTORY_ADDRESS_SIZE) throw new Error(`The length of 'addressList' cannot exceed the length of ${MAX_REQUEST_FACTORY_ADDRESS_SIZE}`);
|
|
290
|
+
conditions.address = { $in: addressList };
|
|
291
|
+
}
|
|
292
|
+
const pagination = formatPagination({
|
|
293
|
+
paging,
|
|
294
|
+
defaultSortField: "renaissanceTime",
|
|
295
|
+
supportedSortFields: [
|
|
296
|
+
"genesisTime",
|
|
297
|
+
"renaissanceTime",
|
|
298
|
+
"owner",
|
|
299
|
+
"numMinted",
|
|
300
|
+
"limit",
|
|
301
|
+
"name"
|
|
302
|
+
]
|
|
303
|
+
});
|
|
304
|
+
debug("listFactories", {
|
|
305
|
+
ownerAddress,
|
|
306
|
+
paging,
|
|
307
|
+
conditions,
|
|
308
|
+
pagination
|
|
309
|
+
});
|
|
310
|
+
return {
|
|
311
|
+
factories: getCollection(this.factory).chain().find(conditions).simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data(),
|
|
312
|
+
paging: formatNextPagination(this.factory.count(Object.keys(conditions).length ? conditions : void 0), pagination)
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
listStakes(params = {}) {
|
|
316
|
+
const { addressFilter = {}, paging = {}, timeFilter = {}, assetFilter = {} } = params;
|
|
317
|
+
const query = getCollection(this.stake).chain();
|
|
318
|
+
const { sender, receiver } = addressFilter;
|
|
319
|
+
const { assets = [] } = assetFilter;
|
|
320
|
+
const pagination = formatPagination({
|
|
321
|
+
paging,
|
|
322
|
+
defaultSortField: "renaissanceTime",
|
|
323
|
+
supportedSortFields: ["genesisTime", "renaissanceTime"]
|
|
324
|
+
});
|
|
325
|
+
if (sender && receiver) query.where((x) => x.sender === sender && x.receiver === receiver);
|
|
326
|
+
else if (sender) query.where((x) => x.sender === sender);
|
|
327
|
+
else if (receiver) query.where((x) => x.receiver === receiver);
|
|
328
|
+
applyArrayFilter(query, assets, "assets", true);
|
|
329
|
+
applyTimeFilter(query, timeFilter, "renaissanceTime", ["genesisTime", "renaissanceTime"]);
|
|
330
|
+
const stakes = query.simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data();
|
|
331
|
+
return {
|
|
332
|
+
stakes,
|
|
333
|
+
paging: buildPagingResult(query.count(), pagination, stakes.length)
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
async listRollups(params = {}) {
|
|
337
|
+
const { paging, tokenAddress = "", erc20TokenAddress = "", foreignTokenAddress = "" } = params;
|
|
338
|
+
const pagination = formatPagination({
|
|
339
|
+
paging,
|
|
340
|
+
defaultSortField: "renaissanceTime",
|
|
341
|
+
supportedSortFields: ["genesisTime", "renaissanceTime"]
|
|
342
|
+
});
|
|
343
|
+
const query = getCollection(this.rollup).chain();
|
|
344
|
+
if (tokenAddress) query.where((x) => x.tokenAddress === tokenAddress);
|
|
345
|
+
const foreignTokenAddr = foreignTokenAddress || erc20TokenAddress;
|
|
346
|
+
if (erc20TokenAddress) query.where((x) => x.foreignToken.contractAddress === toChecksumAddress(foreignTokenAddr));
|
|
347
|
+
debug("listRollups", {
|
|
348
|
+
paging,
|
|
349
|
+
pagination
|
|
350
|
+
});
|
|
351
|
+
return {
|
|
352
|
+
rollups: query.simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data(),
|
|
353
|
+
paging: formatNextPagination(query.count(), pagination)
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
listRollupBlocks(params = {}) {
|
|
357
|
+
const { paging = {}, rollupAddress = "", tokenAddress = "", proposer = "", height = "", timeFilter = {}, txFilter = {}, validatorFilter = {} } = params;
|
|
358
|
+
const query = getCollection(this.rollupBlock).chain();
|
|
359
|
+
const { txs = [] } = txFilter;
|
|
360
|
+
const { validators = [] } = validatorFilter;
|
|
361
|
+
const pagination = formatPagination({
|
|
362
|
+
paging,
|
|
363
|
+
defaultSortField: "genesisTime",
|
|
364
|
+
supportedSortFields: ["genesisTime", "renaissanceTime"]
|
|
365
|
+
});
|
|
366
|
+
if (rollupAddress) query.where((x) => x.rollup === rollupAddress);
|
|
367
|
+
if (Number(height) > 0) query.where((x) => Number(x.height) === Number(height));
|
|
368
|
+
if (proposer) query.where((x) => x.proposer === proposer);
|
|
369
|
+
if (tokenAddress) query.where((x) => x.tokenInfo.address === tokenAddress);
|
|
370
|
+
applyArrayFilter(query, txs, "txs", true);
|
|
371
|
+
applyArrayFilter(query, validators, "validators", true);
|
|
372
|
+
applyTimeFilter(query, timeFilter, "genesisTime", ["genesisTime", "renaissanceTime"]);
|
|
373
|
+
const blocks = query.simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data();
|
|
374
|
+
return {
|
|
375
|
+
blocks,
|
|
376
|
+
paging: buildPagingResult(query.count(), pagination, blocks.length)
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
listRollupValidators(params = {}) {
|
|
380
|
+
const { paging = {}, rollupAddress = "" } = params;
|
|
381
|
+
const query = getCollection(this.rollupValidator).chain();
|
|
382
|
+
const pagination = formatPagination({
|
|
383
|
+
paging,
|
|
384
|
+
defaultSortField: "genesisTime",
|
|
385
|
+
supportedSortFields: [
|
|
386
|
+
"joinTime",
|
|
387
|
+
"leaveTime",
|
|
388
|
+
"genesisTime",
|
|
389
|
+
"renaissanceTime"
|
|
390
|
+
]
|
|
391
|
+
});
|
|
392
|
+
if (rollupAddress) query.where((x) => x.rollup === rollupAddress);
|
|
393
|
+
const validators = query.simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data();
|
|
394
|
+
return {
|
|
395
|
+
validators,
|
|
396
|
+
paging: buildPagingResult(query.count(), pagination, validators.length)
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
listDelegations(params = {}) {
|
|
400
|
+
const { from, to, paging = {}, timeFilter = {} } = params;
|
|
401
|
+
if (!from && !to) return {
|
|
402
|
+
delegations: [],
|
|
403
|
+
paging: {
|
|
404
|
+
cursor: "0",
|
|
405
|
+
next: false,
|
|
406
|
+
total: 0
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
const query = getCollection(this.delegation).chain();
|
|
410
|
+
const pagination = formatPagination({
|
|
411
|
+
paging,
|
|
412
|
+
defaultSortField: "renaissanceTime",
|
|
413
|
+
supportedSortFields: ["genesisTime", "renaissanceTime"]
|
|
414
|
+
});
|
|
415
|
+
if (from && to) query.where((x) => x.from === from && x.to === to);
|
|
416
|
+
else if (from) query.where((x) => x.from === from);
|
|
417
|
+
else if (to) query.where((x) => x.to === to);
|
|
418
|
+
applyTimeFilter(query, timeFilter, "renaissanceTime", ["genesisTime", "renaissanceTime"]);
|
|
419
|
+
const delegations = query.simplesort(pagination.order.field, pagination.order.type === "desc").offset(pagination.cursor).limit(pagination.size).data();
|
|
420
|
+
const total = query.count();
|
|
421
|
+
return {
|
|
422
|
+
delegations: delegations.map((d) => formatDelegationAfterRead(d)),
|
|
423
|
+
paging: buildPagingResult(total, pagination, delegations.length)
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
var base_default = LocalBaseIndexDB;
|
|
428
|
+
|
|
429
|
+
//#endregion
|
|
430
|
+
export { base_default as default };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import LocalBaseIndexDB from "./base.mjs";
|
|
2
|
+
import { md5 } from "@ocap/util/lib/md5";
|
|
3
|
+
import Lokijs from "lokijs";
|
|
4
|
+
import { IIndexDB, IIndexTable, IndexTableTypeMap } from "@ocap/types";
|
|
5
|
+
|
|
6
|
+
//#region src/db/index.d.ts
|
|
7
|
+
declare class MemoryIndexDB extends LocalBaseIndexDB implements IIndexDB {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
md5: typeof md5;
|
|
11
|
+
db: Lokijs;
|
|
12
|
+
tx: IIndexTable<IndexTableTypeMap['tx']>;
|
|
13
|
+
account: IIndexTable<IndexTableTypeMap['account']>;
|
|
14
|
+
asset: IIndexTable<IndexTableTypeMap['asset']>;
|
|
15
|
+
token: IIndexTable<IndexTableTypeMap['token']>;
|
|
16
|
+
factory: IIndexTable<IndexTableTypeMap['factory']>;
|
|
17
|
+
stake: IIndexTable<IndexTableTypeMap['stake']>;
|
|
18
|
+
delegation: IIndexTable<IndexTableTypeMap['delegation']>;
|
|
19
|
+
rollup: IIndexTable<IndexTableTypeMap['rollup']>;
|
|
20
|
+
rollupBlock: IIndexTable<IndexTableTypeMap['rollupBlock']>;
|
|
21
|
+
rollupValidator: IIndexTable<IndexTableTypeMap['rollupValidator']>;
|
|
22
|
+
tokenDistribution: IIndexTable<IndexTableTypeMap['tokenDistribution']>;
|
|
23
|
+
tokenFactory: IIndexTable<IndexTableTypeMap['tokenFactory']>;
|
|
24
|
+
constructor();
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { MemoryIndexDB as default };
|
package/esm/db/index.mjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { name, version } from "../package.mjs";
|
|
2
|
+
import base_default from "../table/base.mjs";
|
|
3
|
+
import transaction_default from "../table/transaction.mjs";
|
|
4
|
+
import base_default$1 from "./base.mjs";
|
|
5
|
+
import { md5 } from "@ocap/util/lib/md5";
|
|
6
|
+
import Lokijs from "lokijs";
|
|
7
|
+
|
|
8
|
+
//#region src/db/index.ts
|
|
9
|
+
let instanceCounter = 0;
|
|
10
|
+
var MemoryIndexDB = class extends base_default$1 {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
this.name = name;
|
|
14
|
+
this.version = version;
|
|
15
|
+
this.md5 = md5;
|
|
16
|
+
instanceCounter += 1;
|
|
17
|
+
this.db = new Lokijs(`ocap-memory-indexdb-${instanceCounter}.db`);
|
|
18
|
+
this.account = new base_default("account", "address", this.db);
|
|
19
|
+
this.asset = new base_default("asset", "address", this.db);
|
|
20
|
+
this.delegation = new base_default("delegation", "address", this.db);
|
|
21
|
+
this.tx = new transaction_default("tx", "hash", this.db);
|
|
22
|
+
this.factory = new base_default("factory", "address", this.db);
|
|
23
|
+
this.token = new base_default("token", "address", this.db);
|
|
24
|
+
this.stake = new base_default("stake", "address", this.db);
|
|
25
|
+
this.rollup = new base_default("rollup", "address", this.db);
|
|
26
|
+
this.rollupBlock = new base_default("rollupBlock", "hash", this.db);
|
|
27
|
+
this.rollupValidator = new base_default("rollupValidator", "address", this.db);
|
|
28
|
+
this.tokenDistribution = new base_default("tokenDistribution", "tokenAddress", this.db);
|
|
29
|
+
this.balance = new base_default("balance", ["address", "tokenAddress"], this.db);
|
|
30
|
+
this.tokenFactory = new base_default("tokenFactory", "address", this.db);
|
|
31
|
+
this.attachReadyListeners();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var db_default = MemoryIndexDB;
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { db_default as default };
|
package/esm/main.d.mts
ADDED
package/esm/main.mjs
ADDED
package/esm/package.mjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Lokijs from "lokijs";
|
|
2
|
+
import { BaseIndex } from "@ocap/indexdb";
|
|
3
|
+
import { IIndexTable } from "@ocap/types";
|
|
4
|
+
|
|
5
|
+
//#region src/table/base.d.ts
|
|
6
|
+
type UniqueIndex = string | string[];
|
|
7
|
+
declare class MemoryIndex<T = unknown> extends BaseIndex<T> implements IIndexTable<T> {
|
|
8
|
+
collection: Lokijs.Collection<T & Record<string, unknown>>;
|
|
9
|
+
/**
|
|
10
|
+
* @param name table name
|
|
11
|
+
* @param uniqIndex primary key(s)
|
|
12
|
+
* @param db LokiJS database instance
|
|
13
|
+
*/
|
|
14
|
+
constructor(name: string, uniqIndex: UniqueIndex, db: Lokijs);
|
|
15
|
+
count(...args: Parameters<Lokijs.Collection['count']>): number;
|
|
16
|
+
_insert(row: Record<string, unknown>): T & Record<string, unknown>;
|
|
17
|
+
_get(key: string | Record<string, unknown>): (T & Record<string, unknown>) | null;
|
|
18
|
+
_update(key: string | Record<string, unknown>, updates: Record<string, unknown>): T & Record<string, unknown>;
|
|
19
|
+
_reset(): void;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { MemoryIndex as default };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { name } from "../package.mjs";
|
|
2
|
+
import { BaseIndex } from "@ocap/indexdb";
|
|
3
|
+
import debugFactory from "debug";
|
|
4
|
+
|
|
5
|
+
//#region src/table/base.ts
|
|
6
|
+
const debug = debugFactory(name);
|
|
7
|
+
var MemoryIndex = class MemoryIndex extends BaseIndex {
|
|
8
|
+
/**
|
|
9
|
+
* @param name table name
|
|
10
|
+
* @param uniqIndex primary key(s)
|
|
11
|
+
* @param db LokiJS database instance
|
|
12
|
+
*/
|
|
13
|
+
constructor(name$1, uniqIndex, db) {
|
|
14
|
+
super(name$1, uniqIndex);
|
|
15
|
+
if (!db) throw new Error("db is required for MemoryIndex");
|
|
16
|
+
this.collection = db.addCollection(name$1, {
|
|
17
|
+
unique: [this.primaryKey],
|
|
18
|
+
clone: true
|
|
19
|
+
});
|
|
20
|
+
this.markReady();
|
|
21
|
+
}
|
|
22
|
+
count(...args) {
|
|
23
|
+
return this.collection.count(...args);
|
|
24
|
+
}
|
|
25
|
+
_insert(row) {
|
|
26
|
+
debug(`insert ${this.name}`, row);
|
|
27
|
+
const id = this.generatePrimaryKey(row);
|
|
28
|
+
return this.collection.insert({
|
|
29
|
+
[this.primaryKey]: id,
|
|
30
|
+
...row
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
_get(key) {
|
|
34
|
+
const id = this.generatePrimaryKey(key);
|
|
35
|
+
return key ? this.collection.by(this.primaryKey, id) ?? null : null;
|
|
36
|
+
}
|
|
37
|
+
_update(key, updates) {
|
|
38
|
+
const id = this.generatePrimaryKey(key);
|
|
39
|
+
const doc = MemoryIndex.prototype._get.call(this, id);
|
|
40
|
+
if (!doc) throw new Error(`${this.name} does not exists: ${key}`);
|
|
41
|
+
Object.assign(doc, updates);
|
|
42
|
+
this.collection.update(doc);
|
|
43
|
+
return doc;
|
|
44
|
+
}
|
|
45
|
+
_reset() {
|
|
46
|
+
this.collection.removeWhere({});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var base_default = MemoryIndex;
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { base_default as default };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import MemoryIndex from "./base.mjs";
|
|
2
|
+
import { TIndexedTransaction } from "@ocap/types";
|
|
3
|
+
|
|
4
|
+
//#region src/table/transaction.d.ts
|
|
5
|
+
declare class Transaction extends MemoryIndex<TIndexedTransaction> {
|
|
6
|
+
_insert(row: Record<string, unknown>): TIndexedTransaction & Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { Transaction as default };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import base_default from "./base.mjs";
|
|
2
|
+
import { formatTxBeforeInsert } from "@ocap/indexdb";
|
|
3
|
+
|
|
4
|
+
//#region src/table/transaction.ts
|
|
5
|
+
var Transaction = class extends base_default {
|
|
6
|
+
_insert(row) {
|
|
7
|
+
return super._insert(formatTxBeforeInsert(row));
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
var transaction_default = Transaction;
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { transaction_default as default };
|