@acala-network/chopsticks 0.9.2-2 → 0.9.2-3
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/dist/cjs/context.js +0 -4
- package/dist/cjs/plugins/decode-key/cli.js +30 -0
- package/dist/cjs/plugins/decode-key/index.js +12 -24
- package/dist/cjs/plugins/dry-run/rpc.js +11 -21
- package/dist/cjs/plugins/follow-chain/cli.js +106 -0
- package/dist/cjs/plugins/follow-chain/index.js +12 -100
- package/dist/cjs/plugins/index.js +21 -14
- package/dist/cjs/plugins/new-block/index.js +14 -35
- package/dist/cjs/plugins/new-block/rpc.js +55 -0
- package/dist/cjs/plugins/run-block/cli.js +84 -0
- package/dist/cjs/plugins/run-block/index.js +12 -229
- package/dist/cjs/plugins/run-block/rpc.js +159 -0
- package/dist/cjs/plugins/set-block-build-mode/index.js +14 -17
- package/dist/cjs/plugins/set-block-build-mode/rpc.js +21 -0
- package/dist/cjs/plugins/set-head/index.js +14 -21
- package/dist/cjs/plugins/set-head/rpc.js +29 -0
- package/dist/cjs/plugins/set-runtime-log-level/index.js +14 -17
- package/dist/cjs/plugins/set-runtime-log-level/rpc.js +21 -0
- package/dist/cjs/plugins/set-storage/index.js +13 -18
- package/dist/cjs/plugins/set-storage/rpc.js +23 -0
- package/dist/cjs/plugins/time-travel/index.js +14 -13
- package/dist/cjs/plugins/time-travel/rpc.js +17 -0
- package/dist/cjs/rpc/index.js +5 -5
- package/dist/cjs/schema/index.js +8 -0
- package/dist/esm/context.js +0 -4
- package/dist/esm/plugins/decode-key/cli.js +20 -0
- package/dist/esm/plugins/decode-key/index.js +1 -20
- package/dist/esm/plugins/dry-run/rpc.js +1 -4
- package/dist/esm/plugins/follow-chain/cli.js +91 -0
- package/dist/esm/plugins/follow-chain/index.js +1 -91
- package/dist/esm/plugins/index.js +15 -10
- package/dist/esm/plugins/new-block/index.js +1 -66
- package/dist/esm/plugins/new-block/rpc.js +82 -0
- package/dist/esm/plugins/run-block/cli.js +74 -0
- package/dist/esm/plugins/run-block/index.js +2 -222
- package/dist/esm/plugins/run-block/rpc.js +148 -0
- package/dist/esm/plugins/set-block-build-mode/index.js +1 -26
- package/dist/esm/plugins/set-block-build-mode/rpc.js +28 -0
- package/dist/esm/plugins/set-head/index.js +1 -29
- package/dist/esm/plugins/set-head/rpc.js +33 -0
- package/dist/esm/plugins/set-runtime-log-level/index.js +1 -25
- package/dist/esm/plugins/set-runtime-log-level/rpc.js +25 -0
- package/dist/esm/plugins/set-storage/index.js +1 -37
- package/dist/esm/plugins/set-storage/rpc.js +37 -0
- package/dist/esm/plugins/time-travel/index.js +1 -21
- package/dist/esm/plugins/time-travel/rpc.js +21 -0
- package/dist/esm/rpc/index.js +6 -6
- package/dist/esm/schema/index.js +2 -0
- package/dist/types/plugins/decode-key/cli.d.ts +2 -0
- package/dist/types/plugins/decode-key/index.d.ts +1 -2
- package/dist/types/plugins/dry-run/rpc.d.ts +0 -1
- package/dist/types/plugins/follow-chain/cli.d.ts +2 -0
- package/dist/types/plugins/follow-chain/index.d.ts +1 -2
- package/dist/types/plugins/index.d.ts +3 -2
- package/dist/types/plugins/new-block/index.d.ts +1 -71
- package/dist/types/plugins/new-block/rpc.d.ts +128 -0
- package/dist/types/plugins/run-block/cli.d.ts +2 -0
- package/dist/types/plugins/run-block/index.d.ts +2 -141
- package/dist/types/plugins/run-block/rpc.d.ts +139 -0
- package/dist/types/plugins/set-block-build-mode/index.d.ts +1 -18
- package/dist/types/plugins/set-block-build-mode/rpc.d.ts +20 -0
- package/dist/types/plugins/set-head/index.d.ts +1 -18
- package/dist/types/plugins/set-head/rpc.d.ts +21 -0
- package/dist/types/plugins/set-runtime-log-level/index.d.ts +1 -17
- package/dist/types/plugins/set-runtime-log-level/rpc.d.ts +17 -0
- package/dist/types/plugins/set-storage/index.d.ts +1 -28
- package/dist/types/plugins/set-storage/rpc.d.ts +28 -0
- package/dist/types/plugins/time-travel/index.d.ts +1 -17
- package/dist/types/plugins/time-travel/rpc.d.ts +17 -0
- package/dist/types/schema/index.d.ts +2 -0
- package/package.json +3 -3
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
_export_star(require("./rpc.js"), exports);
|
|
6
|
+
function _export_star(from, to) {
|
|
7
|
+
Object.keys(from).forEach(function(k) {
|
|
8
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
9
|
+
Object.defineProperty(to, k, {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function() {
|
|
12
|
+
return from[k];
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
return from;
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "rpc", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return rpc;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _chopstickscore = require("@acala-network/chopsticks-core");
|
|
12
|
+
const rpc = async (context, [date])=>{
|
|
13
|
+
const timestamp = typeof date === 'string' ? Date.parse(date) : date;
|
|
14
|
+
if (Number.isNaN(timestamp)) throw new _chopstickscore.ResponseError(1, 'Invalid date');
|
|
15
|
+
await (0, _chopstickscore.timeTravel)(context.chain, timestamp);
|
|
16
|
+
return timestamp;
|
|
17
|
+
};
|
package/dist/cjs/rpc/index.js
CHANGED
|
@@ -16,21 +16,21 @@ const allHandlers = {
|
|
|
16
16
|
version: 1,
|
|
17
17
|
methods: [
|
|
18
18
|
...Object.keys(allHandlers),
|
|
19
|
-
...
|
|
19
|
+
..._index.rpcPluginMethods
|
|
20
20
|
]
|
|
21
21
|
})
|
|
22
22
|
};
|
|
23
|
-
const getHandler = (method)=>{
|
|
23
|
+
const getHandler = async (method)=>{
|
|
24
24
|
const handler = allHandlers[method];
|
|
25
25
|
if (!handler) {
|
|
26
26
|
// no handler for this method, check if it's a plugin
|
|
27
|
-
return _index.
|
|
27
|
+
return (0, _index.loadRpcPlugin)(method);
|
|
28
28
|
}
|
|
29
29
|
return handler;
|
|
30
30
|
};
|
|
31
|
-
const handler = (context)=>({ method, params }, subscriptionManager)=>{
|
|
31
|
+
const handler = (context)=>async ({ method, params }, subscriptionManager)=>{
|
|
32
32
|
_chopstickscore.logger.trace('Handling %s', method);
|
|
33
|
-
const handler = getHandler(method);
|
|
33
|
+
const handler = await getHandler(method);
|
|
34
34
|
if (!handler) {
|
|
35
35
|
_chopstickscore.logger.warn('Method not found %s', method);
|
|
36
36
|
throw new _chopstickscore.ResponseError(-32601, `Method not found: ${method}`);
|
package/dist/cjs/schema/index.js
CHANGED
|
@@ -14,6 +14,12 @@ _export(exports, {
|
|
|
14
14
|
},
|
|
15
15
|
fetchConfig: function() {
|
|
16
16
|
return fetchConfig;
|
|
17
|
+
},
|
|
18
|
+
zHash: function() {
|
|
19
|
+
return zHash;
|
|
20
|
+
},
|
|
21
|
+
zHex: function() {
|
|
22
|
+
return zHex;
|
|
17
23
|
}
|
|
18
24
|
});
|
|
19
25
|
const _chopstickscore = require("@acala-network/chopsticks-core");
|
|
@@ -28,6 +34,8 @@ function _interop_require_default(obj) {
|
|
|
28
34
|
default: obj
|
|
29
35
|
};
|
|
30
36
|
}
|
|
37
|
+
const zHex = _zod.z.custom((val)=>/^0x\w+$/.test(val));
|
|
38
|
+
const zHash = _zod.z.string().length(66).and(zHex);
|
|
31
39
|
const configSchema = _zod.z.object({
|
|
32
40
|
port: _zod.z.number().optional(),
|
|
33
41
|
endpoint: _zod.z.string().optional(),
|
package/dist/esm/context.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import './utils/tunnel.js';
|
|
2
2
|
import { GenesisProvider, defaultLogger, isUrl, setup, timeTravel } from '@acala-network/chopsticks-core';
|
|
3
3
|
import { SqliteDatabase } from '@acala-network/chopsticks-db';
|
|
4
|
-
import { loadRPCPlugins } from './plugins/index.js';
|
|
5
4
|
import { overrideStorage, overrideWasm } from './utils/override.js';
|
|
6
5
|
import axios from 'axios';
|
|
7
6
|
const logger = defaultLogger.child({
|
|
@@ -77,9 +76,6 @@ export const setupContext = async (argv, overrideParent = false)=>{
|
|
|
77
76
|
// added that have storage imports
|
|
78
77
|
await overrideWasm(chain, argv['wasm-override'], at);
|
|
79
78
|
await overrideStorage(chain, argv['import-storage'], at);
|
|
80
|
-
if (!process.env.DISABLE_PLUGINS) {
|
|
81
|
-
await loadRPCPlugins();
|
|
82
|
-
}
|
|
83
79
|
return {
|
|
84
80
|
chain
|
|
85
81
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { decodeKey } from '@acala-network/chopsticks-core';
|
|
2
|
+
import { defaultOptions } from '../../cli-options.js';
|
|
3
|
+
import { setupContext } from '../../context.js';
|
|
4
|
+
export const cli = (y)=>{
|
|
5
|
+
y.command('decode-key <key>', 'Deocde a key', (yargs)=>yargs.positional('key', {
|
|
6
|
+
desc: 'Key to decode',
|
|
7
|
+
type: 'string'
|
|
8
|
+
}).options({
|
|
9
|
+
...defaultOptions
|
|
10
|
+
}), async (argv)=>{
|
|
11
|
+
const context = await setupContext(argv);
|
|
12
|
+
const { storage, decodedKey } = decodeKey(await context.chain.head.meta, context.chain.head, argv.key);
|
|
13
|
+
if (storage && decodedKey) {
|
|
14
|
+
console.log(`${storage.section}.${storage.method}`, decodedKey.args.map((x)=>JSON.stringify(x.toHuman())).join(', '));
|
|
15
|
+
} else {
|
|
16
|
+
console.log('Unknown');
|
|
17
|
+
}
|
|
18
|
+
process.exit(0);
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { defaultOptions } from '../../cli-options.js';
|
|
3
|
-
import { setupContext } from '../../context.js';
|
|
4
|
-
export const cli = (y)=>{
|
|
5
|
-
y.command('decode-key <key>', 'Deocde a key', (yargs)=>yargs.positional('key', {
|
|
6
|
-
desc: 'Key to decode',
|
|
7
|
-
type: 'string'
|
|
8
|
-
}).options({
|
|
9
|
-
...defaultOptions
|
|
10
|
-
}), async (argv)=>{
|
|
11
|
-
const context = await setupContext(argv);
|
|
12
|
-
const { storage, decodedKey } = decodeKey(await context.chain.head.meta, context.chain.head, argv.key);
|
|
13
|
-
if (storage && decodedKey) {
|
|
14
|
-
console.log(`${storage.section}.${storage.method}`, decodedKey.args.map((x)=>JSON.stringify(x.toHuman())).join(', '));
|
|
15
|
-
} else {
|
|
16
|
-
console.log('Unknown');
|
|
17
|
-
}
|
|
18
|
-
process.exit(0);
|
|
19
|
-
});
|
|
20
|
-
};
|
|
1
|
+
export * from './cli.js';
|
|
@@ -2,8 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { ResponseError } from '@acala-network/chopsticks-core';
|
|
3
3
|
import { decodeStorageDiff } from '../../utils/decoder.js';
|
|
4
4
|
import { generateHtmlDiff } from '../../utils/generate-html-diff.js';
|
|
5
|
-
|
|
6
|
-
const zHash = z.string().length(66).and(zHex);
|
|
5
|
+
import { zHash, zHex } from '../../schema/index.js';
|
|
7
6
|
const zParaId = z.string().regex(/^\d+$/).transform(Number);
|
|
8
7
|
const schema = z.object({
|
|
9
8
|
raw: z.boolean().optional(),
|
|
@@ -23,8 +22,6 @@ const schema = z.object({
|
|
|
23
22
|
ump: z.record(zParaId, z.array(zHex).min(1)).optional(),
|
|
24
23
|
at: zHash.optional()
|
|
25
24
|
});
|
|
26
|
-
// custom rpc name (optional). e.g. dryRun will be called as dev_dryRun
|
|
27
|
-
export const name = 'dryRun';
|
|
28
25
|
/**
|
|
29
26
|
* Dry run an extrinsic or messages.
|
|
30
27
|
* If `html` is true, return the generated storage diff html string.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Block, defaultLogger, runTask, taskHandler } from '@acala-network/chopsticks-core';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { createServer } from '../../server.js';
|
|
4
|
+
import { defaultOptions } from '../../cli-options.js';
|
|
5
|
+
import { handler } from '../../rpc/index.js';
|
|
6
|
+
import { setupContext } from '../../context.js';
|
|
7
|
+
const logger = defaultLogger.child({
|
|
8
|
+
name: 'follow-chain'
|
|
9
|
+
});
|
|
10
|
+
const options = _.pick(defaultOptions, [
|
|
11
|
+
'endpoint',
|
|
12
|
+
'wasm-override',
|
|
13
|
+
'runtime-log-level',
|
|
14
|
+
'offchain-worker'
|
|
15
|
+
]);
|
|
16
|
+
export const cli = (y)=>{
|
|
17
|
+
y.command('follow-chain', 'Always follow the latest block on upstream', (yargs)=>yargs.options({
|
|
18
|
+
...options,
|
|
19
|
+
port: {
|
|
20
|
+
desc: 'Port to listen on',
|
|
21
|
+
number: true
|
|
22
|
+
},
|
|
23
|
+
'head-mode': {
|
|
24
|
+
desc: 'Head mode',
|
|
25
|
+
choices: [
|
|
26
|
+
'latest',
|
|
27
|
+
'finalized'
|
|
28
|
+
],
|
|
29
|
+
default: 'finalized'
|
|
30
|
+
}
|
|
31
|
+
}), async (argv)=>{
|
|
32
|
+
const port = argv.port ?? 8000;
|
|
33
|
+
const endpoint = argv.endpoint;
|
|
34
|
+
if (/^(https|http):\/\//.test(endpoint || '')) {
|
|
35
|
+
throw Error('http provider is not supported');
|
|
36
|
+
}
|
|
37
|
+
const context = await setupContext(argv, true);
|
|
38
|
+
const { close, port: listenPort } = await createServer(handler(context), port);
|
|
39
|
+
logger.info(`${await context.chain.api.getSystemChain()} RPC listening on port ${listenPort}`);
|
|
40
|
+
const chain = context.chain;
|
|
41
|
+
chain.api[argv.headMode === 'latest' ? 'subscribeRemoteNewHeads' : 'subscribeRemoteFinalizedHeads'](async (error, data)=>{
|
|
42
|
+
try {
|
|
43
|
+
if (error) throw error;
|
|
44
|
+
logger.info({
|
|
45
|
+
header: data
|
|
46
|
+
}, `Follow ${argv.headMode} head from upstream`);
|
|
47
|
+
const parent = await chain.getBlock(data.parentHash);
|
|
48
|
+
if (!parent) throw Error(`Cannot find parent', ${data.parentHash}`);
|
|
49
|
+
const registry = await parent.registry;
|
|
50
|
+
const header = registry.createType('Header', data);
|
|
51
|
+
const wasm = await parent.wasm;
|
|
52
|
+
const block = new Block(chain, header.number.toNumber(), header.hash.toHex(), parent);
|
|
53
|
+
await chain.setHead(block);
|
|
54
|
+
const calls = [
|
|
55
|
+
[
|
|
56
|
+
'Core_initialize_block',
|
|
57
|
+
[
|
|
58
|
+
header.toHex()
|
|
59
|
+
]
|
|
60
|
+
]
|
|
61
|
+
];
|
|
62
|
+
for (const extrinsic of (await block.extrinsics)){
|
|
63
|
+
calls.push([
|
|
64
|
+
'BlockBuilder_apply_extrinsic',
|
|
65
|
+
[
|
|
66
|
+
extrinsic
|
|
67
|
+
]
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
calls.push([
|
|
71
|
+
'BlockBuilder_finalize_block',
|
|
72
|
+
[]
|
|
73
|
+
]);
|
|
74
|
+
const result = await runTask({
|
|
75
|
+
wasm,
|
|
76
|
+
calls,
|
|
77
|
+
mockSignatureHost: false,
|
|
78
|
+
allowUnresolvedImports: false,
|
|
79
|
+
runtimeLogLevel: argv.runtimeLogLevel || 0
|
|
80
|
+
}, taskHandler(parent));
|
|
81
|
+
if ('Error' in result) {
|
|
82
|
+
throw new Error(result.Error);
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {
|
|
85
|
+
logger.error(e, 'Error when processing new head');
|
|
86
|
+
await close();
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
};
|
|
@@ -1,91 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import { createServer } from '../../server.js';
|
|
4
|
-
import { defaultOptions } from '../../cli-options.js';
|
|
5
|
-
import { handler } from '../../rpc/index.js';
|
|
6
|
-
import { setupContext } from '../../context.js';
|
|
7
|
-
const logger = defaultLogger.child({
|
|
8
|
-
name: 'follow-chain'
|
|
9
|
-
});
|
|
10
|
-
const options = _.pick(defaultOptions, [
|
|
11
|
-
'endpoint',
|
|
12
|
-
'wasm-override',
|
|
13
|
-
'runtime-log-level',
|
|
14
|
-
'offchain-worker'
|
|
15
|
-
]);
|
|
16
|
-
export const cli = (y)=>{
|
|
17
|
-
y.command('follow-chain', 'Always follow the latest block on upstream', (yargs)=>yargs.options({
|
|
18
|
-
...options,
|
|
19
|
-
port: {
|
|
20
|
-
desc: 'Port to listen on',
|
|
21
|
-
number: true
|
|
22
|
-
},
|
|
23
|
-
'head-mode': {
|
|
24
|
-
desc: 'Head mode',
|
|
25
|
-
choices: [
|
|
26
|
-
'latest',
|
|
27
|
-
'finalized'
|
|
28
|
-
],
|
|
29
|
-
default: 'finalized'
|
|
30
|
-
}
|
|
31
|
-
}), async (argv)=>{
|
|
32
|
-
const port = argv.port ?? 8000;
|
|
33
|
-
const endpoint = argv.endpoint;
|
|
34
|
-
if (/^(https|http):\/\//.test(endpoint || '')) {
|
|
35
|
-
throw Error('http provider is not supported');
|
|
36
|
-
}
|
|
37
|
-
const context = await setupContext(argv, true);
|
|
38
|
-
const { close, port: listenPort } = await createServer(handler(context), port);
|
|
39
|
-
logger.info(`${await context.chain.api.getSystemChain()} RPC listening on port ${listenPort}`);
|
|
40
|
-
const chain = context.chain;
|
|
41
|
-
chain.api[argv.headMode === 'latest' ? 'subscribeRemoteNewHeads' : 'subscribeRemoteFinalizedHeads'](async (error, data)=>{
|
|
42
|
-
try {
|
|
43
|
-
if (error) throw error;
|
|
44
|
-
logger.info({
|
|
45
|
-
header: data
|
|
46
|
-
}, `Follow ${argv.headMode} head from upstream`);
|
|
47
|
-
const parent = await chain.getBlock(data.parentHash);
|
|
48
|
-
if (!parent) throw Error(`Cannot find parent', ${data.parentHash}`);
|
|
49
|
-
const registry = await parent.registry;
|
|
50
|
-
const header = registry.createType('Header', data);
|
|
51
|
-
const wasm = await parent.wasm;
|
|
52
|
-
const block = new Block(chain, header.number.toNumber(), header.hash.toHex(), parent);
|
|
53
|
-
await chain.setHead(block);
|
|
54
|
-
const calls = [
|
|
55
|
-
[
|
|
56
|
-
'Core_initialize_block',
|
|
57
|
-
[
|
|
58
|
-
header.toHex()
|
|
59
|
-
]
|
|
60
|
-
]
|
|
61
|
-
];
|
|
62
|
-
for (const extrinsic of (await block.extrinsics)){
|
|
63
|
-
calls.push([
|
|
64
|
-
'BlockBuilder_apply_extrinsic',
|
|
65
|
-
[
|
|
66
|
-
extrinsic
|
|
67
|
-
]
|
|
68
|
-
]);
|
|
69
|
-
}
|
|
70
|
-
calls.push([
|
|
71
|
-
'BlockBuilder_finalize_block',
|
|
72
|
-
[]
|
|
73
|
-
]);
|
|
74
|
-
const result = await runTask({
|
|
75
|
-
wasm,
|
|
76
|
-
calls,
|
|
77
|
-
mockSignatureHost: false,
|
|
78
|
-
allowUnresolvedImports: false,
|
|
79
|
-
runtimeLogLevel: argv.runtimeLogLevel || 0
|
|
80
|
-
}, taskHandler(parent));
|
|
81
|
-
if ('Error' in result) {
|
|
82
|
-
throw new Error(result.Error);
|
|
83
|
-
}
|
|
84
|
-
} catch (e) {
|
|
85
|
-
logger.error(e, 'Error when processing new head');
|
|
86
|
-
await close();
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
};
|
|
1
|
+
export * from './cli.js';
|
|
@@ -4,19 +4,24 @@ import { defaultLogger } from '../logger.js';
|
|
|
4
4
|
const logger = defaultLogger.child({
|
|
5
5
|
name: 'plugin'
|
|
6
6
|
});
|
|
7
|
-
export const
|
|
7
|
+
export const rpcPluginHandlers = {};
|
|
8
8
|
// list of plugins directory
|
|
9
9
|
const plugins = readdirSync(new URL('.', import.meta.url)).filter((file)=>lstatSync(new URL(file, import.meta.url)).isDirectory());
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const methodName = name || _.camelCase(plugin);
|
|
16
|
-
pluginHandlers[`dev_${methodName}`] = rpc;
|
|
17
|
-
logger.debug(`Registered plugin RPC: ${`dev_${methodName}`}`);
|
|
18
|
-
}
|
|
10
|
+
// find all rpc methods
|
|
11
|
+
export const rpcPluginMethods = plugins.filter((name)=>readdirSync(new URL(name, import.meta.url)).some((file)=>file.startsWith('rpc'))).map((name)=>`dev_${_.camelCase(name)}`);
|
|
12
|
+
export const loadRpcPlugin = async (method)=>{
|
|
13
|
+
if (process.env.DISABLE_PLUGINS) {
|
|
14
|
+
return undefined;
|
|
19
15
|
}
|
|
16
|
+
if (rpcPluginHandlers[method]) return rpcPluginHandlers[method];
|
|
17
|
+
const plugin = _.snakeCase(method.split('dev_')[1]).replaceAll('_', '-');
|
|
18
|
+
if (!plugin) return undefined;
|
|
19
|
+
const location = new URL(`${plugin}/index.js`, import.meta.url);
|
|
20
|
+
const { rpc } = await import(location.pathname);
|
|
21
|
+
if (!rpc) return undefined;
|
|
22
|
+
rpcPluginHandlers[method] = rpc;
|
|
23
|
+
logger.debug(`Registered plugin ${plugin} RPC`);
|
|
24
|
+
return rpc;
|
|
20
25
|
};
|
|
21
26
|
export const pluginExtendCli = async (y)=>{
|
|
22
27
|
for (const plugin of plugins){
|
|
@@ -1,66 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { defaultLogger } from '../../logger.js';
|
|
3
|
-
/**
|
|
4
|
-
* Build new blocks.
|
|
5
|
-
*
|
|
6
|
-
* This function is a dev rpc handler. Use `dev_newBlock` as the method name when calling it.
|
|
7
|
-
*
|
|
8
|
-
* @param context - The context object of the rpc handler
|
|
9
|
-
* @param params - The parameters of the rpc handler
|
|
10
|
-
*
|
|
11
|
-
* @example Build 2 blocks
|
|
12
|
-
* ```ts
|
|
13
|
-
* import { WsProvider } from '@polkadot/rpc-provider'
|
|
14
|
-
* const ws = new WsProvider(`ws://localhost:8000`)
|
|
15
|
-
* await ws.send('dev_newBlock', [{ count: 2 }])
|
|
16
|
-
* ```
|
|
17
|
-
* @example Build a block with upward messages
|
|
18
|
-
* ```ts
|
|
19
|
-
* import { WsProvider } from '@polkadot/rpc-provider'
|
|
20
|
-
* const ws = new WsProvider(`ws://localhost:8000`)
|
|
21
|
-
* await ws.send('dev_newBlock', [
|
|
22
|
-
* {
|
|
23
|
-
* ump: {
|
|
24
|
-
* // https://acala.subscan.io/xcm_message/polkadot-ff66f28818d0b74573e62db8317e354b253fbc80
|
|
25
|
-
* 2000: [
|
|
26
|
-
* '0x021000040000000007903fc4db080a130000000007903fc4db08000d010004000101009c4b11a0974cba4a395c94832fba812868a6cb0ba09e8519b3521093ea359905',
|
|
27
|
-
* ],
|
|
28
|
-
* }
|
|
29
|
-
* }
|
|
30
|
-
* ])
|
|
31
|
-
* ```
|
|
32
|
-
*
|
|
33
|
-
* @example Build two blocks with unsafeBlockHeight
|
|
34
|
-
* ```ts
|
|
35
|
-
* import { WsProvider } from '@polkadot/rpc-provider'
|
|
36
|
-
* const ws = new WsProvider(`ws://localhost:8000`)
|
|
37
|
-
* // this will create two blocks with block height 100000001 and 100000002
|
|
38
|
-
* await ws.send('dev_newBlock', [{ count: 2, unsafeBlockHeight: 100000001 }])
|
|
39
|
-
* ```
|
|
40
|
-
*/ export const rpc = async (context, params)=>{
|
|
41
|
-
const [param] = params;
|
|
42
|
-
const { count, to, hrmp, ump, dmp, transactions, unsafeBlockHeight } = param || {};
|
|
43
|
-
const now = context.chain.head.number;
|
|
44
|
-
const diff = to ? to - now : count;
|
|
45
|
-
const finalCount = diff > 0 ? diff : 1;
|
|
46
|
-
let finalHash;
|
|
47
|
-
if (unsafeBlockHeight < now) {
|
|
48
|
-
throw new ResponseError(1, 'unsafeBlockHeight must be greater than current block height');
|
|
49
|
-
}
|
|
50
|
-
for(let i = 0; i < finalCount; i++){
|
|
51
|
-
const block = await context.chain.newBlock({
|
|
52
|
-
transactions,
|
|
53
|
-
horizontalMessages: hrmp,
|
|
54
|
-
upwardMessages: ump,
|
|
55
|
-
downwardMessages: dmp,
|
|
56
|
-
unsafeBlockHeight: i === 0 ? unsafeBlockHeight : undefined
|
|
57
|
-
}).catch((error)=>{
|
|
58
|
-
throw new ResponseError(1, error.toString());
|
|
59
|
-
});
|
|
60
|
-
defaultLogger.debug({
|
|
61
|
-
hash: block.hash
|
|
62
|
-
}, 'dev_newBlock');
|
|
63
|
-
finalHash = block.hash;
|
|
64
|
-
}
|
|
65
|
-
return finalHash;
|
|
66
|
-
};
|
|
1
|
+
export * from './rpc.js';
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ResponseError } from '@acala-network/chopsticks-core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { defaultLogger } from '../../logger.js';
|
|
4
|
+
import { zHex } from '../../schema/index.js';
|
|
5
|
+
const schema = z.object({
|
|
6
|
+
count: z.number().optional(),
|
|
7
|
+
to: z.number().optional(),
|
|
8
|
+
dmp: z.array(z.object({
|
|
9
|
+
sentAt: z.number(),
|
|
10
|
+
msg: zHex
|
|
11
|
+
})).min(1).optional(),
|
|
12
|
+
ump: z.record(z.number(), z.array(zHex).min(1)).optional(),
|
|
13
|
+
hrmp: z.record(z.number(), z.array(z.object({
|
|
14
|
+
sentAt: z.number(),
|
|
15
|
+
data: zHex
|
|
16
|
+
})).min(1)).optional(),
|
|
17
|
+
transactions: z.array(zHex).min(1).optional(),
|
|
18
|
+
unsafeBlockHeight: z.number().optional()
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Build new blocks.
|
|
22
|
+
*
|
|
23
|
+
* This function is a dev rpc handler. Use `dev_newBlock` as the method name when calling it.
|
|
24
|
+
*
|
|
25
|
+
* @param context - The context object of the rpc handler
|
|
26
|
+
* @param params - The parameters of the rpc handler
|
|
27
|
+
*
|
|
28
|
+
* @example Build 2 blocks
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { WsProvider } from '@polkadot/rpc-provider'
|
|
31
|
+
* const ws = new WsProvider(`ws://localhost:8000`)
|
|
32
|
+
* await ws.send('dev_newBlock', [{ count: 2 }])
|
|
33
|
+
* ```
|
|
34
|
+
* @example Build a block with upward messages
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { WsProvider } from '@polkadot/rpc-provider'
|
|
37
|
+
* const ws = new WsProvider(`ws://localhost:8000`)
|
|
38
|
+
* await ws.send('dev_newBlock', [
|
|
39
|
+
* {
|
|
40
|
+
* ump: {
|
|
41
|
+
* // https://acala.subscan.io/xcm_message/polkadot-ff66f28818d0b74573e62db8317e354b253fbc80
|
|
42
|
+
* 2000: [
|
|
43
|
+
* '0x021000040000000007903fc4db080a130000000007903fc4db08000d010004000101009c4b11a0974cba4a395c94832fba812868a6cb0ba09e8519b3521093ea359905',
|
|
44
|
+
* ],
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ])
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Build two blocks with unsafeBlockHeight
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { WsProvider } from '@polkadot/rpc-provider'
|
|
53
|
+
* const ws = new WsProvider(`ws://localhost:8000`)
|
|
54
|
+
* // this will create two blocks with block height 100000001 and 100000002
|
|
55
|
+
* await ws.send('dev_newBlock', [{ count: 2, unsafeBlockHeight: 100000001 }])
|
|
56
|
+
* ```
|
|
57
|
+
*/ export const rpc = async (context, [params])=>{
|
|
58
|
+
const { count, to, hrmp, ump, dmp, transactions, unsafeBlockHeight } = schema.parse(params || {});
|
|
59
|
+
const now = context.chain.head.number;
|
|
60
|
+
const diff = to ? to - now : count;
|
|
61
|
+
const finalCount = diff !== undefined ? Math.max(diff, 1) : 1;
|
|
62
|
+
let finalHash;
|
|
63
|
+
if (unsafeBlockHeight !== undefined && unsafeBlockHeight <= now) {
|
|
64
|
+
throw new ResponseError(1, 'unsafeBlockHeight must be greater than current block height');
|
|
65
|
+
}
|
|
66
|
+
for(let i = 0; i < finalCount; i++){
|
|
67
|
+
const block = await context.chain.newBlock({
|
|
68
|
+
transactions,
|
|
69
|
+
horizontalMessages: hrmp,
|
|
70
|
+
upwardMessages: ump,
|
|
71
|
+
downwardMessages: dmp,
|
|
72
|
+
unsafeBlockHeight: i === 0 ? unsafeBlockHeight : undefined
|
|
73
|
+
}).catch((error)=>{
|
|
74
|
+
throw new ResponseError(1, error.toString());
|
|
75
|
+
});
|
|
76
|
+
defaultLogger.debug({
|
|
77
|
+
hash: block.hash
|
|
78
|
+
}, 'dev_newBlock');
|
|
79
|
+
finalHash = block.hash;
|
|
80
|
+
}
|
|
81
|
+
return finalHash;
|
|
82
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import { runTask, taskHandler } from '@acala-network/chopsticks-core';
|
|
3
|
+
import { defaultOptions, mockOptions } from '../../cli-options.js';
|
|
4
|
+
import { generateHtmlDiffPreviewFile } from '../../utils/generate-html-diff.js';
|
|
5
|
+
import { openHtml } from '../../utils/open-html.js';
|
|
6
|
+
import { setupContext } from '../../context.js';
|
|
7
|
+
export const cli = (y)=>{
|
|
8
|
+
y.command('run-block', 'Replay a block', (yargs)=>yargs.options({
|
|
9
|
+
...defaultOptions,
|
|
10
|
+
...mockOptions,
|
|
11
|
+
'output-path': {
|
|
12
|
+
desc: 'File path to print output',
|
|
13
|
+
string: true
|
|
14
|
+
},
|
|
15
|
+
html: {
|
|
16
|
+
desc: 'Generate html with storage diff'
|
|
17
|
+
},
|
|
18
|
+
open: {
|
|
19
|
+
desc: 'Open generated html'
|
|
20
|
+
}
|
|
21
|
+
}), async (argv)=>{
|
|
22
|
+
const context = await setupContext(argv, true);
|
|
23
|
+
const header = await context.chain.head.header;
|
|
24
|
+
const block = context.chain.head;
|
|
25
|
+
const parent = await block.parentBlock;
|
|
26
|
+
if (!parent) throw Error('cant find parent block');
|
|
27
|
+
const wasm = await parent.wasm;
|
|
28
|
+
const calls = [
|
|
29
|
+
[
|
|
30
|
+
'Core_initialize_block',
|
|
31
|
+
[
|
|
32
|
+
header.toHex()
|
|
33
|
+
]
|
|
34
|
+
]
|
|
35
|
+
];
|
|
36
|
+
for (const extrinsic of (await block.extrinsics)){
|
|
37
|
+
calls.push([
|
|
38
|
+
'BlockBuilder_apply_extrinsic',
|
|
39
|
+
[
|
|
40
|
+
extrinsic
|
|
41
|
+
]
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
calls.push([
|
|
45
|
+
'BlockBuilder_finalize_block',
|
|
46
|
+
[]
|
|
47
|
+
]);
|
|
48
|
+
const result = await runTask({
|
|
49
|
+
wasm,
|
|
50
|
+
calls,
|
|
51
|
+
mockSignatureHost: false,
|
|
52
|
+
allowUnresolvedImports: false,
|
|
53
|
+
runtimeLogLevel: argv.runtimeLogLevel || 0
|
|
54
|
+
}, taskHandler(parent));
|
|
55
|
+
if ('Error' in result) {
|
|
56
|
+
throw new Error(result.Error);
|
|
57
|
+
}
|
|
58
|
+
if (argv.html) {
|
|
59
|
+
const filePath = await generateHtmlDiffPreviewFile(parent, result.Call.storageDiff, block.hash);
|
|
60
|
+
console.log(`Generated preview ${filePath}`);
|
|
61
|
+
if (argv.open) {
|
|
62
|
+
openHtml(filePath);
|
|
63
|
+
}
|
|
64
|
+
} else if (argv.outputPath) {
|
|
65
|
+
writeFileSync(argv.outputPath, JSON.stringify(result, null, 2));
|
|
66
|
+
} else {
|
|
67
|
+
console.dir(result, {
|
|
68
|
+
depth: null,
|
|
69
|
+
colors: false
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
process.exit(0);
|
|
73
|
+
});
|
|
74
|
+
};
|