@acala-network/chopsticks-core 0.8.0-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/lib/api.d.ts +43 -0
- package/lib/api.js +116 -0
- package/lib/blockchain/block-builder.d.ts +10 -0
- package/lib/blockchain/block-builder.js +290 -0
- package/lib/blockchain/block.d.ts +45 -0
- package/lib/blockchain/block.js +221 -0
- package/lib/blockchain/head-state.d.ts +15 -0
- package/lib/blockchain/head-state.js +94 -0
- package/lib/blockchain/index.d.ts +73 -0
- package/lib/blockchain/index.js +351 -0
- package/lib/blockchain/inherent/index.d.ts +19 -0
- package/lib/blockchain/inherent/index.js +53 -0
- package/lib/blockchain/inherent/para-enter.d.ts +7 -0
- package/lib/blockchain/inherent/para-enter.js +37 -0
- package/lib/blockchain/inherent/parachain/babe-randomness.d.ts +7 -0
- package/lib/blockchain/inherent/parachain/babe-randomness.js +23 -0
- package/lib/blockchain/inherent/parachain/nimbus-author-inherent.d.ts +7 -0
- package/lib/blockchain/inherent/parachain/nimbus-author-inherent.js +23 -0
- package/lib/blockchain/inherent/parachain/validation-data.d.ts +19 -0
- package/lib/blockchain/inherent/parachain/validation-data.js +165 -0
- package/lib/blockchain/storage-layer.d.ts +32 -0
- package/lib/blockchain/storage-layer.js +242 -0
- package/lib/blockchain/txpool.d.ts +44 -0
- package/lib/blockchain/txpool.js +210 -0
- package/lib/db/browser.d.ts +2 -0
- package/lib/db/browser.js +33 -0
- package/lib/db/entities.d.ts +16 -0
- package/lib/db/entities.js +50 -0
- package/lib/db/index.d.ts +1 -0
- package/lib/db/index.js +17 -0
- package/lib/db/node.d.ts +2 -0
- package/lib/db/node.js +22 -0
- package/lib/executor.d.ts +41 -0
- package/lib/executor.js +160 -0
- package/lib/genesis-provider.d.ts +44 -0
- package/lib/genesis-provider.js +172 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +13 -0
- package/lib/logger.d.ts +7 -0
- package/lib/logger.js +34 -0
- package/lib/offchain.d.ts +10 -0
- package/lib/offchain.js +49 -0
- package/lib/schema/index.d.ts +62 -0
- package/lib/schema/index.js +11 -0
- package/lib/setup.d.ts +20 -0
- package/lib/setup.js +74 -0
- package/lib/utils/index.d.ts +18 -0
- package/lib/utils/index.js +65 -0
- package/lib/utils/key-cache.d.ts +10 -0
- package/lib/utils/key-cache.js +72 -0
- package/lib/utils/proof.d.ts +15 -0
- package/lib/utils/proof.js +33 -0
- package/lib/utils/set-storage.d.ts +7 -0
- package/lib/utils/set-storage.js +65 -0
- package/lib/utils/time-travel.d.ts +5 -0
- package/lib/utils/time-travel.js +67 -0
- package/lib/xcm/downward.d.ts +2 -0
- package/lib/xcm/downward.js +34 -0
- package/lib/xcm/horizontal.d.ts +2 -0
- package/lib/xcm/horizontal.js +34 -0
- package/lib/xcm/index.d.ts +9 -0
- package/lib/xcm/index.js +29 -0
- package/lib/xcm/upward.d.ts +2 -0
- package/lib/xcm/upward.js +26 -0
- package/package.json +46 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
11
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
12
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
13
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
14
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
15
|
+
};
|
|
16
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
17
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
18
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
19
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
20
|
+
};
|
|
21
|
+
var _a, _GenesisProvider_isConnected, _GenesisProvider_eventemitter, _GenesisProvider_isReadyPromise, _GenesisProvider_genesis, _GenesisProvider_stateRoot;
|
|
22
|
+
import { EventEmitter } from 'eventemitter3';
|
|
23
|
+
import { stringToHex } from '@polkadot/util';
|
|
24
|
+
import axios from 'axios';
|
|
25
|
+
import { genesisSchema } from './schema';
|
|
26
|
+
import { calculateStateRoot, emptyTaskHandler, runTask } from './executor';
|
|
27
|
+
import { isUrl } from './utils';
|
|
28
|
+
export class GenesisProvider {
|
|
29
|
+
constructor(genesis) {
|
|
30
|
+
_GenesisProvider_isConnected.set(this, false);
|
|
31
|
+
_GenesisProvider_eventemitter.set(this, void 0);
|
|
32
|
+
_GenesisProvider_isReadyPromise.set(this, void 0);
|
|
33
|
+
_GenesisProvider_genesis.set(this, void 0);
|
|
34
|
+
_GenesisProvider_stateRoot.set(this, void 0);
|
|
35
|
+
this.clone = () => {
|
|
36
|
+
return new GenesisProvider(__classPrivateFieldGet(this, _GenesisProvider_genesis, "f"));
|
|
37
|
+
};
|
|
38
|
+
this.connect = () => __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
__classPrivateFieldSet(this, _GenesisProvider_isConnected, true, "f");
|
|
40
|
+
__classPrivateFieldGet(this, _GenesisProvider_eventemitter, "f").emit('connected');
|
|
41
|
+
});
|
|
42
|
+
this.disconnect = () => __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
__classPrivateFieldSet(this, _GenesisProvider_isConnected, false, "f");
|
|
44
|
+
__classPrivateFieldGet(this, _GenesisProvider_eventemitter, "f").emit('disconnected');
|
|
45
|
+
});
|
|
46
|
+
this.on = (type, sub) => {
|
|
47
|
+
__classPrivateFieldGet(this, _GenesisProvider_eventemitter, "f").on(type, sub);
|
|
48
|
+
return () => {
|
|
49
|
+
__classPrivateFieldGet(this, _GenesisProvider_eventemitter, "f").removeListener(type, sub);
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
this.getHeader = () => __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
return {
|
|
54
|
+
blockHash: this.blockHash,
|
|
55
|
+
number: 0,
|
|
56
|
+
stateRoot: yield __classPrivateFieldGet(this, _GenesisProvider_stateRoot, "f"),
|
|
57
|
+
digest: {
|
|
58
|
+
logs: [],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
this.getBlock = () => __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
return {
|
|
64
|
+
block: {
|
|
65
|
+
header: yield this.getHeader(),
|
|
66
|
+
extrinsics: [],
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
this.send = (method, params, _isCacheable) => __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
yield this.isReady;
|
|
72
|
+
switch (method) {
|
|
73
|
+
case 'system_properties':
|
|
74
|
+
return __classPrivateFieldGet(this, _GenesisProvider_genesis, "f").properties;
|
|
75
|
+
case 'system_chain':
|
|
76
|
+
return __classPrivateFieldGet(this, _GenesisProvider_genesis, "f").id;
|
|
77
|
+
case 'system_name':
|
|
78
|
+
return __classPrivateFieldGet(this, _GenesisProvider_genesis, "f").name;
|
|
79
|
+
case 'state_getMetadata': {
|
|
80
|
+
const code = __classPrivateFieldGet(this, _GenesisProvider_genesis, "f").genesis.raw.top[stringToHex(':code')];
|
|
81
|
+
return runTask({
|
|
82
|
+
wasm: code,
|
|
83
|
+
calls: [['Metadata_metadata', []]],
|
|
84
|
+
mockSignatureHost: false,
|
|
85
|
+
allowUnresolvedImports: true,
|
|
86
|
+
runtimeLogLevel: 0,
|
|
87
|
+
}, this._jsCallback);
|
|
88
|
+
}
|
|
89
|
+
case 'chain_getHeader':
|
|
90
|
+
return this.getHeader();
|
|
91
|
+
case 'chain_getBlock':
|
|
92
|
+
return this.getBlock();
|
|
93
|
+
case 'chain_getBlockHash':
|
|
94
|
+
return this.blockHash;
|
|
95
|
+
case 'state_getKeysPaged':
|
|
96
|
+
case 'state_getKeysPagedAt':
|
|
97
|
+
return [];
|
|
98
|
+
case 'state_getStorage':
|
|
99
|
+
case 'state_getStorageAt':
|
|
100
|
+
return __classPrivateFieldGet(this, _GenesisProvider_genesis, "f").genesis.raw.top[params[0]];
|
|
101
|
+
default:
|
|
102
|
+
throw Error(`${method} not implemented`);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
this.subscribe = (_type, _method, _params, _cb) => __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
throw Error('unimplemented');
|
|
107
|
+
});
|
|
108
|
+
this.unsubscribe = (_type, _method, _id) => __awaiter(this, void 0, void 0, function* () {
|
|
109
|
+
throw Error('unimplemented');
|
|
110
|
+
});
|
|
111
|
+
__classPrivateFieldSet(this, _GenesisProvider_genesis, genesis, "f");
|
|
112
|
+
__classPrivateFieldSet(this, _GenesisProvider_stateRoot, calculateStateRoot(Object.entries(__classPrivateFieldGet(this, _GenesisProvider_genesis, "f").genesis.raw.top).reduce((accu, item) => {
|
|
113
|
+
accu.push(item);
|
|
114
|
+
return accu;
|
|
115
|
+
}, []), 1), "f");
|
|
116
|
+
__classPrivateFieldSet(this, _GenesisProvider_eventemitter, new EventEmitter(), "f");
|
|
117
|
+
__classPrivateFieldSet(this, _GenesisProvider_isReadyPromise, new Promise((resolve, reject) => {
|
|
118
|
+
__classPrivateFieldGet(this, _GenesisProvider_eventemitter, "f").once('connected', () => {
|
|
119
|
+
resolve();
|
|
120
|
+
});
|
|
121
|
+
__classPrivateFieldGet(this, _GenesisProvider_eventemitter, "f").once('error', reject);
|
|
122
|
+
}), "f");
|
|
123
|
+
}
|
|
124
|
+
get isClonable() {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
get hasSubscriptions() {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
get isConnected() {
|
|
131
|
+
return __classPrivateFieldGet(this, _GenesisProvider_isConnected, "f");
|
|
132
|
+
}
|
|
133
|
+
get isReady() {
|
|
134
|
+
this.connect();
|
|
135
|
+
return __classPrivateFieldGet(this, _GenesisProvider_isReadyPromise, "f");
|
|
136
|
+
}
|
|
137
|
+
get blockHash() {
|
|
138
|
+
return '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3';
|
|
139
|
+
}
|
|
140
|
+
get _jsCallback() {
|
|
141
|
+
const storage = __classPrivateFieldGet(this, _GenesisProvider_genesis, "f").genesis.raw.top;
|
|
142
|
+
return Object.assign(Object.assign({}, emptyTaskHandler), { getStorage: function (key) {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
return storage[key];
|
|
145
|
+
});
|
|
146
|
+
}, getStateRoot: function () {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
+
return '0x49416764844ff0d8bad851e8abe686dff9dd2de78621180ef8e9f99bb7a480f1';
|
|
149
|
+
});
|
|
150
|
+
}, getNextKey: function (_prefix, _key) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
return undefined;
|
|
153
|
+
});
|
|
154
|
+
} });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
_a = GenesisProvider, _GenesisProvider_isConnected = new WeakMap(), _GenesisProvider_eventemitter = new WeakMap(), _GenesisProvider_isReadyPromise = new WeakMap(), _GenesisProvider_genesis = new WeakMap(), _GenesisProvider_stateRoot = new WeakMap();
|
|
158
|
+
GenesisProvider.fromUrl = (url) => __awaiter(void 0, void 0, void 0, function* () {
|
|
159
|
+
const getFile = (url) => __awaiter(void 0, void 0, void 0, function* () {
|
|
160
|
+
if (isUrl(url)) {
|
|
161
|
+
return axios.get(url).then((x) => x.data);
|
|
162
|
+
}
|
|
163
|
+
else if (typeof process === 'object') {
|
|
164
|
+
const { lstatSync, readFileSync } = yield import('node:fs');
|
|
165
|
+
if (lstatSync(url).isFile()) {
|
|
166
|
+
return JSON.parse(String(readFileSync(url)));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
throw Error(`invalid genesis path or url ${url}`);
|
|
170
|
+
});
|
|
171
|
+
return new GenesisProvider(genesisSchema.parse(yield getFile(url)));
|
|
172
|
+
});
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './api';
|
|
2
|
+
export * from './blockchain';
|
|
3
|
+
export * from './blockchain/block';
|
|
4
|
+
export * from './blockchain/block-builder';
|
|
5
|
+
export * from './blockchain/txpool';
|
|
6
|
+
export * from './blockchain/storage-layer';
|
|
7
|
+
export * from './utils';
|
|
8
|
+
export * from './executor';
|
|
9
|
+
export * from './schema';
|
|
10
|
+
export * from './xcm';
|
|
11
|
+
export * from './setup';
|
|
12
|
+
export * from './blockchain/inherent';
|
|
13
|
+
export * from './logger';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './api';
|
|
2
|
+
export * from './blockchain';
|
|
3
|
+
export * from './blockchain/block';
|
|
4
|
+
export * from './blockchain/block-builder';
|
|
5
|
+
export * from './blockchain/txpool';
|
|
6
|
+
export * from './blockchain/storage-layer';
|
|
7
|
+
export * from './utils';
|
|
8
|
+
export * from './executor';
|
|
9
|
+
export * from './schema';
|
|
10
|
+
export * from './xcm';
|
|
11
|
+
export * from './setup';
|
|
12
|
+
export * from './blockchain/inherent';
|
|
13
|
+
export * from './logger';
|
package/lib/logger.d.ts
ADDED
package/lib/logger.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import createLogger from 'pino';
|
|
2
|
+
export const defaultLogger = createLogger({
|
|
3
|
+
level: (typeof process === 'object' && process.env.LOG_LEVEL) || 'info',
|
|
4
|
+
transport: {
|
|
5
|
+
target: 'pino-pretty',
|
|
6
|
+
},
|
|
7
|
+
});
|
|
8
|
+
const innerTruncate = (level = 0) => (val) => {
|
|
9
|
+
const verboseLog = typeof process === 'object' ? !!process.env.VERBOSE_LOG : false;
|
|
10
|
+
const levelLimit = verboseLog ? 10 : 5;
|
|
11
|
+
if (val == null) {
|
|
12
|
+
return val;
|
|
13
|
+
}
|
|
14
|
+
if (level > levelLimit) {
|
|
15
|
+
return '( Too Deep )';
|
|
16
|
+
}
|
|
17
|
+
switch (typeof val) {
|
|
18
|
+
case 'string':
|
|
19
|
+
if (val.length > 66 && !verboseLog) {
|
|
20
|
+
return val.slice(0, 34) + '…' + val.slice(-32);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return val;
|
|
24
|
+
}
|
|
25
|
+
case 'object':
|
|
26
|
+
if (Array.isArray(val)) {
|
|
27
|
+
return val.map(innerTruncate(level + 1));
|
|
28
|
+
}
|
|
29
|
+
return Object.fromEntries(Object.entries(val.toJSON ? val.toJSON() : val).map(([k, v]) => [k, innerTruncate(level + 1)(v)]));
|
|
30
|
+
default:
|
|
31
|
+
return val;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export const truncate = (val) => innerTruncate(0)(val);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Block } from './blockchain/block';
|
|
2
|
+
import { HexString } from '@polkadot/util/types';
|
|
3
|
+
export declare class OffchainWorker {
|
|
4
|
+
readonly pendingExtrinsics: HexString[];
|
|
5
|
+
readonly offchainStorage: Map<string, string | null | undefined>;
|
|
6
|
+
get(key: string): string | null | undefined;
|
|
7
|
+
set(key: string, value: string | null | undefined): void;
|
|
8
|
+
run(block: Block): Promise<void>;
|
|
9
|
+
pushExtrinsic(block: Block, extrinsic: HexString): Promise<`0x${string}`>;
|
|
10
|
+
}
|
package/lib/offchain.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { blake2AsHex } from '@polkadot/util-crypto';
|
|
11
|
+
import { defaultLogger } from './logger';
|
|
12
|
+
import { queueScheduler } from 'rxjs';
|
|
13
|
+
const logger = defaultLogger.child({ name: 'offchain' });
|
|
14
|
+
export class OffchainWorker {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.pendingExtrinsics = [];
|
|
17
|
+
this.offchainStorage = new Map();
|
|
18
|
+
}
|
|
19
|
+
get(key) {
|
|
20
|
+
return this.offchainStorage.get(key);
|
|
21
|
+
}
|
|
22
|
+
set(key, value) {
|
|
23
|
+
this.offchainStorage.set(key, value);
|
|
24
|
+
}
|
|
25
|
+
run(block) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
logger.info({ number: block.number, hash: block.hash }, `Run Offchain Worker for block #${block.number.toLocaleString()}`);
|
|
28
|
+
const header = yield block.header;
|
|
29
|
+
yield block.call('OffchainWorkerApi_offchain_worker', [header.toHex()]);
|
|
30
|
+
logger.info(`Offchain Worker complete for block #${block.number.toLocaleString()}`);
|
|
31
|
+
const txs = this.pendingExtrinsics.splice(0);
|
|
32
|
+
if (txs.length > 0) {
|
|
33
|
+
queueScheduler.schedule((transactions) => __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
yield block.chain.txPool.buildBlock({ transactions });
|
|
35
|
+
}), 100, txs);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
pushExtrinsic(block, extrinsic) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const validity = yield block.chain.validateExtrinsic(extrinsic, '0x01');
|
|
42
|
+
if (validity.isOk) {
|
|
43
|
+
this.pendingExtrinsics.push(extrinsic);
|
|
44
|
+
return blake2AsHex(extrinsic, 256);
|
|
45
|
+
}
|
|
46
|
+
throw validity.asErr;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const genesisSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
properties: z.ZodObject<{
|
|
6
|
+
ss58Format: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
tokenDecimals: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodArray<z.ZodNumber, "many">]>>;
|
|
8
|
+
tokenSymbol: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
ss58Format?: number | undefined;
|
|
11
|
+
tokenDecimals?: number | number[] | undefined;
|
|
12
|
+
tokenSymbol?: string | string[] | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
ss58Format?: number | undefined;
|
|
15
|
+
tokenDecimals?: number | number[] | undefined;
|
|
16
|
+
tokenSymbol?: string | string[] | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
genesis: z.ZodObject<{
|
|
19
|
+
raw: z.ZodObject<{
|
|
20
|
+
top: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
21
|
+
}, "strip", z.ZodTypeAny, {
|
|
22
|
+
top: Record<string, string>;
|
|
23
|
+
}, {
|
|
24
|
+
top: Record<string, string>;
|
|
25
|
+
}>;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
raw: {
|
|
28
|
+
top: Record<string, string>;
|
|
29
|
+
};
|
|
30
|
+
}, {
|
|
31
|
+
raw: {
|
|
32
|
+
top: Record<string, string>;
|
|
33
|
+
};
|
|
34
|
+
}>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
name: string;
|
|
37
|
+
id: string;
|
|
38
|
+
properties: {
|
|
39
|
+
ss58Format?: number | undefined;
|
|
40
|
+
tokenDecimals?: number | number[] | undefined;
|
|
41
|
+
tokenSymbol?: string | string[] | undefined;
|
|
42
|
+
};
|
|
43
|
+
genesis: {
|
|
44
|
+
raw: {
|
|
45
|
+
top: Record<string, string>;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
}, {
|
|
49
|
+
name: string;
|
|
50
|
+
id: string;
|
|
51
|
+
properties: {
|
|
52
|
+
ss58Format?: number | undefined;
|
|
53
|
+
tokenDecimals?: number | number[] | undefined;
|
|
54
|
+
tokenSymbol?: string | string[] | undefined;
|
|
55
|
+
};
|
|
56
|
+
genesis: {
|
|
57
|
+
raw: {
|
|
58
|
+
top: Record<string, string>;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}>;
|
|
62
|
+
export type Genesis = z.infer<typeof genesisSchema>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const genesisSchema = z.object({
|
|
3
|
+
id: z.string(),
|
|
4
|
+
name: z.string(),
|
|
5
|
+
properties: z.object({
|
|
6
|
+
ss58Format: z.number().optional(),
|
|
7
|
+
tokenDecimals: z.union([z.number(), z.array(z.number())]).optional(),
|
|
8
|
+
tokenSymbol: z.union([z.string(), z.array(z.string())]).optional(),
|
|
9
|
+
}),
|
|
10
|
+
genesis: z.object({ raw: z.object({ top: z.record(z.string()) }) }),
|
|
11
|
+
});
|
package/lib/setup.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import '@polkadot/types-codec';
|
|
2
|
+
import { RegisteredTypes } from '@polkadot/types/types';
|
|
3
|
+
import { Blockchain } from './blockchain';
|
|
4
|
+
import { BuildBlockMode } from './blockchain/txpool';
|
|
5
|
+
import { Genesis } from './schema';
|
|
6
|
+
type Options = {
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
block?: string | number | null;
|
|
9
|
+
genesis?: string | Genesis;
|
|
10
|
+
buildBlockMode?: BuildBlockMode;
|
|
11
|
+
db?: string;
|
|
12
|
+
mockSignatureHost?: boolean;
|
|
13
|
+
allowUnresolvedImports?: boolean;
|
|
14
|
+
runtimeLogLevel?: number;
|
|
15
|
+
registeredTypes?: RegisteredTypes;
|
|
16
|
+
offchainWorker?: boolean;
|
|
17
|
+
maxMemoryBlockCount?: number;
|
|
18
|
+
};
|
|
19
|
+
export declare const setup: (options: Options) => Promise<Blockchain>;
|
|
20
|
+
export {};
|
package/lib/setup.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import '@polkadot/types-codec';
|
|
11
|
+
import { WsProvider } from '@polkadot/api';
|
|
12
|
+
import { Api } from './api';
|
|
13
|
+
import { Blockchain } from './blockchain';
|
|
14
|
+
import { GenesisProvider } from './genesis-provider';
|
|
15
|
+
import { InherentProviders, ParaInherentEnter, SetBabeRandomness, SetNimbusAuthorInherent, SetTimestamp, SetValidationData, } from './blockchain/inherent';
|
|
16
|
+
import { defaultLogger } from './logger';
|
|
17
|
+
import { openDb } from './db';
|
|
18
|
+
export const setup = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
+
let provider;
|
|
20
|
+
if (options.genesis) {
|
|
21
|
+
if (typeof options.genesis === 'string') {
|
|
22
|
+
provider = yield GenesisProvider.fromUrl(options.genesis);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
provider = new GenesisProvider(options.genesis);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
provider = new WsProvider(options.endpoint);
|
|
30
|
+
}
|
|
31
|
+
const api = new Api(provider);
|
|
32
|
+
yield api.isReady;
|
|
33
|
+
let blockHash;
|
|
34
|
+
if (options.block == null) {
|
|
35
|
+
blockHash = yield api.getBlockHash();
|
|
36
|
+
}
|
|
37
|
+
else if (typeof options.block === 'string' && options.block.startsWith('0x')) {
|
|
38
|
+
blockHash = options.block;
|
|
39
|
+
}
|
|
40
|
+
else if (Number.isInteger(+options.block)) {
|
|
41
|
+
blockHash = yield api.getBlockHash(Number(options.block));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
throw new Error(`Invalid block number or hash: ${options.block}`);
|
|
45
|
+
}
|
|
46
|
+
defaultLogger.debug(Object.assign(Object.assign({}, options), { blockHash }), 'Args');
|
|
47
|
+
let db;
|
|
48
|
+
if (options.db) {
|
|
49
|
+
db = yield openDb(options.db);
|
|
50
|
+
}
|
|
51
|
+
const header = yield api.getHeader(blockHash);
|
|
52
|
+
const inherents = new InherentProviders(new SetTimestamp(), [
|
|
53
|
+
new SetValidationData(),
|
|
54
|
+
new ParaInherentEnter(),
|
|
55
|
+
new SetNimbusAuthorInherent(),
|
|
56
|
+
new SetBabeRandomness(),
|
|
57
|
+
]);
|
|
58
|
+
return new Blockchain({
|
|
59
|
+
api,
|
|
60
|
+
buildBlockMode: options.buildBlockMode,
|
|
61
|
+
inherentProvider: inherents,
|
|
62
|
+
db,
|
|
63
|
+
header: {
|
|
64
|
+
hash: blockHash,
|
|
65
|
+
number: Number(header.number),
|
|
66
|
+
},
|
|
67
|
+
mockSignatureHost: options.mockSignatureHost,
|
|
68
|
+
allowUnresolvedImports: options.allowUnresolvedImports,
|
|
69
|
+
runtimeLogLevel: options.runtimeLogLevel,
|
|
70
|
+
registeredTypes: options.registeredTypes || {},
|
|
71
|
+
offchainWorker: options.offchainWorker,
|
|
72
|
+
maxMemoryBlockCount: options.maxMemoryBlockCount,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HexString } from '@polkadot/util/types';
|
|
2
|
+
import { StorageKey } from '@polkadot/types';
|
|
3
|
+
import { Blockchain } from '../blockchain';
|
|
4
|
+
export * from './set-storage';
|
|
5
|
+
export * from './time-travel';
|
|
6
|
+
export type GetKeys = (startKey?: string) => Promise<StorageKey<any>[]>;
|
|
7
|
+
export type ProcessKey = (key: StorageKey<any>) => any;
|
|
8
|
+
export declare function fetchKeys(getKeys: GetKeys, processKey: ProcessKey): Promise<void>;
|
|
9
|
+
export declare function fetchKeysToArray(getKeys: GetKeys): Promise<StorageKey<any>[]>;
|
|
10
|
+
export declare const compactHex: (value: Uint8Array) => HexString;
|
|
11
|
+
export declare const getParaId: (chain: Blockchain) => Promise<import("@polkadot/types").U32>;
|
|
12
|
+
export declare const isUrl: (url: string) => boolean;
|
|
13
|
+
export type Deferred<T> = {
|
|
14
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
15
|
+
reject: (reason?: any) => void;
|
|
16
|
+
promise: Promise<T>;
|
|
17
|
+
};
|
|
18
|
+
export declare function defer<T>(): Deferred<T>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { compactStripLength, hexToU8a, u8aToHex } from '@polkadot/util';
|
|
11
|
+
export * from './set-storage';
|
|
12
|
+
export * from './time-travel';
|
|
13
|
+
export function fetchKeys(getKeys, processKey) {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
const processKeys = (keys) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
for (const key of keys) {
|
|
17
|
+
yield processKey(key);
|
|
18
|
+
}
|
|
19
|
+
if (keys.length > 0) {
|
|
20
|
+
return keys[keys.length - 1];
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
});
|
|
24
|
+
const keys = yield getKeys();
|
|
25
|
+
let nextKey = yield processKeys(keys);
|
|
26
|
+
while (nextKey) {
|
|
27
|
+
const keys = yield getKeys(nextKey.toHex());
|
|
28
|
+
nextKey = yield processKeys(keys);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export function fetchKeysToArray(getKeys) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const res = [];
|
|
35
|
+
yield fetchKeys(getKeys, (key) => res.push(key));
|
|
36
|
+
return res;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export const compactHex = (value) => {
|
|
40
|
+
return u8aToHex(compactStripLength(value)[1]);
|
|
41
|
+
};
|
|
42
|
+
export const getParaId = (chain) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
const meta = yield chain.head.meta;
|
|
44
|
+
const raw = yield chain.head.get(compactHex(meta.query.parachainInfo.parachainId()));
|
|
45
|
+
if (!raw)
|
|
46
|
+
throw new Error('Cannot find parachain id');
|
|
47
|
+
return meta.registry.createType('u32', hexToU8a(raw));
|
|
48
|
+
});
|
|
49
|
+
export const isUrl = (url) => {
|
|
50
|
+
try {
|
|
51
|
+
new URL(url);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
export function defer() {
|
|
59
|
+
const deferred = {};
|
|
60
|
+
deferred.promise = new Promise((resolve, reject) => {
|
|
61
|
+
deferred.resolve = resolve;
|
|
62
|
+
deferred.reject = reject;
|
|
63
|
+
});
|
|
64
|
+
return deferred;
|
|
65
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { HexString } from '@polkadot/util/types';
|
|
2
|
+
export declare const PREFIX_LENGTH = 66;
|
|
3
|
+
export default class KeyCache {
|
|
4
|
+
readonly ranges: Array<{
|
|
5
|
+
prefix: string;
|
|
6
|
+
keys: string[];
|
|
7
|
+
}>;
|
|
8
|
+
feed(keys: HexString[]): void;
|
|
9
|
+
next(startKey: HexString): Promise<HexString | undefined>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import _ from 'lodash';
|
|
11
|
+
// 0x + 32 module + 32 method
|
|
12
|
+
export const PREFIX_LENGTH = 66;
|
|
13
|
+
export default class KeyCache {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.ranges = [];
|
|
16
|
+
}
|
|
17
|
+
feed(keys) {
|
|
18
|
+
const _keys = keys.filter((key) => key.length >= PREFIX_LENGTH);
|
|
19
|
+
if (_keys.length === 0)
|
|
20
|
+
return;
|
|
21
|
+
const startKey = _keys[0].slice(PREFIX_LENGTH);
|
|
22
|
+
const endKey = _keys[_keys.length - 1].slice(PREFIX_LENGTH);
|
|
23
|
+
const grouped = _.groupBy(_keys, (key) => key.slice(0, PREFIX_LENGTH));
|
|
24
|
+
for (const [prefix, keys] of Object.entries(grouped)) {
|
|
25
|
+
const ranges = this.ranges.filter((range) => range.prefix === prefix);
|
|
26
|
+
if (ranges.length === 0) {
|
|
27
|
+
// no existing range with prefix
|
|
28
|
+
this.ranges.push({ prefix, keys: keys.map((i) => i.slice(PREFIX_LENGTH)) });
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
let merged = false;
|
|
32
|
+
for (const range of ranges) {
|
|
33
|
+
const startPosition = _.sortedIndex(range.keys, startKey);
|
|
34
|
+
if (startPosition >= 0 && range.keys[startPosition] === startKey) {
|
|
35
|
+
// found existing range with prefix
|
|
36
|
+
range.keys.splice(startPosition, keys.length, ...keys.map((i) => i.slice(PREFIX_LENGTH)));
|
|
37
|
+
merged = true;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
const endPosition = _.sortedIndex(range.keys, endKey);
|
|
41
|
+
if (endPosition >= 0 && range.keys[endPosition] === endKey) {
|
|
42
|
+
// found existing range with prefix
|
|
43
|
+
range.keys.splice(0, endPosition + 1, ...keys.map((i) => i.slice(PREFIX_LENGTH)));
|
|
44
|
+
merged = true;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// insert new prefix with range
|
|
49
|
+
if (!merged) {
|
|
50
|
+
this.ranges.push({ prefix, keys: keys.map((i) => i.slice(PREFIX_LENGTH)) });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// TODO: merge ranges if they overlap
|
|
54
|
+
}
|
|
55
|
+
next(startKey) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
if (startKey.length < PREFIX_LENGTH)
|
|
58
|
+
return;
|
|
59
|
+
const prefix = startKey.slice(0, PREFIX_LENGTH);
|
|
60
|
+
const key = startKey.slice(PREFIX_LENGTH);
|
|
61
|
+
for (const range of this.ranges.filter((range) => range.prefix === prefix)) {
|
|
62
|
+
const index = _.sortedIndex(range.keys, key);
|
|
63
|
+
if (range.keys[index] !== key)
|
|
64
|
+
continue;
|
|
65
|
+
const nextKey = range.keys[index + 1];
|
|
66
|
+
if (nextKey) {
|
|
67
|
+
return [prefix, nextKey].join('');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HrmpChannelId } from '@polkadot/types/interfaces';
|
|
2
|
+
import { u32 } from '@polkadot/types';
|
|
3
|
+
export declare const WELL_KNOWN_KEYS: {
|
|
4
|
+
EPOCH_INDEX: `0x${string}`;
|
|
5
|
+
CURRENT_BLOCK_RANDOMNESS: `0x${string}`;
|
|
6
|
+
ONE_EPOCH_AGO_RANDOMNESS: `0x${string}`;
|
|
7
|
+
TWO_EPOCHS_AGO_RANDOMNESS: `0x${string}`;
|
|
8
|
+
CURRENT_SLOT: `0x${string}`;
|
|
9
|
+
ACTIVE_CONFIG: `0x${string}`;
|
|
10
|
+
};
|
|
11
|
+
export declare const dmqMqcHead: (paraId: u32) => `0x${string}`;
|
|
12
|
+
export declare const upgradeGoAheadSignal: (paraId: u32) => `0x${string}`;
|
|
13
|
+
export declare const hrmpIngressChannelIndex: (paraId: u32) => `0x${string}`;
|
|
14
|
+
export declare const hrmpEgressChannelIndex: (paraId: u32) => `0x${string}`;
|
|
15
|
+
export declare const hrmpChannels: (channelId: HrmpChannelId) => `0x${string}`;
|