@dedot/cli 0.18.8 → 1.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.
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DedotClient } from '@dedot/api';
|
|
2
|
+
import { generateTypes, generateTypesFromEndpoint, resolveBlockHash } from '@dedot/codegen';
|
|
3
|
+
import { WsProvider } from '@dedot/providers';
|
|
2
4
|
import { stringCamelCase, stringPascalCase } from '@dedot/utils';
|
|
3
5
|
import ora from 'ora';
|
|
4
6
|
import * as path from 'path';
|
|
5
|
-
import { parseMetadataFromRaw, parseMetadataFromWasm, parseStaticSubstrate } from './utils.js';
|
|
7
|
+
import { parseMetadataFromRaw, parseMetadataFromWasm, parseStaticSubstrate, findBlockFromSpecVersion, } from './utils.js';
|
|
8
|
+
const shortenHash = (hash, prefixLen = 6, suffixLen = 6) => {
|
|
9
|
+
if (hash.length <= prefixLen + suffixLen + 2)
|
|
10
|
+
return hash;
|
|
11
|
+
return `${hash.slice(0, prefixLen + 2)}...${hash.slice(-suffixLen)}`;
|
|
12
|
+
};
|
|
6
13
|
export const chaintypes = {
|
|
7
14
|
command: 'chaintypes',
|
|
8
15
|
describe: 'Generate Types & APIs for Substrate-based chains',
|
|
9
16
|
handler: async (yargs) => {
|
|
10
|
-
|
|
17
|
+
let { wsUrl, wasm, metadata, output = '', chain = '', dts = true, subpath = true, at, specVersion } = yargs;
|
|
11
18
|
const outDir = path.resolve(output);
|
|
12
19
|
const extension = dts ? 'd.ts' : 'ts';
|
|
13
20
|
const spinner = ora().start();
|
|
@@ -30,17 +37,67 @@ export const chaintypes = {
|
|
|
30
37
|
parsedResult = await parseStaticSubstrate();
|
|
31
38
|
spinner.succeed(`Parsed static substrate generic chaintypes`);
|
|
32
39
|
}
|
|
40
|
+
spinner.start();
|
|
33
41
|
if (parsedResult) {
|
|
34
42
|
const { metadata, runtimeVersion, rpcMethods } = parsedResult;
|
|
35
43
|
const chainName = chain || stringCamelCase(runtimeVersion.specName) || (shouldGenerateGenericTypes ? 'substrate' : 'local');
|
|
36
44
|
spinner.text = `Generating ${stringPascalCase(chainName)} generic chaintypes`;
|
|
37
|
-
generatedResult = await generateTypes(
|
|
45
|
+
generatedResult = await generateTypes({
|
|
46
|
+
chain: chainName,
|
|
47
|
+
metadata: metadata.latest,
|
|
48
|
+
rpcMethods,
|
|
49
|
+
runtimeVersion,
|
|
50
|
+
outDir,
|
|
51
|
+
extension,
|
|
52
|
+
useSubPaths: subpath,
|
|
53
|
+
});
|
|
38
54
|
spinner.succeed(`Generated ${stringPascalCase(chainName)} generic chaintypes`);
|
|
39
55
|
}
|
|
40
56
|
else {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
57
|
+
// Create client once and reuse for both operations
|
|
58
|
+
spinner.text = `Connecting to network: ${wsUrl} ...`;
|
|
59
|
+
const client = await DedotClient.legacy(new WsProvider({ endpoint: wsUrl }));
|
|
60
|
+
spinner.succeed(`Connected to network: ${wsUrl}`);
|
|
61
|
+
try {
|
|
62
|
+
let blockNumber;
|
|
63
|
+
if (specVersion) {
|
|
64
|
+
spinner.start();
|
|
65
|
+
spinner.text = `Resolving block hash for spec version ${specVersion}...`;
|
|
66
|
+
const result = await findBlockFromSpecVersion(client, specVersion);
|
|
67
|
+
at = result.blockHash;
|
|
68
|
+
blockNumber = result.blockNumber;
|
|
69
|
+
spinner.succeed(`Resolved block hash ${shortenHash(at)} (#${blockNumber}) for spec version ${specVersion}`);
|
|
70
|
+
}
|
|
71
|
+
spinner.start();
|
|
72
|
+
let atText = '';
|
|
73
|
+
if (at) {
|
|
74
|
+
let blockHash;
|
|
75
|
+
if (blockNumber === undefined) {
|
|
76
|
+
// at was provided directly by user, resolve it to block hash
|
|
77
|
+
blockHash = await resolveBlockHash(client, at);
|
|
78
|
+
const header = await client.block.header(blockHash);
|
|
79
|
+
blockNumber = header?.number;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// blockNumber is already set from spec resolution, at is the block hash
|
|
83
|
+
blockHash = at;
|
|
84
|
+
}
|
|
85
|
+
atText = ` at ${shortenHash(blockHash)} (#${blockNumber ?? 'unknown'})`;
|
|
86
|
+
}
|
|
87
|
+
spinner.text = `Generating chaintypes via endpoint: ${wsUrl}${atText}`;
|
|
88
|
+
generatedResult = await generateTypesFromEndpoint({
|
|
89
|
+
chain,
|
|
90
|
+
client,
|
|
91
|
+
outDir,
|
|
92
|
+
extension,
|
|
93
|
+
useSubPaths: subpath,
|
|
94
|
+
at,
|
|
95
|
+
});
|
|
96
|
+
spinner.succeed(`Generated chaintypes via endpoint: ${wsUrl}${atText}`);
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
await client.disconnect();
|
|
100
|
+
}
|
|
44
101
|
}
|
|
45
102
|
const { interfaceName, outputFolder } = generatedResult;
|
|
46
103
|
console.log(` ➡ Output directory: file://${outputFolder}`);
|
|
@@ -60,6 +117,7 @@ export const chaintypes = {
|
|
|
60
117
|
else {
|
|
61
118
|
spinner.fail(`Failed to generate chaintypes via endpoint: ${wsUrl}`);
|
|
62
119
|
}
|
|
120
|
+
console.error(`Error details: ${e.message}`);
|
|
63
121
|
console.error(e);
|
|
64
122
|
}
|
|
65
123
|
spinner.stop();
|
|
@@ -102,6 +160,16 @@ export const chaintypes = {
|
|
|
102
160
|
describe: 'Using subpath for shared packages (e.g: dedot/types)',
|
|
103
161
|
alias: 's',
|
|
104
162
|
default: true,
|
|
163
|
+
})
|
|
164
|
+
.option('at', {
|
|
165
|
+
type: 'string',
|
|
166
|
+
describe: 'Block hash or block number to generate chaintypes at',
|
|
167
|
+
alias: 'a',
|
|
168
|
+
})
|
|
169
|
+
.option('specVersion', {
|
|
170
|
+
type: 'number',
|
|
171
|
+
describe: 'Spec version to generate chaintypes at',
|
|
172
|
+
alias: 'x',
|
|
105
173
|
})
|
|
106
174
|
.check((argv) => {
|
|
107
175
|
const inputs = ['wsUrl', 'wasm', 'metadata'];
|
|
@@ -112,6 +180,15 @@ export const chaintypes = {
|
|
|
112
180
|
if (providedInputs.length === 0) {
|
|
113
181
|
throw new Error(`Please provide one of the following options: ${inputs.join(', ')}`);
|
|
114
182
|
}
|
|
183
|
+
if (argv.at && !argv.wsUrl) {
|
|
184
|
+
throw new Error('The --at option can only be used with --wsUrl');
|
|
185
|
+
}
|
|
186
|
+
if (argv.specVersion && !argv.wsUrl) {
|
|
187
|
+
throw new Error('The --specVersion option can only be used with --wsUrl');
|
|
188
|
+
}
|
|
189
|
+
if (argv.specVersion && argv.at) {
|
|
190
|
+
throw new Error('Please provide only one of the following options: --spec-version, --at');
|
|
191
|
+
}
|
|
115
192
|
return true;
|
|
116
193
|
});
|
|
117
194
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DedotClient } from '@dedot/api';
|
|
1
2
|
import { Metadata, RuntimeVersion } from '@dedot/codecs';
|
|
2
3
|
import { HexString } from '@dedot/utils';
|
|
3
4
|
import { DecodedMetadataInfo, ParsedResult } from './types.js';
|
|
@@ -6,3 +7,7 @@ export declare const decodeMetadata: (metadata: HexString | Uint8Array) => Decod
|
|
|
6
7
|
export declare const parseMetadataFromRaw: (metadataFile: string) => Promise<ParsedResult>;
|
|
7
8
|
export declare const parseMetadataFromWasm: (runtimeFile: string) => Promise<ParsedResult>;
|
|
8
9
|
export declare const parseStaticSubstrate: () => Promise<ParsedResult>;
|
|
10
|
+
export declare const findBlockFromSpecVersion: (client: DedotClient, specVersion: number) => Promise<{
|
|
11
|
+
blockHash: HexString;
|
|
12
|
+
blockNumber: number;
|
|
13
|
+
}>;
|
|
@@ -2,7 +2,7 @@ import { rpc } from '@polkadot/types-support/metadata/static-substrate';
|
|
|
2
2
|
import staticSubstrate from '@polkadot/types-support/metadata/v15/substrate-hex';
|
|
3
3
|
import { ConstantExecutor } from '@dedot/api';
|
|
4
4
|
import { $Metadata, PortableRegistry, unwrapOpaqueMetadata } from '@dedot/codecs';
|
|
5
|
-
import { hexToU8a, isHex } from '@dedot/utils';
|
|
5
|
+
import { assert, hexToU8a, isHex } from '@dedot/utils';
|
|
6
6
|
import { getMetadataFromWasmRuntime } from '@dedot/wasm';
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
export const getRuntimeVersion = (metadata) => {
|
|
@@ -56,3 +56,28 @@ export const parseStaticSubstrate = async () => {
|
|
|
56
56
|
rpcMethods: rpc.methods,
|
|
57
57
|
};
|
|
58
58
|
};
|
|
59
|
+
export const findBlockFromSpecVersion = async (client, specVersion) => {
|
|
60
|
+
const upperBound = client.runtimeVersion.specVersion;
|
|
61
|
+
const lowerBound = (await client.rpc.state_getRuntimeVersion(await client.rpc.chain_getBlockHash(0))).specVersion;
|
|
62
|
+
assert(specVersion >= lowerBound, `Specified specVersion ${specVersion} is lower than the earliest specVersion ${lowerBound} of the chain.`);
|
|
63
|
+
assert(specVersion <= upperBound, `Specified specVersion ${specVersion} is higher than the latest specVersion ${upperBound} of the chain at the current block.`);
|
|
64
|
+
let high = (await client.block.best()).number;
|
|
65
|
+
let low = 0;
|
|
66
|
+
while (low <= high) {
|
|
67
|
+
const mid = Math.floor((low + high) / 2);
|
|
68
|
+
const midBlockHash = await client.rpc.chain_getBlockHash(mid);
|
|
69
|
+
assert(midBlockHash, `Failed to get block hash at block number ${mid}`);
|
|
70
|
+
const midRuntimeVersion = await client.rpc.state_getRuntimeVersion(midBlockHash);
|
|
71
|
+
const midSpecVersion = midRuntimeVersion.specVersion;
|
|
72
|
+
if (midSpecVersion === specVersion) {
|
|
73
|
+
return { blockHash: midBlockHash, blockNumber: mid };
|
|
74
|
+
}
|
|
75
|
+
else if (midSpecVersion < specVersion) {
|
|
76
|
+
low = mid + 1;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
high = mid - 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
assert(false, `Could not find a block with specVersion ${specVersion}.`);
|
|
83
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"author": "Thang X. Vu <thang@dedot.dev>",
|
|
5
5
|
"homepage": "https://dedot.dev",
|
|
6
6
|
"repository": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"test": "npx vitest --watch=false"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@dedot/api": "0.
|
|
26
|
-
"@dedot/codecs": "0.
|
|
27
|
-
"@dedot/codegen": "0.
|
|
25
|
+
"@dedot/api": "1.0.0",
|
|
26
|
+
"@dedot/codecs": "1.0.0",
|
|
27
|
+
"@dedot/codegen": "1.0.0",
|
|
28
28
|
"@dedot/wasm": "^0.1.0",
|
|
29
|
-
"@polkadot/types-support": "^16.
|
|
29
|
+
"@polkadot/types-support": "^16.5.3",
|
|
30
30
|
"ora": "^8.2.0",
|
|
31
31
|
"yargs": "^17.7.2"
|
|
32
32
|
},
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"node": ">=18"
|
|
42
42
|
},
|
|
43
43
|
"license": "Apache-2.0",
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "7767062a2188b4ac90561c5ad3cc3f06ac608a24",
|
|
45
45
|
"module": "./index.js",
|
|
46
46
|
"types": "./index.d.ts"
|
|
47
47
|
}
|