@ocap/statedb-fs 1.20.16 → 1.21.1
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 +31 -11
- package/lib/table/account.js +5 -15
- package/lib/table/balance.js +41 -0
- package/lib/table/base.js +78 -13
- package/package.json +4 -4
package/lib/db.js
CHANGED
|
@@ -4,6 +4,7 @@ const Table = require('./table/base');
|
|
|
4
4
|
const Account = require('./table/account');
|
|
5
5
|
const Token = require('./table/token');
|
|
6
6
|
const Rollup = require('./table/rollup');
|
|
7
|
+
const Balance = require('./table/balance');
|
|
7
8
|
|
|
8
9
|
const { name, version } = require('../package.json');
|
|
9
10
|
|
|
@@ -14,17 +15,36 @@ class FsStateDB extends StateDB {
|
|
|
14
15
|
this.name = name;
|
|
15
16
|
this.version = version;
|
|
16
17
|
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
this.balance = new Balance({ name: 'balance', dataDir, uniqIndex: ['address', 'tokenAddress'] });
|
|
19
|
+
this.account = new Account({
|
|
20
|
+
name: 'account',
|
|
21
|
+
dataDir,
|
|
22
|
+
uniqIndex: 'address',
|
|
23
|
+
balanceTable: this.balance,
|
|
24
|
+
syncBalance: true,
|
|
25
|
+
});
|
|
26
|
+
this.factory = new Table({
|
|
27
|
+
name: 'factory',
|
|
28
|
+
dataDir,
|
|
29
|
+
uniqIndex: 'address',
|
|
30
|
+
syncBalance: true,
|
|
31
|
+
balanceTable: this.balance,
|
|
32
|
+
});
|
|
33
|
+
this.stake = new Table({
|
|
34
|
+
name: 'stake',
|
|
35
|
+
dataDir,
|
|
36
|
+
uniqIndex: 'address',
|
|
37
|
+
syncBalance: true,
|
|
38
|
+
balanceTable: this.balance,
|
|
39
|
+
});
|
|
40
|
+
this.asset = new Table({ name: 'asset', dataDir, uniqIndex: 'address' });
|
|
41
|
+
this.delegation = new Table({ name: 'delegation', dataDir, uniqIndex: 'address' });
|
|
42
|
+
this.tx = new Table({ name: 'tx', dataDir, uniqIndex: 'hash' });
|
|
43
|
+
this.token = new Token({ name: 'token', dataDir, uniqIndex: 'address' });
|
|
44
|
+
this.chain = new Table({ name: 'chain', dataDir, uniqIndex: 'address' });
|
|
45
|
+
this.rollup = new Rollup({ name: 'rollup', dataDir, uniqIndex: 'address' });
|
|
46
|
+
this.rollupBlock = new Table({ name: 'rollupBlock', dataDir, uniqIndex: 'hash' });
|
|
47
|
+
this.evidence = new Table({ name: 'evidence', dataDir, uniqIndex: 'hash' });
|
|
28
48
|
|
|
29
49
|
this.attachReadyListeners();
|
|
30
50
|
}
|
package/lib/table/account.js
CHANGED
|
@@ -1,29 +1,19 @@
|
|
|
1
1
|
const { ensureChecksumAddress } = require('@ocap/state/lib/states/account');
|
|
2
|
-
const debug = require('debug')(require('../../package.json').name);
|
|
3
2
|
const FsTable = require('./base');
|
|
4
3
|
|
|
5
4
|
class AccountTable extends FsTable {
|
|
6
5
|
async _get(address, { traceMigration = true } = {}) {
|
|
7
|
-
const current = await
|
|
6
|
+
const current = await super._get(ensureChecksumAddress(address));
|
|
8
7
|
if (current && traceMigration && Array.isArray(current.migratedTo) && current.migratedTo.length) {
|
|
9
|
-
return this.
|
|
8
|
+
return this._get(current.migratedTo[0]);
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
return current;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
throw new Error(`${this.name} already exists: ${key}`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
debug(`insert ${this.name}`, attrs);
|
|
22
|
-
const newDoc = { [this.uniqIndex]: key, ...attrs };
|
|
23
|
-
newDoc[this.uniqIndex] = ensureChecksumAddress(newDoc[this.uniqIndex]);
|
|
24
|
-
const result = await this.collection.insert(newDoc);
|
|
25
|
-
|
|
26
|
-
return result;
|
|
14
|
+
_create(key, attrs = {}, ctx = {}) {
|
|
15
|
+
const address = ensureChecksumAddress(key);
|
|
16
|
+
return super._create(address, { ...attrs, address }, ctx);
|
|
27
17
|
}
|
|
28
18
|
}
|
|
29
19
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const FsTable = require('./base');
|
|
2
|
+
|
|
3
|
+
class BalanceTable extends FsTable {
|
|
4
|
+
async getBalance(address) {
|
|
5
|
+
const tokens = await this.collection.find({ address });
|
|
6
|
+
|
|
7
|
+
return (tokens || []).reduce((acc, token) => {
|
|
8
|
+
acc[token.tokenAddress] = token.balance;
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async updateBalance({ address, tokens, context = {} }, ctx) {
|
|
14
|
+
if (!Object.keys(tokens).length) return {};
|
|
15
|
+
|
|
16
|
+
const tokenBalances = await this.getBalance(address);
|
|
17
|
+
const updatedTokens = Object.keys(tokens)
|
|
18
|
+
.filter(
|
|
19
|
+
(token) => (tokenBalances[token] && tokenBalances[token] !== '0') || (tokens[token] && tokens[token] !== '0')
|
|
20
|
+
)
|
|
21
|
+
.filter((token) => tokenBalances[token] !== tokens[token]);
|
|
22
|
+
|
|
23
|
+
await Promise.all(
|
|
24
|
+
updatedTokens.map(async (token) => {
|
|
25
|
+
const key = { address, tokenAddress: token };
|
|
26
|
+
|
|
27
|
+
if (tokenBalances[token]) {
|
|
28
|
+
await this.update(key, { ...key, balance: tokens[token], context }, ctx);
|
|
29
|
+
} else {
|
|
30
|
+
await this.create(key, { ...key, balance: tokens[token], context }, ctx);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
tokenBalances[token] = tokens[token];
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return tokens;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = BalanceTable;
|
package/lib/table/base.js
CHANGED
|
@@ -8,13 +8,27 @@ const FsAdapter = require('lokijs/src/loki-fs-structured-adapter');
|
|
|
8
8
|
const debug = require('debug')(require('../../package.json').name);
|
|
9
9
|
|
|
10
10
|
class FsTable extends StateDBTable {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @param {Object} param
|
|
13
|
+
* @param {string} param.name db name
|
|
14
|
+
* @param {string|string[]} param.uniqIndex primary keys
|
|
15
|
+
* @param {string} param.dataDir data directory for db
|
|
16
|
+
* @param {boolean} param.syncBalance sync balance table when create / update / get
|
|
17
|
+
* @param {BalanceTable} param.balanceTable balance table
|
|
18
|
+
*/
|
|
19
|
+
constructor({ name, dataDir, uniqIndex, balanceTable, syncBalance = false }) {
|
|
20
|
+
super(uniqIndex);
|
|
13
21
|
|
|
14
22
|
this.name = name;
|
|
15
23
|
this.dataDir = dataDir;
|
|
16
24
|
this.uniqIndex = uniqIndex;
|
|
17
25
|
this.collection = null;
|
|
26
|
+
this.balanceTable = balanceTable;
|
|
27
|
+
this.syncBalance = syncBalance;
|
|
28
|
+
|
|
29
|
+
if (this.syncBalance && !this.balanceTable) {
|
|
30
|
+
throw new Error('balanceTable is required when syncBalance is true');
|
|
31
|
+
}
|
|
18
32
|
|
|
19
33
|
const adapter = new FsAdapter();
|
|
20
34
|
const db = new Lokijs(path.join(dataDir, `${name}.db`), {
|
|
@@ -26,7 +40,7 @@ class FsTable extends StateDBTable {
|
|
|
26
40
|
this.collection = db.getCollection(name);
|
|
27
41
|
|
|
28
42
|
if (this.collection === null) {
|
|
29
|
-
this.collection = db.addCollection(name, { unique: [
|
|
43
|
+
this.collection = db.addCollection(name, { unique: [this.primaryKey], clone: true });
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
this.markReady();
|
|
@@ -35,18 +49,48 @@ class FsTable extends StateDBTable {
|
|
|
35
49
|
}
|
|
36
50
|
|
|
37
51
|
async _create(key, attrs) {
|
|
38
|
-
const
|
|
52
|
+
const id = this.generatePrimaryKey(key);
|
|
53
|
+
// Don't call this._get here cause _get may be overwritten
|
|
54
|
+
const doc = await FsTable.prototype._get.call(this, id);
|
|
39
55
|
if (doc) {
|
|
40
56
|
throw new Error(`${this.name} already exists: ${key}`);
|
|
41
57
|
}
|
|
58
|
+
|
|
42
59
|
debug(`insert ${this.name}`, attrs);
|
|
43
|
-
|
|
60
|
+
|
|
61
|
+
const insertAttrs = { ...attrs };
|
|
62
|
+
// insert without tokens cause we've migrate token to balance table
|
|
63
|
+
if (this.syncBalance) {
|
|
64
|
+
delete insertAttrs.tokens;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const result = await this.collection.insert({ [this.primaryKey]: id, ...insertAttrs });
|
|
68
|
+
|
|
69
|
+
if (this.syncBalance && attrs.tokens) {
|
|
70
|
+
debug(`update balance for ${this.name}`, attrs);
|
|
71
|
+
|
|
72
|
+
result.tokens = await this.balanceTable.updateBalance({
|
|
73
|
+
address: attrs.address,
|
|
74
|
+
tokens: attrs.tokens,
|
|
75
|
+
context: attrs.context,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
44
78
|
|
|
45
79
|
return result;
|
|
46
80
|
}
|
|
47
81
|
|
|
48
|
-
_get(key) {
|
|
49
|
-
|
|
82
|
+
async _get(key) {
|
|
83
|
+
if (!key) return null;
|
|
84
|
+
|
|
85
|
+
const id = this.generatePrimaryKey(key);
|
|
86
|
+
const result = await this.collection.by(this.primaryKey, id);
|
|
87
|
+
|
|
88
|
+
if (result && this.syncBalance) {
|
|
89
|
+
const balance = await this.balanceTable.getBalance(result.address);
|
|
90
|
+
result.tokens = { ...(result.tokens || {}), ...balance };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return result;
|
|
50
94
|
}
|
|
51
95
|
|
|
52
96
|
_history() {
|
|
@@ -54,28 +98,49 @@ class FsTable extends StateDBTable {
|
|
|
54
98
|
}
|
|
55
99
|
|
|
56
100
|
async _update(key, updates) {
|
|
57
|
-
const
|
|
101
|
+
const id = this.generatePrimaryKey(key);
|
|
102
|
+
// Don't call this._get here cause _get may be overwritten
|
|
103
|
+
const doc = await FsTable.prototype._get.call(this, id);
|
|
58
104
|
if (!doc) {
|
|
59
105
|
throw new Error(`${this.name} does not exists: ${key}`);
|
|
60
106
|
}
|
|
61
107
|
|
|
62
|
-
debug(`update ${this.name}`, { key, updates });
|
|
63
108
|
Object.assign(doc, updates);
|
|
64
|
-
|
|
109
|
+
|
|
110
|
+
const updateAttrs = { ...doc };
|
|
111
|
+
// insert without tokens cause we've migrate token to balance table
|
|
112
|
+
if (this.syncBalance) {
|
|
113
|
+
delete updateAttrs.tokens;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await this.collection.update(updateAttrs);
|
|
117
|
+
|
|
118
|
+
if (this.syncBalance && doc.tokens) {
|
|
119
|
+
debug(`update balance for ${this.name}`, doc);
|
|
120
|
+
|
|
121
|
+
doc.tokens = await this.balanceTable.updateBalance({
|
|
122
|
+
address: doc.address,
|
|
123
|
+
tokens: doc.tokens,
|
|
124
|
+
context: doc.context,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
65
127
|
|
|
66
128
|
return doc;
|
|
67
129
|
}
|
|
68
130
|
|
|
69
131
|
updateOrCreate(exist, state, ctx) {
|
|
70
|
-
|
|
132
|
+
const id = this.generatePrimaryKey(state);
|
|
133
|
+
const attrs = omit(state, this.primaryKey);
|
|
134
|
+
|
|
135
|
+
if (!id) {
|
|
71
136
|
throw new Error('Cannot update or create without uniq index');
|
|
72
137
|
}
|
|
73
138
|
|
|
74
139
|
if (exist) {
|
|
75
|
-
return this.update(
|
|
140
|
+
return this.update(id, attrs, ctx);
|
|
76
141
|
}
|
|
77
142
|
|
|
78
|
-
return this.create(
|
|
143
|
+
return this.create(id, attrs, ctx);
|
|
79
144
|
}
|
|
80
145
|
|
|
81
146
|
_reset() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ocap/statedb-fs",
|
|
3
3
|
"description": "OCAP statedb adapter that uses fs as backend",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.21.1",
|
|
5
5
|
"author": "wangshijun <shijun@arcblock.io> (https://www.arcblock.io)",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/ArcBlock/blockchain/issues",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"debug": "^4.3.6",
|
|
37
37
|
"lodash": "^4.17.21",
|
|
38
38
|
"lokijs": "^1.5.12",
|
|
39
|
-
"@ocap/
|
|
40
|
-
"@ocap/
|
|
41
|
-
"@ocap/util": "1.
|
|
39
|
+
"@ocap/state": "1.21.1",
|
|
40
|
+
"@ocap/statedb": "1.21.1",
|
|
41
|
+
"@ocap/util": "1.21.1"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"lint": "eslint tests lib",
|