@acala-network/chopsticks 0.2.2 → 0.3.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.
Files changed (65) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +6 -0
  3. package/dist/api.d.ts +3 -2
  4. package/dist/api.js +15 -20
  5. package/dist/blockchain/block-builder.d.ts +4 -0
  6. package/dist/blockchain/block-builder.js +71 -0
  7. package/dist/blockchain/block.d.ts +12 -8
  8. package/dist/blockchain/block.js +34 -75
  9. package/dist/blockchain/head-state.d.ts +4 -2
  10. package/dist/blockchain/head-state.js +13 -7
  11. package/dist/blockchain/index.d.ts +14 -13
  12. package/dist/blockchain/index.js +31 -27
  13. package/dist/blockchain/inherent/index.d.ts +17 -0
  14. package/dist/blockchain/inherent/index.js +32 -0
  15. package/dist/blockchain/inherent/para-enter.d.ts +7 -0
  16. package/dist/blockchain/inherent/para-enter.js +33 -0
  17. package/dist/blockchain/inherent/parachain/validation-data.d.ts +25 -0
  18. package/dist/blockchain/{inherents.js → inherent/parachain/validation-data.js} +87 -55
  19. package/dist/blockchain/txpool.d.ts +19 -3
  20. package/dist/blockchain/txpool.js +46 -81
  21. package/dist/decode-key.d.ts +2 -0
  22. package/dist/decode-key.js +24 -0
  23. package/dist/executor.d.ts +23 -4
  24. package/dist/executor.js +60 -12
  25. package/dist/executor.test.js +16 -21
  26. package/dist/genesis-provider.d.ts +5 -0
  27. package/dist/genesis-provider.js +21 -2
  28. package/dist/index.d.ts +1 -21
  29. package/dist/index.js +43 -159
  30. package/dist/logger.d.ts +3 -1
  31. package/dist/logger.js +5 -1
  32. package/dist/rpc/dev.js +11 -1
  33. package/dist/rpc/index.js +0 -2
  34. package/dist/rpc/shared.d.ts +0 -6
  35. package/dist/rpc/substrate/author.d.ts +1 -1
  36. package/dist/rpc/substrate/author.js +7 -2
  37. package/dist/rpc/substrate/chain.js +2 -2
  38. package/dist/rpc/substrate/state.js +1 -1
  39. package/dist/rpc/substrate/system.js +3 -3
  40. package/dist/run-block.d.ts +2 -0
  41. package/dist/run-block.js +36 -0
  42. package/dist/schema/index.d.ts +2 -5
  43. package/dist/schema/index.js +1 -2
  44. package/dist/server.d.ts +3 -3
  45. package/dist/server.js +26 -11
  46. package/dist/setup-with-server.d.ts +8 -0
  47. package/dist/setup-with-server.js +23 -0
  48. package/dist/setup.d.ts +10 -0
  49. package/dist/setup.js +62 -0
  50. package/dist/utils/index.d.ts +2 -0
  51. package/dist/utils/index.js +9 -1
  52. package/dist/utils/proof.d.ts +10 -2
  53. package/dist/utils/proof.js +12 -8
  54. package/dist/utils/set-storage.d.ts +2 -1
  55. package/dist/utils/set-storage.js +1 -1
  56. package/dist/utils/time-travel.d.ts +5 -0
  57. package/dist/utils/time-travel.js +64 -0
  58. package/dist/xcm/index.d.ts +3 -0
  59. package/dist/xcm/index.js +67 -0
  60. package/package.json +9 -10
  61. package/dist/blockchain/inherents.d.ts +0 -26
  62. package/dist/rpc/exec.d.ts +0 -3
  63. package/dist/rpc/exec.js +0 -44
  64. package/dist/task.d.ts +0 -38
  65. package/dist/task.js +0 -67
package/dist/index.js CHANGED
@@ -3,150 +3,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.decodeKey = exports.runBlock = exports.setupWithServer = exports.setup = void 0;
7
- require("@polkadot/types-codec");
8
- const api_1 = require("@polkadot/api");
9
- const util_1 = require("@polkadot/util");
10
6
  const helpers_1 = require("yargs/helpers");
11
7
  const node_fs_1 = require("node:fs");
12
8
  const js_yaml_1 = __importDefault(require("js-yaml"));
13
9
  const yargs_1 = __importDefault(require("yargs"));
14
- const api_2 = require("./api");
15
- const blockchain_1 = require("./blockchain");
16
10
  const txpool_1 = require("./blockchain/txpool");
17
11
  const schema_1 = require("./schema");
18
- const genesis_provider_1 = require("./genesis-provider");
19
- const inherents_1 = require("./blockchain/inherents");
20
- const task_1 = require("./task");
21
- const server_1 = require("./server");
22
- const logger_1 = require("./logger");
23
- const rpc_1 = require("./rpc");
24
- const import_storage_1 = require("./utils/import-storage");
25
- const db_1 = require("./db");
26
- const setup = async (argv) => {
27
- let provider;
28
- if (argv.genesis) {
29
- if (typeof argv.genesis === 'string') {
30
- provider = await genesis_provider_1.GenesisProvider.fromUrl(argv.genesis);
31
- }
32
- else {
33
- provider = new genesis_provider_1.GenesisProvider(argv.genesis);
34
- }
35
- }
36
- else {
37
- provider = new api_1.WsProvider(argv.endpoint);
38
- }
39
- const api = new api_2.Api(provider);
40
- await api.isReady;
41
- let blockHash;
42
- if (argv.block == null) {
43
- blockHash = await api.getBlockHash();
44
- }
45
- else if (Number.isInteger(argv.block)) {
46
- blockHash = await api.getBlockHash(Number(argv.block));
47
- }
48
- else {
49
- blockHash = argv.block;
50
- }
51
- logger_1.defaultLogger.info({ ...argv, blockHash }, 'Args');
52
- let db;
53
- if (argv.db) {
54
- db = await (0, db_1.openDb)(argv.db);
55
- }
56
- const header = await api.getHeader(blockHash);
57
- const port = argv.port || Number(process.env.PORT) || 8000;
58
- const tasks = new task_1.TaskManager(port, argv['mock-signature-host'], argv['executor-cmd']);
59
- const blockNumber = +header.number;
60
- const timestamp = argv.timestamp ?? Date.now();
61
- const setTimestamp = new inherents_1.SetTimestamp((newBlockNumber) => {
62
- return timestamp + (newBlockNumber - blockNumber) * 12000; // TODO: make this more flexible
63
- });
64
- const inherents = new inherents_1.InherentProviders(setTimestamp, [new inherents_1.SetValidationData(tasks, 1)]);
65
- const chain = new blockchain_1.Blockchain({
66
- api,
67
- tasks,
68
- buildBlockMode: argv['build-block-mode'],
69
- inherentProvider: inherents,
70
- db,
71
- header: {
72
- hash: blockHash,
73
- number: Number(header.number),
74
- },
75
- });
76
- const context = { chain, api, ws: provider, tasks };
77
- await (0, import_storage_1.importStorage)(chain, argv['import-storage']);
78
- await (0, import_storage_1.overrideWasm)(chain, argv['wasm-override']);
79
- return context;
80
- };
81
- exports.setup = setup;
82
- const setupWithServer = async (argv) => {
83
- const context = await (0, exports.setup)(argv);
84
- const port = argv.port || Number(process.env.PORT) || 8000;
85
- const { port: listeningPort, close } = (0, server_1.createServer)(port, (0, rpc_1.handler)(context));
86
- context.tasks.updateListeningPort(await listeningPort);
87
- if (argv.genesis) {
88
- // mine 1st block when starting from genesis to set some mock validation data
89
- await context.chain.newBlock();
90
- }
91
- return {
92
- ...context,
93
- close,
94
- };
95
- };
96
- exports.setupWithServer = setupWithServer;
97
- const runBlock = async (argv) => {
98
- const context = await (0, exports.setupWithServer)(argv);
99
- const header = await context.chain.head.header;
100
- const parent = header.parentHash.toHex();
101
- const wasm = await context.chain.head.wasm;
102
- const block = context.chain.head;
103
- const calls = [['Core_initialize_block', header.toHex()]];
104
- for (const extrinsic of await block.extrinsics) {
105
- calls.push(['BlockBuilder_apply_extrinsic', extrinsic]);
106
- }
107
- calls.push(['BlockBuilder_finalize_block', '0x']);
108
- await context.tasks.addAndRunTask({
109
- Call: {
110
- blockHash: parent,
111
- wasm,
112
- calls,
113
- },
114
- }, (output) => {
115
- if (argv['output-path']) {
116
- (0, node_fs_1.writeFileSync)(argv['output-path'], JSON.stringify(output, null, 2));
117
- }
118
- else {
119
- console.dir(output, { depth: null, colors: false });
120
- }
121
- });
122
- await context.close();
123
- setTimeout(() => process.exit(0), 50);
124
- };
125
- exports.runBlock = runBlock;
126
- const decodeKey = async (argv) => {
127
- const context = await (0, exports.setup)(argv);
128
- const key = argv.key;
129
- const meta = await context.chain.head.meta;
130
- outer: for (const module of Object.values(meta.query)) {
131
- for (const storage of Object.values(module)) {
132
- const keyPrefix = (0, util_1.u8aToHex)(storage.keyPrefix());
133
- if (key.startsWith(keyPrefix)) {
134
- const decodedKey = meta.registry.createType('StorageKey', key);
135
- decodedKey.setMeta(storage.meta);
136
- console.log(`${storage.section}.${storage.method}`, decodedKey.args.map((x) => x.toHuman()).join(', '));
137
- break outer;
138
- }
139
- }
140
- }
141
- setTimeout(() => process.exit(0), 50);
12
+ const xcm_1 = require("./xcm");
13
+ const decode_key_1 = require("./decode-key");
14
+ const run_block_1 = require("./run-block");
15
+ const setup_with_server_1 = require("./setup-with-server");
16
+ const processConfig = (path) => {
17
+ const configFile = (0, node_fs_1.readFileSync)(path, 'utf8');
18
+ const config = js_yaml_1.default.load(configFile);
19
+ return schema_1.configSchema.parse(config);
142
20
  };
143
- exports.decodeKey = decodeKey;
144
- const processConfig = (argv) => {
21
+ const processArgv = (argv) => {
145
22
  if (argv.config) {
146
- const configFile = (0, node_fs_1.readFileSync)(argv.config, 'utf8');
147
- const config = js_yaml_1.default.load(configFile);
148
- const parsed = schema_1.configSchema.parse(config);
149
- return { ...parsed, ...argv };
23
+ return { ...processConfig(argv.config), ...argv };
150
24
  }
151
25
  return argv;
152
26
  };
@@ -180,19 +54,12 @@ const defaultOptions = {
180
54
  desc: 'Port to listen on',
181
55
  number: true,
182
56
  },
183
- 'executor-cmd': {
184
- desc: 'Command to execute the executor',
185
- string: true,
186
- },
187
57
  'output-path': {
188
58
  desc: 'File path to print output',
189
59
  string: true,
190
60
  },
191
- }), (argv) => {
192
- (0, exports.runBlock)(processConfig(argv)).catch((err) => {
193
- console.error(err);
194
- process.exit(1);
195
- });
61
+ }), async (argv) => {
62
+ await (0, run_block_1.runBlock)(processArgv(argv));
196
63
  })
197
64
  .command('dev', 'Dev mode', (yargs) => yargs.options({
198
65
  ...defaultOptions,
@@ -200,10 +67,6 @@ const defaultOptions = {
200
67
  desc: 'Port to listen on',
201
68
  number: true,
202
69
  },
203
- 'executor-cmd': {
204
- desc: 'Command to execute the executor',
205
- string: true,
206
- },
207
70
  'build-block-mode': {
208
71
  desc: 'Build block mode. Default to Batch',
209
72
  enum: [txpool_1.BuildBlockMode.Batch, txpool_1.BuildBlockMode.Manual, txpool_1.BuildBlockMode.Instant],
@@ -216,11 +79,8 @@ const defaultOptions = {
216
79
  desc: 'Mock signature host so any signature starts with 0xdeadbeef and filled by 0xcd is considered valid',
217
80
  boolean: true,
218
81
  },
219
- }), (argv) => {
220
- (0, exports.setupWithServer)(processConfig(argv)).catch((err) => {
221
- console.error(err);
222
- process.exit(1);
223
- });
82
+ }), async (argv) => {
83
+ await (0, setup_with_server_1.setupWithServer)(processArgv(argv));
224
84
  })
225
85
  .command('decode-key <key>', 'Deocde a key', (yargs) => yargs
226
86
  .positional('key', {
@@ -229,11 +89,35 @@ const defaultOptions = {
229
89
  })
230
90
  .options({
231
91
  ...defaultOptions,
232
- }), (argv) => {
233
- (0, exports.decodeKey)(processConfig(argv)).catch((err) => {
234
- console.error(err);
235
- process.exit(1);
236
- });
92
+ }), async (argv) => {
93
+ await (0, decode_key_1.decodeKey)(processArgv(argv));
94
+ })
95
+ .command('xcm', 'XCM setup with relaychain and parachains', (yargs) => yargs.options({
96
+ relaychain: {
97
+ desc: 'Relaychain config file path',
98
+ string: true,
99
+ },
100
+ parachain: {
101
+ desc: 'Parachain config file path',
102
+ type: 'array',
103
+ string: true,
104
+ required: true,
105
+ },
106
+ }), async (argv) => {
107
+ const parachains = [];
108
+ for (const config of argv.parachain) {
109
+ const { chain } = await (0, setup_with_server_1.setupWithServer)(processConfig(config));
110
+ parachains.push(chain);
111
+ }
112
+ if (parachains.length > 1) {
113
+ await (0, xcm_1.connectParachains)(parachains);
114
+ }
115
+ if (argv.relaychain) {
116
+ const { chain: relaychain } = await (0, setup_with_server_1.setupWithServer)(processConfig(argv.relaychain));
117
+ for (const parachain of parachains) {
118
+ await (0, xcm_1.connectDownward)(relaychain, parachain);
119
+ }
120
+ }
237
121
  })
238
122
  .strict()
239
123
  .help()
package/dist/logger.d.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import { HexString } from '@polkadot/util/types';
1
2
  export declare const defaultLogger: import("pino").Logger<{
2
3
  level: string;
3
4
  transport: {
4
5
  target: string;
5
6
  };
6
7
  }>;
7
- export declare const truncate: (str?: string) => string | undefined;
8
+ export declare const truncate: (str: string | null) => string | null;
9
+ export declare const truncateStorageDiff: (diff: [HexString, HexString | null][]) => [HexString, string | null][];
package/dist/logger.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.truncate = exports.defaultLogger = void 0;
6
+ exports.truncateStorageDiff = exports.truncate = exports.defaultLogger = void 0;
7
7
  const pino_1 = __importDefault(require("pino"));
8
8
  exports.defaultLogger = (0, pino_1.default)({
9
9
  level: process.env.LOG_LEVEL || 'info',
@@ -23,3 +23,7 @@ const truncate = (str) => {
23
23
  }
24
24
  };
25
25
  exports.truncate = truncate;
26
+ const truncateStorageDiff = (diff) => {
27
+ return diff.map(([key, value]) => [key, (0, exports.truncate)(value)]);
28
+ };
29
+ exports.truncateStorageDiff = truncateStorageDiff;
package/dist/rpc/dev.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const shared_1 = require("./shared");
4
4
  const set_storage_1 = require("../utils/set-storage");
5
5
  const logger_1 = require("../logger");
6
+ const time_travel_1 = require("../utils/time-travel");
6
7
  const logger = logger_1.defaultLogger.child({ name: 'rpc-dev' });
7
8
  const handlers = {
8
9
  dev_newBlock: async (context, [param]) => {
@@ -12,7 +13,9 @@ const handlers = {
12
13
  const finalCount = diff > 0 ? diff : 1;
13
14
  let finalHash;
14
15
  for (let i = 0; i < finalCount; i++) {
15
- const block = await context.chain.newBlock();
16
+ const block = await context.chain.newBlock().catch((error) => {
17
+ throw new shared_1.ResponseError(1, error.toString());
18
+ });
16
19
  logger.debug({ hash: block.hash }, 'dev_newBlock');
17
20
  finalHash = block.hash;
18
21
  }
@@ -29,5 +32,12 @@ const handlers = {
29
32
  }, 'dev_setStorages');
30
33
  return hash;
31
34
  },
35
+ dev_timeTravel: async (context, [date]) => {
36
+ const timestamp = typeof date === 'string' ? Date.parse(date) : date;
37
+ if (Number.isNaN(timestamp))
38
+ throw new shared_1.ResponseError(1, 'Invalid date');
39
+ await (0, time_travel_1.timeTravel)(context.chain, timestamp);
40
+ return timestamp;
41
+ },
32
42
  };
33
43
  exports.default = handlers;
package/dist/rpc/index.js CHANGED
@@ -6,10 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.handler = void 0;
7
7
  const shared_1 = require("./shared");
8
8
  const dev_1 = __importDefault(require("./dev"));
9
- const exec_1 = __importDefault(require("./exec"));
10
9
  const substrate_1 = __importDefault(require("./substrate"));
11
10
  const allHandlers = {
12
- ...exec_1.default,
13
11
  ...substrate_1.default,
14
12
  ...dev_1.default,
15
13
  };
@@ -1,7 +1,4 @@
1
- import { ProviderInterface } from '@polkadot/rpc-provider/types';
2
- import { Api } from '../api';
3
1
  import { Blockchain } from '../blockchain';
4
- import { TaskManager } from '../task';
5
2
  export declare const logger: import("pino").default.Logger<{
6
3
  level: string;
7
4
  transport: {
@@ -18,9 +15,6 @@ export declare class ResponseError extends Error {
18
15
  }
19
16
  export interface Context {
20
17
  chain: Blockchain;
21
- api: Api;
22
- ws: ProviderInterface;
23
- tasks: TaskManager;
24
18
  }
25
19
  export interface SubscriptionManager {
26
20
  subscribe: (method: string, subid: string, onCancel?: () => void) => (data: any) => void;
@@ -1,3 +1,3 @@
1
- import { Handlers } from '../shared';
1
+ import { Handlers } from '../../rpc/shared';
2
2
  declare const handlers: Handlers;
3
3
  export default handlers;
@@ -1,10 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const shared_1 = require("../../rpc/shared");
3
4
  const logger_1 = require("../../logger");
4
5
  const logger = logger_1.defaultLogger.child({ name: 'rpc-author' });
5
6
  const handlers = {
6
7
  author_submitExtrinsic: async (context, [extrinsic]) => {
7
- return context.chain.submitExtrinsic(extrinsic);
8
+ return context.chain.submitExtrinsic(extrinsic).catch((error) => {
9
+ throw new shared_1.ResponseError(1, error.toString());
10
+ });
8
11
  },
9
12
  author_submitAndWatchExtrinsic: async (context, [extrinsic], { subscribe, unsubscribe }) => {
10
13
  let update = (_block) => { };
@@ -38,6 +41,8 @@ const handlers = {
38
41
  author_unwatchExtrinsic: async (_context, [subid], { unsubscribe }) => {
39
42
  unsubscribe(subid);
40
43
  },
41
- author_pendingExtrinsics: async (_context) => [],
44
+ author_pendingExtrinsics: async (context) => {
45
+ return context.chain.pendingExtrinsics;
46
+ },
42
47
  };
43
48
  exports.default = handlers;
@@ -5,7 +5,7 @@ const handlers = {
5
5
  chain_getBlockHash: async (context, [blockNumber]) => {
6
6
  const block = await context.chain.getBlockAt(blockNumber);
7
7
  if (!block) {
8
- throw new shared_1.ResponseError(1, 'Block not found');
8
+ throw new shared_1.ResponseError(1, `Block #${blockNumber} not found`);
9
9
  }
10
10
  return block.hash;
11
11
  },
@@ -15,7 +15,7 @@ const handlers = {
15
15
  chain_getBlock: async (context, [hash]) => {
16
16
  const block = await context.chain.getBlock(hash);
17
17
  if (!block) {
18
- throw new shared_1.ResponseError(1, 'Block not found');
18
+ throw new shared_1.ResponseError(1, `Block ${hash} not found`);
19
19
  }
20
20
  return {
21
21
  block: {
@@ -41,7 +41,7 @@ const handlers = {
41
41
  },
42
42
  state_subscribeRuntimeVersion: async (context, _params, { subscribe }) => {
43
43
  let update = (_block) => { };
44
- const id = context.chain.headState.subscrubeRuntimeVersion((block) => update(block));
44
+ const id = await context.chain.headState.subscrubeRuntimeVersion((block) => update(block));
45
45
  const callback = subscribe('state_runtimeVersion', id);
46
46
  update = async (block) => callback(await block.runtimeVersion);
47
47
  context.chain.head.runtimeVersion.then(callback);
@@ -2,13 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const handlers = {
4
4
  system_chain: async (context) => {
5
- return context.api.getSystemChain();
5
+ return context.chain.api.getSystemChain();
6
6
  },
7
7
  system_properties: async (context) => {
8
- return context.api.getSystemProperties();
8
+ return context.chain.api.getSystemProperties();
9
9
  },
10
10
  system_name: async (context) => {
11
- return context.api.getSystemName();
11
+ return context.chain.api.getSystemName();
12
12
  },
13
13
  system_version: async (_context) => {
14
14
  return 'chopsticks-1.1.0';
@@ -0,0 +1,2 @@
1
+ import { Config } from './schema';
2
+ export declare const runBlock: (argv: Config) => Promise<void>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runBlock = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const executor_1 = require("./executor");
6
+ const setup_with_server_1 = require("./setup-with-server");
7
+ const runBlock = async (argv) => {
8
+ const context = await (0, setup_with_server_1.setupWithServer)(argv);
9
+ const header = await context.chain.head.header;
10
+ const wasm = await context.chain.head.wasm;
11
+ const block = context.chain.head;
12
+ const parent = await block.parentBlock;
13
+ if (!parent)
14
+ throw Error('cant find parent block');
15
+ const calls = [['Core_initialize_block', header.toHex()]];
16
+ for (const extrinsic of await block.extrinsics) {
17
+ calls.push(['BlockBuilder_apply_extrinsic', extrinsic]);
18
+ }
19
+ calls.push(['BlockBuilder_finalize_block', '0x']);
20
+ const result = await (0, executor_1.runTask)({
21
+ wasm,
22
+ calls,
23
+ storage: [],
24
+ mockSignatureHost: false,
25
+ allowUnresolvedImports: false,
26
+ }, (0, executor_1.taskHandler)(parent));
27
+ if (argv['output-path']) {
28
+ (0, node_fs_1.writeFileSync)(argv['output-path'], JSON.stringify(result, null, 2));
29
+ }
30
+ else {
31
+ console.dir(result, { depth: null, colors: false });
32
+ }
33
+ await context.close();
34
+ setTimeout(() => process.exit(0), 50);
35
+ };
36
+ exports.runBlock = runBlock;
@@ -65,7 +65,6 @@ export declare const configSchema: z.ZodObject<{
65
65
  port: z.ZodOptional<z.ZodNumber>;
66
66
  endpoint: z.ZodOptional<z.ZodString>;
67
67
  block: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
68
- 'executor-cmd': z.ZodOptional<z.ZodString>;
69
68
  'build-block-mode': z.ZodOptional<z.ZodNativeEnum<typeof BuildBlockMode>>;
70
69
  'import-storage': z.ZodOptional<z.ZodAny>;
71
70
  'mock-signature-host': z.ZodOptional<z.ZodBoolean>;
@@ -133,7 +132,6 @@ export declare const configSchema: z.ZodObject<{
133
132
  }>]>>;
134
133
  timestamp: z.ZodOptional<z.ZodNumber>;
135
134
  }, "strict", z.ZodTypeAny, {
136
- port?: number | undefined;
137
135
  timestamp?: number | undefined;
138
136
  db?: string | undefined;
139
137
  genesis?: string | {
@@ -150,15 +148,14 @@ export declare const configSchema: z.ZodObject<{
150
148
  };
151
149
  };
152
150
  } | undefined;
151
+ port?: number | undefined;
153
152
  endpoint?: string | undefined;
154
153
  block?: string | number | undefined;
155
- 'executor-cmd'?: string | undefined;
156
154
  'build-block-mode'?: BuildBlockMode | undefined;
157
155
  'import-storage'?: any;
158
156
  'mock-signature-host'?: boolean | undefined;
159
157
  'wasm-override'?: string | undefined;
160
158
  }, {
161
- port?: number | undefined;
162
159
  timestamp?: number | undefined;
163
160
  db?: string | undefined;
164
161
  genesis?: string | {
@@ -175,9 +172,9 @@ export declare const configSchema: z.ZodObject<{
175
172
  };
176
173
  };
177
174
  } | undefined;
175
+ port?: number | undefined;
178
176
  endpoint?: string | undefined;
179
177
  block?: string | number | undefined;
180
- 'executor-cmd'?: string | undefined;
181
178
  'build-block-mode'?: BuildBlockMode | undefined;
182
179
  'import-storage'?: any;
183
180
  'mock-signature-host'?: boolean | undefined;
@@ -17,8 +17,7 @@ exports.configSchema = zod_1.z
17
17
  .object({
18
18
  port: zod_1.z.number().optional(),
19
19
  endpoint: zod_1.z.string().optional(),
20
- block: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
21
- 'executor-cmd': zod_1.z.string().optional(),
20
+ block: zod_1.z.union([zod_1.z.string().length(66).startsWith('0x'), zod_1.z.number()]).optional(),
22
21
  'build-block-mode': zod_1.z.nativeEnum(txpool_1.BuildBlockMode).optional(),
23
22
  'import-storage': zod_1.z.any().optional(),
24
23
  'mock-signature-host': zod_1.z.boolean().optional(),
package/dist/server.d.ts CHANGED
@@ -3,7 +3,7 @@ export type Handler = (data: {
3
3
  method: string;
4
4
  params: string[];
5
5
  }, subscriptionManager: SubscriptionManager) => Promise<any>;
6
- export declare const createServer: (port: number, handler: Handler) => {
7
- port: Promise<number>;
6
+ export declare const createServer: (handler: Handler, port?: number) => Promise<{
7
+ port: number;
8
8
  close: () => Promise<void>;
9
- };
9
+ }>;
package/dist/server.js CHANGED
@@ -35,19 +35,34 @@ const parseRequest = (request) => {
35
35
  return undefined;
36
36
  }
37
37
  };
38
- const createServer = (port, handler) => {
39
- logger.debug('Starting on port %d', port);
38
+ const createWS = async (port) => {
40
39
  const wss = new ws_1.WebSocketServer({ port, maxPayload: 1024 * 1024 * 100 });
41
- const promise = new Promise((resolve, reject) => {
40
+ const promise = new Promise((resolve) => {
42
41
  wss.on('listening', () => {
43
- logger.debug(wss.address(), 'Listening');
44
- resolve(wss.address().port);
42
+ resolve([wss, wss.address().port]);
45
43
  });
46
- wss.on('error', (err) => {
47
- logger.error(err, 'Error');
48
- reject(err);
44
+ wss.on('error', (_) => {
45
+ resolve([]);
49
46
  });
50
47
  });
48
+ return promise;
49
+ };
50
+ const createServer = async (handler, port) => {
51
+ let wss;
52
+ let listenPort;
53
+ for (let i = 0; i < 5; i++) {
54
+ const preferPort = (port || 0) + i;
55
+ logger.debug('Try starting on port %d', preferPort);
56
+ const [maybeWss, maybeListenPort] = await createWS(preferPort);
57
+ if (maybeWss && maybeListenPort) {
58
+ wss = maybeWss;
59
+ listenPort = maybeListenPort;
60
+ break;
61
+ }
62
+ }
63
+ if (!wss || !listenPort) {
64
+ throw new Error(`Failed to create WebsocketServer at port ${port}`);
65
+ }
51
66
  wss.on('connection', (ws) => {
52
67
  logger.debug('New connection');
53
68
  const send = (data) => {
@@ -131,10 +146,10 @@ const createServer = (port, handler) => {
131
146
  });
132
147
  });
133
148
  return {
134
- port: promise,
149
+ port: listenPort,
135
150
  close: () => new Promise((resolve, reject) => {
136
- wss.clients.forEach((socket) => socket.close());
137
- wss.close((err) => {
151
+ wss?.clients.forEach((socket) => socket.close());
152
+ wss?.close((err) => {
138
153
  if (err) {
139
154
  reject(err);
140
155
  }
@@ -0,0 +1,8 @@
1
+ import { Config } from './schema';
2
+ export declare const setupWithServer: (argv: Config) => Promise<{
3
+ close: () => Promise<void>;
4
+ listenPort: number;
5
+ chain: import("./blockchain").Blockchain;
6
+ api: import("./api").Api;
7
+ ws: import("@polkadot/rpc-provider/types").ProviderInterface;
8
+ }>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setupWithServer = void 0;
4
+ const server_1 = require("./server");
5
+ const rpc_1 = require("./rpc");
6
+ const shared_1 = require("./rpc/shared");
7
+ const setup_1 = require("./setup");
8
+ const setupWithServer = async (argv) => {
9
+ const context = await (0, setup_1.setup)(argv);
10
+ const port = argv.port || Number(process.env.PORT) || 8000;
11
+ if (argv.genesis) {
12
+ // mine 1st block when starting from genesis to set some mock validation data
13
+ await context.chain.newBlock();
14
+ }
15
+ const { close, port: listenPort } = await (0, server_1.createServer)((0, rpc_1.handler)(context), port);
16
+ shared_1.logger.info(`${await context.chain.api.getSystemChain()} RPC listening on port ${listenPort}`);
17
+ return {
18
+ ...context,
19
+ close,
20
+ listenPort,
21
+ };
22
+ };
23
+ exports.setupWithServer = setupWithServer;
@@ -0,0 +1,10 @@
1
+ import '@polkadot/types-codec';
2
+ import { ProviderInterface } from '@polkadot/rpc-provider/types';
3
+ import { Api } from './api';
4
+ import { Blockchain } from './blockchain';
5
+ import { Config } from './schema';
6
+ export declare const setup: (argv: Config) => Promise<{
7
+ chain: Blockchain;
8
+ api: Api;
9
+ ws: ProviderInterface;
10
+ }>;