@ocap/resolver 1.19.14 → 1.19.16
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/LICENSE +1 -1
- package/lib/index.js +67 -39
- package/lib/token-distribution.js +3 -3
- package/package.json +14 -13
package/LICENSE
CHANGED
package/lib/index.js
CHANGED
|
@@ -22,6 +22,7 @@ const { DEFAULT_TOKEN_DECIMAL } = require('@ocap/util/lib/constant');
|
|
|
22
22
|
const { createExecutor } = require('@ocap/tx-protocols');
|
|
23
23
|
const { decodeAnySafe } = require('@ocap/tx-protocols/lib/util');
|
|
24
24
|
const { Joi } = require('@arcblock/validator');
|
|
25
|
+
const Queue = require('queue');
|
|
25
26
|
|
|
26
27
|
const {
|
|
27
28
|
createIndexedAccount,
|
|
@@ -96,6 +97,12 @@ const maxGasOps = {
|
|
|
96
97
|
'fg:t:claim_block_reward': { create: 2, update: 38 },
|
|
97
98
|
};
|
|
98
99
|
|
|
100
|
+
const txRequestConfig = {
|
|
101
|
+
maxRequest: Number(process.env.TX_MAX_REQUEST) || 200,
|
|
102
|
+
concurrent: Number(process.env.TX_CONCURRENCY) || 10,
|
|
103
|
+
timeout: Number(process.env.TX_TIMEOUT) || 1000 * 30,
|
|
104
|
+
};
|
|
105
|
+
|
|
99
106
|
const formatData = (data) => {
|
|
100
107
|
if (!data) {
|
|
101
108
|
return data;
|
|
@@ -172,7 +179,7 @@ module.exports = class OCAPResolver {
|
|
|
172
179
|
throw new Error('OCAP Resolver requires a valid indexdb implementation to work');
|
|
173
180
|
}
|
|
174
181
|
|
|
175
|
-
this.logger = logger ||
|
|
182
|
+
this.logger = logger || console;
|
|
176
183
|
|
|
177
184
|
this.statedb = statedb;
|
|
178
185
|
this.indexdb = indexdb;
|
|
@@ -182,6 +189,11 @@ module.exports = class OCAPResolver {
|
|
|
182
189
|
this.chainAddr = md5(config.chainId);
|
|
183
190
|
this.tokenItx = Config.genTokenItx(this.config);
|
|
184
191
|
this.consensus = `${statedb.name} v${statedb.version}`;
|
|
192
|
+
this.queue = new Queue({
|
|
193
|
+
autostart: true,
|
|
194
|
+
concurrency: txRequestConfig.concurrent,
|
|
195
|
+
timeout: txRequestConfig.timeout,
|
|
196
|
+
});
|
|
185
197
|
|
|
186
198
|
if (indexdb) {
|
|
187
199
|
this.tokenCache = getTokenCacheInstance(indexdb.token);
|
|
@@ -206,18 +218,21 @@ module.exports = class OCAPResolver {
|
|
|
206
218
|
}
|
|
207
219
|
|
|
208
220
|
this.connectIndexDB();
|
|
209
|
-
this.
|
|
210
|
-
|
|
221
|
+
this.initializeStateDB().catch((err) => {
|
|
222
|
+
this.logger.error('Failed to initialize statedb:', err.message);
|
|
211
223
|
process.exit(1);
|
|
212
224
|
});
|
|
213
225
|
}
|
|
214
226
|
|
|
215
|
-
|
|
227
|
+
sendTx({ tx: txBase64, extra }, ctx = {}) {
|
|
216
228
|
debug('sendTx', { txBase64, request: ctx.request });
|
|
217
229
|
|
|
218
230
|
if (process.env.CHAIN_MODE === 'readonly') {
|
|
219
231
|
throw new CustomError('FORBIDDEN', 'This chain node is running in readonly mode');
|
|
220
232
|
}
|
|
233
|
+
if (this.queue.length >= txRequestConfig.maxRequest) {
|
|
234
|
+
throw new CustomError('FORBIDDEN', 'Chain is busy');
|
|
235
|
+
}
|
|
221
236
|
|
|
222
237
|
// 0. create new context
|
|
223
238
|
// NOTE: if you add more fields here, please remember to change core/tx-protocols/lib/execute.js
|
|
@@ -234,11 +249,18 @@ module.exports = class OCAPResolver {
|
|
|
234
249
|
},
|
|
235
250
|
};
|
|
236
251
|
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
252
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
253
|
+
return new Promise((resolve, reject) => {
|
|
254
|
+
const task = async () => {
|
|
255
|
+
try {
|
|
256
|
+
const result = await this.executor.execute(context);
|
|
257
|
+
resolve(result.txHash);
|
|
258
|
+
} catch (err) {
|
|
259
|
+
reject(err);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
this.queue.push(task);
|
|
263
|
+
});
|
|
242
264
|
}
|
|
243
265
|
|
|
244
266
|
getTx({ hash }, ctx) {
|
|
@@ -786,56 +808,62 @@ module.exports = class OCAPResolver {
|
|
|
786
808
|
return this.runAsLambda((txn) => this.statedb.token.get(id, { txn }));
|
|
787
809
|
}
|
|
788
810
|
|
|
789
|
-
async initializeStateDB(
|
|
811
|
+
async initializeStateDB() {
|
|
790
812
|
const { accounts, token } = this.config;
|
|
791
813
|
const { account: accountDB, chain: chainDB, token: tokenDB } = this.statedb;
|
|
792
814
|
const { account: accountState, chain: chainState, token: tokenState } = states;
|
|
793
815
|
|
|
794
|
-
const ctx = { txn };
|
|
795
816
|
const context = { txTime: new Date().toISOString(), txHash: '' };
|
|
796
817
|
|
|
797
818
|
// Auto persist config to chain state
|
|
798
819
|
// Will throw error if immutable chain config are updated
|
|
799
820
|
const info = await this.getChain();
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
821
|
+
await this.runAsLambda(async (txn) => {
|
|
822
|
+
if (!info) {
|
|
823
|
+
const state = chainState.create({ ...this.config, address: CHAIN_ADDR }, context);
|
|
824
|
+
const result = await chainDB.create(CHAIN_ADDR, state, { txn });
|
|
825
|
+
this.logger.info('create chain state', { result });
|
|
826
|
+
} else if (isEqual(pick(info, Object.keys(this.config)), this.config) === false) {
|
|
827
|
+
const state = chainState.update(info, this.config, context);
|
|
828
|
+
const result = await chainDB.update(CHAIN_ADDR, state, { txn });
|
|
829
|
+
this.logger.info('update chain state', { result });
|
|
830
|
+
}
|
|
831
|
+
});
|
|
809
832
|
|
|
810
833
|
// Auto persist token state, just once
|
|
811
834
|
// Since the token info should not be changed after restart
|
|
812
835
|
if (this.tokenItx) {
|
|
813
836
|
const existToken = await this.getToken(this.tokenItx.address);
|
|
814
837
|
if (!existToken) {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
838
|
+
await this.runAsLambda(async (txn) => {
|
|
839
|
+
const state = tokenState.create(this.tokenItx, context);
|
|
840
|
+
const result = await tokenDB.create(this.tokenItx.address, state, { txn });
|
|
841
|
+
tokenDB.emit('create', result, { txn });
|
|
842
|
+
this.logger.info('create token state', { address: result?.address });
|
|
843
|
+
});
|
|
819
844
|
}
|
|
820
845
|
|
|
821
846
|
// Auto populate token holder accounts if not exist
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
847
|
+
await this.runAsLambda(async (txn) => {
|
|
848
|
+
for (let i = 0; i < accounts.length; i++) {
|
|
849
|
+
const { address, balance, moniker, pk } = accounts[i];
|
|
850
|
+
try {
|
|
851
|
+
const existAccount = await accountDB.get(address, { txn });
|
|
852
|
+
if (!existAccount) {
|
|
853
|
+
const balanceStr = fromTokenToUnit(balance, token.decimal).toString(10);
|
|
854
|
+
const state = accountState.create(
|
|
855
|
+
{ address, tokens: { [this.tokenItx.address]: balanceStr }, moniker: moniker || 'token-holder', pk },
|
|
856
|
+
context
|
|
857
|
+
);
|
|
858
|
+
const result = await accountDB.create(address, state, { txn });
|
|
859
|
+
accountDB.emit('create', result, { txn });
|
|
860
|
+
this.logger.info('init account done', { address });
|
|
861
|
+
}
|
|
862
|
+
} catch (err) {
|
|
863
|
+
this.logger.error('Failed to initialize initial token holders', err);
|
|
834
864
|
}
|
|
835
|
-
} catch (err) {
|
|
836
|
-
console.error('Failed to initialize initial token holders', err);
|
|
837
865
|
}
|
|
838
|
-
}
|
|
866
|
+
});
|
|
839
867
|
}
|
|
840
868
|
}
|
|
841
869
|
|
|
@@ -347,9 +347,9 @@ class TokenDistributionManager {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
async getStakeState(address, ctx) {
|
|
350
|
-
const stakeState =
|
|
351
|
-
|
|
352
|
-
|
|
350
|
+
const stakeState = await this.resolver.runAsLambda((txn) =>
|
|
351
|
+
this.resolver.statedb.stake.get(address, { ...ctx, txn })
|
|
352
|
+
);
|
|
353
353
|
|
|
354
354
|
return stakeState;
|
|
355
355
|
}
|
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.16",
|
|
7
7
|
"description": "GraphQL resolver built upon ocap statedb and GQL layer",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -22,18 +22,19 @@
|
|
|
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.16",
|
|
26
|
+
"@arcblock/did-util": "1.19.16",
|
|
27
|
+
"@arcblock/validator": "1.19.16",
|
|
28
|
+
"@ocap/config": "1.19.16",
|
|
29
|
+
"@ocap/indexdb": "1.19.16",
|
|
30
|
+
"@ocap/mcrypto": "1.19.16",
|
|
31
|
+
"@ocap/message": "1.19.16",
|
|
32
|
+
"@ocap/state": "1.19.16",
|
|
33
|
+
"@ocap/tx-protocols": "1.19.16",
|
|
34
|
+
"@ocap/util": "1.19.16",
|
|
35
35
|
"debug": "^4.3.6",
|
|
36
|
-
"lodash": "^4.17.21"
|
|
36
|
+
"lodash": "^4.17.21",
|
|
37
|
+
"queue": "^6"
|
|
37
38
|
},
|
|
38
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "9c3c349e48fc3c5a63aba6068ba5d31cc46d81c9"
|
|
39
40
|
}
|