@polkadot-api/cli 0.0.1-0a3edb2e805b29fa7d3ebb02c2084a125c4ee78b.1.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/LICENSE +21 -0
- package/README.md +1 -0
- package/metadata.scale +0 -0
- package/out.txt +42 -0
- package/package.json +39 -0
- package/src/CheckboxData.ts +38 -0
- package/src/ExtrinsicData.ts +119 -0
- package/src/_polyfills.ts +3 -0
- package/src/deferred.ts +48 -0
- package/src/descriptor-schema.ts +19 -0
- package/src/guards.ts +20 -0
- package/src/main.ts +839 -0
- package/src/metadata.ts +140 -0
- package/src/smolldot-worker.ts +42 -0
- package/src/testing.ts +32 -0
- package/tsconfig-build.json +4 -0
- package/tsconfig.json +12 -0
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@polkadot-api/cli",
|
|
3
|
+
"version": "0.0.1-0a3edb2e805b29fa7d3ebb02c2084a125c4ee78b.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"sideEffects": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"prettier": {
|
|
8
|
+
"printWidth": 80,
|
|
9
|
+
"semi": false,
|
|
10
|
+
"trailingComma": "all"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@inquirer/prompts": "^3.0.2",
|
|
14
|
+
"@substrate/connect": "^0.7.31",
|
|
15
|
+
"as-table": "^1.0.55",
|
|
16
|
+
"chalk": "^5.3.0",
|
|
17
|
+
"commander": "^11.0.0",
|
|
18
|
+
"fp-ts": "^2.16.1",
|
|
19
|
+
"fs.promises.exists": "^1.1.4",
|
|
20
|
+
"ora": "^7.0.1",
|
|
21
|
+
"rxjs": "^7.8.1",
|
|
22
|
+
"type-fest": "^4.3.1",
|
|
23
|
+
"write-pkg": "^6.0.0",
|
|
24
|
+
"zod": "^3.22.2",
|
|
25
|
+
"@polkadot-api/sc-provider": "0.0.1-0a3edb2e805b29fa7d3ebb02c2084a125c4ee78b.1.0",
|
|
26
|
+
"@polkadot-api/substrate-bindings": "0.0.1-0a3edb2e805b29fa7d3ebb02c2084a125c4ee78b.1.0",
|
|
27
|
+
"@polkadot-api/substrate-client": "0.0.1-0a3edb2e805b29fa7d3ebb02c2084a125c4ee78b.1.0",
|
|
28
|
+
"@polkadot-api/substrate-codegen": "0.0.1-0a3edb2e805b29fa7d3ebb02c2084a125c4ee78b.1.0",
|
|
29
|
+
"@polkadot-api/utils": "0.0.1-0a3edb2e805b29fa7d3ebb02c2084a125c4ee78b.1.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup-node src/main.ts --clean --out-dir build --sourcemap --platform node --format esm",
|
|
33
|
+
"start": "pnpm build && node --enable-source-maps build/main.js",
|
|
34
|
+
"start:interactive": "pnpm start -- -i",
|
|
35
|
+
"test": "echo 'no tests'",
|
|
36
|
+
"lint": "prettier --check README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
|
37
|
+
"format": "prettier --write README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\""
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { checkbox } from "@inquirer/prompts"
|
|
2
|
+
import { ReadonlyRecord } from "fp-ts/lib/ReadonlyRecord"
|
|
3
|
+
import util from "util"
|
|
4
|
+
|
|
5
|
+
export class CheckboxData {
|
|
6
|
+
#data: Record<string, bigint>
|
|
7
|
+
|
|
8
|
+
constructor(data?: Record<string, bigint>) {
|
|
9
|
+
this.#data = data ?? {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get data(): ReadonlyRecord<string, bigint> {
|
|
13
|
+
return this.#data
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async prompt(message: string, items: [string, bigint][]) {
|
|
17
|
+
const selected = await checkbox({
|
|
18
|
+
message,
|
|
19
|
+
choices: items.map(([s, checksum]) => ({
|
|
20
|
+
name: s,
|
|
21
|
+
value: [s, checksum] as const,
|
|
22
|
+
checked: s in this.#data,
|
|
23
|
+
})),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
for (const [s, checksum] of selected) {
|
|
27
|
+
this.#data[s] = checksum
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
[util.inspect.custom]() {
|
|
32
|
+
return this.toJSON()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
toJSON() {
|
|
36
|
+
return this.#data
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { select, checkbox, confirm } from "@inquirer/prompts"
|
|
2
|
+
import type { ReadonlyRecord } from "fp-ts/lib/ReadonlyRecord"
|
|
3
|
+
import util from "util"
|
|
4
|
+
|
|
5
|
+
type Data = Record<
|
|
6
|
+
string,
|
|
7
|
+
{
|
|
8
|
+
checksum: bigint
|
|
9
|
+
events: Record<string, Set<string>>
|
|
10
|
+
errors: Record<string, Set<string>>
|
|
11
|
+
}
|
|
12
|
+
>
|
|
13
|
+
|
|
14
|
+
export class ExtrinsicData {
|
|
15
|
+
#data: Data
|
|
16
|
+
|
|
17
|
+
constructor(data?: Data) {
|
|
18
|
+
this.#data = data ?? {}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get data(): ReadonlyRecord<
|
|
22
|
+
string,
|
|
23
|
+
Readonly<{
|
|
24
|
+
events: ReadonlyRecord<string, ReadonlySet<string>>
|
|
25
|
+
errors: ReadonlyRecord<string, ReadonlySet<string>>
|
|
26
|
+
}>
|
|
27
|
+
> {
|
|
28
|
+
return this.#data
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async prompt(
|
|
32
|
+
extrinsics: [name: string, checksum: bigint][],
|
|
33
|
+
events: ReadonlyArray<readonly [pallet: string, event: string]>,
|
|
34
|
+
errors: ReadonlyArray<readonly [pallet: string, event: string]>,
|
|
35
|
+
) {
|
|
36
|
+
const [ext, checksum] = await select({
|
|
37
|
+
message: "Select an extrinsic",
|
|
38
|
+
choices: extrinsics.map(([s, checksum]) => ({
|
|
39
|
+
name: s,
|
|
40
|
+
value: [s, checksum],
|
|
41
|
+
})),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
if (ext in this.#data) {
|
|
45
|
+
const deleteExt = await confirm({ message: "Delete extrinsic?" })
|
|
46
|
+
if (deleteExt) {
|
|
47
|
+
delete this.#data[ext]
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!this.#data[ext]) {
|
|
53
|
+
this.#data[ext] = { events: {}, errors: {}, checksum }
|
|
54
|
+
}
|
|
55
|
+
for (const [pallet, _] of events) {
|
|
56
|
+
if (!this.#data[ext].events[pallet]) {
|
|
57
|
+
this.#data[ext].events[pallet] = new Set()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
for (const [pallet, _] of errors) {
|
|
61
|
+
if (!this.#data[ext].errors[pallet]) {
|
|
62
|
+
this.#data[ext].errors[pallet] = new Set()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const selectedEvents = this.#data[ext].events
|
|
66
|
+
const selectedErrors = this.#data[ext].errors
|
|
67
|
+
|
|
68
|
+
const newSelectedEvents = await checkbox({
|
|
69
|
+
message: "Select Events for this extrinsic",
|
|
70
|
+
choices: events.map(([pallet, event]) => ({
|
|
71
|
+
name: `${pallet} - ${event}`,
|
|
72
|
+
value: [pallet, event] as [pallet: string, event: string],
|
|
73
|
+
checked: selectedEvents[pallet].has(event),
|
|
74
|
+
})),
|
|
75
|
+
})
|
|
76
|
+
const newSelectedErrors = await checkbox({
|
|
77
|
+
message: "Select Errors for this extrinsic",
|
|
78
|
+
choices: errors.map(([pallet, error]) => ({
|
|
79
|
+
name: `${pallet} - ${error}`,
|
|
80
|
+
value: [pallet, error] as [pallet: string, event: string],
|
|
81
|
+
checked: selectedErrors[pallet].has(error),
|
|
82
|
+
})),
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
for (const [pallet, _] of newSelectedEvents) {
|
|
86
|
+
this.#data[ext].events[pallet].clear()
|
|
87
|
+
}
|
|
88
|
+
for (const [pallet, _] of newSelectedErrors) {
|
|
89
|
+
this.#data[ext].errors[pallet].clear()
|
|
90
|
+
}
|
|
91
|
+
for (const [pallet, event] of newSelectedEvents) {
|
|
92
|
+
this.#data[ext].events[pallet].add(event)
|
|
93
|
+
}
|
|
94
|
+
for (const [pallet, error] of newSelectedErrors) {
|
|
95
|
+
this.#data[ext].errors[pallet].add(error)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
[util.inspect.custom]() {
|
|
100
|
+
return this.toJSON()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
toJSON() {
|
|
104
|
+
return Object.fromEntries(
|
|
105
|
+
Object.entries(this.#data).map(([k, v]) => [
|
|
106
|
+
k,
|
|
107
|
+
{
|
|
108
|
+
checksum: v.checksum,
|
|
109
|
+
events: Object.fromEntries(
|
|
110
|
+
Object.entries(v.events).map(([k, v]) => [k, Array.from(v)]),
|
|
111
|
+
),
|
|
112
|
+
errors: Object.fromEntries(
|
|
113
|
+
Object.entries(v.errors).map(([k, v]) => [k, Array.from(v)]),
|
|
114
|
+
),
|
|
115
|
+
},
|
|
116
|
+
]),
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
}
|
package/src/deferred.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
2
|
+
// This module is browser compatible.
|
|
3
|
+
|
|
4
|
+
// TODO(ry) It'd be better to make Deferred a class that inherits from
|
|
5
|
+
// Promise, rather than an interface. This is possible in ES2016, however
|
|
6
|
+
// typescript produces broken code when targeting ES5 code.
|
|
7
|
+
// See https://github.com/Microsoft/TypeScript/issues/15202
|
|
8
|
+
// At the time of writing, the github issue is closed but the problem remains.
|
|
9
|
+
export interface Deferred<T> extends Promise<T> {
|
|
10
|
+
readonly state: "pending" | "fulfilled" | "rejected"
|
|
11
|
+
resolve(value?: T | PromiseLike<T>): void
|
|
12
|
+
// deno-lint-ignore no-explicit-any
|
|
13
|
+
reject(reason?: any): void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Promise with the `reject` and `resolve` functions placed as methods
|
|
18
|
+
* on the promise object itself.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { deferred } from "https://deno.land/std@$STD_VERSION/async/deferred.ts";
|
|
23
|
+
*
|
|
24
|
+
* const p = deferred<number>();
|
|
25
|
+
* // ...
|
|
26
|
+
* p.resolve(42);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function deferred<T>(): Deferred<T> {
|
|
30
|
+
let methods
|
|
31
|
+
let state = "pending"
|
|
32
|
+
const promise = new Promise<T>((resolve, reject) => {
|
|
33
|
+
methods = {
|
|
34
|
+
async resolve(value: T | PromiseLike<T>) {
|
|
35
|
+
await value
|
|
36
|
+
state = "fulfilled"
|
|
37
|
+
resolve(value)
|
|
38
|
+
},
|
|
39
|
+
// deno-lint-ignore no-explicit-any
|
|
40
|
+
reject(reason?: any) {
|
|
41
|
+
state = "rejected"
|
|
42
|
+
reject(reason)
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
Object.defineProperty(promise, "state", { get: () => state })
|
|
47
|
+
return Object.assign(promise, methods) as Deferred<T>
|
|
48
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
|
|
3
|
+
export default z.record(
|
|
4
|
+
z.object({
|
|
5
|
+
constants: z.record(z.coerce.bigint()).optional(),
|
|
6
|
+
storage: z.record(z.coerce.bigint()).optional(),
|
|
7
|
+
events: z.record(z.coerce.bigint()).optional(),
|
|
8
|
+
errors: z.record(z.coerce.bigint()).optional(),
|
|
9
|
+
extrinsics: z
|
|
10
|
+
.record(
|
|
11
|
+
z.object({
|
|
12
|
+
checksum: z.coerce.bigint(),
|
|
13
|
+
events: z.record(z.array(z.string()).transform((s) => new Set(s))),
|
|
14
|
+
errors: z.record(z.array(z.string()).transform((s) => new Set(s))),
|
|
15
|
+
}),
|
|
16
|
+
)
|
|
17
|
+
.optional(),
|
|
18
|
+
}),
|
|
19
|
+
)
|
package/src/guards.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LookupEntry } from "@polkadot-api/substrate-codegen"
|
|
2
|
+
import { CodecType, metadata } from "@polkadot-api/substrate-bindings"
|
|
3
|
+
|
|
4
|
+
type Metadata = CodecType<typeof metadata>["metadata"]
|
|
5
|
+
|
|
6
|
+
export function assertMetadataIsv14(
|
|
7
|
+
metadata: Metadata,
|
|
8
|
+
): asserts metadata is Metadata & { tag: "v14" } {
|
|
9
|
+
if (metadata.tag !== "v14") {
|
|
10
|
+
throw new Error("unreachable")
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function assertLookupEntryIsEnum(
|
|
15
|
+
lookupEntry: LookupEntry,
|
|
16
|
+
): asserts lookupEntry is LookupEntry & { type: "enum" } {
|
|
17
|
+
if (lookupEntry.type !== "enum") {
|
|
18
|
+
throw new Error("not an enum")
|
|
19
|
+
}
|
|
20
|
+
}
|